diff --git a/README.md b/README.md index 33aac609c..8b49aa754 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # ConvertKit -Wordpress plugin for [ConvertKit](https://convertkit.com). Visit https://wordpress.org/plugins/convertkit/ for more information. +WordPress plugin for [ConvertKit](https://convertkit.com). Visit https://wordpress.org/plugins/convertkit/ for more information. diff --git a/admin/section/base.php b/admin/section/base.php index 7681d2c80..94610a482 100644 --- a/admin/section/base.php +++ b/admin/section/base.php @@ -1,5 +1,8 @@ settings_key = WP_ConvertKit::SETTINGS_PAGE_SLUG; - $this->name = 'general'; - $this->title = 'General Settings'; - $this->tab_text = 'General'; - - parent::__construct(); - } - - /** - * Register and add settings - */ - public function register_fields() { - add_settings_field( - 'api_key', - 'API Key', - array($this, 'api_key_callback'), - $this->settings_key, - $this->name - ); - - add_settings_field( - 'default_form', - 'Default Form', - array($this, 'default_form_callback'), - $this->settings_key, - $this->name, - $this->api->get_resources('forms') - ); - } - - /** - * Prints help info for this section - */ - public function print_section_info() { - ?> -

- Choosing a default form will embed it at the bottom of every post or page - (in single view only) across your site. If you wish to turn off form - embedding or select a different form for an individual post or page, you - can do so within the ConvertKit meta box on the editing form. -

-

- The default form can be inserted into the middle of post or page content - by using the [convertkit] shortcode. -

- ', - $this->settings_key, - isset($this->options['api_key']) ? esc_attr($this->options['api_key']) : '' - ); - - $html .= '

Get your ConvertKit API Key

'; - - echo $html; - } - - /** - * Renders the form select list - * - * @param array $forms Form listing - */ - public function default_form_callback($forms) { - $html = sprintf(''; - - if (empty($forms)) { - $html .= '

Enter your API Key above to get your available forms.

'; - } - - echo $html; - } - - /** - * Sanitizes the settings - * - * @param array $settings The settings fields submitted - * @return array Sanitized settings - */ - public function sanitize_settings($settings) { - return shortcode_atts(array( - 'api_key' => '', - 'default_form' => 0 - ), $settings); - } + /** + * Constructor + */ + public function __construct() { + $this->settings_key = WP_ConvertKit::SETTINGS_PAGE_SLUG; + $this->name = 'general'; + $this->title = 'General Settings'; + $this->tab_text = 'General'; + + parent::__construct(); + } + + /** + * Register and add settings + */ + public function register_fields() { + add_settings_field( + 'api_key', + 'API Key', + array($this, 'api_key_callback'), + $this->settings_key, + $this->name + ); + + add_settings_field( + 'api_secret', + 'API Secret', + array($this, 'api_secret_callback'), + $this->settings_key, + $this->name + ); + + add_settings_field( + 'default_form', + 'Default Form', + array($this, 'default_form_callback'), + $this->settings_key, + $this->name, + $this->api->get_resources('forms') + ); + } + + /** + * Prints help info for this section + */ + public function print_section_info() { + ?> +

+ Choosing a default form will embed it at the bottom of every post or page + (in single view only) across your site. If you wish to turn off form + embedding or select a different form for an individual post or page, you + can do so within the ConvertKit meta box on the editing form. +

+

+ The default form can be inserted into the middle of post or page content + by using the [convertkit] shortcode. +

+ ', + $this->settings_key, + isset($this->options['api_key']) ? esc_attr($this->options['api_key']) : '' + ); + + $html .= '

Get your ConvertKit API Key

'; + + echo $html; + } + + /** + * Renders the input for api key entry + */ + public function api_secret_callback() { + $html = sprintf( + '', + $this->settings_key, + isset($this->options['api_secret']) ? esc_attr($this->options['api_secret']) : '' + ); + + $html .= '

Get your ConvertKit API Secret. This setting is required to unsubscribe subscribers.

'; + + echo $html; + } + + /** + * Renders the form select list + * + * @param array $forms Form listing + */ + public function default_form_callback($forms) { + $html = sprintf(''; + + if (empty($forms)) { + $html .= '

Enter your API Key above to get your available forms.

'; + } + + echo $html; + } + + /** + * Sanitizes the settings + * + * @param array $settings The settings fields submitted + * @return array Sanitized settings + */ + public function sanitize_settings($settings) { + return shortcode_atts(array( + 'api_key' => '', + 'api_secret' => '', + 'default_form' => 0 + ), $settings); + } } diff --git a/admin/section/wishlist_member.php b/admin/section/wishlist_member.php index 793ead283..fc640a3ab 100644 --- a/admin/section/wishlist_member.php +++ b/admin/section/wishlist_member.php @@ -3,6 +3,9 @@ require_once "base.php"; require_once plugin_dir_path( __FILE__ ) . "../../lib/multi_value_field_table.php"; +/** + * Class ConvertKitSettingsWishlistMember + */ class ConvertKitSettingsWishlistMember extends ConvertKitSettingsSection { /** @@ -11,6 +14,9 @@ class ConvertKitSettingsWishlistMember extends ConvertKitSettingsSection { */ private $wlm_levels; + /** + * Cont + */ public function __construct() { if (!function_exists('wlmapi_get_levels')) { return $this->is_registerable = false; diff --git a/admin/settings.php b/admin/settings.php index 0549acfe6..275ad0798 100644 --- a/admin/settings.php +++ b/admin/settings.php @@ -1,131 +1,127 @@ settings_key); - $api_key = $general_options && array_key_exists("api_key", $general_options) ? $general_options['api_key'] : null; - $this->api = new ConvertKitAPI($api_key); - - add_action('admin_menu', array($this, 'add_settings_page')); - add_action('admin_init', array($this, 'register_sections')); - } - - /** - * Add the options page - */ - public function add_settings_page() { - $settings = add_options_page( - __('ConvertKit'), - __('ConvertKit'), - 'manage_options', - $this->settings_key, - array($this, 'display_settings_page') - ); - - add_action('admin_print_styles', array($this, 'admin_styles')); - } - - /** - * Options page callback - */ - public function display_settings_page() { - $active_section = (isset($_GET['tab'])) ? $_GET['tab'] : $this->sections[0]->name; - - ?> -
- sections) > 1) { - $this->display_section_nav($active_section); - } else { + public $api; + public $sections = array(); + public $settings_key = WP_ConvertKit::SETTINGS_PAGE_SLUG; + + public function __construct() { + $general_options = get_option($this->settings_key); + $api_key = $general_options && array_key_exists("api_key", $general_options) ? $general_options['api_key'] : null; + $api_secret = $general_options && array_key_exists("api_secret", $general_options) ? $general_options['api_secret'] : null; + $this->api = new ConvertKitAPI( $api_key, $api_secret ); + + add_action('admin_menu', array($this, 'add_settings_page')); + add_action('admin_init', array($this, 'register_sections')); + } + + /** + * Add the options page + */ + public function add_settings_page() { + $settings = add_options_page( + __('ConvertKit'), + __('ConvertKit'), + 'manage_options', + $this->settings_key, + array($this, 'display_settings_page') + ); + + add_action('admin_print_styles', array($this, 'admin_styles')); + } + + /** + * Options page callback + */ + public function display_settings_page() { + $active_section = (isset($_GET['tab'])) ? $_GET['tab'] : $this->sections[0]->name; + ?> +
+ sections) > 1) { + $this->display_section_nav($active_section); + } else { + ?> +

+ + +
+ sections as $section): + if ($active_section == $section->name): + $section->render(); + endif; + endforeach; + ?> +

+ If you have questions or problems, please contact + support@convertkit.com +

+
+
+ -

- - -
+

+
- - - is_registerable) { - array_push($this->sections, $section_instance); - } - } - - /** - * Register each section - */ - public function register_sections() { - wp_register_style( 'wp-convertkit-admin', plugins_url('../resources/backend/wp-convertkit.css', __FILE__) ); - - $this->register_section('ConvertKitSettingsGeneral'); - $this->register_section('ConvertKitSettingsWishlistMember'); - } + foreach($this->sections as $section): + printf( + '%s', + $this->settings_key, + $section->name, + $active_section == $section->name ? 'nav-tab-active' : '', + esc_html($section->tab_text) + ); + endforeach; + ?> + + is_registerable) { + array_push($this->sections, $section_instance); + } + } + + /** + * Register each section + */ + public function register_sections() { + wp_register_style( 'wp-convertkit-admin', plugins_url('../resources/backend/wp-convertkit.css', __FILE__) ); + + $this->register_section('ConvertKitSettingsGeneral'); + $this->register_section('ConvertKitSettingsWishlistMember'); + } } if( is_admin() ) { - $convertkit_settings = new ConvertKitSettings(); + $convertkit_settings = new ConvertKitSettings(); - include 'section/general.php'; - include 'section/wishlist_member.php'; + include 'section/general.php'; + include 'section/wishlist_member.php'; } diff --git a/lib/convertkit-api.php b/lib/convertkit-api.php index 84f99e03a..dcbc99b68 100644 --- a/lib/convertkit-api.php +++ b/lib/convertkit-api.php @@ -5,183 +5,227 @@ */ class ConvertKitAPI { - protected $api_key; - - protected $api_version = 2; - protected $api_url_base = 'https://api.convertkit.com/'; - protected $resources = array(); - protected $markup = array(); - - /** - * Constructor for ConvertKitAPI instance - * - * @param String $api_key ConvertKit API Key - */ - public function __construct($api_key) { - $this->api_key = $api_key; - } - - /** - * Gets a resource index - * - * GET /{$resource}/ - * - * @param string $resource Resource type - * @return object API response - */ - public function get_resources($resource) { - if(!array_key_exists($resource, $this->resources)) { - $api_response = $this->_get_api_response($resource); - - if (is_null($api_response) || is_wp_error($api_response) || isset($api_response['error']) || isset($api_response['error_message'])) { - $this->resources[$resource] = array(); - } else { - $this->resources[$resource] = $api_response; - } - } - - return $this->resources[$resource]; - } - - /** - * Adds a subscriber to a form - * - * @param string $form_id Form ID - * @param array $options Array of user data - */ - public function form_subscribe($form_id, $options) { - $request = sprintf('forms/%s/subscribe', $form_id); - - $args = array( - 'email' => $options['email'], - 'fname' => $options['fname'] - ); - - return $this->make_request($request, 'POST', $args); - } - - /** - * Unsubscribes a subscriber from a form - * - * @param string $form_id Resource ID - * @param array $options Array of user data - */ - public function form_unsubscribe($form_id, $options) { - $request = sprintf('forms/%s/unsubscribe', $form_id); - - $args = array( - 'email' => $options['email'] - ); - - return $this->make_request($request, 'POST', $args); - } - - public function get_resource($url) { - $resource = ''; - - if(!empty($url) && isset($this->markup[$url])) { - $resource = $this->markup[$url]; - } else if(!empty($url)) { - $response = wp_remote_get($url, array( 'timeout' => 2 )); - - if(!is_wp_error($response)) { - if(!function_exists('str_get_html')) { - require_once(dirname(__FILE__).'/../vendor/simple-html-dom/simple-html-dom.php'); - } - - if(!function_exists('url_to_absolute')) { - require_once(dirname(__FILE__).'/../vendor/url-to-absolute/url-to-absolute.php'); - } - - $url_parts = parse_url($url); - - $body = wp_remote_retrieve_body($response); - $html = str_get_html($body); - foreach($html->find('a, link') as $element) { - if(isset($element->href)) { - $element->href = url_to_absolute($url, $element->href); - } - } - - foreach($html->find('img, script') as $element) { - if(isset($element->src)) { - $element->src = url_to_absolute($url, $element->src); - } - } - - foreach($html->find('form') as $element) { - if(isset($element->action)) { - $element->action = url_to_absolute($url, $element->action); - } else { - $element->action = $url; - } - } - - $this->markup[$url] = $resource = $html->save(); - } - } - - return $resource; - } - - private function _get_api_response($path = '') { - $args = array('k' => $this->api_key, 'v' => $this->api_version); - $url = add_query_arg($args, path_join($this->api_url_base, $path)); - - $response = wp_remote_get($url, array( 'timeout' => 2 )); - - if(is_wp_error($response)) { - $data = $response; - } else { - $data = json_decode(wp_remote_retrieve_body($response), true); - } - - return $data; - } - - /** - * Make a request to the ConvertKit API - * - * @param string $request Request string - * @param string $method HTTP Method - * @param array $args Request arguments - * @return object Response object - */ - public function make_request($request, $method = 'GET', $args = array()) { - $url = $this->build_request_url($request, $args); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); - - $results = curl_exec($ch); - - curl_close($ch); - - return json_decode($results); - } - - /** - * Merge default request arguments with those of this request - * - * @param array $args Request arguments - * @return array Request arguments - */ - public function filter_request_arguments($args = array()) { - return array_merge($args, array('k' => $this->api_key, 'v' => $this->api_version)); - } - - /** - * Build the full request URL - * - * @param string $request Request path - * @param array $args Request arguments - * @return string Request URL - */ - public function build_request_url($request, array $args) { - return $this->api_url_base . $request . '?' . http_build_query($this->filter_request_arguments($args)); - } + /** @var string */ + protected $api_key; + + /** @var string */ + protected $api_secret; + + /** @var string */ + protected $api_version = 'v3'; + + /** @var string */ + protected $api_url_base = 'https://api.convertkit.com/'; + + /** @var array */ + protected $resources = array(); + + /** @var array */ + protected $markup = array(); + + /** + * Constructor for ConvertKitAPI instance + * + * @param string $api_key ConvertKit API Key + * @param string $api_secret ConvertKit API Secret + */ + public function __construct($api_key, $api_secret) { + $this->api_key = $api_key; + $this->api_secret = $api_secret; + } + + /** + * Gets a resource index + * + * GET /{$resource}/ + * + * @param string $resource Resource type + * @return object API response + */ + public function get_resources($resource) { + + if(!array_key_exists($resource, $this->resources)) { + // v3 only has 'forms' resource. + $api_response = $this->_get_api_response('forms'); + + if (is_null($api_response) || is_wp_error($api_response) || isset($api_response['error']) || isset($api_response['error_message'])) { + $this->resources[$resource] = array(); + } else { + $_resource = array(); + // v3 doesn't have landing_pages resource. Instead check 'type' for 'hosted' + if ( 'forms' == $resource ) { + foreach ( $api_response as $form ){ + if ( 'embed' == $form['type'] ){ + $_resource[] = $form; + } + } + } elseif ( 'landing_pages' == $resource ) { + foreach ( $api_response as $landing_page ){ + if ( 'hosted' == $landing_page['type'] ){ + $_resource[] = $landing_page; + } + } + } + + $this->resources[$resource] = $_resource; + } + } + + return $this->resources[$resource]; + } + + /** + * Adds a subscriber to a form + * + * @param string $form_id Form ID + * @param array $options Array of user data + * @return object + */ + public function form_subscribe($form_id, $options) { + $request = sprintf('forms/%s/subscribe', $form_id); + + $args = array( + 'email' => $options['email'], + 'fname' => $options['fname'] + ); + + return $this->make_request($request, 'POST', $args); + } + + /** + * Remove subscription from a form + * + * @param array $options Array of user data + * @return object Response object + */ + public function form_unsubscribe($options) { + $request = 'unsubscribe'; + + $args = array( + 'api_secret' => $this->api_secret, + 'email' => $options['email'] + ); + + return $this->make_request($request, 'POST', $args); + } + + /** + * Get markup from ConvertKit for the provided $url + * + * @param $url + * @return string + */ + public function get_resource($url) { + $resource = ''; + + if(!empty($url) && isset($this->markup[$url])) { + $resource = $this->markup[$url]; + } else if(!empty($url)) { + $response = wp_remote_get($url, array( 'timeout' => 2 )); + + if(!is_wp_error($response)) { + if(!function_exists('str_get_html')) { + require_once(dirname(__FILE__).'/../vendor/simple-html-dom/simple-html-dom.php'); + } + + if(!function_exists('url_to_absolute')) { + require_once(dirname(__FILE__).'/../vendor/url-to-absolute/url-to-absolute.php'); + } + + $url_parts = parse_url($url); + + $body = wp_remote_retrieve_body($response); + $html = str_get_html($body); + foreach($html->find('a, link') as $element) { + if(isset($element->href)) { + $element->href = url_to_absolute($url, $element->href); + } + } + + foreach($html->find('img, script') as $element) { + if(isset($element->src)) { + $element->src = url_to_absolute($url, $element->src); + } + } + + foreach($html->find('form') as $element) { + if(isset($element->action)) { + $element->action = url_to_absolute($url, $element->action); + } else { + $element->action = $url; + } + } + + $this->markup[$url] = $resource = $html->save(); + } + } + + return $resource; + } + + /** + * Do a remote request. + * + * @param string $path + * @return array + */ + private function _get_api_response($path = '') { + $args = array('api_key' => $this->api_key); + $api_path = $this->api_url_base . $this->api_version; + $url = add_query_arg($args, path_join($api_path, $path)); + $response = wp_remote_get($url, array( 'timeout' => 2 )); + + if(is_wp_error($response)) { + return array(); + } else { + $data = json_decode(wp_remote_retrieve_body($response), true); + } + + return isset($data[$path]) ? $data[$path] : array(); + } + + /** + * Make a request to the ConvertKit API + * + * @param string $request Request string + * @param string $method HTTP Method + * @param array $args Request arguments + * @return object Response object + */ + public function make_request($request, $method = 'GET', $args = array()) { + $url = $this->build_request_url($request, $args); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + + $results = curl_exec($ch); + curl_close($ch); + + return json_decode($results); + } + + /** + * Merge default request arguments with those of this request + * + * @param array $args Request arguments + * @return array Request arguments + */ + public function filter_request_arguments($args = array()) { + return array_merge($args, array('k' => $this->api_key, 'v' => $this->api_version)); + } + + /** + * Build the full request URL + * + * @param string $request Request path + * @param array $args Request arguments + * @return string Request URL + */ + public function build_request_url($request, array $args) { + return $this->api_url_base . $request . '?' . http_build_query($this->filter_request_arguments($args)); + } } diff --git a/lib/integration/wishlist_member.php b/lib/integration/wishlist_member.php index 109f522aa..6919e921e 100644 --- a/lib/integration/wishlist_member.php +++ b/lib/integration/wishlist_member.php @@ -3,15 +3,23 @@ require_once plugin_dir_path( __FILE__ ) . "../../lib/convertkit-api.php"; if(!class_exists('ConvertKitWishlistIntegration')) { + + /** + * Class ConvertKitWishlistIntegration + */ class ConvertKitWishlistIntegration { protected $api; protected $options; + /** + * Constructor + */ public function __construct() { $general_options = get_option('_wp_convertkit_settings'); $this->options = get_option('_wp_convertkit_integration_wishlistmember_settings'); $api_key = $general_options && array_key_exists("api_key", $general_options) ? $general_options['api_key'] : null; - $this->api = new ConvertKitAPI($api_key); + $api_secret = $general_options && array_key_exists("api_secret", $general_options) ? $general_options['api_secret'] : null; + $this->api = new ConvertKitAPI($api_key,$api_secret); add_action( 'wishlistmember_add_user_levels', // hook @@ -48,12 +56,15 @@ public function add_user_levels($member_id, $levels) { } /** + * Note: Form level unsubscribe is not available in v3 of the API. + * * Callback function for wishlistmember_remove_user_levels action * * @param string $member_id ID for member that has just had levels removed * @param array $levels Levels from which member was removed */ public function remove_user_levels($member_id, $levels) { + /* $member = $this->get_member($member_id); foreach ($levels as $wlm_level_id) { @@ -68,6 +79,7 @@ public function remove_user_levels($member_id, $levels) { ); } } + */ } /** @@ -103,7 +115,6 @@ public function member_resource_subscribe($member, $form_id) { */ public function member_resource_unsubscribe($member, $form_id) { return $this->api->form_unsubscribe( - $form_id, array( 'email' => $member['user_email'] ) diff --git a/lib/multi_value_field_table.php b/lib/multi_value_field_table.php index 95b9aede2..47b0c0102 100644 --- a/lib/multi_value_field_table.php +++ b/lib/multi_value_field_table.php @@ -1,142 +1,145 @@ 'item', - 'plural' => 'items', - 'ajax' => false - )); - } - - /** - * Set default column attributes - * - * @param array $item A singular item (one full row's worth of data) - * @param array $column_name The name/slug of the column to be processed - * @return string Text or HTML to be placed inside the column - */ - public function column_default($item, $column_name) { - return $item[$column_name]; - } - - /** - * Provide a callback function to render the checkbox column - * - * @param array $item A row's worth of data - * @return string The formatted string with a checkbox - */ - public function column_cb($item) { - return sprintf( - '', - $this->_args['singular'], - $item['id'] - ); - } - - /** - * Get the bulk actions for this table - * - * @return array Bulk actions - */ - public function get_bulk_actions() { - return $this->_bulk_actions; - } - - /** - * Get a list of columns - * - * @return array - */ - public function get_columns() { - return $this->_columns; - } - - /** - * Add a column to the table - * - * @param string $key Machine-readable column name - * @param string $title Title shown to the user - * @param boolean $sortable Whether or not this is sortable (defaults false) - */ - public function add_column($key, $title, $sortable = false) { - $this->_columns[$key] = $title; - - if ($sortable) $this->_sortable_columns[$key] = array($key, false); - } - - /** - * Add an item (row) to the table - * - * @param array $item A row's worth of data - */ - public function add_item($item) { - array_push($this->_data, $item); - } - - /** - * Add a bulk action to the table - * - * @param string $key Machine-readable action name - * @param string $name Title shown to the user - */ - public function add_bulk_action($key, $name) { - $this->_bulk_actions[$key] = $name; - } - - /** - * Prepares the items (rows) to be rendered - */ - public function prepare_items() { - $total_items = count($this->_data); - $per_page = 25; - - $columns = $this->_columns; - $hidden = array(); - $sortable = $this->_sortable_columns; - - $this->_column_headers = array($columns, $hidden, $sortable); - - $current_page = $this->get_pagenum(); - - $sorted_data = $this->reorder($this->_data); - - $data = array_slice($sorted_data, (($current_page-1)*$per_page),$per_page); - - $this->items = $data; - - $this->set_pagination_args(array( - 'total_items' => $total_items, - 'per_page' => $per_page, - 'total_pages' => ceil($total_items/$per_page) - )); - } - - /** - * Reorder the data according to the sort parameters - * - * @return array Row data, sorted - */ - public function reorder($data) { - function usort_reorder($a, $b) { - $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title'; //If no sort, default to title - $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; //If no order, default to asc - $result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order - return ($order==='asc') ? $result : -$result; //Send final sort direction to usort - } - usort($data, 'usort_reorder'); - - return $data; - } + private $_bulk_actions = array(); + private $_columns = array(); + private $_sortable_columns = array(); + private $_data = array(); + + function __construct() { + global $status, $page; + + parent::__construct(array( + 'singular' => 'item', + 'plural' => 'items', + 'ajax' => false + )); + } + + /** + * Set default column attributes + * + * @param array $item A singular item (one full row's worth of data) + * @param array $column_name The name/slug of the column to be processed + * @return string Text or HTML to be placed inside the column + */ + public function column_default($item, $column_name) { + return $item[$column_name]; + } + + /** + * Provide a callback function to render the checkbox column + * + * @param array $item A row's worth of data + * @return string The formatted string with a checkbox + */ + public function column_cb($item) { + return sprintf( + '', + $this->_args['singular'], + $item['id'] + ); + } + + /** + * Get the bulk actions for this table + * + * @return array Bulk actions + */ + public function get_bulk_actions() { + return $this->_bulk_actions; + } + + /** + * Get a list of columns + * + * @return array + */ + public function get_columns() { + return $this->_columns; + } + + /** + * Add a column to the table + * + * @param string $key Machine-readable column name + * @param string $title Title shown to the user + * @param boolean $sortable Whether or not this is sortable (defaults false) + */ + public function add_column($key, $title, $sortable = false) { + $this->_columns[$key] = $title; + + if ($sortable) $this->_sortable_columns[$key] = array($key, false); + } + + /** + * Add an item (row) to the table + * + * @param array $item A row's worth of data + */ + public function add_item($item) { + array_push($this->_data, $item); + } + + /** + * Add a bulk action to the table + * + * @param string $key Machine-readable action name + * @param string $name Title shown to the user + */ + public function add_bulk_action($key, $name) { + $this->_bulk_actions[$key] = $name; + } + + /** + * Prepares the items (rows) to be rendered + */ + public function prepare_items() { + $total_items = count($this->_data); + $per_page = 25; + + $columns = $this->_columns; + $hidden = array(); + $sortable = $this->_sortable_columns; + + $this->_column_headers = array($columns, $hidden, $sortable); + + $current_page = $this->get_pagenum(); + + $sorted_data = $this->reorder($this->_data); + + $data = array_slice($sorted_data, (($current_page-1)*$per_page),$per_page); + + $this->items = $data; + + $this->set_pagination_args(array( + 'total_items' => $total_items, + 'per_page' => $per_page, + 'total_pages' => ceil($total_items/$per_page) + )); + } + + /** + * Reorder the data according to the sort parameters + * + * @return array Row data, sorted + */ + public function reorder($data) { + function usort_reorder($a, $b) { + $orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title'; //If no sort, default to title + $order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; //If no order, default to asc + $result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order + return ($order==='asc') ? $result : -$result; //Send final sort direction to usort + } + usort($data, 'usort_reorder'); + + return $data; + } } diff --git a/lib/template-tags.php b/lib/template-tags.php index 906f3e2db..d38c432de 100644 --- a/lib/template-tags.php +++ b/lib/template-tags.php @@ -1,5 +1,10 @@ - + diff --git a/wp-convertkit.php b/wp-convertkit.php index d55df2ab3..ed97516ee 100644 --- a/wp-convertkit.php +++ b/wp-convertkit.php @@ -3,7 +3,7 @@ Plugin Name: WP ConvertKit Plugin URI: http://convertkit.com/ Description: Quickly and easily integrate ConvertKit forms into your site. - Version: 1.3.9 + Version: 1.4.0 Author: ConvertKit Author URI: http://convertkit.com/ */ @@ -12,31 +12,46 @@ require_once plugin_dir_path( __FILE__ ) . "/lib/integration/wishlist_member.php"; if(!class_exists('WP_ConvertKit')) { + /** + * Class WP_ConvertKit + */ class WP_ConvertKit { - // Plugin Version - const VERSION = '1.3.9'; + const VERSION = '1.4.0'; - // DB Keys const POST_META_KEY = '_wp_convertkit_post_meta'; + const SETTINGS_NAME = '_wp_convertkit_settings'; - // Page Slugs const SETTINGS_PAGE_SLUG = '_wp_convertkit_settings'; + /** @var ConvertKitAPI */ private static $api; - // Data Caching + /** @var int Data Caching */ private static $cache_period = 0; + + /** @var null */ private static $meta_defaults = null; + + /** @var array */ private static $settings_defaults = array( 'api_key' => '', 'default_form' => 0, ); + /** @var array */ private static $forms_markup = array(); + + /** @var array */ private static $landing_pages_markup = array(); + /** @var string */ + private static $forms_version = '5'; + + /** + * Initialize the class + */ public static function init() { self::add_actions(); self::add_filters(); @@ -47,6 +62,9 @@ public static function init() { self::_api_connect(); } + /** + * Add WP Actions + */ private static function add_actions() { if(is_admin()) { add_action('add_meta_boxes_page', array(__CLASS__, 'add_meta_boxes')); @@ -58,6 +76,9 @@ private static function add_actions() { add_action('save_post', array(__CLASS__, 'save_post_meta'), 10, 2); } + /** + * Add WP Filters + */ private static function add_filters() { if(!is_admin()) { add_filter('the_content', array(__CLASS__, 'append_form')); @@ -66,22 +87,30 @@ private static function add_filters() { add_filter('plugin_action_links_' . plugin_basename(__FILE__), array(__CLASS__, 'add_settings_page_link')); } + /** + * Register ConvertKit shortcodes + */ private static function register_shortcodes() { add_shortcode('convertkit', array(__CLASS__, 'shortcode')); } - // Callbacks - - /// Settings Related - + /** + * Plugin action links callback + * + * @param $links + * @return array + */ public static function add_settings_page_link($links) { $settings_link = sprintf('%s', self::_get_settings_page_link(), __('Settings')); return array('settings' => $settings_link) + $links; } - /// Page / Post Editing - + /** + * Add Meta Boxes callback + * + * @param $post + */ public static function add_meta_boxes($post) { $forms = self::$api->get_resources('forms'); $landing_pages = self::$api->get_resources('landing_pages'); @@ -91,6 +120,11 @@ public static function add_meta_boxes($post) { } } + /** + * Metabox callback + * + * @param $post + */ public static function display_meta_box($post) { $forms = self::$api->get_resources('forms'); $landing_pages = self::$api->get_resources('landing_pages'); @@ -101,6 +135,12 @@ public static function display_meta_box($post) { include('views/backend/meta-boxes/meta-box.php'); } + /** + * Save post meta callback + * + * @param $post_id + * @param $post + */ public static function save_post_meta($post_id, $post) { $data = stripslashes_deep($_POST); if(wp_is_post_autosave($post_id) || wp_is_post_revision($post_id) || !isset($data['wp-convertkit-save-meta-nonce']) || !wp_verify_nonce($data['wp-convertkit-save-meta-nonce'], 'wp-convertkit-save-meta')) { @@ -110,8 +150,12 @@ public static function save_post_meta($post_id, $post) { self::_set_meta($post_id, $data['wp-convertkit']); } - /// Page / Post Display - + /** + * Page/Post display callback + * + * @param $content + * @return string + */ public static function append_form($content) { if(is_singular(array('post')) || is_page()) { $content .= wp_convertkit_get_form_embed(self::_get_meta(get_the_ID())); @@ -120,6 +164,9 @@ public static function append_form($content) { return $content; } + /** + * Replace page content if a landing_page is set + */ public static function page_takeover() { $queried_object = get_queried_object(); if(isset($queried_object->post_type) && 'page' === $queried_object->post_type && ($landing_page_url = self::_get_meta($queried_object->ID, 'landing_page'))) { @@ -133,16 +180,22 @@ public static function page_takeover() { } - /// Shortcodes - + /** + * Shortcode callback + * + * @param $attributes + * @param null $content + * @return mixed|void + */ public static function shortcode($attributes, $content = null) { return wp_convertkit_get_form_embed($attributes); } - // Data Retrieval - - /// Page / Post Meta Data - + /** + * Retrieve meta + * + * @return array|null + */ private static function _get_meta_defaults() { if(is_null(self::$meta_defaults)) { self::$meta_defaults = array( @@ -154,6 +207,12 @@ private static function _get_meta_defaults() { return self::$meta_defaults; } + /** + * @param $post_id + * @param null $meta_key + * + * @return array|bool + */ private static function _get_meta($post_id, $meta_key = null) { $post_id = empty($post_id) ? get_the_ID() : $post_id; @@ -174,6 +233,12 @@ private static function _get_meta($post_id, $meta_key = null) { return is_null($meta_key) ? $meta : (isset($meta[$meta_key]) ? $meta[$meta_key] : false); } + /** + * @param $post_id + * @param $meta + * + * @return mixed + */ private static function _set_meta($post_id, $meta) { $post_id = empty($post_id) ? get_the_ID() : $post_id; @@ -182,38 +247,52 @@ private static function _set_meta($post_id, $meta) { return $meta; } - /// Settings - + /** + * Get plugin settings + * + * @param null $settings_key + * @return mixed|null|void + */ private static function _get_settings($settings_key = null) { $settings = get_option(self::SETTINGS_NAME, self::$settings_defaults); return is_null($settings_key) ? $settings : (isset($settings[$settings_key]) ? $settings[$settings_key] : null); } - /// API - + /** + * Get instance of ConvertKitAPI + */ private static function _api_connect() { $api_key = self::_get_settings('api_key'); + $api_secret = self::_get_settings('api_secret'); - self::$api = new ConvertKitAPI($api_key); + self::$api = new ConvertKitAPI($api_key,$api_secret); } - // Links - + /** + * Get link to the plugin settings page + * + * @param array $query_args + * @return string + */ private static function _get_settings_page_link($query_args = array()) { $query_args = array('page' => self::SETTINGS_PAGE_SLUG) + $query_args; return add_query_arg($query_args, admin_url('options-general.php')); } - // Template Tags - + /** + * Retrieve hosted form markup form the API and format + * + * @param $attributes + * @return string + */ public static function get_form_embed($attributes) { $attributes = shortcode_atts(array( 'form' => -1, ), $attributes); - extract($attributes); + $form = $attributes['form']; $form_id = intval(($form < 0) ? self::_get_settings('default_form') : $form); $form = false; @@ -230,7 +309,14 @@ public static function get_form_embed($attributes) { } } - $form_markup = self::$api->get_resource($form['embed']); + $url = add_query_arg( array( + 'api_key' => self::_get_settings('api_key'), + 'v' => self::$forms_version, + ), + 'https://forms.convertkit.com/' . $form['id'] . '.html' + ); + + $form_markup = self::$api->get_resource( $url ); return $form_markup; }