Esempio n. 1
0
 /**
  * @dataProvider provideConflictDetection
  */
 public function testConflictDetection(Entity $base, Entity $current, Entity $new, $expectedConflicts)
 {
     $differ = new EntityDiffer();
     $patcher = new EntityPatcher();
     $patch = $differ->diffEntities($base, $new);
     $patchedCurrent = unserialize(serialize($current));
     $patcher->patchEntity($patchedCurrent, $patch);
     $cleanPatch = $differ->diffEntities($base, $patchedCurrent);
     $conflicts = $patch->count() - $cleanPatch->count();
     $this->assertEquals($expectedConflicts, $conflicts, 'check number of conflicts detected');
 }
 /**
  * Returns a patched copy of this Content object.
  *
  * @param EntityContentDiff $patch
  *
  * @throws PatcherException
  * @return EntityContent
  */
 public function getPatchedCopy(EntityContentDiff $patch)
 {
     /* @var EntityHandler $handler */
     $handler = $this->getContentHandler();
     if ($this->isRedirect()) {
         $entityAfterPatch = $this->makeEmptyEntity();
     } else {
         $entityAfterPatch = unserialize(serialize($this->getEntity()));
     }
     // FIXME: this should either be done in the derivatives, or the patcher
     // should be injected, so the application can add support for additional entity types.
     $patcher = new EntityPatcher();
     $patcher->patchEntity($entityAfterPatch, $patch->getEntityDiff());
     $redirAfterPatch = $this->getPatchedRedirect($patch->getRedirectDiff());
     if ($redirAfterPatch !== null && !$entityAfterPatch->isEmpty()) {
         throw new PatcherException('EntityContent must not contain Entity data as well as' . ' a redirect after applying the patch!');
     } elseif ($redirAfterPatch) {
         $patched = $handler->makeEntityRedirectContent($redirAfterPatch);
         if (!$patched) {
             throw new PatcherException('Cannot create a redirect using content model ' . $this->getModel() . '!');
         }
     } else {
         $patched = $handler->makeEntityContent(new EntityInstanceHolder($entityAfterPatch));
     }
     return $patched;
 }
Esempio n. 3
0
 /**
  * Attempts to fix an edit conflict by patching the intended change into the latest revision after
  * checking for conflicts. This modifies $this->newEntity but does not write anything to the
  * database. Saving of the new content may still fail.
  *
  * @return bool True if the conflict could be resolved, false otherwise
  */
 public function fixEditConflict()
 {
     $baseRev = $this->getBaseRevision();
     $latestRev = $this->getLatestRevision();
     if (!$latestRev) {
         wfLogWarning('Failed to load latest revision of entity ' . $this->newEntity->getId() . '! ' . 'This may indicate entries missing from thw wb_entities_per_page table.');
         return false;
     }
     $entityDiffer = new EntityDiffer();
     $entityPatcher = new EntityPatcher();
     // calculate patch against base revision
     // NOTE: will fail if $baseRev or $base are null, which they may be if
     // this gets called at an inappropriate time. The data flow in this class
     // should be improved.
     $patch = $entityDiffer->diffEntities($baseRev->getEntity(), $this->newEntity);
     if ($patch->isEmpty()) {
         // we didn't technically fix anything, but if there is nothing to change,
         // so just keep the current content as it is.
         $this->newEntity = $latestRev->getEntity()->copy();
         return true;
     }
     // apply the patch( base -> new ) to the latest revision.
     $patchedLatest = $latestRev->getEntity()->copy();
     $entityPatcher->patchEntity($patchedLatest, $patch);
     // detect conflicts against latest revision
     $cleanPatch = $entityDiffer->diffEntities($latestRev->getEntity(), $patchedLatest);
     $conflicts = $patch->count() - $cleanPatch->count();
     if ($conflicts > 0) {
         // patch doesn't apply cleanly
         if ($this->userWasLastToEdit($this->user, $this->newEntity->getId(), $this->getBaseRevisionId())) {
             // it's a self-conflict
             if ($cleanPatch->count() === 0) {
                 // patch collapsed, possibly because of diff operation change from base to latest
                 return false;
             } else {
                 // we still have a working patch, try to apply
                 $this->status->warning('wikibase-self-conflict-patched');
             }
         } else {
             // there are unresolvable conflicts.
             return false;
         }
     } else {
         // can apply cleanly
         $this->status->warning('wikibase-conflict-patched');
     }
     // remember the patched entity as the actual new entity to save
     $this->newEntity = $patchedLatest;
     return true;
 }
Esempio n. 4
0
 public function testGivenNonSupportedEntity_exceptionIsThrown()
 {
     $patcher = new EntityPatcher();
     $this->setExpectedException('RuntimeException');
     $patcher->patchEntity(new EntityOfUnknownType(), new EntityDiff());
 }