|
1
|
|
|
<?php |
|
2
|
|
|
namespace EWW\Dpf\Services\Transfer; |
|
3
|
|
|
|
|
4
|
|
|
/* |
|
5
|
|
|
* This file is part of the TYPO3 CMS project. |
|
6
|
|
|
* |
|
7
|
|
|
* It is free software; you can redistribute it and/or modify it under |
|
8
|
|
|
* the terms of the GNU General Public License, either version 2 |
|
9
|
|
|
* of the License, or any later version. |
|
10
|
|
|
* |
|
11
|
|
|
* For the full copyright and license information, please read the |
|
12
|
|
|
* LICENSE.txt file that was distributed with this source code. |
|
13
|
|
|
* |
|
14
|
|
|
* The TYPO3 project - inspiring people to share! |
|
15
|
|
|
*/ |
|
16
|
|
|
|
|
17
|
|
|
$extpath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('dpf'); |
|
18
|
|
|
|
|
19
|
|
|
\Httpful\Bootstrap::init(); |
|
20
|
|
|
|
|
21
|
|
|
|
|
22
|
|
|
use \EWW\Dpf\Services\Logger\TransferLogger; |
|
23
|
|
|
use \Httpful\Request; |
|
24
|
|
|
|
|
25
|
|
|
class FedoraRepository implements Repository |
|
26
|
|
|
{ |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* documentTransferLogRepository |
|
30
|
|
|
* |
|
31
|
|
|
* @var \EWW\Dpf\Domain\Repository\DocumentTransferLogRepository |
|
32
|
|
|
* @inject |
|
33
|
|
|
*/ |
|
34
|
|
|
protected $documentTransferLogRepository; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* clientConfigurationManager |
|
38
|
|
|
* |
|
39
|
|
|
* @var \EWW\Dpf\Configuration\ClientConfigurationManager |
|
40
|
|
|
* @inject |
|
41
|
|
|
*/ |
|
42
|
|
|
protected $clientConfigurationManager; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* objectManager |
|
46
|
|
|
* |
|
47
|
|
|
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface |
|
48
|
|
|
* @inject |
|
49
|
|
|
*/ |
|
50
|
|
|
protected $objectManager; |
|
51
|
|
|
|
|
52
|
|
|
protected $response; |
|
53
|
|
|
|
|
54
|
|
|
protected $errors = array(); |
|
55
|
|
|
|
|
56
|
|
|
const X_ON_BEHALF_OF = 'X-On-Behalf-Of'; |
|
57
|
|
|
const QUCOSA_TYPE = 'application/vnd.qucosa.mets+xml'; |
|
58
|
|
|
|
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* Saves a new document into the Fedora repository |
|
62
|
|
|
* |
|
63
|
|
|
* @param \EWW\Dpf\Domain\Model\Document $document |
|
64
|
|
|
* @return string |
|
65
|
|
|
* @throws \Exception |
|
66
|
|
|
*/ |
|
67
|
|
|
public function ingest($document, $metsXml) |
|
68
|
|
|
{ |
|
69
|
|
|
try { |
|
70
|
|
|
|
|
71
|
|
|
$response = Request::post($this->clientConfigurationManager->getSwordHost() . "/sword/" . $this->getSWORDCollection()) |
|
72
|
|
|
->sendsXml() |
|
73
|
|
|
->body($metsXml) |
|
74
|
|
|
->authenticateWith($this->clientConfigurationManager->getSwordUser(), $this->clientConfigurationManager->getSwordPassword()) |
|
75
|
|
|
->sendsType(FedoraRepository::QUCOSA_TYPE) |
|
76
|
|
|
->addHeader(FedoraRepository::X_ON_BEHALF_OF, $this->getOwnerId()) |
|
77
|
|
|
->addHeader('Slug', $document->getReservedObjectIdentifier()) |
|
78
|
|
|
->send(); |
|
79
|
|
|
|
|
80
|
|
|
// if transfer successful |
|
81
|
|
|
if (!$response->hasErrors() && $response->code == 201) { |
|
82
|
|
|
return $this->getRemoteDocumentId($response); |
|
83
|
|
|
} else { |
|
84
|
|
|
TransferLogger::Log('INGEST', $document->getUid(), null, $response); |
|
85
|
|
|
throw new \EWW\Dpf\Exceptions\IngestDocumentErrorException("Fedora error while ingest document."); |
|
86
|
|
|
} |
|
87
|
|
|
} |
|
88
|
|
|
catch (\Exception $exception) { |
|
89
|
|
|
TransferLogger::Log('INGEST', $document->getUid(), null, $exception->getMessage()); |
|
90
|
|
|
|
|
91
|
|
|
if ($exception instanceof \Httpful\Exception\ConnectionErrorException) { |
|
92
|
|
|
$message = $exception->getMessage(); |
|
93
|
|
|
throw new \EWW\Dpf\Exceptions\RepositoryConnectionErrorException($message); |
|
94
|
|
|
} else { |
|
95
|
|
|
throw $exception; |
|
96
|
|
|
} |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
return null; |
|
|
|
|
|
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* Updates an existing document in the Fedora repository |
|
104
|
|
|
* |
|
105
|
|
|
* @param \EWW\Dpf\Domain\Model\Document $document |
|
106
|
|
|
* @param string $metsXml |
|
107
|
|
|
* @return string |
|
108
|
|
|
* @throws \Exception |
|
109
|
|
|
*/ |
|
110
|
|
|
public function update($document, $metsXml) |
|
111
|
|
|
{ |
|
112
|
|
|
|
|
113
|
|
|
$remoteId = $document->getObjectIdentifier(); |
|
114
|
|
|
|
|
115
|
|
|
try { |
|
116
|
|
|
$response = Request::put($this->clientConfigurationManager->getSwordHost() . "/sword/" . $this->getSWORDCollection() . "/" . $remoteId) |
|
117
|
|
|
->sendsXml() |
|
118
|
|
|
->body($metsXml) |
|
119
|
|
|
->authenticateWith($this->clientConfigurationManager->getSwordUser(), $this->clientConfigurationManager->getSwordPassword()) |
|
120
|
|
|
->sendsType(FedoraRepository::QUCOSA_TYPE) |
|
121
|
|
|
->addHeader(FedoraRepository::X_ON_BEHALF_OF, $this->getOwnerId()) |
|
122
|
|
|
->send(); |
|
123
|
|
|
|
|
124
|
|
|
// if transfer successful |
|
125
|
|
|
if (!$response->hasErrors() && $response->code == 200) { |
|
126
|
|
|
return $this->getRemoteDocumentId($response); |
|
127
|
|
|
} else { |
|
128
|
|
|
TransferLogger::Log('UPDATE', $document->getUid(), $remoteId, $response); |
|
129
|
|
|
throw new \EWW\Dpf\Exceptions\UpdateDocumentErrorException("Fedora error while update document."); |
|
130
|
|
|
} |
|
131
|
|
|
} catch (\Exception $exception) { |
|
132
|
|
|
TransferLogger::Log('UPDATE', $document->getUid(), null, $exception->getMessage()); |
|
133
|
|
|
|
|
134
|
|
|
if ($exception instanceof \Httpful\Exception\ConnectionErrorException) { |
|
135
|
|
|
$message = $exception->getMessage(); |
|
136
|
|
|
throw new \EWW\Dpf\Exceptions\RepositoryConnectionErrorException($message); |
|
137
|
|
|
} else { |
|
138
|
|
|
throw $exception; |
|
139
|
|
|
} |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
return null; |
|
|
|
|
|
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* Gets an existing document from the Fedora repository |
|
147
|
|
|
* |
|
148
|
|
|
* @param string $remoteId |
|
149
|
|
|
* @return string |
|
150
|
|
|
* @throws \Exception |
|
151
|
|
|
*/ |
|
152
|
|
|
public function retrieve($remoteId) |
|
153
|
|
|
{ |
|
154
|
|
|
|
|
155
|
|
|
try { |
|
156
|
|
|
$response = Request::get($this->clientConfigurationManager->getFedoraHost() . "/fedora/objects/" . $remoteId . "/methods/qucosa:SDef/getMETSDissemination") |
|
157
|
|
|
->authenticateWith($this->clientConfigurationManager->getFedoraUser(), $this->clientConfigurationManager->getFedoraPassword()) |
|
158
|
|
|
->addHeader(FedoraRepository::X_ON_BEHALF_OF, $this->getOwnerId()) |
|
159
|
|
|
->send(); |
|
160
|
|
|
|
|
161
|
|
|
// if transfer successful |
|
162
|
|
|
if (!$response->hasErrors() && $response->code == 200) { |
|
163
|
|
|
return $response->__toString(); |
|
164
|
|
|
} else { |
|
165
|
|
|
TransferLogger::Log('RETRIEVE', null, $remoteId, $response); |
|
166
|
|
|
throw new \EWW\Dpf\Exceptions\RetrieveDocumentErrorException("Fedora has returned an error."); |
|
167
|
|
|
} |
|
168
|
|
|
} catch (\Exception $exception) { |
|
169
|
|
|
TransferLogger::Log('RETRIEVE', null, $remoteId, $exception->getMessage()); |
|
170
|
|
|
|
|
171
|
|
|
if ($exception instanceof \Httpful\Exception\ConnectionErrorException) { |
|
172
|
|
|
$message = $exception->getMessage(); |
|
173
|
|
|
throw new \EWW\Dpf\Exceptions\RepositoryConnectionErrorException($message); |
|
174
|
|
|
} else { |
|
175
|
|
|
throw $exception; |
|
176
|
|
|
} |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
return null; |
|
|
|
|
|
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
/** |
|
183
|
|
|
* Reserves a new DocumentId (qucosa id) |
|
184
|
|
|
* |
|
185
|
|
|
* @param string $remoteId |
|
186
|
|
|
* @return string |
|
187
|
|
|
* @throws \Exception |
|
188
|
|
|
*/ |
|
189
|
|
|
public function getNextDocumentId() |
|
190
|
|
|
{ |
|
191
|
|
|
try { |
|
192
|
|
|
$response = Request::get($this->clientConfigurationManager->getFedoraHost() . "/fedora/management/getNextPID?numPIDs=1&namespace=qucosa&xml=true") |
|
193
|
|
|
->authenticateWith($this->clientConfigurationManager->getFedoraUser(), $this->clientConfigurationManager->getFedoraPassword()) |
|
194
|
|
|
->addHeader(FedoraRepository::X_ON_BEHALF_OF, $this->getOwnerId()) |
|
195
|
|
|
//->addHeader() |
|
196
|
|
|
->send(); |
|
197
|
|
|
|
|
198
|
|
|
// if transfer successful |
|
199
|
|
|
if (!$response->hasErrors() && $response->code == 200) { |
|
200
|
|
|
return $response->__toString(); |
|
201
|
|
|
} else { |
|
202
|
|
|
TransferLogger::Log('GET_NEXT_DOCUMENT_ID', null, null, $response); |
|
203
|
|
|
throw new \EWW\Dpf\Exceptions\NextDocumentIdErrorException("Fedora error while getting a document id."); |
|
204
|
|
|
} |
|
205
|
|
|
} catch (\Exception $exception) { |
|
206
|
|
|
TransferLogger::Log('GET_NEXT_DOCUMENT_ID', null, null, $exception->getMessage()); |
|
207
|
|
|
|
|
208
|
|
|
if ($exception instanceof \Httpful\Exception\ConnectionErrorException) { |
|
209
|
|
|
$message = $exception->getMessage(); |
|
210
|
|
|
throw new \EWW\Dpf\Exceptions\RepositoryConnectionErrorException($message); |
|
211
|
|
|
} else { |
|
212
|
|
|
throw $exception; |
|
213
|
|
|
} |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
return null; |
|
|
|
|
|
|
217
|
|
|
} |
|
218
|
|
|
|
|
219
|
|
|
/** |
|
220
|
|
|
* Removes an existing document from the Fedora repository |
|
221
|
|
|
* |
|
222
|
|
|
* @param \EWW\Dpf\Domain\Model\Document $document |
|
223
|
|
|
* @param $state |
|
224
|
|
|
* @return boolean |
|
225
|
|
|
* @throws \Exception |
|
226
|
|
|
*/ |
|
227
|
|
|
public function delete($document, $state) |
|
228
|
|
|
{ |
|
229
|
|
|
|
|
230
|
|
|
$remoteId = $document->getObjectIdentifier(); |
|
231
|
|
|
|
|
232
|
|
|
$state = ($state) ? "?" . $state : ""; |
|
233
|
|
|
|
|
234
|
|
|
try { |
|
235
|
|
|
$response = Request::delete($this->clientConfigurationManager->getSwordHost() . "/sword/" . $this->getSWORDCollection() . "/" . $remoteId . $state) |
|
236
|
|
|
->authenticateWith($this->clientConfigurationManager->getSwordUser(), $this->clientConfigurationManager->getSwordPassword()) |
|
237
|
|
|
->addHeader(FedoraRepository::X_ON_BEHALF_OF, $this->getOwnerId()) |
|
238
|
|
|
->send(); |
|
239
|
|
|
|
|
240
|
|
|
// if transfer successful |
|
241
|
|
|
if (!$response->hasErrors() && $response->code == 204) { |
|
242
|
|
|
return true; |
|
243
|
|
|
} else { |
|
244
|
|
|
TransferLogger::Log('DELETE', $document->getUid(), $remoteId, $response); |
|
245
|
|
|
switch ($state) { |
|
246
|
|
|
case "revert": |
|
247
|
|
|
throw new \EWW\Dpf\Exceptions\ActivateDocumentErrorException("Fedora error while activate document."); |
|
248
|
|
|
break; |
|
249
|
|
|
case "inactivate": |
|
250
|
|
|
throw new \EWW\Dpf\Exceptions\RestoreDocumentErrorException("Fedora error while restore document."); |
|
251
|
|
|
break; |
|
252
|
|
|
default: |
|
253
|
|
|
throw new \EWW\Dpf\Exceptions\DeleteDocumentErrorException("Fedora error while delete document."); |
|
254
|
|
|
break; |
|
255
|
|
|
} |
|
256
|
|
|
} |
|
257
|
|
|
} catch (\Exception $exception) { |
|
258
|
|
|
TransferLogger::Log('DELETE', $document->getUid(), null, $exception->getMessage()); |
|
259
|
|
|
|
|
260
|
|
|
if ($exception instanceof \Httpful\Exception\ConnectionErrorException) { |
|
261
|
|
|
$message = $exception->getMessage(); |
|
262
|
|
|
throw new \EWW\Dpf\Exceptions\RepositoryConnectionErrorException($message); |
|
263
|
|
|
} else { |
|
264
|
|
|
throw $exception; |
|
265
|
|
|
} |
|
266
|
|
|
} |
|
267
|
|
|
|
|
268
|
|
|
return false; |
|
|
|
|
|
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
/** |
|
272
|
|
|
* Gets the remoteDocumentId from the repository XML response. |
|
273
|
|
|
* |
|
274
|
|
|
* @param \Httpful\Response $response |
|
275
|
|
|
* @return string |
|
276
|
|
|
*/ |
|
277
|
|
|
protected function getRemoteDocumentId($response) |
|
278
|
|
|
{ |
|
279
|
|
|
|
|
280
|
|
|
// Get repository ID and write into document |
|
281
|
|
|
$responseDom = new \DOMDocument(); |
|
282
|
|
|
$responseDom->loadXML($response->raw_body); |
|
283
|
|
|
$responseXpath = new \DOMXPath($responseDom); |
|
284
|
|
|
$responseXpath->registerNamespace("atom", "http://www.w3.org/2005/Atom"); |
|
285
|
|
|
$responseNodes = $responseXpath->query("/atom:entry/atom:id"); |
|
286
|
|
|
|
|
287
|
|
|
if ($responseNodes->length > 0) { |
|
288
|
|
|
$objectIdentifier = $responseNodes->item(0)->nodeValue; |
|
289
|
|
|
return $objectIdentifier; |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
|
|
return null; |
|
293
|
|
|
} |
|
294
|
|
|
|
|
295
|
|
|
protected function getOwnerId() |
|
296
|
|
|
{ |
|
297
|
|
|
$ownerId = $this->clientConfigurationManager->getOwnerId(); |
|
298
|
|
|
if (empty($ownerId)) { |
|
299
|
|
|
throw new \Exception('Owner id can not be empty or null!'); |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
return $ownerId; |
|
303
|
|
|
} |
|
304
|
|
|
|
|
305
|
|
|
protected function getSWORDCollection() |
|
306
|
|
|
{ |
|
307
|
|
|
return $this->clientConfigurationManager->getSwordCollectionNamespace(); |
|
308
|
|
|
} |
|
309
|
|
|
} |
|
310
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.