layoutRepository = $layoutRepository; $this->elementTypeRepository = $elementTypeRepository; $this->projectRepository = $projectRepository; $this->draftQuery = $draftQuery; $this->story = $story; $this->exportsRepository = $exportsRepository; $this->valueRepository = $valueRepository; $this->entityManager = $entityManager; $this->workflowCustomRepository = $workflowCustomRepository; $this->pageRepository = $pageRepository; $this->templateRepository = $templateRepository; $this->pageAutoGeneQuery = $pageAutoGeneQuery; } /** * @param TemplateView $view * @param int $projectId * * @return bool|Exception */ public function save(ElementFieldsTemplatesView $view, int $projectId, bool $lastStep) { $fields = []; $idsFieldUpdate = []; $idsElementType = []; $storyLayout = []; $variables = []; $result = true; $elementTypeFieldIdsToRemoveFromExportValues = ["projectId" => $projectId, "layouts" => []]; $variableProjectRepo = $this->entityManager->getRepository(VariableProject::class); if (isset($view->elementFieldsTemplates) && !empty($view->elementFieldsTemplates)) { foreach ($view->elementFieldsTemplates as $fieldView) { if($fieldView->elementTypeId){ $elementType = $this->elementTypeRepository->findElementTypeByIdProject($fieldView->elementTypeId, $projectId); } else { $elementType = $this->elementTypeRepository->findNoElementTypeByIdProject($projectId); } if (isset($elementType)) { $idsElementType[] = $elementType->getId(); $entity = $this->layoutRepository->getLayout($fieldView->variableProjectId, $elementType->getId()); if (!$entity) { $variableProject = $variableProjectRepo->findOneBy(['id' => $fieldView->variableProjectId]); $entity = new Layout(); if(!empty($variableProject)){ $entity->setVariableProject($variableProject); if(!empty($elementType->getElementTypePIM())){ $variables[] = $fieldView->variableProjectId; } } } else { if($entity->getElementTypeFieldId() != $fieldView->elementFieldId){ $variables[] = $fieldView->variableProjectId; } } $entity->setElementType($elementType); $entity->setInputs($fieldView->inputs); $entity->setName($fieldView->name); $entity->setElementTypeFieldId($fieldView->elementFieldId); $entity->setEditable($fieldView->editable); $fields[] = $entity; if (null !== $entity->getId()) { $idsFieldUpdate[] = $entity->getId(); } } $storyLayout[] = ['variableProject' => $fieldView->variableProjectId, 'element_field_id' => $fieldView->elementFieldId]; } } $result = $this->manageLayoutsAndValues($projectId, $idsElementType, $idsFieldUpdate); $project = $this->projectRepository->findById($projectId); if ($project->getCurrentStep() < 4) { $project->setCurrentStep(4); $this->projectRepository->create($project); } if (!empty($fields)) { $this->layoutRepository->saveMultiple($fields); } if(!empty($variables)){ $pages = $this->pageRepository->findByVariableProjectAndProjectId($projectId, $variables); $pagesId = []; if(!empty($pages)){ foreach ($pages as $page) { $pagesId[] = ['id' => $page->getId()]; if(!$page->getPageDuplicates()->isEmpty()){ foreach ($page->getPageDuplicates() as $dupli) { $pagesId[] = ['id' => $page->getId(), "pageDuplicateId" => $dupli->getId()]; } } } if(!empty($pagesId)){ $this->pageAutoGeneQuery->addPageToGenerate($pagesId); } } } if (!empty($storyLayout)) { $this->story->execute('Step 5', ['value' => $storyLayout], $projectId, get_class($project), 0); } if (isset($lastStep) && $lastStep) { $this->draftQuery->changeDraft($projectId); } if (!$project->getArchiving()) { $this->cascadeExportValuesRemove($elementTypeFieldIdsToRemoveFromExportValues); } return $result; } /** * @param int $projectId * @param array $idsElementType * @param array $idsFieldUpdate * * @return bool|Exception */ private function manageLayoutsAndValues(int $projectId, array $idsElementType, array $idsFieldUpdate) { $layoutsToDelete = []; if (!empty($idsElementType) && !empty($idsFieldUpdate)) { $layoutsToDelete = $this->layoutRepository->getMultipleNotIn($projectId, $idsElementType, $idsFieldUpdate); } else { $layoutsToDelete = $this->layoutRepository->findByProjectId($projectId); } if (!empty($layoutsToDelete)) { $deleted = $this->layoutRepository->removeMultiple($layoutsToDelete); if (!$deleted instanceof Exception) { $arrayExportIds = $this->exportsRepository->listIdsByProjectId($projectId); // Find project's export ids $exportIds = array_column($arrayExportIds, "id"); $values = []; foreach ($layoutsToDelete as $layoutToDelete) { $matchingValues = []; if(!empty($layoutToDelete->getVariableProject())){ $matchingValues = $this->valueRepository->findByExportIdsAndAssociations($exportIds, $layoutToDelete->getVariableProject()->getId(), $layoutToDelete->getElementTypeFieldId()); // Find Value based on export ids and association between templateTwigId and pimElementTypeFieldId } if (!empty($matchingValues)) { $values = [...$values, ...$matchingValues]; // Merge array } else { continue; } } $result = $this->valueRepository->removeMultiple($values); } else { $result = $deleted; } } else { $result = true; } return $result; } /** Delete ExportValue (or update ExportValue's value in case of fieldset) when an assocation changes * @param array $elementTypeFieldIdsToRemoveFromExportValues * * @return void */ private function cascadeExportValuesRemove(array $elementTypeFieldIdsToRemoveFromExportValues): void { if (isset($elementTypeFieldIdsToRemoveFromExportValues["projectId"]) && isset($elementTypeFieldIdsToRemoveFromExportValues["layouts"])) { $concatRequest = []; $valuesToRemove = []; $valuesToUpdate = []; $projectId = $elementTypeFieldIdsToRemoveFromExportValues["projectId"]; foreach ($elementTypeFieldIdsToRemoveFromExportValues["layouts"] as $layout) { if (array_key_exists("templateTwigId", $layout) && array_key_exists("elementTypeFieldId", $layout) && array_key_exists("elementTypeFieldIdFromView", $layout)) { $templateTwigId = $layout["templateTwigId"]; $elementTypeFieldId = $layout["elementTypeFieldId"]; $elementTypeFieldIdFromView = $layout["elementTypeFieldIdFromView"]; $concat = "$projectId.$templateTwigId.$elementTypeFieldId.$elementTypeFieldIdFromView"; if (!in_array($concat, $concatRequest)) { $value = $this->valueRepository->findByProjectLayoutAssociation($projectId, $templateTwigId, $elementTypeFieldId); // Finds existing ExportValue for the new association $valueFromView = $this->valueRepository->findByProjectLayoutAssociation($projectId, $templateTwigId, $elementTypeFieldIdFromView); // Finds existing ExportValue for the old association $concatRequest[] = $concat; if (is_array($value) && is_array($valueFromView)) { $value = array_merge($value, $valueFromView); if (isset($layout["twigInputId"])) { foreach ($value as $val) { $arrayData = json_decode($val->getValue(), true); if ($arrayData && "idLastCol" === array_key_first($arrayData) && isset($arrayData["collections"]) && !empty($arrayData["collections"])) { $copyCollections = [...$arrayData["collections"]]; $mappedArray = array_map(function ($collection) use ($layout) { $fields = array_map(function ($field) use ($layout) { if (isset($field["templateInputId"]) && isset($field["value"]) && $field["templateInputId"]) { $field["value"] = ""; } return $field; }, $collection); $collection = $fields; return $collection; }, $copyCollections); $arrayData["collections"] = $mappedArray; } else { $arrayData["value"] = ""; } $val->setValue(json_encode($arrayData)); $valuesToUpdate[] = $val; } } else { $valuesToRemove = array_merge($valuesToRemove, array_map(function ($val) { return $val; }, $value)); } } } } } $this->cascadeOnPages(array_merge($valuesToRemove, $valuesToUpdate)); $this->valueRepository->removeMultiple($valuesToRemove); $this->valueRepository->saveMultiple($valuesToUpdate); } } /** * Get Page and PageDuplicate associated to an ExportValue to reset their workflow's current_step * @param array $exportValues * * @return void */ private function cascadeOnPages(array $exportValues): void { // @TODO: Since export_value isn't linked to page (only int) unlike padge duplicate we need to differentiate the manner we get page object : Update data models following the project/cdf/tempate fusion to add object relation instead of int attribute to get page object in the same way $pageToRetrieve = []; foreach ($exportValues as $exportValue) { $pageToRetrieve[] = $exportValue->getFlatplanPageId(); // ONLY THE PAGE NOT DUPLICATE } if (!empty($pageToRetrieve)) { $repository = $this->entityManager->getRepository(Page::class); $pages = $repository->findBy(["id" => $pageToRetrieve]); foreach ($pages as $page) { $this->invalidPageWorkflow($page); foreach ($page->getPageDuplicates() as $duplicate) { $this->invalidPageWorkflow($duplicate); } } // Update Page will cascade update on PageDuplicate $this->pageRepository->saveMultiple($pages); } } /** * Invalid current place for Page and Page Duplicate * @param mixed $page [Can be a Page or a PageDuplicate] * * @return void */ private function invalidPageWorkflow($page): void { $currentPlace = $page->getCurrentPlace(); if ($currentPlace) { if (!isset($this->currentPlaces[$currentPlace])) { $place = $this->workflowCustomRepository->findLowestCurrentPlace($currentPlace); if ($place) { $this->currentPlaces[$currentPlace] = $place; } } else { $place = $this->currentPlaces[$currentPlace]; } $page->setCurrentPlace($place); } } }