/**
  * Regression Test for OPUSVIER-3051
  */
 public function testDocumentServerDateModifiedNotUpdatedWhenCollectionSortOrderChanged()
 {
     // check for expected test data
     $collectionRole1 = new Opus_CollectionRole(1);
     $this->assertEquals(1, $collectionRole1->getPosition(), 'Test setup changed');
     $collectionRole2 = new Opus_CollectionRole(2);
     $this->assertEquals(2, $collectionRole2->getPosition(), 'Test setup changed');
     $docfinder = new Opus_DocumentFinder();
     $docfinder->setCollectionRoleId(2);
     $collectionRoleDocs = $docfinder->ids();
     $this->assertTrue(in_array(146, $collectionRoleDocs), 'Test setup changed');
     // test if server_date_modified is altered
     $docBefore = new Opus_Document(146);
     $this->dispatch('/admin/collectionroles/move/roleid/1/pos/2');
     $docAfter = new Opus_Document(146);
     // revert change in test data
     $this->resetRequest();
     $this->resetResponse();
     $this->dispatch('/admin/collectionroles/move/roleid/1/pos/1');
     $this->assertEquals((string) $docBefore->getServerDateModified(), (string) $docAfter->getServerDateModified());
 }
 /**
  * Im Rahmen der Zuweisung von Dokumenten, die Collections der Collection Role
  * series zugeordnet sind, müssen verschiedene Konflikte behandelt werden.
  *
  * Im Folgenden werden nur Dokumente betrachtet, die mindestens einer Collection
  * der Collection Role series (kurz: series-Collection) zugeordnet sind.
  *
  * Fall 1 (Dokumente ohne IdentifierSerial):
  * Da die Bandnummer einer Schriftenreihe Opus_Series obligatorisch ist, können
  * Dokumente ohne IdentifierSerial nicht migriert werden. Sie verbleiben
  * unangetastet. Die Zuweisung(en) zu series-Collection(s) wird (werden) nicht
  * verändert.
  *
  * Fall 2 (Dokumente mit mehr als einem IdentifierSerial):
  * Da ein Dokument pro Schriftenreihe nur eine Bandnummer besitzen kann, können
  * Dokumente mit mehr als einem Wert für das Feld IdentifierSerial nicht
  * migriert werden. Sie verbleiben unangetastet. Die Zuweisung(en) zu
  * series-Collection(s) wird (werden) nicht verändert.
  *
  * Fall 3 (Dokumente mit einem IdentifierSerial):
  * Da in einer Schriftenreihe nicht zwei Dokumente mit der gleichen Bandnummer
  * existieren können, muss beim Zuweisen von Dokumenten darauf geachtet werden,
  * dass eine Bandnummer nicht mehrfach vergeben wird.
  * Wird versucht ein Dokument zu einer Schriftenreihe mit einer bereits
  * in Benutzung befindlichen Bandnummer zuzuweisen, so wird die Zuweisung
  * nicht durchgeführt. Die Zuweisung des Dokuments zur series-Collection wird
  * in diesem Fall unverändert beibehalten.
  *
  * Im Falle der erfolgreichen Zuweisung des Dokuments zu einer Schriftenreihe
  * wird die Verknüpfung mit der korrespondierenden series-Collection
  * entfernt. Außerdem wird das Feld IdentifierSerial entfernt.
  *
  *
  * @return array an array that contains both the number of conflicts found and
  * the number of documents that were successfully migrated
  */
 private function migrateDocuments()
 {
     $numOfConflicts = 0;
     $numOfDocsMigrated = 0;
     $finder = new Opus_DocumentFinder();
     $finder->setCollectionRoleId($this->seriesRole->getId());
     $serialIdsInUse = array();
     foreach ($finder->ids() as $docId) {
         $doc = new Opus_Document($docId);
         $serialIds = $doc->getIdentifierSerial();
         $numOfSerialIds = count($serialIds);
         if ($numOfSerialIds == 0) {
             $this->logger->warn("doc #{$docId} : does not have a field IdentifierSerial -- leave it untouched");
             $numOfConflicts++;
             continue;
         }
         if ($numOfSerialIds > 1) {
             $this->logger->warn("doc #{$docId} : has {$numOfSerialIds} values for field IdentifierSerial -- leave it untouched");
             $numOfConflicts++;
             continue;
         }
         $serialId = $serialIds[0]->getValue();
         $remainingCollections = array();
         foreach ($doc->getCollection() as $collection) {
             // only consider collection in collection role series
             if ($collection->getRoleId() != $this->seriesRole->getId()) {
                 array_push($remainingCollections, $collection);
             } else {
                 $collectionId = $collection->getId();
                 if (!$collection->isRoot()) {
                     // check for conflict
                     if (array_key_exists($collectionId, $serialIdsInUse) && in_array($serialId, $serialIdsInUse[$collectionId])) {
                         // conflict was found: serialId for series $collectionId already in use
                         $this->logger->warn("doc #{$docId} : could not assign to series #{$collectionId}: value {$serialId} already in use");
                         $this->logger->warn("doc #{$docId} : leave assignment to collection #{$collectionId} untouched");
                         array_push($remainingCollections, $collection);
                         $numOfConflicts++;
                     } else {
                         // no conflict
                         $series = new Opus_Series($collectionId);
                         $doc->addSeries($series)->setNumber($serialId);
                         $doc->setIdentifierSerial(array());
                         // mark usage of serialId for collection $collectionId
                         if (array_key_exists($collectionId, $serialIdsInUse)) {
                             array_push($serialIdsInUse[$collectionId], $serialId);
                         } else {
                             $serialIdsInUse[$collectionId] = array($serialId);
                         }
                         $this->logger->info("doc #{$docId} : assign document to series #{$collectionId} with value {$serialId}");
                         $this->logger->info("doc #{$docId} : removed assignment from collection #{$collectionId}");
                         $this->logger->info("doc #{$docId} : removed field IdentifierSerial with value " . $serialId);
                         $numOfDocsMigrated++;
                     }
                 } else {
                     // series root collection assignment will not be migrated
                     $this->logger->warn("doc #{$docId} : is assigned to root collection #{$collectionId} of collection role series: leave assignment untouched");
                     array_push($remainingCollections, $collection);
                     $numOfConflicts++;
                 }
             }
         }
         $doc->setCollection($remainingCollections);
         $doc->unregisterPlugin('Opus_Document_Plugin_Index');
         $doc->store();
     }
     return array('numOfConflicts' => $numOfConflicts, 'numOfDocsMigrated' => $numOfDocsMigrated);
 }
 /**
  * Retrieve all document ids for a valid oai request.
  *
  * @param array &$oaiRequest
  * @return array
  */
 public function query(array $oaiRequest)
 {
     $finder = new Opus_DocumentFinder();
     // add server state restrictions
     $finder->setServerStateInList($this->deliveringDocumentStates);
     $metadataPrefix = $oaiRequest['metadataPrefix'];
     if ('xMetaDissPlus' === $metadataPrefix || 'xMetaDiss' === $metadataPrefix) {
         $finder->setFilesVisibleInOai();
     }
     if ('xMetaDiss' === $metadataPrefix) {
         $finder->setTypeInList($this->xMetaDissRestriction);
     }
     if ('epicur' === $metadataPrefix) {
         $finder->setIdentifierTypeExists('urn');
     }
     if (array_key_exists('set', $oaiRequest)) {
         $setarray = explode(':', $oaiRequest['set']);
         if (!isset($setarray[0])) {
             return array();
         }
         if ($setarray[0] == 'doc-type') {
             if (count($setarray) === 2 and !empty($setarray[1])) {
                 $finder->setType($setarray[1]);
             } else {
                 return array();
             }
         } else {
             if ($setarray[0] == 'bibliography') {
                 if (count($setarray) !== 2 or empty($setarray[1])) {
                     return array();
                 }
                 $setValue = $setarray[1];
                 $bibliographyMap = array("true" => 1, "false" => 0);
                 if (false === isset($setValue, $bibliographyMap[$setValue])) {
                     return array();
                 }
                 $finder->setBelongsToBibliography($bibliographyMap[$setValue]);
             } else {
                 if (count($setarray) < 1 or count($setarray) > 2) {
                     $msg = "Invalid SetSpec: Must be in format 'set:subset'.";
                     throw new Oai_Model_Exception($msg);
                 }
                 // Trying to locate collection role and filter documents.
                 $role = Opus_CollectionRole::fetchByOaiName($setarray[0]);
                 if (is_null($role)) {
                     $msg = "Invalid SetSpec: Top level set does not exist.";
                     throw new Oai_Model_Exception($msg);
                 }
                 $finder->setCollectionRoleId($role->getId());
                 // Trying to locate given collection and filter documents.
                 if (count($setarray) == 2) {
                     $subsetName = $setarray[1];
                     $foundSubsets = array_filter($role->getOaiSetNames(), function ($s) use($subsetName) {
                         return $s['oai_subset'] === $subsetName;
                     });
                     if (count($foundSubsets) < 1) {
                         $msg = "Invalid SetSpec: Subset does not exist.";
                         throw new Oai_Model_Exception($msg);
                     }
                     foreach ($foundSubsets as $subset) {
                         if ($subset['oai_subset'] !== $subsetName) {
                             $msg = "Invalid SetSpec: Internal error.";
                             throw new Oai_Model_Exception($msg);
                         }
                         $finder->setCollectionId($subset['id']);
                     }
                 }
             }
         }
     }
     if (array_key_exists('from', $oaiRequest) and !empty($oaiRequest['from'])) {
         $from = DateTime::createFromFormat('Y-m-d', $oaiRequest['from']);
         $finder->setServerDateModifiedAfter($from->format('Y-m-d'));
     }
     if (array_key_exists('until', $oaiRequest)) {
         $until = DateTime::createFromFormat('Y-m-d', $oaiRequest['until']);
         $until->add(new DateInterval('P1D'));
         $finder->setServerDateModifiedBefore($until->format('Y-m-d'));
     }
     return $finder->ids();
 }