socialIssueRepository = $socialIssueRepository; $this->socialActionRepository = $socialActionRepository; $this->goalRepository = $goalRepository; $this->resultRepository = $resultRepository; $this->evaluationRepository = $evaluationRepository; $this->entityManager = $entityManager; } /** * @throws Exception */ public function import(iterable $dataset): bool { // Initialisation of the previous result row with the proper data structure. $result = [ 'socialIssues' => [ 'socialIssue' => null, 'socialIssueChild' => null, ], 'socialActions' => [ 'socialAction' => null, 'socialActionChild' => null, ], 'goal' => null, 'result' => null, 'eval' => null, ]; foreach ($dataset as $key => $row) { $result = $this ->import1( $key, // Columns cleanup before importing data. array_map( static fn (string $column): ?string => '' === $column ? null : $column, array_map('trim', $row) ), $result ); } return true; } /** * @return array */ private function findByJson(ObjectRepository $repository, string $field, array $jsonCriterias): array { $qb = $this ->entityManager ->createQueryBuilder() ->select('s') ->from($repository->getClassName(), 's'); $expr = $qb->expr(); $temporaryJsonCriterias = []; foreach ($jsonCriterias as $key => $value) { $temporaryJsonCriterias[] = [$field, $key, $value, sprintf(':placeholder_%s_%s', $field, $key)]; } $jsonParameters = array_reduce( $temporaryJsonCriterias, static function (array $carry, array $row): array { [,, $value, $placeholder] = $row; return array_merge( $carry, [ $placeholder => sprintf('"%s"', $value), ] ); }, [] ); $jsonPredicates = array_map( static function (array $row) use ($expr): Comparison { [$field, $key,, $placeholder] = $row; $left = sprintf( "GET_JSON_FIELD_BY_KEY(s.%s, '%s')", $field, $key ); return $expr ->eq( $left, $placeholder ); }, $temporaryJsonCriterias ); return $qb ->select('s') ->where(...$jsonPredicates) ->setParameters($jsonParameters) ->getQuery() ->getResult(); } /** * @throws Exception * * @return object */ private function getOrCreateEntity(ObjectRepository $repository, string $field, array $jsonCriterias = []) { $results = $this ->findByJson( $repository, $field, $jsonCriterias ); if ([] === $results) { $entity = $repository->getClassName(); return new $entity(); } if (count($results) === 1) { return reset($results); } throw new Exception( 'Unable to create entity.' ); } private function handleEvaluation(?string $evaluationTitle, SocialAction $socialAction): ?Evaluation { if (null === $evaluationTitle) { return null; } /** @var Evaluation $eval */ $eval = $this->getOrCreateEntity($this->evaluationRepository, 'title', ['fr' => $evaluationTitle]); $eval->setTitle(['fr' => $evaluationTitle]); $socialAction->addEvaluation($eval); $this->entityManager->persist($eval); return $eval; } private function handleGoal(?string $goalTitle, SocialAction $socialAction): ?Goal { if (null === $goalTitle) { return null; } /** @var Goal $goal */ $goal = $this->getOrCreateEntity($this->goalRepository, 'title', ['fr' => $goalTitle]); $goal->setTitle(['fr' => $goalTitle]); $socialAction->addGoal($goal); $goal->addSocialAction($socialAction); $this->entityManager->persist($socialAction); $this->entityManager->persist($goal); return $goal; } private function handleResult(?string $resultTitle, SocialAction $socialAction, ?Goal $goal): ?Result { if (null === $resultTitle) { return null; } /** @var Result $result */ $result = $this->getOrCreateEntity($this->resultRepository, 'title', ['fr' => $resultTitle]); $result->setTitle(['fr' => $resultTitle]); if (null !== $goal) { $result->addGoal($goal); $goal->addResult($result); $this->entityManager->persist($goal); } else { $result->addSocialAction($socialAction); $socialAction->addResult($result); } $this->entityManager->persist($result); $this->entityManager->persist($socialAction); return $result; } /** * @throws Exception * * @return array */ private function handleSocialAction( ?string $socialActionTitle, ?string $socialActionChildTitle, SocialIssue $socialIssue, float $orderingParent, float $orderingChild, ?SocialAction $previousSocialAction, ?SocialAction $previousSocialActionChild ): array { if (null === $socialActionTitle) { return [ 'socialAction' => null, 'socialActionChild' => null, ]; } $return = []; if (null !== $previousSocialAction && ($previousSocialAction->getTitle()['fr'] === $socialActionTitle)) { $return = [ 'socialAction' => $parent = $previousSocialAction, ]; $parentIsSame = true; } else { $return['socialAction'] = $parent = (new SocialAction())->setTitle(['fr' => $socialActionTitle]) ->setOrdering($orderingParent); $parent->setIssue($socialIssue); $this->entityManager->persist($parent); $parentIsSame = false; } if (null === $socialActionChildTitle) { $return['socialActionChild'] = null; } elseif ($parentIsSame && null !== $previousSocialActionChild && $previousSocialActionChild->getTitle()['fr'] === $socialActionChildTitle) { $return['socialActionChild'] = $previousSocialActionChild; } else { $return['socialActionChild'] = $child = (new SocialAction())->setTitle(['fr' => $socialActionChildTitle]); $child->setParent($parent); $child->setIssue($socialIssue)->setOrdering($orderingChild); $this->entityManager->persist($child); } return $return; } /** * @throws Exception * * @return array */ private function handleSocialIssue( ?string $socialIssueTitle, ?string $socialIssueChildTitle, float $orderingParent, float $orderingChild, ?SocialIssue $previousSocialIssue, ?SocialIssue $previousSocialIssueChild ): array { $return = []; if (null !== $previousSocialIssue && ($previousSocialIssue->getTitle()['fr'] === $socialIssueTitle)) { $return = [ 'socialIssue' => $parent = $previousSocialIssue, ]; $parentIsSame = true; } elseif (null !== $socialIssueTitle) { $return['socialIssue'] = $parent = (new SocialIssue())->setTitle(['fr' => $socialIssueTitle]) ->setOrdering($orderingParent); $this->entityManager->persist($parent); $parentIsSame = false; } else { return [ 'socialIssue' => null, 'socialIssueChild' => null, ]; } if ($parentIsSame && null !== $previousSocialIssueChild && ($previousSocialIssueChild->getTitle()['fr'] === $socialIssueChildTitle)) { $return['socialIssueChild'] = $previousSocialIssueChild; } elseif (null !== $socialIssueChildTitle) { $return['socialIssueChild'] = $child = (new SocialIssue())->setTitle(['fr' => $socialIssueChildTitle]) ->setOrdering($orderingChild); $child->setParent($parent); $this->entityManager->persist($child); } else { $return['socialIssueChild'] = null; } return $return; } /** * Row Structure:. * * Index 0: Parent SocialIssue * Index 1: Child SocialIssue * Index 2: Parent SocialAction * Index 3: Child SocialAction * Index 4: Goal * Index 5: Result * Index 6: Evaluation * * @param array $row * @param array|SocialIssue|string, SocialAction|null>|Evaluation|Goal|Result> $previousRow * * @throws Exception * * @return array|SocialIssue|string, SocialAction|null>|Evaluation|Goal|Result> */ private function import1(int $key, array $row, array $previousRow): array { $baseOrdering = $key * 10.0; $socialIssues = $this ->handleSocialIssue( $row[0], $row[1], $key + 1.0, $key + 3.0, $previousRow['socialIssues']['socialIssue'] ?? null, $previousRow['socialIssues']['socialIssueChild'] ?? null ); $socialIssue = $socialIssues['socialIssueChild'] ?? $socialIssues['socialIssue']; if (null === $socialIssue) { throw new Exception(sprintf("no social issue on row {$key}, values: %s", implode(', ', $row))); } $socialActions = $this ->handleSocialAction( $row[2], $row[3], $socialIssue, $key + 5.0, $key + 7.0, $previousRow['socialActions']['socialAction'] ?? null, $previousRow['socialActions']['socialActionChild'] ?? null ); $socialAction = $socialActions['socialActionChild'] ?? $socialActions['socialAction']; if (null !== $socialAction) { $goal = $this->handleGoal($row[4], $socialAction); $result = $this->handleResult($row[5], $socialAction, $goal); $eval = $this->handleEvaluation($row[6], $socialAction); } $this->entityManager->flush(); return [ 'socialIssues' => $socialIssues, 'socialActions' => $socialActions, 'goal' => $goal ?? null, 'result' => $result ?? null, 'eval' => $eval ?? null, ]; } }