diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..4107895 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: PHP Standards +run-name: PHP Standards 🔀 ${{ github.ref_name }} + +on: push + +jobs: + Lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Install dependencies + run: | + composer install --prefer-dist --no-progress + + - name: Lint PHP files + run: ./lint.sh check diff --git a/composer.lock b/composer.lock index bed8850..15e1992 100644 --- a/composer.lock +++ b/composer.lock @@ -253,16 +253,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.8.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7" + "reference": "14f5fff1e64118595db5408e946f3a22c75807f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5805f7a4e4958dbb5e944ef1e6edae0a303765e7", - "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/14f5fff1e64118595db5408e946f3a22c75807f7", + "reference": "14f5fff1e64118595db5408e946f3a22c75807f7", "shasum": "" }, "require": { @@ -272,11 +272,11 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "bin/phpcs", - "bin/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", "extra": { @@ -329,7 +329,7 @@ "type": "open_collective" } ], - "time": "2023-12-08T12:32:31+00:00" + "time": "2024-01-11T20:47:48+00:00" }, { "name": "wp-coding-standards/wpcs", diff --git a/omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php b/omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php index dedcb15..0b7507a 100644 --- a/omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php +++ b/omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php @@ -2,7 +2,7 @@ /** * Plugin Name: Omnisend for Gravity Forms Add-On * Description: A gravity forms add-on to sync contacts with Omnisend. In collaboration with Omnisnnd for WooCommerce plugin it enables better customer tracking - * Version: 1.0.4 + * Version: 1.1.0 * Author: Omnisend * Author URI: https://www.omnisend.com * Developer: Omnisend @@ -20,7 +20,8 @@ exit; } -define( 'OMNISEND_GRAVITY_ADDON_VERSION', '1.0.4' ); +const OMNISEND_GRAVITY_ADDON_NAME = 'Omnisend for Gravity Forms Add-On'; +const OMNISEND_GRAVITY_ADDON_VERSION = '1.0.4'; add_action( 'gform_loaded', array( 'Omnisend_AddOn_Bootstrap', 'load' ), 5 ); diff --git a/omnisend-for-gravity-forms/class-omnisendaddon.php b/omnisend-for-gravity-forms/class-omnisendaddon.php index 358f226..b8ba1b5 100644 --- a/omnisend-for-gravity-forms/class-omnisendaddon.php +++ b/omnisend-for-gravity-forms/class-omnisendaddon.php @@ -5,6 +5,8 @@ * @package OmnisendGravityFormsPlugin */ +use Omnisend\Public\V1\Contact; + if ( ! defined( 'ABSPATH' ) ) { exit; } @@ -13,31 +15,41 @@ class OmnisendAddOn extends GFAddOn { - protected $_version = OMNISEND_GRAVITY_ADDON_VERSION; - protected $_min_gravityforms_version = '1.9'; - protected $_slug = 'omnisend-for-gravity-forms-add-on'; - protected $_path = 'omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php'; - protected $_full_path = __FILE__; - protected $_title = 'Omnisend for Gravity Forms'; - protected $_short_title = 'Omnisend'; + protected $_version = OMNISEND_GRAVITY_ADDON_VERSION; // phpcs:ignore + protected $_min_gravityforms_version = '1.9'; // phpcs:ignore + protected $_slug = 'omnisend-for-gravity-forms-add-on'; // phpcs:ignore + protected $_path = 'omnisend-for-gravity-forms/class-omnisend-addon-bootstrap.php'; // phpcs:ignore + protected $_full_path = __FILE__; // phpcs:ignore + protected $_title = 'Omnisend for Gravity Forms'; // phpcs:ignore + protected $_short_title = 'Omnisend'; // phpcs:ignore - private static $_instance = null; + private static $_instance = null; // phpcs:ignore public function minimum_requirements() { return array( 'plugins' => array( - 'omnisend-connect/omnisend-woocommerce.php', + 'omnisend/class-omnisend-core-bootstrap.php' => 'Email Marketing by Omnisend', ), - array( $this, 'omnisend_api_key_existence' ), + array( $this, 'omnisend_custom_requirement_callback' ), ); } - public function omnisend_api_key_existence( $meets_requirements ) { - $api_key = get_option( 'omnisend_api_key', null ); - if ( is_null( $api_key ) ) { + public function omnisend_custom_requirement_callback( $meets_requirements ) { + + if ( ! is_plugin_active( 'omnisend/class-omnisend-core-bootstrap.php' ) ) { + return $meets_requirements; + } + + if ( ! class_exists( 'Omnisend\Public\V1\Omnisend' ) ) { + $meets_requirements['meets_requirements'] = false; + $meets_requirements['errors'][] = 'Your Email Marketing by Omnisend is not up to date. Please update plugins'; + return $meets_requirements; + } + + if ( ! Omnisend\Public\V1\Omnisend::is_connected() ) { $meets_requirements['meets_requirements'] = false; - $meets_requirements['errors'][] = 'Your Email Marketing for WooCommerce by Omnisend is not configured properly. Please configure it firstly'; + $meets_requirements['errors'][] = 'Your Email Marketing by Omnisend is not configured properly. Please configure it firstly'; } return $meets_requirements; } @@ -253,21 +265,13 @@ public function form_settings_fields( $form ) { * @param array $form The form currently being processed. */ public function after_submission( $entry, $form ) { - if ( ! is_plugin_active( 'omnisend-connect/omnisend-woocommerce.php' ) ) { + if ( ! class_exists( 'Omnisend\Public\V1\Omnisend' ) ) { return; } try { - $settings = $this->get_form_settings( $form ); - $email_consent = 'nonSubscribed'; - $phone_consent = 'nonSubscribed'; - - $consent_object = array( - 'source' => 'gravity-forms', - 'createdAt' => gmdate( 'c' ), - 'ip' => $entry['ip'], - 'userAgent' => $entry['user_agent'], - ); + $contact = new Contact(); + $settings = $this->get_form_settings( $form ); $fields_to_process = array( 'email', @@ -284,23 +288,25 @@ public function after_submission( $entry, $form ) { 'phone_consent', ); - $email = ''; - $phone_number = ''; - $postal_code = ''; - $address = ''; - $country = ''; - $city = ''; - $state = ''; - $first_name = ''; - $last_name = ''; - $birthday = ''; + $email = ''; + $phone_number = ''; + $postal_code = ''; + $address = ''; + $country = ''; + $city = ''; + $state = ''; + $first_name = ''; + $last_name = ''; + $birthday = ''; + $email_consent = false; + $phone_consent = false; foreach ( $fields_to_process as $field ) { if ( isset( $settings[ $field ] ) && $settings[ $field ] != '-1' ) { if ( in_array( $field, array( 'email_consent', 'phone_consent' ) ) ) { if ( $entry[ $settings[ $field ] ] == '1' ) { - ${$field} = 'subscribed'; + ${$field} = true; } } else { ${$field} = $entry[ $settings[ $field ] ]; @@ -308,139 +314,76 @@ public function after_submission( $entry, $form ) { } } - $identifiers = array(); - if ( $email != '' ) { - $email_identifier = array( - 'type' => 'email', - 'channels' => array( - 'email' => array( - 'status' => $email_consent, - 'statusDate' => gmdate( 'c' ), - ), - ), - 'id' => $email, - ); - - if ( $email_consent == 'subscribed' ) { - $email_identifier['consent'] = $consent_object; - } - array_push( $identifiers, $email_identifier ); - } else { - error_log( 'Email is not mapped. Skipping Omnisend contact creation.' ); - return; + if ( $email == '' ) { + return; // Email is not mapped. Skipping Omnisend contact creation. } - if ( $phone_number != '' ) { - $phone_identifier = array( - 'type' => 'phone', - 'channels' => array( - 'sms' => array( - 'status' => $phone_consent, - 'statusDate' => gmdate( 'c' ), - ), - ), - 'id' => $phone_number, - ); - if ( $phone_consent == 'subscribed' ) { - $phone_identifier['consent'] = $consent_object; - } + $contact->set_email( $email ); - array_push( $identifiers, $phone_identifier ); + if ( $phone_number != '' ) { + $contact->set_phone( $phone_number ); } - $data = array( 'identifiers' => $identifiers ); - $fields_to_data_keys = array( - 'first_name' => 'firstName', - 'last_name' => 'lastName', - 'birthday' => 'birthdate', - 'postal_code' => 'postalCode', - 'address' => 'address', - 'state' => 'state', - 'country' => 'country', - 'city' => 'city', - 'send_welcome_email' => 'sendWelcomeEmail', - ); - - foreach ( $fields_to_data_keys as $variable => $data_key ) { - if ( ! empty( $$variable ) ) { - $data[ $data_key ] = $$variable; - } + $contact->set_first_name( $first_name ); + $contact->set_last_name( $last_name ); + $contact->set_birthday( $birthday ); + $contact->set_postal_code( $postal_code ); + $contact->set_address( $address ); + $contact->set_state( $state ); + $contact->set_country( $country ); + $contact->set_city( $city ); + $contact->add_tag( 'gravity_forms' ); + $contact->add_tag( 'gravity_forms ' . $form['title'] ); + + if ( $email_consent ) { + $contact->set_email_consent( 'gravity-forms' ); + $contact->set_email_opt_in( 'gravity-forms' ); } - $form_name = preg_replace( '/[^A-Za-z0-9\-]/', '', $form['title'] ); - $data['tags'] = array( 'gravity_forms', 'gravity_forms ' . $form_name ); + if ( $phone_consent ) { + $contact->set_phone_consent( 'gravity-forms' ); // todo looks a bit strange. Maybe one function is enough? + $contact->set_phone_opt_in( 'gravity-forms' ); + } - if ( - isset( $settings['send_welcome_email'] ) && - $settings['send_welcome_email'] == '1' - ) { - $data['sendWelcomeEmail'] = true; + if ( isset( $settings['send_welcome_email'] ) && $settings['send_welcome_email'] == '1' ) { + $contact->set_welcome_email( true ); } - $custom_properties = $this->mapCustomProperties( $form, $entry, $settings, array_keys( $data ) ); - if ( ! empty( $custom_properties ) ) { - $data['customProperties'] = (object) $custom_properties; + $this->mapCustomProperties( $form, $entry, $settings, $contact ); + + $response = \Omnisend\Public\V1\Omnisend::get_client( OMNISEND_GRAVITY_ADDON_NAME, OMNISEND_GRAVITY_ADDON_VERSION )->create_contact( $contact ); + if ( is_wp_error( $response ) ) { + error_log( 'Error in after_submission: ' . $response->get_error_message()); // phpcs:ignore + return; } - if ( ! $this->createOmnisendContact( $data ) ) { + if ( ! is_string( $response ) ) { + error_log( 'Unexpected error. Please contact Omnisend support.'); // phpcs:ignore return; } $this->enableWebTracking( $email, $phone_number ); } catch ( Exception $e ) { - error_log( 'Error in after_submission: ' . $e->getMessage() ); + // todo check if it is possible to get exception? If not remove handling. + error_log( 'Error in after_submission: ' . $e->getMessage() ); // phpcs:ignore } } - private function createOmnisendContact( $body ) { - $api_key = get_option( 'omnisend_api_key', null ); - $endpoint = 'https://api.omnisend.com/v3/contacts'; - - $data = array( - 'body' => wp_json_encode( $body ), - 'headers' => array( - 'Content-Type' => 'application/json', - 'X-API-Key' => $api_key, - ), - 'timeout' => 10, - ); - - $response = wp_remote_post( $endpoint, $data ); - - if ( is_wp_error( $response ) ) { - error_log( 'wp_remote_post error: ' . $response->get_error_message() ); - return false; - } - - $http_code = wp_remote_retrieve_response_code( $response ); - if ( $http_code >= 400 ) { - $body = wp_remote_retrieve_body( $response ); - error_log( "HTTP error: {$http_code} - " . wp_remote_retrieve_response_message( $response ) . " - {$body}" ); - return false; - } - - return true; - } - - - private function mapCustomProperties( $form, $entry, $settings, $excluded_fields ) { - $custom_properties = array(); - $prefix = 'gravity_forms_'; + private function mapCustomProperties( $form, $entry, $settings, Contact $contact ) { + $prefix = 'gravity_forms_'; foreach ( $form['fields'] as $field ) { $field_id = $field['id']; $field_label = $field['label']; if ( ! in_array( $field_id, $settings ) || $settings[ array_search( $field_id, $settings ) ] === '-1' ) { // Replace spaces with underscores, remove invalid characters, lowercase. - $safe_label = str_replace( ' ', '_', $field_label ); - $safe_label = preg_replace( '/[^A-Za-z0-9_]/', '', $safe_label ); - $safe_label = strtolower( $safe_label ); + $safe_label = strtolower( str_replace( ' ', '_', $field_label ) ); if ( $field['type'] !== 'checkbox' ) { // Check if the value is set and not empty. if ( ! empty( $entry[ $field_id ] ) ) { - $custom_properties[ $prefix . $safe_label ] = $entry[ $field_id ]; + $contact->add_custom_property( $prefix . $safe_label, $entry[ $field_id ] ); } } else { $selected_choices = array(); @@ -454,16 +397,15 @@ private function mapCustomProperties( $form, $entry, $settings, $excluded_fields } // Only add to customProperties if selectedChoices is not empty. if ( ! empty( $selected_choices ) ) { - $custom_properties[ $prefix . $safe_label ] = $selected_choices; + $contact->add_custom_property( $prefix . $safe_label, $selected_choices ); } } } } - return $custom_properties; } public function get_menu_icon() { - return file_get_contents( $this->get_base_path() . '/images/menu-icon.svg' ); + return file_get_contents( $this->get_base_path() . '/images/menu-icon.svg' ); // phpcs:ignore } private function enableWebTracking( $email, $phone ) { @@ -480,7 +422,7 @@ private function enableWebTracking( $email, $phone ) { wp_localize_script( 'omnisend-snippet-script', 'omnisendIdentifiers', $identifiers ); } - public function settings_welcome_automation_details( $field, $echo = true ) { + public function settings_welcome_automation_details( $field, $echo = true ) { // phpcs:ignore echo '