query( "DELETE FROM `" . BIT_DB_PREFIX . "liberty_xref` WHERE `content_id` = ? AND `item` = ?", [ $contentId, $item ] ); if( $xkey !== '' || $xkeyExt !== '' ) { $gBitDb->associateInsert( BIT_DB_PREFIX . 'liberty_xref', [ 'xref_id' => $gBitDb->GenID( 'liberty_xref_seq' ), 'content_id' => $contentId, 'item' => $item, 'xorder' => $xorder, 'xkey' => $xkey !== '' ? substr( $xkey, 0, 32 ) : null, 'xkey_ext' => $xkeyExt !== '' ? substr( $xkeyExt, 0, 250 ) : null, 'last_update_date' => $gBitDb->NOW(), ] ); } } /** * Import or update a single contact from a CSV row. * * Looks up the contact by lc.title; creates a new record if not found. * Calls Contact::store() then upserts all xref items (SCREF, #P, #C, #F, #W, #E, ACCNO). * 10-digit all-digit phone/fax values have a leading zero prepended (Excel strips it). * * @param array $row 0-based column values; see file header for column layout. * @param int $rowNum 1-based row number used in error messages. * @return array{loaded:int, updated:int, skipped:int, errors:string[]} */ function contactCsvImportRow( array $row, int $rowNum ): array { global $gBitDb; $result = [ 'loaded' => 0, 'updated' => 0, 'skipped' => 0, 'errors' => [] ]; $title = trim( $row[0] ?? '' ); $type = trim( $row[1] ?? '' ); $personName = trim( $row[2] ?? '' ); $scref = trim( $row[3] ?? '' ); $phone = trim( $row[4] ?? '' ); // Restore leading zero stripped by Excel on 10-digit UK numbers if( strlen( $phone ) === 10 && ctype_digit( $phone ) ) { $phone = '0' . $phone; } $address = trim( $row[5] ?? '' ); $postcode = trim( $row[6] ?? '' ); $fax = trim( $row[7] ?? '' ); if( strlen( $fax ) === 10 && ctype_digit( $fax ) ) { $fax = '0' . $fax; } $website = trim( $row[8] ?? '' ); $email = trim( $row[9] ?? '' ); $accno = trim( $row[10] ?? '' ); if( empty( $title ) ) { $result['skipped']++; return $result; } // --- Find existing or create new via Contact subclass --- $isPerson = ( $type === '$00' ); $contentId = $gBitDb->getOne( "SELECT `content_id` FROM `" . BIT_DB_PREFIX . "liberty_content` WHERE `content_type_guid` IN ('contactperson','contactbusiness','contact') AND `title` = ?", [ $title ] ); $contact = $isPerson ? new ContactPerson( null, $contentId ?: null ) : new ContactBusiness( null, $contentId ?: null ); if( $contentId ) { $contact->load(); } $pHash = [ 'title' => $title, 'edit' => '', 'format_guid' => 'bithtml', ]; if( $contentId ) { $pHash['content_id'] = $contentId; } if( !empty( $type ) && $type[0] === '$' ) { $pHash['contact_types'] = [ $type ]; if( $isPerson ) { $pHash['name'] = $personName; } } if( !$contact->store( $pHash ) ) { $result['skipped']++; $result['errors'][] = "Row $rowNum: failed to store '$title': " . implode( ', ', $contact->mErrors ?? [] ); return $result; } $contentId ? $result['updated']++ : $result['loaded']++; $contentId = $contact->mContentId; // --- Remaining xref items --- contactCsvUpsertXref( $contentId, 'SCREF', $scref ); contactCsvUpsertXref( $contentId, '#P', $phone, '', 1 ); contactCsvUpsertXref( $contentId, '#C', $postcode, $address ); contactCsvUpsertXref( $contentId, '#F', $fax, '', 1 ); contactCsvUpsertXref( $contentId, '#W', '', $website ); contactCsvUpsertXref( $contentId, '#E', '', $email ); contactCsvUpsertXref( $contentId, 'ACCNO', $accno ); return $result; }