$data Customer data. * @return Customer * * @throws DomainException When invariants fail. */ public function create( array $data ): Customer { $now = $this->clock->now(); $customer = new Customer( null, Uuid::generate(), isset( $data['wp_user_id'] ) ? (int) $data['wp_user_id'] : null, trim( (string) ( $data['first_name'] ?? '' ) ), isset( $data['last_name'] ) ? trim( (string) $data['last_name'] ) : null, new EmailAddress( trim( (string) ( $data['email'] ?? '' ) ) ), null, isset( $data['phone'] ) && '' !== trim( (string) $data['phone'] ) ? new PhoneNumber( trim( (string) $data['phone'] ) ) : null, null, isset( $data['timezone'] ) && '' !== trim( (string) $data['timezone'] ) ? new TimeZoneId( trim( (string) $data['timezone'] ) ) : null, isset( $data['locale'] ) ? trim( (string) $data['locale'] ) : null, isset( $data['notes'] ) ? trim( (string) $data['notes'] ) : null, (bool) ( $data['marketing_consent'] ?? false ), isset( $data['marketing_consent'] ) && $data['marketing_consent'] ? $now : null, CustomerStatus::Active, null, $now, $now, ); $this->customers->save( $customer ); if ( null !== $this->bus && null !== $customer->id() ) { $this->bus->dispatch( new CustomerCreated( (int) $customer->id(), $now ) ); } return $customer; } /** * Update an existing customer. * * @param int $id Customer id. * @param array $data Customer data. * @return Customer * * @throws DomainException When the customer is missing or invariants fail. */ public function update( int $id, array $data ): Customer { $customer = $this->customers->find_by_id( $id ); if ( null === $customer ) { throw new DomainException( 'customer.not_found', 'Customer not found.' ); } $now = $this->clock->now(); $marketing_consent = array_key_exists( 'marketing_consent', $data ) ? (bool) $data['marketing_consent'] : $customer->marketing_consent(); $updated = new Customer( $customer->id(), $customer->uuid(), array_key_exists( 'wp_user_id', $data ) ? ( null !== $data['wp_user_id'] ? (int) $data['wp_user_id'] : null ) : $customer->wp_user_id(), array_key_exists( 'first_name', $data ) ? trim( (string) $data['first_name'] ) : $customer->first_name(), array_key_exists( 'last_name', $data ) ? ( null !== $data['last_name'] ? trim( (string) $data['last_name'] ) : null ) : $customer->last_name(), array_key_exists( 'email', $data ) ? new EmailAddress( trim( (string) $data['email'] ) ) : $customer->email(), $customer->email_verified_at(), array_key_exists( 'phone', $data ) ? ( null !== $data['phone'] && '' !== trim( (string) $data['phone'] ) ? new PhoneNumber( trim( (string) $data['phone'] ) ) : null ) : $customer->phone(), $customer->phone_verified_at(), array_key_exists( 'timezone', $data ) ? ( null !== $data['timezone'] ? new TimeZoneId( trim( (string) $data['timezone'] ) ) : null ) : $customer->timezone(), array_key_exists( 'locale', $data ) ? trim( (string) $data['locale'] ) : $customer->locale(), array_key_exists( 'notes', $data ) ? trim( (string) $data['notes'] ) : $customer->notes(), $marketing_consent, $marketing_consent && null === $customer->consent_recorded_at() ? $now : $customer->consent_recorded_at(), array_key_exists( 'status', $data ) ? CustomerStatus::from( (string) $data['status'] ) : $customer->status(), $customer->meta(), $customer->created_at(), $now, ); $this->customers->save( $updated ); return $updated; } /** * Delete a customer (soft delete). * * @param int $id Customer id. * * @throws DomainException When the customer is missing. */ public function delete( int $id ): void { $customer = $this->customers->find_by_id( $id ); if ( null === $customer ) { throw new DomainException( 'customer.not_found', 'Customer not found.' ); } $this->customers->soft_delete( $customer, $this->clock->now() ); } }