Open Monograph Press  3.3.0
SubmissionFileDAO.inc.php
1 <?php
2 
33 import('lib.pkp.classes.db.DAO');
34 import('lib.pkp.classes.submission.Genre'); // GENRE_CATEGORY_... constants
35 import('lib.pkp.classes.plugins.PKPPubIdPluginDAO');
36 import('lib.pkp.classes.submission.SubmissionFile');
37 
38 class SubmissionFileDAO extends DAO implements PKPPubIdPluginDAO {
43  var $_delegates = array();
44 
45 
46  //
47  // Public methods
48  //
58  function getRevision($fileId, $revision, $fileStage = null, $submissionId = null) {
59  if (!($fileId && $revision)) return null;
60  $revisions = $this->_getInternally($submissionId, $fileStage, $fileId, $revision, null, null, null, null, null, false, null);
61  return $this->_checkAndReturnRevision($revisions);
62  }
63 
72  function getFileIdsBySetting($settingName, $settingValue, $submissionId = null, $contextId = null) {
73  $params = array($settingName);
74 
75  $sql = 'SELECT DISTINCT f.file_id
76  FROM submission_files f
77  INNER JOIN submissions s ON s.submission_id = f.submission_id';
78  if (is_null($settingValue)) {
79  $sql .= ' LEFT JOIN submission_file_settings fs ON f.file_id = fs.file_id AND fs.setting_name = ?
80  WHERE (fs.setting_value IS NULL OR fs.setting_value = \'\')';
81  } else {
82  $params[] = (string) $settingValue;
83  $sql .= ' INNER JOIN submission_file_settings fs ON f.file_id = fs.file_id
84  WHERE fs.setting_name = ? AND fs.setting_value = ?';
85  }
86 
87  if ($submissionId) {
88  $params[] = (int) $submissionId;
89  $sql .= ' AND f.submission_id = ?';
90  }
91 
92  if ($contextId) {
93  $params[] = (int) $contextId;
94  $sql .= ' AND s.context_id = ?';
95  }
96 
97  $sql .= ' ORDER BY f.file_id';
98  $result = $this->retrieve($sql, $params);
99 
100  $fileIds = array();
101  while (!$result->EOF) {
102  $row = $result->getRowAssoc(false);
103  $fileIds[] = $row['file_id'];
104  $result->MoveNext();
105  }
106 
107  $result->Close();
108  return $fileIds;
109  }
110 
121  function getByPubId($pubIdType, $pubId, $submissionId = null, $contextId = null) {
122  $file = null;
123  if (!empty($pubId)) {
124  $fileIds = $this->getFileIdsBySetting('pub-id::'.$pubIdType, $pubId, $submissionId, $contextId);
125  if (!empty($fileIds)) {
126  assert(count($fileIds) == 1);
127  $fileId = $fileIds[0];
128  $file = $this->getLatestRevision($fileId, SUBMISSION_FILE_PROOF, $submissionId);
129  }
130  }
131  return $file;
132  }
133 
141  function getByBestId($fileId, $submissionId) {
142  $file = null;
143  if ($fileId != '') $file = $this->getByPubId('publisher-id', $fileId, $submissionId, null);
144  if (!isset($file)) {
145  list($fileId, $revision) = array_map(function($a) {
146  return (int) $a;
147  }, preg_split('/-/', $fileId));
148  $file = $this->getRevision($fileId, $revision, null, $submissionId);
149  }
150  if ($file && $file->getFileStage() == SUBMISSION_FILE_PROOF) return $file;
151  if ($file && $file->getFileStage() == SUBMISSION_FILE_DEPENDENT) return $file;
152  return null;
153  }
154 
163  function getLatestRevision($fileId, $fileStage = null, $submissionId = null) {
164  if (!$fileId) return null;
165 
166  $revisions = $this->_getInternally($submissionId, $fileStage, $fileId, null, null, null, null, null, null, true, null, null);
167  return $this->_checkAndReturnRevision($revisions);
168  }
169 
178  function getLatestRevisions($submissionId, $fileStage = null, $rangeInfo = null) {
179  if (!$submissionId) return null;
180  return $this->_getInternally($submissionId, $fileStage, null, null, null, null, null, null, null, true, $rangeInfo);
181  }
182 
193  function getAllRevisions($fileId, $fileStage = null, $submissionId = null, $rangeInfo = null) {
194  if (!$fileId) return null;
195  return $this->_getInternally($submissionId, $fileStage, $fileId, null, null, null, null, null, null, false, $rangeInfo);
196  }
197 
204  function getBySubmissionId($submissionId, $rangeInfo = null) {
205  if (!$submissionId) return null;
206  return $this->_getInternally($submissionId, null, null, null, null, null, null, null, null, false, $rangeInfo);
207  }
208 
219  function getLatestRevisionsByAssocId($assocType, $assocId, $submissionId = null, $fileStage = null, $rangeInfo = null) {
220  if (!($assocType && $assocId)) return null;
221  return $this->_getInternally($submissionId, $fileStage, null, null, $assocType, $assocId, null, null, null, true, $rangeInfo);
222  }
223 
233  function getAllRevisionsByAssocId($assocType, $assocId, $fileStage = null, $rangeInfo = null) {
234  if (!($assocType && $assocId)) return null;
235  return $this->_getInternally(null, $fileStage, null, null, $assocType, $assocId, null, null, null, false, $rangeInfo);
236  }
237 
245  function getRevisionsByReviewRound($reviewRound, $fileStage = null,
246  $uploaderUserId = null) {
247  if (!is_a($reviewRound, 'ReviewRound')) return null;
248  return $this->_getInternally($reviewRound->getSubmissionId(),
249  $fileStage, null, null, null, null, null,
250  $uploaderUserId, $reviewRound->getId()
251  );
252  }
253 
261  function getLatestRevisionsByReviewRound($reviewRound, $fileStage = null) {
262  if (!$reviewRound) return array();
263  return $this->_getInternally($reviewRound->getSubmissionId(),
264  $fileStage, null, null, null, null, $reviewRound->getStageId(),
265  null, $reviewRound->getId(), true
266  );
267  }
268 
274  function getLatestRevisionNumber($fileId) {
275  assert(!is_null($fileId));
276 
277  // Retrieve the latest revision from the database.
278  $result = $this->retrieve(
279  'SELECT MAX(revision) AS max_revision FROM submission_files WHERE file_id = ?',
280  (int) $fileId
281  );
282  if($result->RecordCount() != 1) return null;
283 
284  $row = $result->FetchRow();
285  $result->Close();
286 
287  $latestRevision = (int)$row['max_revision'];
288  assert($latestRevision > 0);
289  return $latestRevision;
290  }
291 
302  function insertObject($submissionFile, $sourceFile, $isUpload = false) {
303  // Make sure that the implementation of the updated file
304  // is compatible with its genre (upcast but no downcast).
305  $submissionFile = $this->_castToGenre($submissionFile);
306 
307  // Find the required target implementation and delegate.
308  $targetImplementation = strtolower_codesafe(
309  $this->_getFileImplementationForGenreId(
310  $submissionFile->getGenreId())
311  );
312  $targetDaoDelegate = $this->_getDaoDelegate($targetImplementation);
313  $insertedFile = $targetDaoDelegate->insertObject($submissionFile, $sourceFile, $isUpload);
314 
315  // If the updated file does not have the correct target type then we'll have
316  // to retrieve it again from the database to cast it to the right type (downcast).
317  if ($insertedFile && strtolower_codesafe(get_class($insertedFile)) != $targetImplementation) {
318  $insertedFile = $this->_castToDatabase($insertedFile);
319  }
320  return $insertedFile;
321  }
322 
341  function updateObject($updatedFile, $previousFileId = null, $previousRevision = null) {
342  // Make sure that the implementation of the updated file
343  // is compatible with its genre.
344  $updatedFile = $this->_castToGenre($updatedFile);
345 
346  // Complete the identifying data of the previous file if not given.
347  $previousFileId = (int)($previousFileId ? $previousFileId : $updatedFile->getFileId());
348  $previousRevision = (int)($previousRevision ? $previousRevision : $updatedFile->getRevision());
349 
350  // Retrieve the previous file.
351  $previousFile = $this->getRevision($previousFileId, $previousRevision);
352  assert(is_a($previousFile, 'SubmissionFile'));
353 
354  // Canonicalized the implementation of the previous file.
355  $previousImplementation = strtolower_codesafe(get_class($previousFile));
356 
357  // Find the required target implementation and delegate.
358  $targetImplementation = strtolower_codesafe(
359  $this->_getFileImplementationForGenreId(
360  $updatedFile->getGenreId())
361  );
362  $targetDaoDelegate = $this->_getDaoDelegate($targetImplementation);
363 
364  // If the implementation in the database differs from the target
365  // implementation then we'll have to delete + insert the object
366  // to make sure that the database contains consistent data.
367  if ($previousImplementation != $targetImplementation) {
368  // We'll have to copy the previous file to its target
369  // destination so that it is not lost when we delete the
370  // previous file.
371  // When the implementation (i.e. genre) changes then the
372  // file locations will also change so we should not get
373  // a file name clash.
374  $previousFilePath = $previousFile->getFilePath();
375  $targetFilePath = $updatedFile->getFilePath();
376 
377  assert($previousFilePath != $targetFilePath && !file_exists($targetFilePath));
378  import('lib.pkp.classes.file.FileManager');
379  $fileManager = new FileManager();
380  $fileManager->copyFile($previousFilePath, $targetFilePath);
381 
382  // We use the delegates directly to make sure
383  // that we address the right implementation in the database
384  // on delete and insert.
385  $sourceDaoDelegate = $this->_getDaoDelegate($previousImplementation);
386  $sourceDaoDelegate->deleteObject($previousFile);
387  $targetDaoDelegate->insertObject($updatedFile, $targetFilePath);
388  } else {
389  // If the implementation in the database does not change then we
390  // can do an efficient update.
391  if (!$targetDaoDelegate->updateObject($updatedFile, $previousFile)) {
392  return null;
393  }
394  }
395 
396  // If the updated file does not have the correct target type then we'll have
397  // to retrieve it again from the database to cast it to the right type.
398  if (strtolower_codesafe(get_class($updatedFile)) != $targetImplementation) {
399  $updatedFile = $this->_castToDatabase($updatedFile);
400  }
401 
402  return $updatedFile;
403  }
404 
417  function setAsLatestRevision($revisedFileId, $newFileId, $submissionId, $fileStage) {
418  $revisedFileId = (int)$revisedFileId;
419  $newFileId = (int)$newFileId;
420  $submissionId = (int)$submissionId;
421  $fileStage = (int)$fileStage;
422 
423  // Check whether the two files are already revisions of each other.
424  if ($revisedFileId == $newFileId) return null;
425 
426  // Retrieve the latest revisions of the two submission files.
427  $revisedFile = $this->getLatestRevision($revisedFileId, $fileStage, $submissionId);
428  $newFile = $this->getLatestRevision($newFileId, $fileStage, $submissionId);
429  if (!($revisedFile && $newFile)) return null;
430 
431  // Save identifying data of the changed file required for update.
432  $previousFileId = $newFile->getFileId();
433  $previousRevision = $newFile->getRevision();
434 
435  // Copy data over from the revised file to the new file.
436  $newFile->setFileId($revisedFileId);
437  $newFile->setRevision($revisedFile->getRevision()+1);
438  $newFile->setGenreId($revisedFile->getGenreId());
439  $newFile->setAssocType($revisedFile->getAssocType());
440  $newFile->setAssocId($revisedFile->getAssocId());
441 
442  // Update the file in the database.
443  return $this->updateObject($newFile, $previousFileId, $previousRevision);
444  }
445 
452  function assignRevisionToReviewRound($fileId, $revision, $reviewRound) {
453  if (!is_numeric($fileId) || !is_numeric($revision)) fatalError('Invalid file!');
454 
455  // Avoid duplication errors -- clear out any existing entries
456  $this->deleteReviewRoundAssignment($reviewRound->getSubmissionId(), $reviewRound->getStageId(), $fileId, $revision);
457 
458  return $this->update(
459  'INSERT INTO review_round_files
460  (submission_id, review_round_id, stage_id, file_id, revision)
461  VALUES (?, ?, ?, ?, ?)',
462  array(
463  (int)$reviewRound->getSubmissionId(),
464  (int)$reviewRound->getId(),
465  (int)$reviewRound->getStageId(),
466  (int)$fileId,
467  (int)$revision
468  )
469  );
470  }
471 
477  function deleteRevision($submissionFile) {
478  return $this->deleteRevisionById($submissionFile->getFileId(), $submissionFile->getRevision(), $submissionFile->getFileStage(), $submissionFile->getSubmissionId());
479  }
480 
491  function deleteRevisionById($fileId, $revision, $fileStage = null, $submissionId = null) {
492  return $this->_deleteInternally($submissionId, $fileStage, $fileId, $revision);
493  }
494 
504  function deleteLatestRevisionById($fileId, $fileStage= null, $submissionId = null) {
505  return $this->_deleteInternally($submissionId, $fileStage, $fileId, null, null, null, null, null, true);
506  }
507 
518  function deleteAllRevisionsById($fileId, $fileStage = null, $submissionId = null) {
519  return $this->_deleteInternally($submissionId, $fileStage, $fileId);
520  }
521 
530  function deleteAllRevisionsBySubmissionId($submissionId, $fileStage = null) {
531  return $this->_deleteInternally($submissionId, $fileStage);
532  }
533 
542  function deleteAllRevisionsByAssocId($assocType, $assocId, $fileStage = null) {
543  return $this->_deleteInternally(null, $fileStage, null, null, $assocType, $assocId);
544  }
545 
550  function deleteAllRevisionsByReviewRound($reviewRoundId) {
551  // Remove currently assigned review files.
552  return $this->update('DELETE FROM review_round_files WHERE review_round_id = ?', (int)$reviewRoundId);
553  }
554 
562  function deleteReviewRoundAssignment($submissionId, $stageId, $fileId, $revision) {
563  // Remove currently assigned review files.
564  $this->update(
565  'DELETE FROM review_round_files
566  WHERE submission_id = ? AND stage_id = ? AND file_id = ? AND revision = ?',
567  array(
568  (int) $submissionId,
569  (int) $stageId,
570  (int) $fileId,
571  (int) $revision
572  )
573  );
574  }
575 
581  function transferOwnership($oldUserId, $newUserId) {
582  $submissionFiles = $this->_getInternally(null, null, null, null, null, null, null, $oldUserId);
583  foreach ($submissionFiles as $file) {
584  $daoDelegate = $this->_getDaoDelegateForObject($file);
585  $file->setUploaderUserId($newUserId);
586  $daoDelegate->updateObject($file, $file); // nothing else changes
587  }
588  }
589 
596  function newDataObjectByGenreId($genreId) {
597  // Identify the delegate.
598  $daoDelegate = $this->_getDaoDelegateForGenreId($genreId);
599 
600  // Instantiate and return the object.
601  return $daoDelegate->newDataObject();
602  }
603 
604 
605  //
606  // Abstract template methods to be implemented by subclasses.
607  //
619  function getDelegateClassNames() {
620  return array(
621  'submissionfile' => 'lib.pkp.classes.submission.SubmissionFileDAODelegate',
622  'submissionartworkfile' => 'lib.pkp.classes.submission.SubmissionArtworkFileDAODelegate',
623  'supplementaryfile' => 'lib.pkp.classes.submission.SupplementaryFileDAODelegate',
624  );
625  }
626 
633  function getGenreCategoryMapping() {
634  return array(
635  GENRE_CATEGORY_DOCUMENT => 'submissionfile',
636  GENRE_CATEGORY_ARTWORK => 'submissionartworkfile',
637  GENRE_CATEGORY_SUPPLEMENTARY => 'supplementaryfile',
638  );
639  }
640 
645  function baseQueryForFileSelection() {
646  // Build the basic query that joins the class tables.
647  // The DISTINCT is required to de-dupe the review_round_files join in
648  // SubmissionFileDAO.
649  return 'SELECT DISTINCT
650  sf.file_id AS submission_file_id, sf.revision AS submission_revision,
651  af.file_id AS artwork_file_id, af.revision AS artwork_revision,
652  suf.file_id AS supplementary_file_id, suf.revision AS supplementary_revision,
653  p.locale AS submission_locale,
654  sf.*, af.*, suf.*
655  FROM submission_files sf
656  LEFT JOIN submission_artwork_files af ON sf.file_id = af.file_id AND sf.revision = af.revision
657  LEFT JOIN submission_supplementary_files suf ON sf.file_id = suf.file_id AND sf.revision = suf.revision
658  LEFT JOIN submissions as s ON s.submission_id = sf.submission_id
659  LEFT JOIN publications p ON s.current_publication_id = p.publication_id ';
660  }
661 
662 
663  //
664  // Protected helper methods
665  //
672  function fromRow($row, $fileImplementation = null) {
673  switch(true) {
674  case isset($row['artwork_file_id']) && is_numeric($row['artwork_file_id']):
675  $daoDelegate = $this->_getDaoDelegate('SubmissionArtworkFile');
676  break;
677  case isset($row['supplementary_file_id']) && is_numeric($row['supplementary_file_id']):
678  $daoDelegate = $this->_getDaoDelegate('SupplementaryFile');
679  break;
680  default:
681  $daoDelegate = $this->_getDaoDelegate('SubmissionFile');
682  }
683 
684  // Let the DAO delegate instantiate the file implementation.
685  return $daoDelegate->fromRow($row);
686  }
687 
688 
693  function getAllFileStages() {
694  // Bring in the file stages definition.
695  import('lib.pkp.classes.submission.SubmissionFile');
696  return array(
697  SUBMISSION_FILE_SUBMISSION,
698  SUBMISSION_FILE_NOTE,
699  SUBMISSION_FILE_REVIEW_FILE,
700  SUBMISSION_FILE_REVIEW_ATTACHMENT,
701  SUBMISSION_FILE_FINAL,
702  SUBMISSION_FILE_FAIR_COPY,
703  SUBMISSION_FILE_EDITOR,
704  SUBMISSION_FILE_COPYEDIT,
705  SUBMISSION_FILE_PROOF,
706  SUBMISSION_FILE_PRODUCTION_READY,
707  SUBMISSION_FILE_ATTACHMENT,
708  SUBMISSION_FILE_REVIEW_REVISION,
709  SUBMISSION_FILE_DEPENDENT,
710  SUBMISSION_FILE_QUERY,
711  );
712  }
713 
717  function pubIdExists($pubIdType, $pubId, $excludePubObjectId, $contextId) {
718  $submissionFileDAODelegate = $this->_getDaoDelegate('submissionfile');
719  return $submissionFileDAODelegate->pubIdExists($pubIdType, $pubId, $excludePubObjectId, $contextId);
720  }
721 
725  function changePubId($pubObjectId, $pubIdType, $pubId) {
726  $submissionFileDAODelegate = $this->_getDaoDelegate('submissionfile');
727  $submissionFileDAODelegate->changePubId($pubObjectId, $pubIdType, $pubId);
728  }
729 
733  function deletePubId($pubObjectId, $pubIdType) {
734  $submissionFileDAODelegate = $this->_getDaoDelegate('submissionfile');
735  $submissionFileDAODelegate->deletePubId($pubObjectId, $pubIdType);
736  }
737 
741  function deleteAllPubIds($contextId, $pubIdType) {
742  $submissionFileDAODelegate = $this->_getDaoDelegate('submissionfile');
743  $submissionFileDAODelegate->deleteAllPubIds($contextId, $pubIdType);
744  }
745 
756  public function getWorkflowStageId($submissionFile) {
757  switch ($submissionFile->getFileStage()) {
758  case SUBMISSION_FILE_SUBMISSION:
759  return WORKFLOW_STAGE_ID_SUBMISSION;
760  case SUBMISSION_FILE_REVIEW_FILE:
761  case SUBMISSION_FILE_REVIEW_ATTACHMENT:
762  case SUBMISSION_FILE_REVIEW_REVISION:
763  $reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /* @var $reviewRoundDao ReviewRoundDAO */
764  $reviewRound = $reviewRoundDao->getBySubmissionFileId($submissionFile->getFileId());
765  return $reviewRound->getStageId();
766  case SUBMISSION_FILE_FINAL:
767  case SUBMISSION_FILE_COPYEDIT:
768  return WORKFLOW_STAGE_ID_EDITING;
769  case SUBMISSION_FILE_PROOF:
770  case SUBMISSION_FILE_PRODUCTION_READY:
771  case SUBMISSION_FILE_DEPENDENT:
772  return WORKFLOW_STAGE_ID_PRODUCTION;
773  case SUBMISSION_FILE_QUERY:
774  $noteDao = DAORegistry::getDAO('NoteDAO'); /* @var $noteDao NoteDAO */
775  $note = $noteDao->getById($submissionFile->getAssocId());
776  $queryDao = DAORegistry::getDAO('QueryDAO'); /* @var $queryDao QueryDAO */
777  $query = $queryDao->getById($note->getAssocId());
778  return $query?$query->getStageId():null;
779  }
780  }
781 
782  //
783  // Private helper methods
784  //
790  private function _getFileImplementationForGenreId($genreId) {
791  static $genreCache = array();
792 
793  if (!isset($genreCache[$genreId])) {
794  if (is_null($genreId)) {
795  // If no genreId is given fall back to the document category
796  $genreCategory = GENRE_CATEGORY_DOCUMENT;
797 
798  } else {
799  // We have to instantiate the genre to find out about
800  // its category.
801  $genreDao = DAORegistry::getDAO('GenreDAO'); /* @var $genreDao GenreDAO */
802  $genre = $genreDao->getById($genreId);
803  $genreCategory = $genre->getCategory();
804  }
805 
806  // Identify the file implementation.
807  $genreMapping = $this->getGenreCategoryMapping();
808  assert(isset($genreMapping[$genreCategory]));
809  $genreCache[$genreId] = $genreMapping[$genreCategory];
810  }
811 
812  return $genreCache[$genreId];
813  }
814 
821  private function _getDaoDelegateForGenreId($genreId) {
822  // Find the required file implementation.
823  $fileImplementation = $this->_getFileImplementationForGenreId($genreId);
824 
825  // Return the DAO delegate.
826  return $this->_getDaoDelegate($fileImplementation);
827  }
828 
835  private function _getDaoDelegateForObject($object) {
836  return $this->_getDaoDelegate(get_class($object));
837  }
838 
846  private function _getDaoDelegate($fileImplementation) {
847  // Normalize the file implementation name.
848  $fileImplementation = strtolower_codesafe($fileImplementation);
849 
850  // Did we already instantiate the requested delegate?
851  if (!isset($this->_delegates[$fileImplementation])) {
852  // Instantiate the requested delegate.
853  $delegateClasses = $this->getDelegateClassNames();
854  assert(isset($delegateClasses[$fileImplementation]));
855  $delegateClass = $delegateClasses[$fileImplementation];
856  $this->_delegates[$fileImplementation] = instantiate($delegateClass, 'SubmissionFileDAODelegate');
857  }
858 
859  // Return the delegate.
860  return $this->_delegates[$fileImplementation];
861  }
862 
879  private function _getInternally($submissionId = null, $fileStage = null, $fileId = null, $revision = null,
880  $assocType = null, $assocId = null, $stageId = null, $uploaderUserId = null,
881  $reviewRoundId = null, $latestOnly = false, $rangeInfo = null) {
882  // Retrieve the base query.
883  $sql = $this->baseQueryForFileSelection();
884 
885  // Add the revision round file join if a revision round
886  // filter was requested.
887  if ($reviewRoundId) {
888  $sql .= 'INNER JOIN review_round_files rrf
889  ON sf.submission_id = rrf.submission_id
890  AND sf.file_id = rrf.file_id
891  AND sf.revision '.($latestOnly ? '>=' : '=').' rrf.revision ';
892  }
893 
894  // Filter the query.
895  list($filterClause, $params) = $this->_buildFileSelectionFilter(
896  $submissionId, $fileStage, $fileId, $revision,
897  $assocType, $assocId, $stageId, $uploaderUserId, $reviewRoundId);
898 
899  // Did the user request all or only the latest revision?
900  if ($latestOnly) {
901  // Filter the latest revision of each file.
902  // NB: We have to do this in the SQL for paging to work
903  // correctly. We use a partial cartesian join here to
904  // maintain MySQL 3.23 backwards compatibility. This
905  // should be ok as we usually only have few revisions per
906  // file.
907  $sql .= 'LEFT JOIN submission_files sf2 ON sf.file_id = sf2.file_id AND sf.revision < sf2.revision
908  WHERE sf2.revision IS NULL AND '.$filterClause;
909  } else {
910  $sql .= 'WHERE '.$filterClause;
911  }
912 
913  // Order the query.
914  $sql .= ' ORDER BY sf.submission_id ASC, sf.file_stage ASC, sf.file_id ASC, sf.revision DESC';
915 
916  // Execute the query.
917  if ($rangeInfo) {
918  $result = $this->retrieveRange($sql, $params, $rangeInfo);
919  } else {
920  $result = $this->retrieve($sql, $params);
921  }
922 
923  // Build the result array.
924  $submissionFiles = array();
925  while (!$result->EOF) {
926  // Retrieve the next result row.
927  $row = $result->GetRowAssoc(false);
928 
929  // Construct a combined id from file id and revision
930  // that uniquely identifies the file.
931  $idAndRevision = $row['submission_file_id'].'-'.$row['submission_revision'];
932 
933  // Check for duplicates.
934  assert(!isset($submissionFiles[$idAndRevision]));
935 
936  // Instantiate the file and add it to the
937  // result array with a unique key.
938  // N.B. The subclass implementation of fromRow receives just the $row
939  // but calls SubmissionFileDAO::fromRow($row, $fileImplementation) as defined here.
940  $submissionFiles[$idAndRevision] = $this->fromRow($row);
941 
942  // Move the query cursor to the next record.
943  $result->MoveNext();
944  }
945  $result->Close();
946 
947  return $submissionFiles;
948  }
949 
965  private function _deleteInternally($submissionId = null, $fileStage = null, $fileId = null, $revision = null,
966  $assocType = null, $assocId = null, $stageId = null, $uploaderUserId = null,
967  $latestOnly = false) {
968 
969  // Identify all matched files.
970  $deletedFiles = $this->_getInternally($submissionId, $fileStage, $fileId, $revision,
971  $assocType, $assocId, $stageId, $uploaderUserId, null, $latestOnly, null);
972  if (empty($deletedFiles)) return 0;
973 
974  foreach($deletedFiles as $deletedFile) { /* @var $deletedFile SubmissionFile */
975  // Delete file in the database.
976  // NB: We cannot safely bulk-delete because MySQL 3.23
977  // does not support multi-column IN-clauses. Same is true
978  // for multi-table access or subselects in the DELETE
979  // statement. And having a long (... AND ...) OR (...)
980  // clause could hit length limitations.
981  $daoDelegate = $this->_getDaoDelegateForObject($deletedFile);
982  if (!$daoDelegate->deleteObject($deletedFile)) return false;
983  }
984 
985  // Return the number of deleted files.
986  return count($deletedFiles);
987  }
988 
1004  private function _buildFileSelectionFilter($submissionId, $fileStage,
1005  $fileId, $revision, $assocType, $assocId, $stageId, $uploaderUserId, $reviewRoundId) {
1006 
1007  // Make sure that at least one entity filter has been set.
1008  assert($submissionId>0 || (int)$uploaderUserId || (int)$fileId || (int)$assocId);
1009 
1010  // Both, assoc type and id, must be set (or unset) together.
1011  assert(((int)$assocType && (int)$assocId) || !((int)$assocType || (int)$assocId));
1012 
1013  // Collect the filtered columns and ids in
1014  // an array for consistent handling.
1015  $filters = array(
1016  'sf.submission_id' => $submissionId,
1017  'sf.file_stage' => $fileStage,
1018  'sf.file_id' => $fileId,
1019  'sf.revision' => $revision,
1020  'sf.assoc_type' => $assocType,
1021  'sf.assoc_id' => $assocId,
1022  'sf.uploader_user_id' => $uploaderUserId,
1023  'rrf.stage_id' => $stageId,
1024  'rrf.review_round_id' => $reviewRoundId,
1025  );
1026 
1027  // Build and return a SQL where clause and a parameter
1028  // array.
1029  $filterClause = '';
1030  $params = array();
1031  $conjunction = '';
1032  foreach($filters as $filteredColumn => $filteredId) {
1033  if ($filteredId) {
1034  $filterClause .= $conjunction.' '.$filteredColumn.' = ?';
1035  $conjunction = ' AND';
1036  $params[] = (int)$filteredId;
1037  }
1038  }
1039  return array($filterClause, $params);
1040  }
1041 
1054  private function _castToGenre($submissionFile) {
1055  // Find the required target implementation.
1056  $targetImplementation = strtolower_codesafe(
1057  $this->_getFileImplementationForGenreId(
1058  $submissionFile->getGenreId())
1059  );
1060 
1061  // If the current implementation of the updated object
1062  // is the same as the target implementation, skip cast.
1063  if (is_a($submissionFile, $targetImplementation)) return $submissionFile;
1064 
1065  // The updated file has to be upcast by manually
1066  // instantiating the target object and copying data
1067  // to the target.
1068  $targetDaoDelegate = $this->_getDaoDelegate($targetImplementation);
1069  $targetFile = $targetDaoDelegate->newDataObject();
1070  $targetFile = $submissionFile->upcastTo($targetFile);
1071  return $targetFile;
1072  }
1073 
1080  private function _castToDatabase($submissionFile) {
1081  return $this->getRevision(
1082  $submissionFile->getFileId(),
1083  $submissionFile->getRevision()
1084  );
1085  }
1086 
1093  private function _checkAndReturnRevision($revisions) {
1094  assert(count($revisions) <= 1);
1095  if (empty($revisions)) return null;
1096 
1097  $revision = array_pop($revisions);
1098  assert(is_a($revision, 'SubmissionFile'));
1099  return $revision;
1100  }
1101 
1109  function copyFile($context, $submissionFile, $fileStage){
1110  import('lib.pkp.classes.file.SubmissionFileManager');
1111  $submissionFileManager = new SubmissionFileManager($context->getId(), $submissionFile->getSubmissionId());
1112  $fileId = $submissionFile->getFileId();
1113  $revision = $submissionFile->getRevision();
1114  list($newFileId, $newRevision) = $submissionFileManager->copyFileToFileStage($fileId, $revision, $fileStage, null, $submissionFile->getViewable());
1115  return $newFileId;
1116  }
1117 }
1118 
1119 
SubmissionFileDAO\updateObject
updateObject($updatedFile, $previousFileId=null, $previousRevision=null)
Definition: SubmissionFileDAO.inc.php:344
SubmissionFileDAO\getAllRevisions
getAllRevisions($fileId, $fileStage=null, $submissionId=null, $rangeInfo=null)
Definition: SubmissionFileDAO.inc.php:196
SubmissionFileDAO\getLatestRevisionNumber
getLatestRevisionNumber($fileId)
Definition: SubmissionFileDAO.inc.php:277
PKPPubIdPluginDAO
Interface that DAOs would need to implement in order for pub ID support to be added.
Definition: PKPPubIdPluginDAO.inc.php:16
SubmissionFileManager
Helper class for database-backed submission file management tasks.
Definition: SubmissionFileManager.inc.php:30
SubmissionFileDAO\baseQueryForFileSelection
baseQueryForFileSelection()
Definition: SubmissionFileDAO.inc.php:648
instantiate
& instantiate($fullyQualifiedClassName, $expectedTypes=null, $expectedPackages=null, $expectedMethods=null, $constructorArg=null)
Definition: functions.inc.php:165
SubmissionFileDAO\deleteLatestRevisionById
deleteLatestRevisionById($fileId, $fileStage=null, $submissionId=null)
Definition: SubmissionFileDAO.inc.php:507
SubmissionFileDAO\getRevision
getRevision($fileId, $revision, $fileStage=null, $submissionId=null)
Definition: SubmissionFileDAO.inc.php:61
SubmissionFileDAO\getFileIdsBySetting
getFileIdsBySetting($settingName, $settingValue, $submissionId=null, $contextId=null)
Definition: SubmissionFileDAO.inc.php:75
SubmissionFileDAO\deleteAllRevisionsByReviewRound
deleteAllRevisionsByReviewRound($reviewRoundId)
Definition: SubmissionFileDAO.inc.php:553
DAO\retrieveRange
& retrieveRange($sql, $params=false, $dbResultRange=null, $callHooks=true)
Definition: DAO.inc.php:176
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
SubmissionFileDAO\transferOwnership
transferOwnership($oldUserId, $newUserId)
Definition: SubmissionFileDAO.inc.php:584
SubmissionFileDAO\getByBestId
getByBestId($fileId, $submissionId)
Definition: SubmissionFileDAO.inc.php:144
DAO\retrieve
& retrieve($sql, $params=false, $callHooks=true)
Definition: DAO.inc.php:85
SubmissionFileDAO\deleteAllRevisionsByAssocId
deleteAllRevisionsByAssocId($assocType, $assocId, $fileStage=null)
Definition: SubmissionFileDAO.inc.php:545
SubmissionFileDAO\fromRow
fromRow($row, $fileImplementation=null)
Definition: SubmissionFileDAO.inc.php:675
SubmissionFileDAO\getByPubId
getByPubId($pubIdType, $pubId, $submissionId=null, $contextId=null)
Definition: SubmissionFileDAO.inc.php:124
SubmissionFileDAO\changePubId
changePubId($pubObjectId, $pubIdType, $pubId)
Definition: SubmissionFileDAO.inc.php:728
SubmissionFileDAO\deleteReviewRoundAssignment
deleteReviewRoundAssignment($submissionId, $stageId, $fileId, $revision)
Definition: SubmissionFileDAO.inc.php:565
SubmissionFileDAO\copyFile
copyFile($context, $submissionFile, $fileStage)
Definition: SubmissionFileDAO.inc.php:1112
SubmissionFileDAO\insertObject
insertObject($submissionFile, $sourceFile, $isUpload=false)
Definition: SubmissionFileDAO.inc.php:305
SubmissionFileDAO\$_delegates
$_delegates
Definition: SubmissionFileDAO.inc.php:46
SubmissionFileDAO\getLatestRevisionsByReviewRound
getLatestRevisionsByReviewRound($reviewRound, $fileStage=null)
Definition: SubmissionFileDAO.inc.php:264
DAO\update
update($sql, $params=false, $callHooks=true, $dieOnError=true)
Definition: DAO.inc.php:214
SubmissionFileDAO\getWorkflowStageId
getWorkflowStageId($submissionFile)
Definition: SubmissionFileDAO.inc.php:759
SubmissionFileDAO\deleteAllRevisionsById
deleteAllRevisionsById($fileId, $fileStage=null, $submissionId=null)
Definition: SubmissionFileDAO.inc.php:521
SubmissionFileDAO\getGenreCategoryMapping
getGenreCategoryMapping()
Definition: SubmissionFileDAO.inc.php:636
SubmissionFileDAO\newDataObjectByGenreId
newDataObjectByGenreId($genreId)
Definition: SubmissionFileDAO.inc.php:599
SubmissionFileDAO\getAllRevisionsByAssocId
getAllRevisionsByAssocId($assocType, $assocId, $fileStage=null, $rangeInfo=null)
Definition: SubmissionFileDAO.inc.php:236
SubmissionFileDAO\assignRevisionToReviewRound
assignRevisionToReviewRound($fileId, $revision, $reviewRound)
Definition: SubmissionFileDAO.inc.php:455
SubmissionFileDAO\deleteAllPubIds
deleteAllPubIds($contextId, $pubIdType)
Definition: SubmissionFileDAO.inc.php:744
strtolower_codesafe
strtolower_codesafe($str)
Definition: functions.inc.php:280
SubmissionFileDAO\pubIdExists
pubIdExists($pubIdType, $pubId, $excludePubObjectId, $contextId)
Definition: SubmissionFileDAO.inc.php:720
SubmissionFileDAO\deleteAllRevisionsBySubmissionId
deleteAllRevisionsBySubmissionId($submissionId, $fileStage=null)
Definition: SubmissionFileDAO.inc.php:533
SubmissionFileDAO\getAllFileStages
getAllFileStages()
Definition: SubmissionFileDAO.inc.php:696
SubmissionFileDAO\getLatestRevisions
getLatestRevisions($submissionId, $fileStage=null, $rangeInfo=null)
Definition: SubmissionFileDAO.inc.php:181
SubmissionFileDAO\getDelegateClassNames
getDelegateClassNames()
Definition: SubmissionFileDAO.inc.php:622
SubmissionFileDAO\getLatestRevision
getLatestRevision($fileId, $fileStage=null, $submissionId=null)
Definition: SubmissionFileDAO.inc.php:166
fatalError
if(!function_exists('import')) fatalError($reason)
Definition: functions.inc.php:32
FileManager
Class defining basic operations for file management.
Definition: FileManager.inc.php:35
SubmissionFileDAO\deleteRevision
deleteRevision($submissionFile)
Definition: SubmissionFileDAO.inc.php:480
SubmissionFileDAO\getBySubmissionId
getBySubmissionId($submissionId, $rangeInfo=null)
Definition: SubmissionFileDAO.inc.php:207
SubmissionFileDAO
Abstract base class for retrieving and modifying SubmissionFile objects and their decendents (e....
Definition: SubmissionFileDAO.inc.php:38
SubmissionFileDAO\getRevisionsByReviewRound
getRevisionsByReviewRound($reviewRound, $fileStage=null, $uploaderUserId=null)
Definition: SubmissionFileDAO.inc.php:248
SubmissionFileDAO\deletePubId
deletePubId($pubObjectId, $pubIdType)
Definition: SubmissionFileDAO.inc.php:736
DAO
Operations for retrieving and modifying objects from a database.
Definition: DAO.inc.php:31
SubmissionFileDAO\getLatestRevisionsByAssocId
getLatestRevisionsByAssocId($assocType, $assocId, $submissionId=null, $fileStage=null, $rangeInfo=null)
Definition: SubmissionFileDAO.inc.php:222
SubmissionFileDAO\setAsLatestRevision
setAsLatestRevision($revisedFileId, $newFileId, $submissionId, $fileStage)
Definition: SubmissionFileDAO.inc.php:420
SubmissionFileDAO\deleteRevisionById
deleteRevisionById($fileId, $revision, $fileStage=null, $submissionId=null)
Definition: SubmissionFileDAO.inc.php:494