Example #1
0
 /**
  * Queries the associated storage whether the entity data should be saved or not
  *
  * @see Storage::shouldBeSaved()
  *
  * @param string $entityName Determines the storage
  * @param array $data Data passed to VersionPress\Storages\Storage::shouldBeSaved()
  * @return bool
  */
 public function shouldBeSaved($entityName, $data)
 {
     $storage = $this->storageFactory->getStorage($entityName);
     if ($storage === null) {
         return false;
     }
     return $storage->shouldBeSaved($data);
 }
 /**
  * @test
  * @testdox Factory creates right storages
  */
 public function factoryCreatesRightStorages()
 {
     $storages = ['post' => DirectoryStorage::class, 'comment' => DirectoryStorage::class, 'option' => DirectoryStorage::class, 'term' => DirectoryStorage::class, 'termmeta' => MetaEntityStorage::class, 'term_taxonomy' => DirectoryStorage::class, 'user' => DirectoryStorage::class, 'usermeta' => MetaEntityStorage::class, 'postmeta' => MetaEntityStorage::class];
     /** @var \wpdb $wpdbStub */
     $wpdbStub = new \stdClass();
     $wpdbStub->prefix = 'prefix_';
     $database = new Database($wpdbStub);
     $changeInfoFactory = $this->getMockBuilder(ChangeInfoFactory::class)->disableOriginalConstructor()->getMock();
     $tableSchemaStorage = $this->getMockBuilder(TableSchemaStorage::class)->disableOriginalConstructor()->getMock();
     $factory = new StorageFactory(__DIR__ . '/vpdb', new DbSchemaInfo([__DIR__ . '/../../.versionpress/schema.yml'], 'wp_', PHP_INT_MAX), $database, [], $changeInfoFactory, $tableSchemaStorage);
     foreach ($storages as $entityName => $expectedClass) {
         $this->assertInstanceOf($expectedClass, $factory->getStorage($entityName));
     }
 }
Example #3
0
 /**
  * Calls Git `add -A` on files that are related to the given $changeInfo.
  * The "exchange format" is an array documented in {@see TrackedChangedInfo::getChangedFiles()}.
  *
  * @param TrackedChangeInfo|ChangeInfoEnvelope $changeInfo
  */
 private function stageRelatedFiles($changeInfo)
 {
     if ($changeInfo instanceof ChangeInfoEnvelope) {
         /** @var TrackedChangeInfo $subChangeInfo */
         foreach ($changeInfo->getChangeInfoList() as $subChangeInfo) {
             $this->stageRelatedFiles($subChangeInfo);
         }
         return;
     }
     $changes = $changeInfo->getChangedFiles();
     foreach ($changes as $change) {
         if ($change["type"] === "storage-file") {
             $entityName = $change["entity"];
             $entityId = $change["id"];
             $parentId = $change["parent-id"];
             $path = $this->storageFactory->getStorage($entityName)->getEntityFilename($entityId, $parentId);
         } elseif ($change["type"] === "all-storage-files") {
             $entityName = $change["entity"];
             $path = $this->storageFactory->getStorage($entityName)->getPathCommonToAllEntities();
         } elseif ($change["type"] === "path") {
             $path = $change["path"];
         } else {
             continue;
         }
         $this->repository->stageAll($path);
     }
 }
Example #4
0
 /**
  * For standard entities just checks the storage.
  * For child entities (like postmeta) loads all entities and checks them.
  *
  * @param $referencedEntityName
  * @param $referencedEntityId
  * @param $maybeParentId
  * @return bool
  */
 private function entityExists($referencedEntityName, $referencedEntityId, $maybeParentId)
 {
     if (!$this->dbSchemaInfo->isChildEntity($referencedEntityName)) {
         return $this->storageFactory->getStorage($referencedEntityName)->exists($referencedEntityId, null);
     }
     // Optimalization for child entities saved within their parents
     if ($this->storageFactory->getStorage($referencedEntityName)->exists($referencedEntityId, $maybeParentId)) {
         return true;
     }
     $allEntities = $this->storageFactory->getStorage($referencedEntityName)->loadAll();
     return isset($allEntities[$referencedEntityId]);
 }
 private function saveMnReferences($referenceDetails)
 {
     $junctionTable = $referenceDetails['junction-table'];
     $sourceEntity = $referenceDetails['source-entity'];
     $targetEntity = $referenceDetails['target-entity'];
     $sourceColumn = $referenceDetails['source-column'];
     $targetColumn = $referenceDetails['target-column'];
     $storage = $this->storageFactory->getStorage($junctionTable);
     $dbRows = $this->getEntitiesFromDatabase($junctionTable);
     foreach ($dbRows as $row) {
         $reference = ["vp_{$sourceEntity}" => $this->idCache[$sourceEntity][intval($row[$sourceColumn])], "vp_{$targetEntity}" => $this->idCache[$targetEntity][intval($row[$targetColumn])]];
         $storage->save($reference);
     }
 }
Example #6
0
 /**
  * Saves entities of type identified by $entityName to their appropriate storage
  * (chosen by factory).
  *
  * @param string $entityName
  */
 private function saveEntitiesOfTypeToStorage($entityName)
 {
     $storage = $this->storageFactory->getStorage($entityName);
     $entities = $this->getEntitiesFromDatabase($entityName);
     $entities = $this->replaceForeignKeysWithReferencesInAllEntities($entityName, $entities);
     $entities = array_values(array_filter($entities, function ($entity) use($storage) {
         return $storage->shouldBeSaved($entity);
     }));
     $urlReplacer = $this->urlReplacer;
     $entities = $this->extendEntitiesWithVpids($entityName, $entities);
     $entities = array_map(function ($entity) use($urlReplacer) {
         return $urlReplacer->replace($entity);
     }, $entities);
     $entities = $this->doEntitySpecificActions($entityName, $entities);
     $storage->prepareStorage();
     if (!$this->dbSchema->isChildEntity($entityName)) {
         $this->saveStandardEntities($storage, $entities);
     } else {
         // meta entities
         $entityInfo = $this->dbSchema->getEntityInfo($entityName);
         $parentReference = "vp_" . $entityInfo->parentReference;
         $this->saveMetaEntities($storage, $entities, $parentReference);
     }
 }
 private function getStorage($synchronizerName)
 {
     return $this->storageFactory->getStorage($synchronizerName);
 }
Example #8
0
 /**
  * @param $entityName
  */
 private static function assertEntitiesEqualDatabase($entityName)
 {
     $storage = self::$storageFactory->getStorage($entityName);
     $entityInfo = self::$schemaInfo->getEntityInfo($entityName);
     $allDbEntities = self::selectAll(self::$schemaInfo->getPrefixedTableName($entityName));
     $idMap = self::getVpIdMap();
     $allDbEntities = self::identifyEntities($entityName, $allDbEntities, $idMap);
     $allDbEntities = self::replaceForeignKeys($entityName, $allDbEntities, $idMap);
     $dbEntities = array_filter($allDbEntities, [$storage, 'shouldBeSaved']);
     $urlReplacer = new AbsoluteUrlReplacer(self::$testConfig->testSite->url);
     $storageEntities = array_map(function ($entity) use($urlReplacer) {
         return $urlReplacer->restore($entity);
     }, $storage->loadAll());
     $countOfentitiesInDb = count($dbEntities);
     $countOfentitiesInStorage = count($storageEntities);
     if ($countOfentitiesInDb !== $countOfentitiesInStorage) {
         if ($countOfentitiesInStorage > $countOfentitiesInDb) {
             $problematicEntities = self::findMissingEntities($entityName, $storageEntities, $dbEntities);
         } else {
             $problematicEntities = self::findExceedingEntities($entityName, $storageEntities, $dbEntities);
         }
         throw new \PHPUnit_Framework_AssertionFailedError("Different count of synchronized entities ({$entityName}): DB = {$countOfentitiesInDb}, " . "storage = {$countOfentitiesInStorage}\nProblematic entities: " . join(", ", $problematicEntities));
     }
     foreach ($dbEntities as $dbEntity) {
         $id = $dbEntity[$entityInfo->vpidColumnName];
         $storageEntity = $storageEntities[$id];
         $dbEntity = self::$shortcodesReplacer->replaceShortcodesInEntity($entityName, $dbEntity);
         foreach ($dbEntity as $column => $value) {
             if ($entityInfo->idColumnName === $column || isset($entityInfo->getIgnoredColumns()[$column])) {
                 continue;
             }
             if (!isset($storageEntity[$column])) {
                 throw new \PHPUnit_Framework_AssertionFailedError("{$entityName}[{$column}] with value = {$value}, ID = {$id} not found in storage");
             }
             if (is_string($storageEntity[$column])) {
                 $storageEntity[$column] = str_replace("\r\n", "\n", $storageEntity[$column]);
             }
             if (is_string($value)) {
                 $value = str_replace("\r\n", "\n", $value);
             }
             if ($storageEntity[$column] != $value) {
                 throw new \PHPUnit_Framework_AssertionFailedError("Different values ({$entityName}[{$column}]: {$id}): DB = {$value}, storage = {$storageEntity[$column]}");
             }
         }
     }
     $missingReferences = [];
     $exceedingReferences = [];
     foreach ($entityInfo->mnReferences as $reference => $targetEntity) {
         if ($entityInfo->isVirtualReference($reference)) {
             continue;
         }
         $referenceDetails = ReferenceUtils::getMnReferenceDetails(self::$schemaInfo, $entityName, $reference);
         $sourceColumn = $referenceDetails['source-column'];
         $targetColumn = $referenceDetails['target-column'];
         $junctionTable = $referenceDetails['junction-table'];
         $prefixedJunctionTable = self::$schemaInfo->getPrefixedTableName($junctionTable);
         $prefixedVpIdTable = self::$schemaInfo->getPrefixedTableName('vp_id');
         $sourceTable = self::$schemaInfo->getTableName($referenceDetails['source-entity']);
         $targetTable = self::$schemaInfo->getTableName($referenceDetails['target-entity']);
         $junctionTableContent = self::fetchAll("SELECT HEX(s_vp_id.vp_id), HEX(t_vp_id.vp_id) FROM {$prefixedJunctionTable} j\n                 JOIN {$prefixedVpIdTable} s_vp_id ON j.{$sourceColumn} = s_vp_id.id AND s_vp_id.`table`='{$sourceTable}'\n                 JOIN {$prefixedVpIdTable} t_vp_id ON j.{$targetColumn} = t_vp_id.id AND t_vp_id.`table` = '{$targetTable}'", MYSQLI_NUM);
         $checkedReferences = [];
         $missingReferences[$junctionTable] = [];
         foreach ($storageEntities as $storageEntity) {
             if (!isset($storageEntity["vp_{$targetEntity}"])) {
                 continue;
             }
             foreach ($storageEntity["vp_{$targetEntity}"] as $referenceVpId) {
                 if (!ArrayUtils::any($junctionTableContent, function ($junctionRow) use($storageEntity, $referenceVpId) {
                     return $junctionRow[0] === $storageEntity['vp_id'] && $junctionRow[1] === $referenceVpId;
                 })) {
                     $missingReferences[$junctionTable][] = [$sourceColumn => $storageEntity['vp_id'], $targetColumn => $referenceVpId];
                 }
                 $checkedReferences[] = [$storageEntity['vp_id'], $referenceVpId];
             }
         }
         $exceedingReferences[$junctionTable] = array_map(function ($pair) use($sourceColumn, $targetColumn) {
             return [$sourceColumn => $pair[0], $targetColumn => $pair[1]];
         }, array_filter($junctionTableContent, function ($pair) use($checkedReferences) {
             foreach ($checkedReferences as $reference) {
                 if ($reference[0] === $pair[0] && $reference[1] === $pair[1]) {
                     return false;
                 }
             }
             return true;
         }));
     }
     self::reportResultOfMnReferenceCheck($missingReferences, "Missing");
     self::reportResultOfMnReferenceCheck($exceedingReferences, "Exceeding");
 }