HEX
Server: Apache/2.4.68 (Debian)
System: Linux as-cs-widget-demo-us-central1 6.1.0-44-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.164-1 (2026-03-09) x86_64
User: root (0)
PHP: 8.2.32
Disabled: NONE
Upload Files
File: /var/www/kevin-demo/wp-content/plugins/wpforms-sendinblue/src/Provider/Actions/SubscribeAction.php
<?php

namespace WPFormsSendinblue\Provider\Actions;

use WPFormsSendinblue\Api\Http\Response;
use WPFormsSendinblue\Api\Exceptions\ResponseException;
use WPFormsSendinblue\Api\Exceptions\RequiredArgumentMissingException;

/**
 * Class SubscribeAction.
 *
 * @since 1.0.0
 */
class SubscribeAction extends Action {

	/**
	 * Run action.
	 *
	 * @since 1.0.0
	 * @since 1.1.0 Added an opt-in subscribe.
	 *
	 * @throws ResponseException Invalid response.
	 * @throws RequiredArgumentMissingException Required argument is missing.
	 */
	public function run() {

		if ( ! empty( $this->connection_data['fields_required']['opt_in']['value'] ) ) {
			$this->opt_in_subscribe();

			return;
		}

		$this->subscribe();
	}

	/**
	 * Process default subscription process.
	 *
	 * @since 1.1.0
	 *
	 * @throws ResponseException Invalid response.
	 * @throws RequiredArgumentMissingException Required argument is missing.
	 */
	private function subscribe() {

		$this->update_contact_information();
		$this->update_contact_email();
	}

	/**
	 * Process opt-in subscription process.
	 *
	 * @since 1.1.0
	 *
	 * @throws ResponseException Invalid response.
	 * @throws RequiredArgumentMissingException Required argument is missing.
	 * phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
	 */
	private function opt_in_subscribe() {

		$email        = sanitize_email( $this->field_mapper->get_field_value_by_id( $this->field_mapper->get_required_field_value( 'email', 'field_id' ) ) );
		$list_id      = absint( $this->field_mapper->get_required_field_value( 'list', 'list_id' ) );
		$redirect_url = ! empty( $this->connection_data['fields_required']['redirect_url']['value'] ) ? $this->connection_data['fields_required']['redirect_url']['value'] : '';
		$template_id  = ! empty( $this->connection_data['fields_required']['template_id']['list_id'] ) ? $this->connection_data['fields_required']['template_id']['list_id'] : 0;
		$attributes   = $this->map_custom_fields();

		$response = $this->create_opt_in_contact( $email, $list_id, $template_id, $redirect_url, $attributes );

		if ( $this->is_invalid_phone( $response ) ) {
			unset( $attributes['SMS'] );
			$response = $this->create_opt_in_contact( $email, $list_id, $template_id, $redirect_url, $attributes );
		}

		if ( $response->has_errors() ) {
			throw new ResponseException( esc_html( $response->get_response_message() ) );
		}
	}

	/**
	 * Update contact information.
	 *
	 * @since 1.0.0
	 *
	 * @throws ResponseException Invalid response.
	 * @throws RequiredArgumentMissingException Required argument is missing.
	 */
	private function update_contact_information() {

		$email = sanitize_email( $this->field_mapper->get_field_value_by_id( $this->field_mapper->get_required_field_value( 'email', 'field_id' ) ) );

		if ( ! $email ) {
			throw new RequiredArgumentMissingException( 'email' );
		}

		$list_id    = absint( $this->field_mapper->get_required_field_value( 'list', 'list_id' ) );
		$attributes = $this->map_custom_fields();
		$response   = $this->create_contact( $email, $list_id, $attributes );

		if ( $this->is_invalid_phone( $response ) ) {
			unset( $attributes['SMS'] );
			$response = $this->create_contact( $email, $list_id, $attributes );
		}

		if ( $response->has_errors() ) {
			throw new ResponseException( esc_html( $response->get_response_message() ) );
		}
	}

	/**
	 * Is invalid phone response.
	 *
	 * @since 1.0.0
	 *
	 * @param Response $response Response from API.
	 *
	 * @return bool
	 */
	private function is_invalid_phone( $response ) {

		$body = $response->get_body();

		return ! empty( $body['code'] ) && ! empty( $body['message'] ) && $body['code'] === 'invalid_parameter' && $body['message'] === 'Invalid phone number';
	}

	/**
	 * Create a contact.
	 *
	 * @since 1.0.0
	 *
	 * @param string $email      Contact's email.
	 * @param int    $list_id    List ID for contact.
	 * @param array  $attributes List of attributes.
	 *
	 * @return Response
	 */
	private function create_contact( $email, $list_id, $attributes ) {

		return $this->connection->create_contact(
			$email,
			$list_id,
			$attributes
		);
	}

	/**
	 * Create DOI contact.
	 *
	 * @since 1.0.0
	 *
	 * @param string $email        Contact's email.
	 * @param int    $list_id      List ID for contact.
	 * @param int    $template_id  Email template ID.
	 * @param string $redirect_url Redirect URL for an opt-in button.
	 * @param array  $attributes   List of attributes.
	 *
	 * @return Response
	 */
	private function create_opt_in_contact( $email, $list_id, $template_id, $redirect_url, $attributes ) {

		return $this->connection->create_opt_in_contact(
			$email,
			$list_id,
			$template_id,
			$redirect_url,
			$attributes
		);
	}

	/**
	 * Update contact email.
	 *
	 * @since 1.0.0
	 *
	 * @throws ResponseException Invalid response.
	 * @throws RequiredArgumentMissingException Required argument is missing.
	 * phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
	 */
	private function update_contact_email() {

		$new_email_id = $this->field_mapper->get_not_required_field_value( 'new_email', 'field_id' );

		if ( wpforms_is_empty_string( $new_email_id ) ) {
			return;
		}

		$new_email = sanitize_email( $this->field_mapper->get_field_value_by_id( $new_email_id ) );
		$email     = sanitize_email( $this->field_mapper->get_field_value_by_id( $this->field_mapper->get_required_field_value( 'email', 'field_id' ) ) );

		if ( empty( $new_email ) || empty( $email ) || $new_email === $email ) {
			return;
		}

		$response = $this->connection->rename_contact(
			$email,
			$new_email
		);

		if ( $response->has_errors() ) {
			// This exception will be thrown if the contact with a new email already exists.
			// So rename will be skipped and logged.
			throw new ResponseException( esc_html( $response->get_response_message() ) );
		}
	}

	/**
	 * Get list of registered attributes in Sendinblue service.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	private function get_attributes() {

		$attributes = $this->connection->get_attributes();

		if ( ! array_key_exists( 'attributes', $attributes->get_body() ) ) {
			return [];
		}

		$attributes = $attributes->get_body()['attributes'];

		foreach ( $attributes as $key => $attribute ) {
			$attributes[ $attribute['name'] ] = $attribute;

			unset( $attributes[ $key ] );
		}

		return $attributes;
	}

	/**
	 * Map Sendinblue attributes and form fields.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	private function map_custom_fields() {

		if ( empty( $this->connection_data['fields_meta'] ) ) {
			return [];
		}

		$custom_fields = [];
		$attributes    = $this->get_attributes();

		foreach ( $this->connection_data['fields_meta'] as $field ) {

			if ( ! isset( $field['name'] ) ) {
				continue;
			}

			$field_id = $this->field_mapper->get_custom_field_value( $field['name'] );

			if ( wpforms_is_empty_string( $field_id ) ) {
				continue;
			}

			$value = $this->field_mapper->get_formatted_field_value_by_id( $field_id, $attributes[ $field['name'] ] );

			if ( $value === null || wpforms_is_empty_string( $value ) ) {
				continue;
			}

			$custom_fields[ $field['name'] ] = $value;
		}

		return $custom_fields;
	}
}