factory = $factory; $this->recordServiceContainer = $recordServiceContainer; $this->entityManager = $entityManager; $this->acl = $acl; } /** * @param string[] $attributeList * @param string $attachmentId * @throws Forbidden * @throws Error */ public function import( string $entityType, array $attributeList, string $attachmentId, Params $params ): Result { if (!$this->acl->check($entityType, Table::ACTION_CREATE)) { throw new Forbidden("No create access for '{$entityType}'."); } $result = $this->factory ->create() ->setEntityType($entityType) ->setAttributeList($attributeList) ->setAttachmentId($attachmentId) ->setParams($params) ->run(); $id = $result->getId(); if ($id) { $import = $this->entityManager->getEntity(ImportEntity::ENTITY_TYPE, $id); if ($import) { $this->recordServiceContainer ->get(ImportEntity::ENTITY_TYPE) ->processActionHistoryRecord('create', $import); } } return $result; } /** * @throws Forbidden * @throws Error */ public function importContentsWithParamsId(string $contents, string $importParamsId): Result { if (!$contents) { throw new Error("Contents is empty."); } /** @var ?ImportEntity $source */ $source = $this->entityManager->getEntity(ImportEntity::ENTITY_TYPE, $importParamsId); if (!$source) { throw new Error("Import '{$importParamsId}' not found."); } $entityType = $source->getTargetEntityType(); $attributeList = $source->getTargetAttributeList() ?? []; if (!$entityType) { throw new Error("No entity-type."); } $params = Params::fromRaw($source->getParams()) ->withIdleMode(false) ->withManualMode(false); $attachmentId = $this->uploadFile($contents); return $this->import($entityType, $attributeList, $attachmentId, $params); } public function importById(string $id, bool $startFromLastIndex = false, bool $forceResume = false): Result { /** @var ?ImportEntity $import */ $import = $this->entityManager->getEntity(ImportEntity::ENTITY_TYPE, $id); if (!$import) { throw new NotFound("Import '{$id}' not found."); } $status = $import->getStatus(); if ($status !== ImportEntity::STATUS_STANDBY) { if (!in_array($status, [ImportEntity::STATUS_IN_PROCESS, ImportEntity::STATUS_FAILED])) { throw new Forbidden("Can't run import with '{$status}' status."); } if (!$forceResume) { throw new Forbidden("Import has '{$status}' status. Use -r flag to force resume."); } } $entityType = $import->getTargetEntityType(); $attributeList = $import->getTargetAttributeList() ?? []; if (!$entityType) { throw new Error("No entity-type."); } $params = Params::fromRaw($import->getParams()) ->withStartFromLastIndex($startFromLastIndex); $attachmentId = $import->getFileId(); if (!$attachmentId) { throw new Error("No file-id."); } return $this->factory ->create() ->setEntityType($entityType) ->setAttributeList($attributeList) ->setAttachmentId($attachmentId) ->setParams($params) ->setId($id) ->run(); } public function revert(string $id): void { $import = $this->entityManager->getEntity('Import', $id); if (!$import) { throw new NotFound("Could not find import record."); } if (!$this->acl->checkEntityDelete($import)) { throw new Forbidden("No access import record."); } $importEntityList = $this->entityManager ->getRDBRepository('ImportEntity') ->sth() ->where([ 'importId' => $import->getId(), 'isImported' => true, ]) ->find(); $removeFromDb = false; $createdAt = $import->get('createdAt'); if ($createdAt) { $dtNow = new DateTime(); $createdAtDt = new DateTime($createdAt); $dayDiff = ($dtNow->getTimestamp() - $createdAtDt->getTimestamp()) / 60 / 60 / 24; if ($dayDiff < self::REVERT_PERMANENTLY_REMOVE_PERIOD_DAYS) { $removeFromDb = true; } } foreach ($importEntityList as $importEntity) { $entityType = $importEntity->get('entityType'); $entityId = $importEntity->get('entityId'); if (!$entityType || !$entityId) { continue; } if (!$this->entityManager->hasRepository($entityType)) { continue; } $entity = $this->entityManager ->getRDBRepository($entityType) ->select(['id']) ->where(['id' => $entityId]) ->findOne(); if (!$entity) { continue; } $this->entityManager->removeEntity($entity, [ 'noStream' => true, 'noNotifications' => true, 'import' => true, 'silent' => true, ]); if ($removeFromDb) { $this->entityManager ->getRDBRepository($entityType) ->deleteFromDb($entityId); } } $this->entityManager->removeEntity($import); $this->recordServiceContainer ->get(ImportEntity::ENTITY_TYPE) ->processActionHistoryRecord('delete', $import); } /** * @return string Attachment ID. */ public function uploadFile(string $contents): string { $attachment = $this->entityManager->getNewEntity(Attachment::ENTITY_TYPE); $attachment->set('type', 'text/csv'); $attachment->set('role', 'Import File'); $attachment->set('name', 'import-file.csv'); $attachment->set('contents', $contents); $this->entityManager->saveEntity($attachment); return $attachment->getId(); } public function removeDuplicates(string $id): void { $import = $this->entityManager->getEntity(ImportEntity::ENTITY_TYPE, $id); if (!$import) { throw new NotFound("Import '{$id}' not found."); } if (!$this->acl->checkEntityDelete($import)) { throw new Forbidden("No delete access."); } $importEntityList = $this->entityManager ->getRDBRepository('ImportEntity') ->sth() ->where([ 'importId' => $import->getId(), 'isDuplicate' => true, ]) ->find(); foreach ($importEntityList as $importEntity) { $entityType = $importEntity->get('entityType'); $entityId = $importEntity->get('entityId'); if (!$entityType || !$entityId) { continue; } if (!$this->entityManager->hasRepository($entityType)) { continue; } $entity = $this->entityManager ->getRDBRepository($entityType) ->select(['id']) ->where(['id' => $entityId]) ->findOne(); if (!$entity) { continue; } $this->entityManager->removeEntity($entity, [ 'noStream' => true, 'noNotifications' => true, 'import' => true, 'silent' => true, ]); $this->entityManager ->getRDBRepository($entityType) ->deleteFromDb($entityId); } } public function unmarkAsDuplicate(string $importId, string $entityType, string $entityId): void { $entity = $this->entityManager ->getRDBRepository('ImportEntity') ->where([ 'importId' => $importId, 'entityType' => $entityType, 'entityId' => $entityId, ]) ->findOne(); if (!$entity) { throw new NotFound(); } $entity->set('isDuplicate', false); $this->entityManager->saveEntity($entity); } }