entryRepository = $entryRepository; $this->entryFieldRepository = $entryFieldRepository; } /** * Create a new entry and its entry fields. * * @param Entry $entryData * * @return int Entry ID */ public function createEntry(Entry $entryData): int { // Insert entry and get ID return $this->entryRepository->add($entryData); } /** * Add entry fields to the repository. * * @param array $formFields * @param int $entryId * @param array $submissionData * @throws ValidationException */ public function addEntryFields(array $formFields, int $entryId, array $submissionData): void { $parentChildrenMap = $this->buildParentChildrenMap($formFields); $parentSubfieldKeys = $this->buildParentSubfieldKeys($parentChildrenMap, $submissionData); foreach ($formFields as $field) { $value = $this->resolveFieldValue($field, $submissionData, $parentChildrenMap, $parentSubfieldKeys); $entryField = EntryFieldFactory::create([ 'entryId' => $entryId, 'fieldId' => $field->getId(), 'fieldValue' => $value, ]); $this->entryFieldRepository->add($entryField); } } /** * Build parent-children map. * * @param array $formFields * @return array> */ private function buildParentChildrenMap(array $formFields): array { $parentChildrenMap = []; foreach ($formFields as $field) { $parentId = method_exists($field, 'getParentId') ? $field->getParentId() : null; if ($parentId && $parentId > 0) { $parentChildrenMap[$parentId][] = $field->getId(); } } return $parentChildrenMap; } /** * Build subfield key map for each parent. * * @param array> $parentChildrenMap * @param array $submissionData * @return array */ private function buildParentSubfieldKeys(array $parentChildrenMap, array $submissionData): array { $parentSubfieldKeys = []; foreach ($parentChildrenMap as $parentId => $childIds) { $parentValue = $submissionData[$parentId] ?? []; $keys = array_keys($parentValue); foreach ($childIds as $i => $childId) { $parentSubfieldKeys[$childId] = $keys[$i] ?? null; } } return $parentSubfieldKeys; } /** * Resolve the value for a field based on its type and parent/child relationship. * * @param object $field * @param array $submissionData * @param array> $parentChildrenMap * @param array $parentSubfieldKeys * @return mixed */ private function resolveFieldValue( object $field, array $submissionData, array $parentChildrenMap, array $parentSubfieldKeys ) { $fieldId = $field->getId(); $fieldType = $field->getType(); $parentId = method_exists($field, 'getParentId') ? $field->getParentId() : null; $parentValue = $this->getParentSubfieldValue($fieldId, $parentId, $submissionData, $parentSubfieldKeys); if ($parentValue !== null) { return $parentValue; } if (in_array($fieldType, ['name', 'address'], true) && ($parentId === null || $parentId === 0)) { return $this->getCompoundFieldValue($fieldId, $parentChildrenMap, $parentSubfieldKeys, $submissionData); } return $this->getDefaultFieldValue($fieldId, $submissionData); } /** * @param int $fieldId * @param int|null $parentId * @param array $submissionData * @param array $parentSubfieldKeys * @return mixed|null */ private function getParentSubfieldValue( int $fieldId, ?int $parentId, array $submissionData, array $parentSubfieldKeys ) { if ($parentId && isset($parentSubfieldKeys[$fieldId])) { $subKey = $parentSubfieldKeys[$fieldId]; if (isset($submissionData[$parentId][$subKey])) { return $submissionData[$parentId][$subKey]; } } return null; } /** * @param int $fieldId * @param array> $parentChildrenMap * @param array $parentSubfieldKeys * @param array $submissionData * @return string */ private function getCompoundFieldValue( int $fieldId, array $parentChildrenMap, array $parentSubfieldKeys, array $submissionData ): string { $childValues = []; if (!empty($parentChildrenMap[$fieldId])) { foreach ($parentChildrenMap[$fieldId] as $childId) { $subKey = $parentSubfieldKeys[$childId] ?? null; if ($subKey && isset($submissionData[$fieldId][$subKey])) { $val = $submissionData[$fieldId][$subKey]; if ($val !== '') { $childValues[] = $val; } } } } return implode(' ', $childValues); } /** * @param int $fieldId * @param array $submissionData * @return mixed|string */ private function getDefaultFieldValue(int $fieldId, array $submissionData) { return $submissionData[$fieldId] ?? ''; } /** * Get a specific entry by its ID. * * @param int $entryId * * @return object * * @throws NotFoundException If the entry is not found */ public function getEntry(int $entryId): object { $entry = $this->entryRepository->getById($entryId); if (!$entry) { throw new NotFoundException( BackendStrings::getExceptionStrings()['entry_not_found'] ); } return $entry; } /** * Search for entries based on parameters. * * @param array $params * * @return array */ public function searchEntries(array $params): array { return $this->entryRepository->search($params); } /** * Get the count of entry filters. * * @param array|null $params * * @return array */ public function getFilterCount(?array $params = null): array { return $this->entryRepository->getFilterCount($params); } /** * Delete an entry by its ID. * * @param int $id * * @return int */ public function deleteEntry(int $id): int { return $this->entryRepository->delete($id); } /** * Get all entry fields for a specific entry ID. * * @param int $entryId * * @return array */ public function getFieldsByEntryId(int $entryId): array { return $this->entryFieldRepository->findBy(['entryId' => $entryId]); } /** * Update the starred status of an entry. * * @param int $entryId * @param bool $value * * @return void */ public function updateEntryStarred(int $entryId, bool $value): void { $this->entryRepository->updateEntryStarred($entryId, $value); } /** * Update the status of an entry. * * @param int $entryId * @param string $status * * @return void */ public function updateEntryStatus(int $entryId, string $status): void { $this->entryRepository->updateEntryStatus($entryId, $status); } /** * Fetch entries along with their associated fields. * * @param array> $entries * @return array */ public function getEntryFields(array $entries): array { return $this->entryRepository->getEntryFields($entries); } /** * Get the count of entries for multiple form IDs. * * @param int[] $formIds * @return array formId => count */ public function getEntryCountByFormIds(array $formIds): array { return $this->entryRepository->getEntryCountByFormIds($formIds); } /** * Delete all entry fields for multiple entry IDs in bulk. * * @param int[] $entryIds * @return int Number of deleted entry fields */ public function deleteEntryFieldsByEntryIds(array $entryIds): int { if (empty($entryIds)) { return 0; } $allFields = $this->entryFieldRepository->findIdsByEntryIds($entryIds); if (empty($allFields)) { return 0; } return $this->entryFieldRepository->deleteMany($allFields); } /** * Delete multiple entries by their IDs in bulk. * * @param int[] $ids * @return int Number of deleted entries */ public function deleteEntriesByIds(array $ids): int { if (empty($ids)) { return 0; } return $this->entryRepository->deleteMany($ids); } /** * Delete all entries for multiple form IDs in bulk. * * @param int[] $formIds * @return int Number of deleted entries * @throws InvalidArgumentException */ public function deleteEntriesByFormIds(array $formIds): int { if (empty($formIds)) { throw new InvalidArgumentException( BackendStrings::getExceptionStrings()['no_form_ids_provided'] ); } // Delete entry fields by form IDs using a subquery $this->entryFieldRepository->deleteByFormIds($formIds); // Delete entries by formId return $this->entryRepository->deleteManyByForeignKeyValues($formIds); } /** * Check if a value already exists in entry fields for a specific field. * * @param int $formId * @param int $fieldId * @param string $value * @return bool */ public function checkDuplicateValue(int $formId, int $fieldId, string $value): bool { return $this->entryFieldRepository->checkDuplicateValue($formId, $fieldId, $value); } }