null,'external_customer_label'=>null,'external_contact_snapshot'=>null]; $save=CatalogValidator::boolean($input['save_external_contact']??false,'save_external_contact'); if(BookingCustomerService::type($customer)!=='external'){ foreach(self::FIELDS as $field)if($field!=='save_external_contact'&&isset($input[$field])&&$input[$field]!=='')CatalogValidator::invalid($field,__('External contact fields are only valid for external bookings.','abece-booking')); if($save)CatalogValidator::invalid('save_external_contact',__('External contact fields are only valid for external bookings.','abece-booking'));return $empty; } $old=($booking&&BookingCustomerService::type($booking)==='external')?$booking:null; $id=CatalogValidator::integer(array_key_exists('external_contact_id',$input)?$input['external_contact_id']:($old['external_contact_id']??null),'external_contact_id',1,PHP_INT_MAX,true); $same=$old&&$id===$old['external_contact_id'];$snapshot=$same?json_decode($old['external_contact_snapshot']??'null',true):null; $contact=null; if($id&&!$same){$contact=$persist?$this->contacts->lock($id):$this->contacts->find($id);if(!$contact||!$contact['is_active'])throw new CatalogException('abece_booking_external_contact_unavailable',__('Select an active external contact.','abece-booking'),400,'external_contact_id');} $label=MembershipValidator::text(array_key_exists('external_customer_label',$input)?$input['external_customer_label']:($same?$old['external_customer_label']:($contact['display_name']??null)),'external_customer_label',190,true); $phone=MembershipValidator::text($input['external_phone']??($snapshot['phone']??$contact['phone']??null),'external_phone',50,true); $email=ExternalContactsService::email($input['external_email']??($snapshot['email']??$contact['email']??null)); // Explicit null values clear contact details rather than falling back to a snapshot. if(array_key_exists('external_phone',$input))$phone=MembershipValidator::text($input['external_phone'],'external_phone',50,true); if(array_key_exists('external_email',$input))$email=ExternalContactsService::email($input['external_email']); if(!$label){if($same&&!array_intersect(self::FIELDS,array_keys($input)))return array_intersect_key($old,$empty);CatalogValidator::invalid('external_customer_label',__('Enter the external customer name or booking label.','abece-booking'));} if($save&&$id)CatalogValidator::invalid('save_external_contact',__('The selected contact is already saved.','abece-booking')); if($save&&$persist){$contact=$this->directory->save(['display_name'=>$label,'phone'=>$phone,'email'=>$email]);$id=$contact['id'];} $data=['external_contact_id'=>$id,'external_customer_label'=>$label,'external_contact_snapshot'=>wp_json_encode(['display_name'=>$label,'phone'=>$phone,'email'=>$email])]; if($same&&$label===$old['external_customer_label']&&$phone===($snapshot['phone']??null)&&$email===($snapshot['email']??null))$data['external_contact_snapshot']=$old['external_contact_snapshot']; return $data; } public function used(?int $id): void {if($id)$this->contacts->used($id);} }