acf
This commit is contained in:
		| @ -0,0 +1,457 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * @author          Tassos Marinos <info@tassos.gr> | ||||
|  * @link            https://www.tassos.gr | ||||
|  * @copyright       Copyright © 2024 Tassos All Rights Reserved | ||||
|  * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later | ||||
|  */ | ||||
|  | ||||
| namespace NRFramework\Integrations; | ||||
|  | ||||
| // No direct access | ||||
| defined('_JEXEC') or die; | ||||
|  | ||||
| class ActiveCampaign extends Integration | ||||
| { | ||||
| 	/** | ||||
| 	 * Create a new instance | ||||
| 	 * @param array $options The service's required options | ||||
| 	 */ | ||||
| 	public function __construct($options) | ||||
| 	{ | ||||
| 		parent::__construct(); | ||||
| 		$this->setKey($options); | ||||
| 		$this->setEndpoint($options['endpoint'] . '/api/3'); | ||||
| 		$this->options->set('headers.Api-Token', $this->key); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  Subscribe user to ActiveCampaign List | ||||
| 	 * | ||||
| 	 *  https://developers.activecampaign.com/v3/reference#create-contact | ||||
| 	 * | ||||
| 	 *  @param   string  $email           The Email of the Contact | ||||
| 	 *  @param   string  $name            The name of the Contact (Name can be also declared in Custom Fields) | ||||
| 	 *  @param   string  $list            List ID | ||||
| 	 *  @param   string  $tags            Tags for this contact (comma-separated). Example: "tag1, tag2, etc" | ||||
| 	 *  @param   array   $customfields    Custom Fields | ||||
| 	 *  @param   boolean $updateexisting  Update Existing User | ||||
| 	 * | ||||
| 	 *  @return  void                    | ||||
| 	 */ | ||||
| 	public function subscribe($email, $name, $lists, $tags = '', $customfields = [], $updateexisting = true) | ||||
| 	{ | ||||
| 		// Detect name | ||||
| 		$name = (is_null($name) || empty($name)) ? $this->getNameFromCustomFields($customfields) : explode(' ', $name, 2); | ||||
| 		$apiAction = ($updateexisting) ? 'contact/sync' : 'contacts'; | ||||
|  | ||||
| 		$data = [ | ||||
| 			'contact' => [ | ||||
| 				'email'     => $email, | ||||
| 				'phone'		=> $this->getPhone($customfields), | ||||
| 				'ip4' 		=> \NRFramework\User::getIP() | ||||
| 			], | ||||
| 		]; | ||||
|  | ||||
| 		// Add first and last name only if they are not empty, as ActiveCampaign will empty the fields if they are empty. | ||||
| 		if (isset($name[0]) && $name[0]) | ||||
| 		{ | ||||
| 			$data['contact']['firstName'] = $name[0]; | ||||
| 		} | ||||
| 		if (isset($name[1]) && $name[1]) | ||||
| 		{ | ||||
| 			$data['contact']['lastName'] = $name[1]; | ||||
| 		} | ||||
|  | ||||
| 		$this->post($apiAction, $data); | ||||
|  | ||||
| 		if (!$this->request_successful) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// Retrive the contact's ID | ||||
| 		$contact_id = $this->getContactIDFromResponse(); | ||||
| 		 | ||||
| 		// Add Lists to Contact | ||||
| 		$this->addListsToContact($contact_id, $lists); | ||||
|  | ||||
| 		// Add Tags to Contact | ||||
| 		if (!empty($tags)) | ||||
| 		{ | ||||
| 			$tags = is_array($tags) ? $tags : explode(',', $tags); | ||||
|  | ||||
| 			$tag_ids = $this->convertTagNamesToIDs($tags); | ||||
|  | ||||
| 			if ($tag_ids && !empty($tag_ids)) | ||||
| 			{ | ||||
| 				$this->addTagsToContact($tag_ids, $contact_id); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Add Custom Fields to Contact | ||||
| 		$this->addCustomFieldsToContact($customfields, $contact_id); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the phone number of the contact. | ||||
| 	 *  | ||||
| 	 * @param   array   $customfields | ||||
| 	 *  | ||||
| 	 * @return  string | ||||
| 	 */ | ||||
| 	private function getPhone($customfields) | ||||
| 	{ | ||||
| 		$phone = $this->getCustomFieldValue('phone', $customfields); | ||||
|  | ||||
| 		if (is_string($phone)) | ||||
| 		{ | ||||
| 			return $phone; | ||||
| 		} | ||||
| 	 | ||||
| 		if (isset($phone['code']) && isset($phone['value']) && $phone['value']) | ||||
| 		{ | ||||
| 			$calling_code = \NRFramework\Countries::getCallingCodeByCountryCode($phone['code']); | ||||
| 			$calling_code = $calling_code !== '' ? '+' . $calling_code : ''; | ||||
| 			 | ||||
| 			$phone = $calling_code . $phone['value']; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			$phone = ''; | ||||
| 		} | ||||
|  | ||||
| 		return $phone; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Update Custom Field Values for a Contact | ||||
| 	 *  | ||||
| 	 * API Reference: https://developers.activecampaign.com/v3/reference#fieldvalues | ||||
| 	 * | ||||
| 	 * @param  array   $custom_fields	Array of custom field values | ||||
| 	 * @param  integer $contact_id		The contact's ID | ||||
| 	 * | ||||
| 	 * @return mixed	Null on failure, void on success | ||||
| 	 */ | ||||
| 	private function addCustomFieldsToContact($custom_fields, $contact_id) | ||||
| 	{ | ||||
| 		if (empty($custom_fields)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 		 | ||||
| 		$custom_fields = array_change_key_case($custom_fields); | ||||
|  | ||||
| 		if (!$all_custom_fields = $this->getAllCustomFields()) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		foreach ($custom_fields as $custom_field_key => $custom_field_value) | ||||
| 		{ | ||||
| 			if (empty($custom_field_value)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$custom_field = strtolower(trim($custom_field_key)); | ||||
|  | ||||
| 			if (!array_key_exists($custom_field, $all_custom_fields)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			// Let's add Custom Field to our contact | ||||
| 			$custom_field_data = $all_custom_fields[$custom_field]; | ||||
|  | ||||
| 			// Radio buttons expect a string. Not an array. | ||||
| 			if ($custom_field_data['type'] == 'checkbox' && is_array($custom_field_value)) | ||||
| 			{ | ||||
| 				$custom_field_value = implode('||', $custom_field_value); | ||||
| 				$custom_field_value = '||' . $custom_field_value . '||'; | ||||
| 			} | ||||
|  | ||||
| 			$this->post('fieldValues', [ | ||||
| 				'fieldValue' => [ | ||||
| 					'contact' => $contact_id, | ||||
| 					'field'   => $custom_field_data['id'], | ||||
| 					'value'   => $custom_field_value | ||||
| 				] | ||||
| 			]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Add tags to contact | ||||
| 	 *  | ||||
| 	 * API Reference: https://developers.activecampaign.com/v3/reference#create-contact-tag | ||||
| 	 * | ||||
| 	 * @param array   $tag_ids		Array of tag IDs | ||||
| 	 * @param integer $contact_id	The contact's ID | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	private function addTagsToContact($tag_ids, $contact_id) | ||||
| 	{ | ||||
| 		foreach ($tag_ids as $tag_id) | ||||
| 		{ | ||||
| 			$this->post('contactTags', [ | ||||
| 				'contactTag' => [ | ||||
| 					'contact' => $contact_id, | ||||
| 					'tag'     => $tag_id, | ||||
| 				] | ||||
| 			]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Convert a list of tag names to tag IDs | ||||
| 	 * | ||||
| 	 * @param  array $tags	Array ot tag names | ||||
| 	 * | ||||
| 	 * @return mixed	Null on failure, assosiative tag name-based array on success. | ||||
| 	 */ | ||||
| 	private function convertTagNamesToIDs($tags) | ||||
| 	{ | ||||
| 		if (!$account_tags = $this->getAllTags()) | ||||
| 		{ | ||||
| 			return;  | ||||
| 		} | ||||
|  | ||||
| 		$account_tags = array_map('strtolower', $account_tags); | ||||
|  | ||||
| 		$tag_ids = []; | ||||
| 		 | ||||
| 		foreach ($tags as $tag) | ||||
| 		{ | ||||
| 			if (empty($tag)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$tag = strtolower(trim($tag)); | ||||
|  | ||||
| 			if (!$tag_id = array_search($tag, $account_tags)) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$tag_ids[] = $tag_id; | ||||
| 		} | ||||
|  | ||||
| 		return $tag_ids; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Retrieve all contact-based tags | ||||
| 	 *  | ||||
| 	 * API Reference: https://developers.activecampaign.com/v3/reference#list-all-tasks | ||||
| 	 * | ||||
| 	 * @return mixed	Null on failure, assosiative array on success | ||||
| 	 */ | ||||
| 	private function getAllTags() | ||||
| 	{ | ||||
| 		$tags = $this->get('tags'); | ||||
|  | ||||
| 		if (!$tags || !is_array($tags) || !isset($tags['tags'])) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$tags_ = []; | ||||
|  | ||||
| 		foreach ($tags['tags'] as $tag) | ||||
| 		{ | ||||
| 			if ($tag['tagType'] != 'contact') | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$tags_[$tag['id']] = $tag['tag']; | ||||
| 		} | ||||
|  | ||||
| 		return $tags_; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Add lists to contact | ||||
| 	 * | ||||
| 	 * @param  integer $contact_id	The Active Campaign Contact ID | ||||
| 	 * @param  mixed   $lists		The list ID to add the contact to. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	private function addListsToContact($contact_id, $lists) | ||||
| 	{ | ||||
| 		$lists = is_array($lists) ? $lists : explode(',', $lists); | ||||
|  | ||||
| 		foreach ($lists as $list) | ||||
| 		{ | ||||
| 			$this->post('contactLists', [ | ||||
| 				'contactList' => [ | ||||
| 					'list' => $list, | ||||
| 					'contact' => $contact_id, | ||||
| 					'status' => 1 | ||||
| 				] | ||||
| 			]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Determine the newly created contact's ID | ||||
| 	 * | ||||
| 	 * @return string | ||||
| 	 */ | ||||
| 	private function getContactIDFromResponse()  | ||||
| 	{ | ||||
| 		$response = $this->last_response; | ||||
|  | ||||
| 		if (isset($response->body) && isset($response->body['contact']) && isset($response->body['contact']['id'])) | ||||
| 		{ | ||||
| 			return $response->body['contact']['id']; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Search for First Name and Last Name in Custom Fields and return an array with both values. | ||||
| 	 * | ||||
| 	 * @param	array	$customfields	The Custom Fields array passed by the user. | ||||
| 	 * | ||||
| 	 * @return	array | ||||
| 	 */ | ||||
| 	private function getNameFromCustomFields($customfields) | ||||
| 	{ | ||||
| 		return [ | ||||
| 			(string) $this->getCustomFieldValue(['first_name', 'First Name'], $customfields), | ||||
| 			(string) $this->getCustomFieldValue(['last_name', 'Last Name'], $customfields) | ||||
| 		]; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  Retrieve all account lists | ||||
| 	 *   | ||||
| 	 *  API Reference: https://developers.activecampaign.com/v3/reference#retrieve-all-lists | ||||
| 	 *   | ||||
| 	 *  @return  mixed  Null on failure, Array on success | ||||
| 	 */ | ||||
| 	public function getLists() | ||||
| 	{ | ||||
| 		$data = $this->get('lists'); | ||||
|  | ||||
| 		if (!$data || !isset($data['lists']) || count($data['lists']) == 0) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$lists = []; | ||||
|  | ||||
| 		foreach ($data['lists'] as $list) | ||||
| 		{ | ||||
| 			$lists[] = [ | ||||
| 				'id'   => $list['id'], | ||||
| 				'name' => $list['name'] | ||||
| 			]; | ||||
| 		} | ||||
|  | ||||
| 		return $lists; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  Get the last error returned by either the network transport, or by the API. | ||||
| 	 *  | ||||
| 	 *  API Reference: https://developers.activecampaign.com/v3/reference#errors | ||||
| 	 * | ||||
| 	 *  @return  string | ||||
| 	 */ | ||||
| 	public function getLastError() | ||||
| 	{ | ||||
| 		$error_code = $this->last_response->code; | ||||
| 		$error_message = 'Active Campaign Error'; | ||||
|  | ||||
| 		switch ((int) $error_code) | ||||
| 		{ | ||||
| 			case 403: | ||||
| 				$error_message = 'The request could not be authenticated or the authenticated user is not authorized to access the requested resource.'; | ||||
| 				break; | ||||
| 			case 404: | ||||
| 				$error_message = 'The requested resource does not exist.'; | ||||
| 				break; | ||||
| 			case 422: | ||||
| 				$error_message = 'The request could not be processed, usually due to a missing or invalid parameter.'; | ||||
|  | ||||
| 				if (isset($this->last_response->body['errors']) && isset($this->last_response->body['errors'][0])) | ||||
| 				{ | ||||
| 					$error_message = $this->last_response->body['errors'][0]['title']; | ||||
| 				} | ||||
|  | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| 		return $error_message; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  Returns the Active Campaign Account's Custom Fields | ||||
| 	 * | ||||
| 	 *  API Reference: https://developers.activecampaign.com/v3/reference#retrieve-fields-1 | ||||
| 	 * | ||||
| 	 *  @return  array | ||||
| 	 */ | ||||
| 	public function getAllCustomFields() | ||||
| 	{ | ||||
| 		$fields = $this->get('fields'); | ||||
|  | ||||
| 		if (!$fields || !isset($fields['fields']))  | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		// Make our life easier by creating a title-based assosiative array  | ||||
| 		$f = []; | ||||
|  | ||||
| 		foreach ($fields['fields'] as $key => $field) | ||||
| 		{ | ||||
| 			if (!$field || !isset($field['title'])) | ||||
| 			{ | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			$key = strtolower(trim($field['title'])); | ||||
|  | ||||
| 			$f[$key] = $field; | ||||
| 		} | ||||
|  | ||||
| 		return $f; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Make an HTTP GET request for retrieving data. | ||||
| 	 *  | ||||
| 	 * ActiveCampaign has a limit of max 100 results per page. | ||||
| 	 * https://developers.activecampaign.com/reference#pagination | ||||
| 	 *  | ||||
| 	 * @param   string 		  $method URL of the API request method | ||||
| 	 * @param   array		  $args Assoc array of arguments (usually your data) | ||||
| 	 *  | ||||
| 	 * @return  array|false   Assoc array of API response, decoded from JSON | ||||
| 	 */ | ||||
| 	public function get($method, $args = array()) | ||||
| 	{ | ||||
| 		$args['limit']  = isset($args['limit']) ? $args['limit'] : 100; | ||||
| 		$args['offset'] = isset($args['offset']) ? $args['offset'] : 0; | ||||
|  | ||||
| 		$response = parent::get($method, $args); | ||||
|  | ||||
| 		if ($args['offset'] < (int) $response['meta']['total']) | ||||
| 		{ | ||||
| 			$args['offset'] += $args['limit']; | ||||
| 			$response_next = $this->get($method, $args); | ||||
| 			$response[$method] = array_merge($response[$method], $response_next[$method]); | ||||
| 		} | ||||
|  | ||||
| 		return $response; | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user