queryBuilder = $queryBuilder; $this->acl = $acl; $this->recordServiceContainer = $recordServiceContainer; $this->entityManager = $entityManager; $this->fieldUtil = $fieldUtil; $this->user = $user; } public function process(Params $params, Data $data): Result { $entityType = $params->getEntityType(); if (!$this->acl->check($entityType, 'edit')) { throw new Forbidden("No edit access for '{$entityType}'."); } if ($this->acl->get('massUpdatePermission') !== 'yes') { throw new Forbidden("No mass-update permission."); } $valueMap = $data->getRaw(); $service = $this->recordServiceContainer->get($entityType); $repository = $this->entityManager->getRDBRepository($entityType); $service->filterUpdateInput($valueMap); $fieldToCopyList = $this->detectFieldToCopyList($entityType, $valueMap); $query = $this->queryBuilder->build($params); $collection = $repository ->clone($query) ->sth() ->find(); $ids = []; $count = 0; foreach ($collection as $i => $entity) { if (!$this->acl->check($entity, 'edit')) { continue; } $itemValueMap = $this->prepareItemValueMap($entityType, $valueMap, $i, $fieldToCopyList); $entity->set($itemValueMap); try { $service->processValidation($entity, $itemValueMap); } catch (Exception $e) { continue; } if (!$service->checkAssignment($entity)) { continue; } $repository->save($entity, [ 'massUpdate' => true, 'skipStreamNotesAcl' => true, 'modifiedById' => $this->user->getId(), ]); $ids[] = $entity->getId(); $count++; $service->processActionHistoryRecord('update', $entity); } $result = [ 'count' => $count, 'ids' => $ids, ]; return Result::fromArray($result); } protected function prepareItemValueMap( string $entityType, stdClass $valueMap, int $i, array $fieldToCopyList ): stdClass { $clonedValueMap = ObjectUtil::clone($valueMap); if (!count($fieldToCopyList)) { return $clonedValueMap; } if ($i === 0) { return $clonedValueMap; } foreach ($fieldToCopyList as $field) { $type = $this->fieldUtil->getEntityTypeFieldParam($entityType, $field, 'type'); if ($type === 'file' || $type === 'image') { $this->copyFileField($field, $clonedValueMap); continue; } if ($type === 'attachmentMultiple') { $this->copyAttachmentMultipleField($field, $clonedValueMap); continue; } } return $clonedValueMap; } protected function copyFileField(string $field, stdClass $valueMap): void { $idAttribute = $field . 'Id'; $id = $valueMap->$idAttribute ?? null; if (!$id) { return; } $attachment = $this->entityManager->getEntity('Attachment', $id); if (!$attachment) { $valueMap->$idAttribute = null; return; } /** @var AttachmentRepository $attachmentRepository */ $attachmentRepository = $this->entityManager->getRepository('Attachment'); $copiedAttachment = $attachmentRepository->getCopiedAttachment($attachment); $valueMap->$idAttribute = $copiedAttachment->getId(); } protected function copyAttachmentMultipleField(string $field, stdClass $valueMap): void { $idsAttribute = $field . 'Ids'; $ids = $valueMap->$idsAttribute ?? []; if (!count($ids)) { return; } /** @var AttachmentRepository $attachmentRepository */ $attachmentRepository = $this->entityManager->getRepository('Attachment'); $copiedIds = []; foreach ($ids as $id) { $attachment = $this->entityManager->getEntity('Attachment', $id); if (!$attachment) { continue; } $copiedAttachment = $attachmentRepository->getCopiedAttachment($attachment); $copiedIds[] = $copiedAttachment->getId(); } $valueMap->$idsAttribute = $copiedIds; } protected function detectFieldToCopyList(string $entityType, stdClass $valueMap): array { $resultFieldList = []; $fieldList = array_merge( $this->fieldUtil->getFieldByTypeList($entityType, 'file'), $this->fieldUtil->getFieldByTypeList($entityType, 'image'), $this->fieldUtil->getFieldByTypeList($entityType, 'attachmentMultiple') ); foreach ($fieldList as $field) { $actualAttributeList = $this->fieldUtil->getActualAttributeList($entityType, $field); $met = false; foreach ($actualAttributeList as $attribute) { $value = $valueMap->$attribute ?? null; if ($value) { $met = true; } } if ($met) { $resultFieldList[] = $field; } } return $resultFieldList; } }