Open Journal Systems  3.3.0
NativeXmlSubmissionFileFilter.inc.php
1 <?php
2 
16 import('lib.pkp.plugins.importexport.native.filter.NativeImportFilter');
17 
23  function __construct($filterGroup) {
24  $this->setDisplayName('Native XML submission file import');
25  parent::__construct($filterGroup);
26  }
27 
28  //
29  // Implement template methods from NativeImportFilter
30  //
35  function getPluralElementName() {
36  return 'submission_files';
37  }
38 
44  return 'submission_file';
45  }
46 
47  //
48  // Implement template methods from PersistableFilter
49  //
53  function getClassName() {
54  return 'lib.pkp.plugins.importexport.native.filter.NativeXmlSubmissionFileFilter';
55  }
56 
57 
63  function handleElement($node) {
64  $deployment = $this->getDeployment();
65  $stageName = $node->getAttribute('stage');
66  $fileId = $node->getAttribute('id');
67  $stageNameIdMapping = $deployment->getStageNameStageIdMapping();
68  assert(isset($stageNameIdMapping[$stageName]));
69  $stageId = $stageNameIdMapping[$stageName];
70 
71  $submissionFiles = array();
72  // Handle metadata in subelements
73  for ($n = $node->firstChild; $n !== null; $n=$n->nextSibling) {
74  if (is_a($n, 'DOMElement')) {
75  $this->handleChildElement($n, $stageId, $fileId, $submissionFiles);
76  }
77  }
78 
79  return $submissionFiles;
80  }
81 
90  function handleChildElement($node, $stageId, $fileId, &$submissionFiles) {
91  $deployment = $this->getDeployment();
92  $submission = $deployment->getSubmission();
93  switch ($node->tagName) {
94  case 'revision':
95  $submissionFile = $this->handleRevisionElement($node, $stageId, $fileId);
96  if ($submissionFile) $submissionFiles[] = $submissionFile;
97  break;
98  default:
99  $deployment->addWarning(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.unknownElement', array('param' => $node->tagName)));
100  }
101  }
102 
109  function handleRevisionElement($node, $stageId, $fileId) {
110  static $genresByContextId = array();
111 
112  $deployment = $this->getDeployment();
113  $submission = $deployment->getSubmission();
114  $context = $deployment->getContext();
115 
116  $errorOccured = false;
117 
118  $revisionId = $node->getAttribute('number');
119 
120  $source = $node->getAttribute('source');
121  $sourceFileAndRevision = null;
122  if ($source) {
123  $sourceFileAndRevision = explode('-', $source);
124  }
125 
126  $genreId = null;
127  $genreName = $node->getAttribute('genre');
128  if ($genreName) {
129  // Build a cached list of genres by context ID by name
130  if (!isset($genresByContextId[$context->getId()])) {
131  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
132  $genres = $genreDao->getByContextId($context->getId());
133  while ($genre = $genres->next()) {
134  foreach ($genre->getName(null) as $locale => $name) {
135  $genresByContextId[$context->getId()][$name] = $genre;
136  }
137  }
138  }
139  if (!isset($genresByContextId[$context->getId()][$genreName])) {
140  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.unknownGenre', array('param' => $genreName)));
141  $errorOccured = true;
142  } else {
143  $genre = $genresByContextId[$context->getId()][$genreName];
144  $genreId = $genre->getId();
145  }
146  }
147 
148  $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $submissionFileDao SubmissionFileDAO */
149  $submissionFile = $submissionFileDao->newDataObjectByGenreId($genreId);
150  $submissionFile->setSubmissionId($submission->getId());
151  $submissionFile->setSubmissionLocale($submission->getLocale());
152  $submissionFile->setGenreId($genreId);
153  $submissionFile->setFileStage($stageId);
154  $submissionFile->setDateUploaded(Core::getCurrentDate());
155  $submissionFile->setDateModified(Core::getCurrentDate());
156  if ($node->getAttribute('available') == 'true') $submissionFile->setViewable(true);
157 
158  $submissionFile->setOriginalFileName($filename = $node->getAttribute('filename'));
159  for ($n = $node->firstChild; $n !== null; $n=$n->nextSibling) {
160  if (is_a($n, 'DOMElement')) {
161  $filename = $this->handleRevisionChildElement($n, $submission, $submissionFile);
162  }
163  }
164  if (!$filename) {
165  // $this->handleRevisionChildElement() failed to provide any file (error message should have been handled in called method)
166  $errorOccured = true;
167  } else {
168  clearstatcache(true, $filename);
169  if (!file_exists($filename) || !filesize($filename)) {
170  // $this->handleRevisionChildElement() failed to provide a real file
171  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.native.error.submissionFileImportFailed'));
172  $errorOccured = true;
173  }
174  }
175 
176  $uploaderUsername = $node->getAttribute('uploader');
177  if (!$uploaderUsername) {
178  $user = $deployment->getUser();
179  } else {
180  // Determine the user based on the username
181  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
182  $user = $userDao->getByUsername($uploaderUsername);
183  }
184  if ($user) {
185  $submissionFile->setUploaderUserId($user->getId());
186  } else {
187  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.unknownUploader', array('param' => $uploaderUsername)));
188  $errorOccured = true;
189  }
190 
191  $fileSize = $node->getAttribute('filesize');
192  $fileSizeOnDisk = filesize($filename);
193  if ($fileSize) {
194  if ($fileSize != $fileSizeOnDisk) {
195  $deployment->addWarning(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.filesizeMismatch', array('expected' => $fileSize, 'actual' => $fileSizeOnDisk)));
196  }
197  }
198  else {
199  $fileSize = $fileSizeOnDisk;
200  }
201  $submissionFile->setFileSize($fileSize);
202 
203  $fileType = $node->getAttribute('filetype');
204  $submissionFile->setFileType($fileType);
205 
206  $submissionFile->setRevision($revisionId);
207 
208  if ($sourceFileAndRevision) {
209  // the source file revision should already be processed, so get the new source file ID
210  $sourceFileId = $deployment->getFileDBId($sourceFileAndRevision[0], $sourceFileAndRevision[1]);
211  if ($sourceFileId) {
212  $submissionFile->setSourceFileId($sourceFileId);
213  $submissionFile->setSourceRevision($sourceFileAndRevision[1]);
214  }
215  }
216 
217  // if the same file is already inserted, take its DB file ID
218  $DBId = $deployment->getFileDBId($fileId);
219  if ($DBId) {
220  $submissionFile->setFileId($DBId);
221  $DBRevision = $deployment->getFileDBId($fileId, $revisionId);
222  // If both the file id and the revision id is duplicated, we cannot insert the record
223  if ($DBRevision) {
224  $errorOccured = true;
225  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.duplicateRevisionForSubmission', array('fileId' => $fileId, 'revisionId' => $revisionId)));
226  }
227  }
228 
229  if ($errorOccured) {
230  // if error occured, the file cannot be inserted into DB, becase
231  // genre, uploader and user group are required (e.g. at name generation).
232  $submissionFile = null;
233  } else {
234  $insertedSubmissionFile = $submissionFileDao->insertObject($submissionFile, $filename, false);
235  $deployment->setFileDBId($fileId, $revisionId, $insertedSubmissionFile->getFileId());
236  }
237 
238  import('lib.pkp.classes.file.FileManager');
239  $fileManager = new FileManager();
240  $fileManager->deleteByPath($filename);
241  return $submissionFile;
242  }
243 
251  function handleRevisionChildElement($node, $submission, $submissionFile) {
252  $deployment = $this->getDeployment();
253  $context = $deployment->getContext();
254  $submission = $deployment->getSubmission();
255  switch ($node->tagName) {
256  case 'submission_file_ref':
257  if ($submissionFile->getFileStage() == SUBMISSION_FILE_DEPENDENT) {
258  $fileId = $node->getAttribute('id');
259  $revisionId = $node->getAttribute('revision');
260  $dbFileId = $deployment->getFileDBId($fileId, $revisionId);
261  if ($dbFileId) {
262  $submissionFile->setAssocType(ASSOC_TYPE_SUBMISSION_FILE);
263  $submissionFile->setAssocId($dbFileId);
264  }
265  }
266  break;
267  case 'id':
268  $this->parseIdentifier($node, $submissionFile);
269  break;
270  case 'name':
271  $locale = $node->getAttribute('locale');
272  if (empty($locale)) $locale = $context->getPrimaryLocale();
273  $submissionFile->setName($node->textContent, $locale);
274  $submissionFile->setSubmissionLocale($locale);
275  break;
276  case 'href':
277  $submissionFile->setFileType($node->getAttribute('mime_type'));
278  import('lib.pkp.classes.file.TemporaryFileManager');
279  $temporaryFileManager = new TemporaryFileManager();
280  $temporaryFilename = tempnam($temporaryFileManager->getBasePath(), 'src');
281  $filesrc = $node->getAttribute('src');
282  $errorFlag = false;
283  if (preg_match('|\w+://.+|', $filesrc)) {
284  // process as a URL
285  $client = Application::get()->getHttpClient();
286  $response = $client->request('GET', $filesrc);
287  file_put_contents($temporaryFilename, $response->getBody());
288  if (!filesize($temporaryFilename)) {
289  $errorFlag = true;
290  }
291  } elseif (substr($filesrc, 0, 1) === '/') {
292  // local file (absolute path)
293  if (!copy($filesrc, $temporaryFilename)) {
294  $errorFlag = true;
295  }
296  } elseif (is_readable($deployment->getImportPath() . '/' . $filesrc)) {
297  // local file (relative path)
298  $filesrc = $deployment->getImportPath() . '/' . $filesrc;
299  if(!copy($filesrc, $temporaryFilename)) {
300  $errorFlag = true;
301  }
302  } else {
303  // unhandled file path
304  $errorFlag = true;
305  }
306  if ($errorFlag) {
307  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.temporaryFileFailed', array('dest' => $temporaryFilename, 'source' => $filesrc)));
308  $fileManager = new FileManager();
309  $fileManager->deleteByPath($temporaryFilename);
310  $temporaryFilename = '';
311  }
312  return $temporaryFilename;
313  break;
314  case 'embed':
315  $submissionFile->setFileType($node->getAttribute('mime_type'));
316  import('lib.pkp.classes.file.TemporaryFileManager');
317  $temporaryFileManager = new TemporaryFileManager();
318  $temporaryFilename = tempnam($temporaryFileManager->getBasePath(), 'embed');
319  if (($e = $node->getAttribute('encoding')) != 'base64') {
320  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.unknownEncoding', array('param' => $e)));
321  } else {
322  $content = base64_decode($node->textContent, true);
323  $errorFlag = false;
324  if (!$content) {
325  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.encodingError', array('param' => $e)));
326  $errorFlag = true;
327  } elseif (!file_put_contents($temporaryFilename, $content)) {
328  $deployment->addError(ASSOC_TYPE_SUBMISSION, $submission->getId(), __('plugins.importexport.common.error.temporaryFileFailed', array('dest' => $temporaryFilename, 'source' => 'embed')));
329  $errorFlag = true;
330  }
331  if ($errorFlag) {
332  $fileManager = new FileManager();
333  $fileManager->deleteByPath($temporaryFilename);
334  $temporaryFilename = '';
335  }
336  }
337  return $temporaryFilename;
338  break;
339  }
340  }
341 
347  function parseIdentifier($element, $submissionFile) {
348  $deployment = $this->getDeployment();
349  $advice = $element->getAttribute('advice');
350  switch ($element->getAttribute('type')) {
351  case 'internal':
352  // "update" advice not supported yet.
353  assert(!$advice || $advice == 'ignore');
354  break;
355  case 'public':
356  if ($advice == 'update') {
357  $submissionFile->setStoredPubId('publisher-id', $element->textContent);
358  }
359  break;
360  default:
361  if ($advice == 'update') {
362  // Load pub id plugins
363  $pubIdPlugins = PluginRegistry::loadCategory('pubIds', true, $deployment->getContext()->getId());
364  $submissionFile->setStoredPubId($element->getAttribute('type'), $element->textContent);
365  }
366  }
367  }
368 
374  function instantiateSubmissionFile($tagName) {
375  assert(false); // Subclasses should override
376  }
377 }
378 
379 
NativeXmlSubmissionFileFilter\handleElement
handleElement($node)
Definition: NativeXmlSubmissionFileFilter.inc.php:63
NativeXmlSubmissionFileFilter
Base class that converts a Native XML document to a submission file.
Definition: NativeXmlSubmissionFileFilter.inc.php:18
NativeXmlSubmissionFileFilter\__construct
__construct($filterGroup)
Definition: NativeXmlSubmissionFileFilter.inc.php:23
TemporaryFileManager
Definition: TemporaryFileManager.inc.php:19
NativeXmlSubmissionFileFilter\handleRevisionElement
handleRevisionElement($node, $stageId, $fileId)
Definition: NativeXmlSubmissionFileFilter.inc.php:109
NativeXmlSubmissionFileFilter\parseIdentifier
parseIdentifier($element, $submissionFile)
Definition: NativeXmlSubmissionFileFilter.inc.php:347
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
NativeXmlSubmissionFileFilter\getSingularElementName
getSingularElementName()
Definition: NativeXmlSubmissionFileFilter.inc.php:43
NativeImportExportFilter\getDeployment
getDeployment()
Definition: NativeImportExportFilter.inc.php:49
NativeXmlSubmissionFileFilter\getClassName
getClassName()
Definition: NativeXmlSubmissionFileFilter.inc.php:53
NativeXmlSubmissionFileFilter\handleRevisionChildElement
handleRevisionChildElement($node, $submission, $submissionFile)
Definition: NativeXmlSubmissionFileFilter.inc.php:251
PluginRegistry\loadCategory
static loadCategory($category, $enabledOnly=false, $mainContextId=null)
Definition: PluginRegistry.inc.php:103
NativeImportFilter
Base class that converts a Native XML document to a DataObject.
Definition: NativeImportFilter.inc.php:18
NativeXmlSubmissionFileFilter\instantiateSubmissionFile
instantiateSubmissionFile($tagName)
Definition: NativeXmlSubmissionFileFilter.inc.php:374
Core\getCurrentDate
static getCurrentDate($ts=null)
Definition: Core.inc.php:63
NativeXmlSubmissionFileFilter\getPluralElementName
getPluralElementName()
Definition: NativeXmlSubmissionFileFilter.inc.php:35
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
FileManager
Class defining basic operations for file management.
Definition: FileManager.inc.php:35
Filter\setDisplayName
setDisplayName($displayName)
Definition: Filter.inc.php:140
NativeXmlSubmissionFileFilter\handleChildElement
handleChildElement($node, $stageId, $fileId, &$submissionFiles)
Definition: NativeXmlSubmissionFileFilter.inc.php:90