Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlamarwheeler committed Feb 19, 2016
0 parents commit 27a4977
Show file tree
Hide file tree
Showing 7 changed files with 626 additions and 0 deletions.
48 changes: 48 additions & 0 deletions components/integration/functions/integration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

if(!defined('ABSPATH')) { exit; }

if(!function_exists('ckwc_instance')) {
function ckwc_instance() {
$integrations = WC()->integrations->get_integrations();

return isset($integrations['ckwc']) ? $integrations['ckwc'] : false;
}
}

if(!function_exists('ckwc_get_subscription_options')) {
function ckwc_get_subscription_options() {
$options = get_transient('ckwc_options_' . ckwc_instance()->api_key);

if(!is_array($options)) {
$courses = ckwc_convertkit_api_get_courses();
$forms = ckwc_convertkit_api_get_forms();
$tags = ckwc_convertkit_api_get_tags();

if(!is_wp_error($courses) && !is_wp_error($forms) && !is_wp_error($tags)) {
$options = array(
array(
'key' => 'course',
'name' => __('Courses'),
'options' => array_combine(wp_list_pluck($courses, 'id'), wp_list_pluck($courses, 'name')),
),
array(
'key' => 'form',
'name' => __('Forms'),
'options' => array_combine(wp_list_pluck($forms, 'id'), wp_list_pluck($forms, 'name')),
),
array(
'key' => 'tag',
'name' => __('Tags'),
'options' => array_combine(wp_list_pluck($tags, 'id'), wp_list_pluck($tags, 'name')),
),
);

set_transient('ckwc_options_' . ckwc_instance()->api_key, $options, 5 * MINUTE_IN_SECONDS);
}
}

return $options;
}
}

333 changes: 333 additions & 0 deletions components/integration/integration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
<?php

if(!defined('ABSPATH')) { exit; }

class CKWC_Integration extends WC_Integration {
public function __construct() {
$this->id = 'ckwc';
$this->method_title = __('ConvertKit');
$this->method_description = __('Enter your ConvertKit settings below to control how WooCommerce integrates with your ConvertKit account.');

// Initialize form fields
$this->init_form_fields();

// Initialize settings
$this->init_settings();

// API interaction
$this->api_key = $this->get_option('api_key');
$this->subscription = $this->get_option('subscription');

// Enabled and when it should take place
$this->enabled = $this->get_option('enabled');
$this->event = $this->get_option('event');

// Opt-in field
$this->display_opt_in = $this->get_option('display_opt_in');
$this->opt_in_label = $this->get_option('opt_in_label');
$this->opt_in_status = $this->get_option('opt_in_status');
$this->opt_in_location = $this->get_option('opt_in_location');

if(is_admin()) {
add_action("woocommerce_update_options_integration_{$this->id}", array($this, 'process_admin_options'));

add_filter("woocommerce_settings_api_sanitized_fields_{$this->id}", array($this, 'sanitize_settings'));

add_action('add_meta_boxes_product', array($this, 'add_meta_boxes'));
add_action('save_post_product', array($this, 'save_product'));
}

if('yes' === $this->enabled && 'yes' === $this->display_opt_in) {
add_filter('woocommerce_checkout_fields', array($this, 'add_opt_in_checkbox'));
}

if('yes' === $this->enabled) {
add_action('woocommerce_checkout_update_order_meta', array($this, 'save_opt_in_checkbox'));

add_action('woocommerce_checkout_update_order_meta', array($this, 'order_status'), 99999, 1);
add_action('woocommerce_order_status_changed', array($this, 'order_status'), 99999, 3);
}

}

#region Product Integration

public function add_meta_boxes($post) {
add_meta_box('ckwc', __('Convert Kit Integration'), array($this, 'display_meta_box'), null, $context = 'side', $priority = 'default');
}

public function display_meta_box($post) {
$subscription = get_post_meta($post->ID, 'ckwc_subscription', true);
$options = empty($this->api_key) ? false : ckwc_get_subscription_options();

include('views/meta-box.php');
}

public function save_product($post_id) {
$data = stripslashes_deep($_POST);

if(isset($data['ckwc_nonce']) && wp_verify_nonce($data['ckwc_nonce'], 'ckwc') && isset($data['ckwc_subscription'])) {
update_post_meta($post_id, 'ckwc_subscription', $data['ckwc_subscription']);
}
}

#endregion Product Integration

#region Create Form Fields and Settings

public function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __('Enable/Disable'),
'type' => 'checkbox',
'label' => __('Enable ConvertKit integration'),
'default' => 'no',
),

'event' => array(
'title' => __('Subscribe Event'),
'type' => 'select',
'default' => 'pending',
'description' => __('When should customers be subscribed?'),
'desc_tip' => false,
'options' => array(
'pending' => __('Order Created'),
'processing' => __('Order Processing'),
'completed' => __('Order Completed'),
),
),

'display_opt_in' => array(
'title' => __('Display Opt-In Checkbox'),
'label' => __('Display an Opt-In checkbox on checkout'),
'type' => 'checkbox',
'default' => 'no',
'description' => __('If enabled, customers will only be subscribed if the "Opt-In" checkbox presented on checkout is checked.'),
'desc_tip' => false,
),

'opt_in_label' => array(
'title' => __('Opt-In Checkbox Label'),
'type' => 'text',
'default' => __('I want to subscribe to the newsletter'),
'description' => __('Optional (only used if the above field is checked): Customize the label next to the opt-in checkbox.'),
'desc_tip' => false,
),

'opt_in_status' => array(
'title' => __('Opt-In Checkbox<br />Default Status'),
'type' => 'select',
'default' => 'checked',
'description' => __('The default state of the opt-in checkbox'),
'desc_tip' => false,
'options' => array(
'checked' => __('Checked'),
'unchecked' => __('Unchecked'),
),
),

'opt_in_location' => array(
'title' => __('Opt-In Checkbox<br />Display Location'),
'type' => 'select',
'default' => 'billing',
'description' => __('Where to display the opt-in checkbox on the checkout page (under Billing Info or Order Info).'),
'desc_tip' => false,
'options' => array(
'billing' => __('Billing'),
'order' => __('Order'),
),
),

'api_key' => array(
'title' => __('API Key'),
'type' => 'text',
'default' => '',
'description' => sprintf(__('If you already have an account, <a href="%s" target="_blank">click here to retrieve your API Key</a>.<br />If you don\'t have a ConvertKit account, you can <a href="%s" target="_blank">sign up for one here</a>.'), esc_attr(esc_html('https://app.convertkit.com/account/edit')), esc_attr(esc_url('http://convertkit.com/pricing/'))),
'desc_tip' => false,
),

'subscription' => array(
'title' => __('Subscription'),
'type' => 'subscription',
'default' => '',
'description' => __('Customers will be added to the selected item'),
),
);


ob_start();
include('resources/integration.js');
$code = ob_get_clean();

wc_enqueue_js($code);
}

public function generate_subscription_html($key, $data) {
$field = $this->get_field_key($key);
$defaults = array(
'title' => '',
'disabled' => false,
'class' => '',
'css' => '',
'placeholder' => '',
'type' => 'text',
'desc_tip' => false,
'description' => '',
'custom_attributes' => array(),
'options' => array()
);

$data = wp_parse_args($data, $defaults);

$options = false;

if(!empty($this->api_key)) {
$options = ckwc_get_subscription_options();
}

ob_start();

?>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="<?php echo esc_attr($field); ?>"><?php echo wp_kses_post($data['title']); ?></label>
<?php echo $this->get_tooltip_html($data); ?>
</th>
<td class="forminp">
<?php if($options) { ?>
<fieldset>
<legend class="screen-reader-text"><span><?php echo wp_kses_post($data['title']); ?></span></legend>
<select class="select <?php echo esc_attr($data['class']); ?>" name="<?php echo esc_attr($field); ?>" id="<?php echo esc_attr($field); ?>" style="<?php echo esc_attr($data['css']); ?>" <?php disabled($data['disabled'], true); ?> <?php echo $this->get_custom_attribute_html($data); ?>>
<option <?php selected('', $this->get_option($key)); ?> value=""><?php _e('Select a subscription option...'); ?></option>
<?php foreach($options as $option_group) { if(empty($option_group['options'])) { continue; } ?>
<optgroup label="<?php echo esc_attr($option_group['name']); ?>">
<?php foreach($option_group['options'] as $id => $name) { $value = "{$option_group['key']}:{$id}"; ?>
<option <?php selected($value, $this->get_option($key)); ?> value="<?php echo esc_attr($value); ?>"><?php echo esc_html($name); ?></option>
<?php } ?>
</optgroup>
<?php } ?>
</select>
<?php echo $this->get_description_html($data); ?>
</fieldset>
<?php } else { ?>
<p class="description"><?php _e('Please provide a valid ConvertKit API Key.'); ?></p>
<?php } ?>
</td>
</tr>
<?php

return ob_get_clean();
}

#endregion Create Form Fields and Settings

#region Sanitize Settings

public function sanitize_settings($settings) {
$settings['api_key'] = trim($settings['api_key']);

return $settings;
}

#endregion Sanitize Settings

#region Validate Settings

public function validate_api_key_field($key) {
$field = $this->get_field_key($key);
$value = $_POST[$field];

if(empty($value)) {
$this->errors[$key] = __('Please provide your ConvertKit API Key.');
} else {
$forms = ckwc_convertkit_api_get_forms($value);

if(is_wp_error($forms)) {
$this->errors[$key] = __('Your ConvertKit API Key appears to be invalid. Please double check the value.');
}
}

return $value;
}

#endregion Validate Settings

#region Display Errors

public function display_errors() {
if(!empty($this->errors)) {
foreach($this->errors as $key => $value) {
printf('<div class="error" id="ckwc_error_%s"><p>%s</p></div>', esc_attr($key), esc_html($value));
}
}
}

#endregion Display Errors

#region Frontend Checkout Fields

public function add_opt_in_checkbox($fields) {
$section = 'billing' === $this->opt_in_location ? 'billing' : 'order';

$fields[$section]['ckwc_opt_in'] = array(
'type' => 'checkbox',
'label' => $this->opt_in_label,
'default' => 'checked' === $this->opt_in_status,
);

return $fields;
}

public function save_opt_in_checkbox($order_id) {
$opt_in = ('no' === $this->display_opt_in || isset($_POST['ckwc_opt_in'])) ? 'yes' : 'no';

update_post_meta($order_id, 'ckwc_opt_in', $opt_in);
}

#endregion Frontend Checkout Fields

#region Process Subscription

public function order_status($order_id, $status_old = 'new', $status_new = 'pending') {
$api_key_correct = !empty($this->api_key);
$status_correct = $status_new === $this->event;
$opt_in_correct = 'yes' === get_post_meta($order_id, 'ckwc_opt_in', 'no');

if($api_key_correct && $status_correct && $opt_in_correct) {
$order = wc_get_order($order_id);
$items = $order->get_items();
$name = sprintf("%s %s", $order->billing_first_name, $order->billing_last_name);
$email = $order->billing_email;

$subscriptions = array($this->subscription);

foreach($items as $item) {
$subscriptions[] = get_post_meta($item['product_id'], 'ckwc_subscription', true);
}

$subscriptions = array_filter(array_unique($subscriptions));

foreach($subscriptions as $subscription) {
$subscription_parts = explode(':', $subscription);
$subscription_type = $subscription_parts[0];
$subscription_id = $subscription_parts[1];
$subscription_function = "ckwc_convertkit_api_add_subscriber_to_{$subscription_type}";

if(function_exists($subscription_function)) {
call_user_func($subscription_function, $subscription_id, $email, $name);
}
}
}
}

#endregion Process Subscription
}

require_once('functions/integration.php');

function ckwc_woocommerce_integrations($integrations) {
$integrations[] = 'CKWC_Integration';

return $integrations;
}
add_filter('woocommerce_integrations', 'ckwc_woocommerce_integrations');
7 changes: 7 additions & 0 deletions components/integration/resources/integration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
jQuery(document).ready(function($) {
$('#woocommerce_ckwc_display_opt_in').change(function() {
var $dependents = $('[id^="woocommerce_ckwc_opt_in_"]').parents('tr');

$dependents.toggle($(this).prop('checked'));
}).trigger('change');
});
Loading

0 comments on commit 27a4977

Please sign in to comment.