Constant Contact Forms - Version 1.1.0

Version Description

  • Added: Widget that allows you to select a form to display.
  • Added: Small metabox in form editor showing shortcode to use for current form.
  • Added: Field and filter for text shown on the rendered submit button.
  • Added: Developers: Inline documentation of actions and filters.
  • Fixed: Loading position of Constant Contact stylesheet. Should now load in <head>.
  • Fixed: Removed redundant "Add form" button on Constant Contact form editor TinyMCE.
  • Fixed: Removed required attribute for Address line 2 when line 1 is required.
  • Updated: Labels in Constant Contact Form list around none available and none in trash.
Download this release

Release Info

Developer constantcontact
Plugin Icon 128x128 Constant Contact Forms
Version 1.1.0
Comparing to
See all releases

Code changes from version 1.0.2 to 1.1.0

constant-contact-forms.php CHANGED
@@ -12,7 +12,7 @@
12
  * Plugin Name: Constant Contact Forms for WordPress
13
  * Plugin URI: https://www.constantcontact.com
14
  * Description: Be a better marketer. All it takes is Constant Contact email marketing.
15
- * Version: 1.0.2
16
  * Author: Constant Contact
17
  * Author URI: https://www.constantcontact.com
18
  * License: GPLv3
@@ -77,7 +77,7 @@ class Constant_Contact {
77
  * @var string
78
  * @since 1.0.0
79
  */
80
- const VERSION = '1.0.1';
81
 
82
  /**
83
  * URL of plugin directory
@@ -197,10 +197,10 @@ class Constant_Contact {
197
  */
198
  protected function __construct() {
199
 
200
- // Set up our plugin name
201
  $this->plugin_name = __( 'Constant Contact', 'constant-contact-forms' );
202
 
203
- // Set up some helper properties
204
  $this->basename = plugin_basename( __FILE__ );
205
  $this->url = plugin_dir_url( __FILE__ );
206
  $this->path = plugin_dir_path( __FILE__ );
@@ -210,16 +210,16 @@ class Constant_Contact {
210
  return;
211
  }
212
 
213
- // Load our plugin and our libraries
214
  $this->plugin_classes();
215
  $this->load_libs();
216
 
217
- // If we're in the admin, also load up the admin classes
218
  if ( is_admin() ) {
219
  $this->admin_plugin_classes();
220
  }
221
 
222
- // Include our helper functions function for end-users
223
  Constant_Contact::include_file( 'helper-functions', false );
224
  }
225
 
@@ -277,17 +277,18 @@ class Constant_Contact {
277
  */
278
  public function hooks() {
279
 
280
- // Hook in our older includes and our init method
281
  add_action( 'init', array( $this, 'init' ) );
282
  add_action( 'init', array( $this, 'includes' ), 5 );
 
283
 
284
  // Our vendor files will do a check for ISSSL, so we want to set it to be that.
285
- // See Guzzle for more info and usage of this
286
  if ( is_ssl() || ! defined( 'ISSSL' ) ) {
287
  define( 'ISSSL', true );
288
  }
289
 
290
- // Allow shortcodes in widgets for our plugin
291
  add_filter( 'widget_text', 'do_shortcode' );
292
 
293
  if ( is_admin() ) {
@@ -313,10 +314,10 @@ class Constant_Contact {
313
  function _deactivate() {
314
 
315
  // If we deactivate the plugin, remove our saved dismiss state for the activation
316
- // admin notice that pops up, so we can re-prompt the user to connect
317
  $this->notifications->delete_dismissed_notification( 'activation' );
318
 
319
- // Remove our saved transients for our lists, so we force a refresh on re-connection
320
  delete_transient( 'ctct_lists' );
321
 
322
  }
@@ -329,7 +330,7 @@ class Constant_Contact {
329
  */
330
  public function init() {
331
 
332
- // Load our textdomain
333
  load_plugin_textdomain( $this->text_domain, false, dirname( $this->basename ) . '/languages/' );
334
  }
335
 
@@ -341,7 +342,7 @@ class Constant_Contact {
341
  */
342
  public function load_libs() {
343
 
344
- // Set an array of libraries we need to load
345
  $libs = array(
346
  'CMB2/init.php',
347
  'constantcontact/autoload.php',
@@ -362,15 +363,15 @@ class Constant_Contact {
362
  'defuse-php-encryption/RuntimeTests.php',
363
  );
364
 
365
- // If we don't alrady have WDS_Shortcodes loaded somewhere else, load it up
366
  if ( ! function_exists( 'wds_shortcodes' ) ) {
367
  $libs[] = 'WDS-Shortcodes/wds-shortcodes.php';
368
  }
369
 
370
- // Loop through our vendor libraries and load them
371
  foreach ( $libs as $lib ) {
372
 
373
- // Require_once our file
374
  require_once( $this->dir( "vendor/{$lib}" ) );
375
  }
376
  }
@@ -382,22 +383,31 @@ class Constant_Contact {
382
  */
383
  public function includes() {
384
 
385
- // Only load this if we have the WDS Shortcodes class
386
  if ( class_exists( 'WDS_Shortcodes' ) ) {
387
 
388
- // Set up our base WDS_Shortcodes class
 
 
 
389
  $this->shortcode = new ConstantContact_Shortcode();
390
 
391
- // Set our custom shortcode with correct version and data
392
  $this->shortcode_admin = new ConstantContact_Shortcode_Admin(
393
  $this->shortcode->shortcode,
394
  self::VERSION,
395
  $this->shortcode->atts_defaults
396
  );
397
 
398
- // Launch it
399
  $this->shortcode_admin->hooks();
400
  }
 
 
 
 
 
 
401
  }
402
 
403
  /**
@@ -408,9 +418,9 @@ class Constant_Contact {
408
  */
409
  public function ajax_save_clear_first_form() {
410
 
411
- if ( isset( $_POST['action'] ) && 'ctct_dismiss_first_modal' === $_POST['action'] ) { // Input var okay
412
 
413
- // Save our dismiss for the first form modal
414
  update_option( 'ctct_first_form_modal_dismissed', time() );
415
  }
416
  wp_die();
@@ -462,33 +472,34 @@ class Constant_Contact {
462
  *
463
  * @since 1.0.0
464
  * @param string $filename Name of the file to be included.
 
465
  * @return bool Result of include call.
466
  */
467
  public static function include_file( $filename, $include_class = true ) {
468
 
469
- // By default, all files are named 'class-something.php'
470
  if ( $include_class ) {
471
  $filename = 'class-' . $filename;
472
  }
473
 
474
- // Get the file
475
  $file = self::dir( 'includes/' . $filename . '.php' );
476
 
477
- // If its there, include it
478
  if ( file_exists( $file ) ) {
479
  return include_once( $file );
480
  }
481
 
482
- // Wasn't there
483
  return false;
484
  }
485
 
486
  /**
487
- * This plugin's directory
488
  *
489
  * @since 1.0.0
490
  * @param string $path (optional) appended path.
491
- * @return string Directory and path
492
  */
493
  public static function dir( $path = '' ) {
494
  static $dir;
@@ -501,7 +512,7 @@ class Constant_Contact {
501
  *
502
  * @since 1.0.0
503
  * @param string $path (optional) appended path.
504
- * @return string URL and path
505
  */
506
  public static function url( $path = '' ) {
507
  static $url;
@@ -524,11 +535,40 @@ class Constant_Contact {
524
 
525
  return file_get_contents( $license );
526
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
527
  }
528
- // Kick it off.
529
  add_action( 'plugins_loaded', array( constant_contact(), 'hooks' ) );
530
 
531
- // Hook in Activation / Deactivation hooks
532
  register_activation_hook( __FILE__ , array( constant_contact(), '_activate' ) );
533
  register_deactivation_hook( __FILE__ , array( constant_contact(), '_deactivate' ) );
534
 
12
  * Plugin Name: Constant Contact Forms for WordPress
13
  * Plugin URI: https://www.constantcontact.com
14
  * Description: Be a better marketer. All it takes is Constant Contact email marketing.
15
+ * Version: 1.1.0
16
  * Author: Constant Contact
17
  * Author URI: https://www.constantcontact.com
18
  * License: GPLv3
77
  * @var string
78
  * @since 1.0.0
79
  */
80
+ const VERSION = '1.1.0';
81
 
82
  /**
83
  * URL of plugin directory
197
  */
198
  protected function __construct() {
199
 
200
+ // Set up our plugin name.
201
  $this->plugin_name = __( 'Constant Contact', 'constant-contact-forms' );
202
 
203
+ // Set up some helper properties.
204
  $this->basename = plugin_basename( __FILE__ );
205
  $this->url = plugin_dir_url( __FILE__ );
206
  $this->path = plugin_dir_path( __FILE__ );
210
  return;
211
  }
212
 
213
+ // Load our plugin and our libraries.
214
  $this->plugin_classes();
215
  $this->load_libs();
216
 
217
+ // If we're in the admin, also load up the admin classes.
218
  if ( is_admin() ) {
219
  $this->admin_plugin_classes();
220
  }
221
 
222
+ // Include our helper functions function for end-users.
223
  Constant_Contact::include_file( 'helper-functions', false );
224
  }
225
 
277
  */
278
  public function hooks() {
279
 
280
+ // Hook in our older includes and our init method.
281
  add_action( 'init', array( $this, 'init' ) );
282
  add_action( 'init', array( $this, 'includes' ), 5 );
283
+ add_action( 'widgets_init', array( $this, 'widgets' ) );
284
 
285
  // Our vendor files will do a check for ISSSL, so we want to set it to be that.
286
+ // See Guzzle for more info and usage of this.
287
  if ( is_ssl() || ! defined( 'ISSSL' ) ) {
288
  define( 'ISSSL', true );
289
  }
290
 
291
+ // Allow shortcodes in widgets for our plugin.
292
  add_filter( 'widget_text', 'do_shortcode' );
293
 
294
  if ( is_admin() ) {
314
  function _deactivate() {
315
 
316
  // If we deactivate the plugin, remove our saved dismiss state for the activation
317
+ // admin notice that pops up, so we can re-prompt the user to connect.
318
  $this->notifications->delete_dismissed_notification( 'activation' );
319
 
320
+ // Remove our saved transients for our lists, so we force a refresh on re-connection.
321
  delete_transient( 'ctct_lists' );
322
 
323
  }
330
  */
331
  public function init() {
332
 
333
+ // Load our textdomain.
334
  load_plugin_textdomain( $this->text_domain, false, dirname( $this->basename ) . '/languages/' );
335
  }
336
 
342
  */
343
  public function load_libs() {
344
 
345
+ // Set an array of libraries we need to load.
346
  $libs = array(
347
  'CMB2/init.php',
348
  'constantcontact/autoload.php',
363
  'defuse-php-encryption/RuntimeTests.php',
364
  );
365
 
366
+ // If we don't alrady have WDS_Shortcodes loaded somewhere else, load it up.
367
  if ( ! function_exists( 'wds_shortcodes' ) ) {
368
  $libs[] = 'WDS-Shortcodes/wds-shortcodes.php';
369
  }
370
 
371
+ // Loop through our vendor libraries and load them.
372
  foreach ( $libs as $lib ) {
373
 
374
+ // Require_once our file.
375
  require_once( $this->dir( "vendor/{$lib}" ) );
376
  }
377
  }
383
  */
384
  public function includes() {
385
 
386
+ // Only load this if we have the WDS Shortcodes class.
387
  if ( class_exists( 'WDS_Shortcodes' ) ) {
388
 
389
+ if ( $this->is_ctct_editor_screen() ) {
390
+ return;
391
+ }
392
+ // Set up our base WDS_Shortcodes class.
393
  $this->shortcode = new ConstantContact_Shortcode();
394
 
395
+ // Set our custom shortcode with correct version and data.
396
  $this->shortcode_admin = new ConstantContact_Shortcode_Admin(
397
  $this->shortcode->shortcode,
398
  self::VERSION,
399
  $this->shortcode->atts_defaults
400
  );
401
 
402
+ // Launch it.
403
  $this->shortcode_admin->hooks();
404
  }
405
+
406
+ }
407
+
408
+ public function widgets() {
409
+ require_once constant_contact()->path . 'includes/widgets/contact-form-select.php';
410
+ register_widget( 'ConstantContactWidget' );
411
  }
412
 
413
  /**
418
  */
419
  public function ajax_save_clear_first_form() {
420
 
421
+ if ( isset( $_POST['action'] ) && 'ctct_dismiss_first_modal' === $_POST['action'] ) { // Input var okay.
422
 
423
+ // Save our dismiss for the first form modal.
424
  update_option( 'ctct_first_form_modal_dismissed', time() );
425
  }
426
  wp_die();
472
  *
473
  * @since 1.0.0
474
  * @param string $filename Name of the file to be included.
475
+ * @param bool $include_class Whether or ot to include the class.
476
  * @return bool Result of include call.
477
  */
478
  public static function include_file( $filename, $include_class = true ) {
479
 
480
+ // By default, all files are named 'class-something.php'.
481
  if ( $include_class ) {
482
  $filename = 'class-' . $filename;
483
  }
484
 
485
+ // Get the file.
486
  $file = self::dir( 'includes/' . $filename . '.php' );
487
 
488
+ // If its there, include it.
489
  if ( file_exists( $file ) ) {
490
  return include_once( $file );
491
  }
492
 
493
+ // Wasn't there.
494
  return false;
495
  }
496
 
497
  /**
498
+ * This plugin's directory.
499
  *
500
  * @since 1.0.0
501
  * @param string $path (optional) appended path.
502
+ * @return string Directory and path
503
  */
504
  public static function dir( $path = '' ) {
505
  static $dir;
512
  *
513
  * @since 1.0.0
514
  * @param string $path (optional) appended path.
515
+ * @return string URL and path
516
  */
517
  public static function url( $path = '' ) {
518
  static $url;
535
 
536
  return file_get_contents( $license );
537
  }
538
+
539
+ /**
540
+ * Check if we are editing a Constant Contact post type post.
541
+ *
542
+ * @since 1.1.0
543
+ *
544
+ * @param int $post_id Post ID to check for.
545
+ * @return bool
546
+ */
547
+ public function is_ctct_editor_screen( $post_id = 0 ) {
548
+
549
+ if ( empty( $post_id ) ) {
550
+ if ( ! empty( $_GET ) && isset( $_GET['post'] ) ) {
551
+ $post_id = absint( $_GET['post'] );
552
+ }
553
+ }
554
+
555
+ if ( empty( $_GET ) ) {
556
+ return false;
557
+ }
558
+
559
+ if ( isset( $_GET['post_type'] ) && 'ctct_forms' === (string) $_GET['post_type'] ) {
560
+ return true;
561
+ }
562
+
563
+ if ( 'ctct_forms' === get_post_type( $post_id ) ) {
564
+ return true;
565
+ }
566
+
567
+ return false;
568
+ }
569
  }
 
570
  add_action( 'plugins_loaded', array( constant_contact(), 'hooks' ) );
571
 
 
572
  register_activation_hook( __FILE__ , array( constant_contact(), '_activate' ) );
573
  register_deactivation_hook( __FILE__ , array( constant_contact(), '_deactivate' ) );
574
 
includes/class-admin-pages.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage AdminPages
5
  * @author Constant Contact
@@ -12,18 +14,18 @@
12
  class ConstantContact_Admin_Pages {
13
 
14
  /**
15
- * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
21
 
22
  /**
23
- * Constructor
24
  *
25
- * @since 1.0.0
26
- * @return void
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -38,18 +40,17 @@ class ConstantContact_Admin_Pages {
38
  */
39
  public function hooks() {
40
 
41
- // Add our styles to the site
42
  add_action( 'admin_init', array( $this, 'styles' ) );
43
  }
44
 
45
  /**
46
  * Global admin style enqueue stuff
47
  *
48
- * @since 1.0.0
49
  */
50
  public function styles() {
51
 
52
- // Register our admin form styles
53
  wp_register_style(
54
  'constant-contact-forms',
55
  constant_contact()->url() . 'assets/css/admin-forms.css',
@@ -57,7 +58,6 @@ class ConstantContact_Admin_Pages {
57
  constant_contact()->version
58
  );
59
 
60
- // Register our admin pages styles
61
  wp_register_style(
62
  'constant_contact_admin_pages',
63
  constant_contact()->url() . 'assets/css/admin-pages.css',
@@ -67,14 +67,21 @@ class ConstantContact_Admin_Pages {
67
  }
68
 
69
  /**
70
- * Gets the help text for help page
71
  *
72
- * @since 1.0.0
73
- * @return array array of all the help text
 
74
  */
75
  public function get_help_texts() {
76
 
77
- // Grab our help text. This can be filtered elsewhere, as well.
 
 
 
 
 
 
78
  return apply_filters( 'constant_contact_help_texts', array(
79
  array(
80
  'title' => __( 'This is a sample help header', 'constant-contact-forms' ),
@@ -88,14 +95,20 @@ class ConstantContact_Admin_Pages {
88
  }
89
 
90
  /**
91
- * Get faq text for help page
92
  *
93
  * @since 1.0.0
94
- * @return array array of all the text
95
  */
96
  public function get_faq_texts() {
97
 
98
- // Get our FAQ texts. This can be filtered
 
 
 
 
 
 
99
  return apply_filters( 'constant_contact_faq_texts', array(
100
  array(
101
  'title' => __( 'Is this a sample question?', 'constant-contact-forms' ),
@@ -115,7 +128,6 @@ class ConstantContact_Admin_Pages {
115
  */
116
  public function help_page() {
117
 
118
- // Enqueue our JS and styles
119
  wp_enqueue_script( 'ctct_form' );
120
  wp_enqueue_style( 'constant_contact_admin_pages' );
121
 
@@ -132,16 +144,16 @@ class ConstantContact_Admin_Pages {
132
  </h2>
133
  <ol id="help_ctct">
134
  <?php
135
- // Grab our FAQs
136
  $helps = $this->get_help_texts();
137
 
138
- // Make sure we have some
139
  if ( is_array( $helps ) ) {
140
 
141
- // Loop through each$help
142
  foreach ( $helps as $help ) {
143
 
144
- // Make sure we have the right data
145
  if ( ! isset( $help['title'] ) || ! isset( $help['content'] ) ) {
146
  continue;
147
  }
@@ -166,16 +178,14 @@ class ConstantContact_Admin_Pages {
166
  </h2>
167
  <ol id="faq_ctct">
168
  <?php
169
- // Grab our FAQs
170
  $faqs = $this->get_faq_texts();
171
 
172
- // Make sure we have some
173
  if ( is_array( $faqs ) ) {
174
 
175
- // Loop through each faq
176
  foreach ( $faqs as $faq ) {
177
 
178
- // Make sure we have the right data
179
  if ( ! isset( $faq['title'] ) || ! isset( $faq['content'] ) ) {
180
  continue;
181
  }
@@ -201,23 +211,21 @@ class ConstantContact_Admin_Pages {
201
  }
202
 
203
  /**
204
- * Display our about page
205
  *
206
- * @since 1.0.0
207
  */
208
  public function about_page() {
209
 
210
- // make it so pretty
211
  wp_enqueue_style( 'constant_contact_admin_pages' );
212
 
213
- // Set our placeholder vars for links and stuff
214
  $proof = $auth_link = $new_link = '';
215
 
216
  // @codingStandardsIgnoreStart
217
  if ( ! constant_contact()->api->is_connected() ) {
218
  // @codingStandardsIgnoreEnd
219
 
220
- // Get our middleware link
221
  $proof = constant_contact()->authserver->set_verification_option();
222
  $auth_link = constant_contact()->authserver->do_connect_url( $proof );
223
  $new_link = constant_contact()->authserver->do_signup_url( $proof );
@@ -246,7 +254,7 @@ class ConstantContact_Admin_Pages {
246
  <p>
247
  <?php esc_attr_e( 'Using your sign-up forms to collect email addresses? Email marketing is a great way to stay connected with visitors after they’ve left your site. And with an active Constant Contact account, every new subscriber you capture will be automatically added to your selected email lists. ', 'constant-contact-forms' ); ?>
248
  </p>
249
- <?php if ( $new_link ) { // If we have a link, then display the connect button ?>
250
  <a href="<?php echo esc_url_raw( $new_link ); ?>" target="_blank" class="button button-orange" title="<?php esc_attr_e( 'Try us Free', 'constant-contact-forms' ); ?>"><?php esc_attr_e( 'Try us Free', 'constant-contact-forms' ); ?></a>
251
  <?php } ?>
252
  </div>
@@ -256,7 +264,7 @@ class ConstantContact_Admin_Pages {
256
  </span>
257
  <div class="clear"></div>
258
  <hr>
259
- <?php if ( $auth_link ) { // If we have a link, then display the connect button ?>
260
  <h2><?php esc_attr_e( 'Already have a Constant Contact account?', 'constant-contact-forms' ); ?></h2>
261
  <a href="<?php echo esc_url_raw( $auth_link ); ?>" class="button button-blue ctct-connect">
262
  <?php esc_html_e( 'Connect the plugin', 'constant-contact-forms' ); ?>
1
  <?php
2
  /**
3
+ * Admin Pages.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage AdminPages
7
  * @author Constant Contact
14
  class ConstantContact_Admin_Pages {
15
 
16
  /**
17
+ * Parent plugin class.
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
23
 
24
  /**
25
+ * Constructor.
26
  *
27
+ * @since 1.0.0
28
+ * @param object $plugin Plugin parent.
29
  */
30
  public function __construct( $plugin ) {
31
  $this->plugin = $plugin;
40
  */
41
  public function hooks() {
42
 
43
+ // Add our styles to the site.
44
  add_action( 'admin_init', array( $this, 'styles' ) );
45
  }
46
 
47
  /**
48
  * Global admin style enqueue stuff
49
  *
50
+ * @since 1.0.0
51
  */
52
  public function styles() {
53
 
 
54
  wp_register_style(
55
  'constant-contact-forms',
56
  constant_contact()->url() . 'assets/css/admin-forms.css',
58
  constant_contact()->version
59
  );
60
 
 
61
  wp_register_style(
62
  'constant_contact_admin_pages',
63
  constant_contact()->url() . 'assets/css/admin-pages.css',
67
  }
68
 
69
  /**
70
+ * Gets the help text for help page.
71
  *
72
+ * @since 1.0.0
73
+ *
74
+ * @return array Array of all the help text.
75
  */
76
  public function get_help_texts() {
77
 
78
+ /**
79
+ * Filters our default help texts.
80
+ *
81
+ * @since 1.0.0
82
+ *
83
+ * @param array $value Array of arrays with title/content values
84
+ */
85
  return apply_filters( 'constant_contact_help_texts', array(
86
  array(
87
  'title' => __( 'This is a sample help header', 'constant-contact-forms' ),
95
  }
96
 
97
  /**
98
+ * Get faq text for help page.
99
  *
100
  * @since 1.0.0
101
+ * @return array Array of all the text.
102
  */
103
  public function get_faq_texts() {
104
 
105
+ /**
106
+ * Filters our FAQ text for the help page.
107
+ *
108
+ * @since 1.0.0
109
+ *
110
+ * @param array $value Array of arrays for help text.
111
+ */
112
  return apply_filters( 'constant_contact_faq_texts', array(
113
  array(
114
  'title' => __( 'Is this a sample question?', 'constant-contact-forms' ),
128
  */
129
  public function help_page() {
130
 
 
131
  wp_enqueue_script( 'ctct_form' );
132
  wp_enqueue_style( 'constant_contact_admin_pages' );
133
 
144
  </h2>
145
  <ol id="help_ctct">
146
  <?php
147
+ // Grab our FAQs.
148
  $helps = $this->get_help_texts();
149
 
150
+ // Make sure we have some.
151
  if ( is_array( $helps ) ) {
152
 
153
+ // Loop through each $help.
154
  foreach ( $helps as $help ) {
155
 
156
+ // Make sure we have the right data.
157
  if ( ! isset( $help['title'] ) || ! isset( $help['content'] ) ) {
158
  continue;
159
  }
178
  </h2>
179
  <ol id="faq_ctct">
180
  <?php
181
+ // Grab our FAQs.
182
  $faqs = $this->get_faq_texts();
183
 
 
184
  if ( is_array( $faqs ) ) {
185
 
 
186
  foreach ( $faqs as $faq ) {
187
 
188
+ // Make sure we have the right data.
189
  if ( ! isset( $faq['title'] ) || ! isset( $faq['content'] ) ) {
190
  continue;
191
  }
211
  }
212
 
213
  /**
214
+ * Display our about page.
215
  *
216
+ * @since 1.0.0
217
  */
218
  public function about_page() {
219
 
 
220
  wp_enqueue_style( 'constant_contact_admin_pages' );
221
 
 
222
  $proof = $auth_link = $new_link = '';
223
 
224
  // @codingStandardsIgnoreStart
225
  if ( ! constant_contact()->api->is_connected() ) {
226
  // @codingStandardsIgnoreEnd
227
 
228
+ // Get our middleware link.
229
  $proof = constant_contact()->authserver->set_verification_option();
230
  $auth_link = constant_contact()->authserver->do_connect_url( $proof );
231
  $new_link = constant_contact()->authserver->do_signup_url( $proof );
254
  <p>
255
  <?php esc_attr_e( 'Using your sign-up forms to collect email addresses? Email marketing is a great way to stay connected with visitors after they’ve left your site. And with an active Constant Contact account, every new subscriber you capture will be automatically added to your selected email lists. ', 'constant-contact-forms' ); ?>
256
  </p>
257
+ <?php if ( $new_link ) { // If we have a link, then display the connect button. ?>
258
  <a href="<?php echo esc_url_raw( $new_link ); ?>" target="_blank" class="button button-orange" title="<?php esc_attr_e( 'Try us Free', 'constant-contact-forms' ); ?>"><?php esc_attr_e( 'Try us Free', 'constant-contact-forms' ); ?></a>
259
  <?php } ?>
260
  </div>
264
  </span>
265
  <div class="clear"></div>
266
  <hr>
267
+ <?php if ( $auth_link ) { // If we have a link, then display the connect button. ?>
268
  <h2><?php esc_attr_e( 'Already have a Constant Contact account?', 'constant-contact-forms' ); ?></h2>
269
  <a href="<?php echo esc_url_raw( $auth_link ); ?>" class="button button-blue ctct-connect">
270
  <?php esc_html_e( 'Connect the plugin', 'constant-contact-forms' ); ?>
includes/class-admin.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Admin
5
  * @author Constant Contact
@@ -44,7 +46,7 @@ class ConstantContact_Admin {
44
  protected $options_page = '';
45
 
46
  /**
47
- * Parent plugin class
48
  *
49
  * @var class
50
  * @since 0.0.1
@@ -62,8 +64,7 @@ class ConstantContact_Admin {
62
  /**
63
  * Constructor
64
  *
65
- * @since 1.0.0
66
- * @return void
67
  */
68
  public function __construct( $plugin, $basename ) {
69
  $this->plugin = $plugin;
@@ -134,6 +135,11 @@ class ConstantContact_Admin {
134
  */
135
  public function admin_page_display() {
136
 
 
 
 
 
 
137
  do_action( 'constant_contact_admin_before' );
138
 
139
  ?>
@@ -142,20 +148,20 @@ class ConstantContact_Admin {
142
  <div id="options-wrap">
143
  <?php
144
 
145
- // If we have a page get var set, let's try to pull out the page we're looking for
146
- if ( isset( $_GET['page'] ) ) { // Input var okay.
147
 
148
- $page_key = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // Input var okay.
149
 
150
  $page = explode( $this->key . '_', $page_key );
151
  } else {
152
  $page = array();
153
  }
154
 
155
- // If we have a second element set, let's check out what it should be
156
  if ( isset( $page[1] ) && $page[1] ) {
157
 
158
- // switch through our whitelisted pages that we shoud include
159
  switch ( esc_attr( $page[1] ) ) {
160
  case 'about':
161
  constant_contact()->admin_pages->about_page();
@@ -174,6 +180,12 @@ class ConstantContact_Admin {
174
  </div>
175
  </div>
176
  <?php
 
 
 
 
 
 
177
  do_action( 'constant_contact_admin_after' );
178
  }
179
 
@@ -183,7 +195,7 @@ class ConstantContact_Admin {
183
  * @since 1.0.0
184
  *
185
  * @param int $object_id Option key.
186
- * @param array $updated Array of updated fields.
187
  */
188
  public function settings_notices( $object_id, $updated ) {
189
  if ( $object_id !== $this->key || empty( $updated ) ) {
@@ -221,6 +233,7 @@ class ConstantContact_Admin {
221
  * @internal
222
  *
223
  * @since 1.0.0
 
224
  * @param array $columns post list columns.
225
  * @return array $columns Array of columns to add.
226
  */
@@ -233,7 +246,7 @@ class ConstantContact_Admin {
233
  }
234
 
235
  /**
236
- * Content of custom post columns.
237
  *
238
  * @internal
239
  *
@@ -243,10 +256,10 @@ class ConstantContact_Admin {
243
  */
244
  public function custom_columns( $column, $post_id ) {
245
 
246
- // Force our $post_id to an int
247
  $post_id = absint( $post_id );
248
 
249
- // if its a 0 bail out
250
  if ( ! $post_id ) {
251
  return;
252
  }
@@ -262,40 +275,55 @@ class ConstantContact_Admin {
262
  }
263
 
264
  /**
265
- * Add social media links to plugin screen
 
 
266
  *
267
- * @since 1.0.0
268
  * @param array $links plugin action links.
 
269
  */
270
  public function add_social_links( $links ) {
271
- // Get twitter share link
272
  $twitter_cta = __( 'Check out the official WordPress plugin from @constantcontact :', 'constant-contact-forms' );
273
 
274
  // Add about page.
275
  $add_links[] = $this->get_admin_link( __( 'About', 'constant-contact-forms' ), 'about' );
276
  $add_links[] = $this->get_admin_link( __( 'License', 'constant-contact-forms' ), 'license' );
277
 
 
 
 
 
 
 
 
278
  $site_link = apply_filters( 'constant_contact_social_base_url' , 'https://constantcontact.com/' );
279
 
280
- // Start our social share links
281
  $social_share = __( 'Spread the word!', 'constant-contact-forms' );
282
  $add_links[] = '<a title="' . $social_share . '" href="https://www.facebook.com/sharer/sharer.php?u=' . urlencode( $site_link ) . '" target="_blank" class="dashicons-before dashicons-facebook"></a>';
283
  $add_links[] = '<a title="' . $social_share . '" href="https://twitter.com/home?status=' . $twitter_cta . ' ' . $site_link . '" target="_blank" class="dashicons-before dashicons-twitter"></a>';
284
  $add_links[] = '<a title="' . $social_share . '" href="https://plus.google.com/share?url=' . urlencode( $site_link ) . '" target="_blank" class="dashicons-before dashicons-googleplus"></a>';
285
 
286
- // Allow filtering our links
 
 
 
 
 
 
287
  $add_links = apply_filters( 'constant_contact_social_links', $add_links );
288
 
289
- // Send it back
290
  return array_merge( $links, $add_links );
291
  }
292
 
293
  /**
294
  * Get a link to an admin page.
295
  *
296
- * @since 1.0.1
297
- * @param string $text The link text to use.
298
- * @param string $link_slug The slug of the admin page.
 
299
  * @return string
300
  */
301
  public function get_admin_link( $text, $link_slug ) {
@@ -313,22 +341,20 @@ class ConstantContact_Admin {
313
  }
314
 
315
  /**
316
- * Scripts
317
  *
318
- * @since 1.0.0
319
- * @return void
320
  */
321
  public function scripts() {
322
 
323
  global $pagenow;
324
 
325
- // Check if we are in debug mode. allow
326
  $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG === true ? true : false;
327
 
328
- // based on our debug mode, potentially add a min prefix
329
  $suffix = ( true === $debug ) ? '' : '.min';
330
 
331
- // Register our javascript file.
332
  wp_register_script(
333
  'ctct_form',
334
  constant_contact()->url() . 'assets/js/ctct-plugin-admin' . $suffix . '.js',
@@ -340,6 +366,13 @@ class ConstantContact_Admin {
340
  wp_localize_script(
341
  'ctct_form',
342
  'ctct_texts',
 
 
 
 
 
 
 
343
  apply_filters( 'constant_contact_localized_js_texts', array(
344
  'leavewarning' => __( 'You have unsaved changes.', 'constant-contact-forms' ),
345
  'move_up' => __( 'move up', 'constant-contact-forms' ),
@@ -347,7 +380,13 @@ class ConstantContact_Admin {
347
  ) )
348
  );
349
 
350
- // Allow filtering of allowed pages that we load scripts on
 
 
 
 
 
 
351
  $allowed_pages = apply_filters( 'constant_contact_script_load_pages', array( 'post.php', 'post-new.php' ) );
352
 
353
  if ( $pagenow && in_array( $pagenow, $allowed_pages, true ) ) {
1
  <?php
2
  /**
3
+ * Admin
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Admin
7
  * @author Constant Contact
46
  protected $options_page = '';
47
 
48
  /**
49
+ * Parent plugin class.
50
  *
51
  * @var class
52
  * @since 0.0.1
64
  /**
65
  * Constructor
66
  *
67
+ * @since 1.0.0
 
68
  */
69
  public function __construct( $plugin, $basename ) {
70
  $this->plugin = $plugin;
135
  */
136
  public function admin_page_display() {
137
 
138
+ /**
139
+ * Fires before the Constant Contact admin page display.
140
+ *
141
+ * @since 1.0.0
142
+ */
143
  do_action( 'constant_contact_admin_before' );
144
 
145
  ?>
148
  <div id="options-wrap">
149
  <?php
150
 
151
+ // If we have a page get var set, let's try to pull out the page we're looking for.
152
+ if ( isset( $_GET['page'] ) ) {
153
 
154
+ $page_key = sanitize_text_field( wp_unslash( $_GET['page'] ) );
155
 
156
  $page = explode( $this->key . '_', $page_key );
157
  } else {
158
  $page = array();
159
  }
160
 
161
+ // If we have a second element set, let's check out what it should be.
162
  if ( isset( $page[1] ) && $page[1] ) {
163
 
164
+ // Switch through our whitelisted pages that we shoud include.
165
  switch ( esc_attr( $page[1] ) ) {
166
  case 'about':
167
  constant_contact()->admin_pages->about_page();
180
  </div>
181
  </div>
182
  <?php
183
+
184
+ /**
185
+ * Fires after the Constant Contact admin page display.
186
+ *
187
+ * @since 1.0.0
188
+ */
189
  do_action( 'constant_contact_admin_after' );
190
  }
191
 
195
  * @since 1.0.0
196
  *
197
  * @param int $object_id Option key.
198
+ * @param array $updated Array of updated fields.
199
  */
200
  public function settings_notices( $object_id, $updated ) {
201
  if ( $object_id !== $this->key || empty( $updated ) ) {
233
  * @internal
234
  *
235
  * @since 1.0.0
236
+ *
237
  * @param array $columns post list columns.
238
  * @return array $columns Array of columns to add.
239
  */
246
  }
247
 
248
  /**
249
+ * Content of custom post columns.
250
  *
251
  * @internal
252
  *
256
  */
257
  public function custom_columns( $column, $post_id ) {
258
 
259
+ // Force our $post_id to an int.
260
  $post_id = absint( $post_id );
261
 
262
+ // If its a 0 bail out.
263
  if ( ! $post_id ) {
264
  return;
265
  }
275
  }
276
 
277
  /**
278
+ * Add social media links to plugin screen.
279
+ *
280
+ * @since 1.0.0
281
  *
 
282
  * @param array $links plugin action links.
283
+ * @return array
284
  */
285
  public function add_social_links( $links ) {
286
+ // Get Twitter share link.
287
  $twitter_cta = __( 'Check out the official WordPress plugin from @constantcontact :', 'constant-contact-forms' );
288
 
289
  // Add about page.
290
  $add_links[] = $this->get_admin_link( __( 'About', 'constant-contact-forms' ), 'about' );
291
  $add_links[] = $this->get_admin_link( __( 'License', 'constant-contact-forms' ), 'license' );
292
 
293
+ /**
294
+ * Filters the Constant Contact base url used for social links.
295
+ *
296
+ * @since 1.0.0
297
+ *
298
+ * @param string $value Social URL base.
299
+ */
300
  $site_link = apply_filters( 'constant_contact_social_base_url' , 'https://constantcontact.com/' );
301
 
302
+ // Start our social share links.
303
  $social_share = __( 'Spread the word!', 'constant-contact-forms' );
304
  $add_links[] = '<a title="' . $social_share . '" href="https://www.facebook.com/sharer/sharer.php?u=' . urlencode( $site_link ) . '" target="_blank" class="dashicons-before dashicons-facebook"></a>';
305
  $add_links[] = '<a title="' . $social_share . '" href="https://twitter.com/home?status=' . $twitter_cta . ' ' . $site_link . '" target="_blank" class="dashicons-before dashicons-twitter"></a>';
306
  $add_links[] = '<a title="' . $social_share . '" href="https://plus.google.com/share?url=' . urlencode( $site_link ) . '" target="_blank" class="dashicons-before dashicons-googleplus"></a>';
307
 
308
+ /**
309
+ * Filters the final custom social links.
310
+ *
311
+ * @since 1.0.0
312
+ *
313
+ * @param array $add_links Array of social links with HTML markup.
314
+ */
315
  $add_links = apply_filters( 'constant_contact_social_links', $add_links );
316
 
 
317
  return array_merge( $links, $add_links );
318
  }
319
 
320
  /**
321
  * Get a link to an admin page.
322
  *
323
+ * @since 1.0.1
324
+ *
325
+ * @param string $text The link text to use.
326
+ * @param string $link_slug The slug of the admin page.
327
  * @return string
328
  */
329
  public function get_admin_link( $text, $link_slug ) {
341
  }
342
 
343
  /**
344
+ * Scripts.
345
  *
346
+ * @since 1.0.0
 
347
  */
348
  public function scripts() {
349
 
350
  global $pagenow;
351
 
352
+ // Check if we are in debug mode. allow.
353
  $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG === true ? true : false;
354
 
355
+ // Based on our debug mode, potentially add a min prefix.
356
  $suffix = ( true === $debug ) ? '' : '.min';
357
 
 
358
  wp_register_script(
359
  'ctct_form',
360
  constant_contact()->url() . 'assets/js/ctct-plugin-admin' . $suffix . '.js',
366
  wp_localize_script(
367
  'ctct_form',
368
  'ctct_texts',
369
+ /**
370
+ * Filters the text used as part of the ctct_form javascript object.
371
+ *
372
+ * @since 1.0.0
373
+ *
374
+ * @param array $value Array of strings to be used with javascript calls.
375
+ */
376
  apply_filters( 'constant_contact_localized_js_texts', array(
377
  'leavewarning' => __( 'You have unsaved changes.', 'constant-contact-forms' ),
378
  'move_up' => __( 'move up', 'constant-contact-forms' ),
380
  ) )
381
  );
382
 
383
+ /**
384
+ * Filters the allowed pages to enqueue the ctct_form script on.
385
+ *
386
+ * @since 1.0.0
387
+ *
388
+ * @param array $value Array of WP Admin base files to conditionally load on.
389
+ */
390
  $allowed_pages = apply_filters( 'constant_contact_script_load_pages', array( 'post.php', 'post-new.php' ) );
391
 
392
  if ( $pagenow && in_array( $pagenow, $allowed_pages, true ) ) {
includes/class-api.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage API
5
  * @author Constant Contact
@@ -18,9 +20,9 @@ use Ctct\Exceptions\CtctException;
18
  class ConstantContact_API {
19
 
20
  /**
21
- * Parent plugin class
22
  *
23
- * @var class
24
  * @since 0.0.1
25
  */
26
  protected $plugin = null;
@@ -28,8 +30,9 @@ class ConstantContact_API {
28
  /**
29
  * Constructor
30
  *
31
- * @since 1.0.0
32
- * @return void
 
33
  */
34
  public function __construct( $plugin ) {
35
  $this->plugin = $plugin;
@@ -39,6 +42,7 @@ class ConstantContact_API {
39
  * Get new instance of ConstantContact.
40
  *
41
  * @since 1.0.0
 
42
  * @return object ConstantContact_API
43
  */
44
  public function cc() {
@@ -46,16 +50,17 @@ class ConstantContact_API {
46
  }
47
 
48
  /**
49
- * Returns api token string to access api
50
  *
51
  * @since 1.0.0
 
52
  * @param string $type api key type.
53
- * @return string api token
54
  */
55
  public function get_api_token( $type = '' ) {
56
 
57
  // Depending on our request, we'll try to grab a defined value
58
- // otherwise we'll grab it from our options
59
  switch ( $type ) {
60
  case 'CTCT_APIKEY':
61
 
@@ -83,34 +88,41 @@ class ConstantContact_API {
83
  }
84
 
85
  /**
86
- * Info of the connected CTCT account
87
  *
88
- * @since 1.0.0
89
- * @return array current connected ctct account info
 
90
  */
91
  public function get_account_info() {
92
 
93
- // If we're not connectd, bail out
94
  if ( ! $this->is_connected() ) {
95
  return;
96
  }
97
 
98
- // Get our saved account info
99
  $acct_data = get_transient( 'constant_contact_acct_info' );
100
 
101
- // allow bypassing transient with a filter
 
 
 
 
 
 
102
  $bypass_acct_cache = apply_filters( 'constant_contact_bypass_acct_info_cache', false );
103
 
104
- // IF we dont' have a transient, or we want to bypass, hit our api
105
  if ( false === $acct_data || $bypass_acct_cache ) {
106
  try {
107
 
108
- // Grab our account
109
  $acct_data = $this->cc()->accountService->getAccountInfo( $this->get_api_token() );
110
 
111
- // Make sure we got a response before trying to save our transient
112
  if ( $acct_data ) {
113
- // Save our data to a transient for a day
114
  set_transient( 'constant_contact_acct_info', $acct_data, 1 * DAY_IN_SECONDS );
115
  }
116
  } catch ( CtctException $ex ) {
@@ -118,27 +130,28 @@ class ConstantContact_API {
118
  }
119
  }
120
 
121
- // Return our account data
122
  return $acct_data;
123
  }
124
 
125
  /**
126
- * Contacts of the connected CTCT account
127
  *
128
- * @since 1.0.0
129
- * @return array current connect ctct account contacts
 
130
  */
131
  public function get_contacts() {
132
 
133
- // Verify we're connected
134
  if ( ! $this->is_connected() ) {
135
  return array();
136
  }
137
 
138
- // first, check our saved transient for a value
139
  $contacts = get_transient( 'ctct_contact' );
140
 
141
- // If we didn't get anything, then re-do the API call
142
  if ( false === $contacts ) {
143
  try {
144
  $contacts = $this->cc()->contactService->getContacts( $this->get_api_token() );
@@ -154,34 +167,36 @@ class ConstantContact_API {
154
  }
155
 
156
  /**
157
- * Lists of the connected CTCT account
158
  *
159
- * @since 1.0.0
160
- * @return array current connect ctct lists
 
 
161
  */
162
  public function get_lists( $force_skip_cache = false ) {
163
 
164
- // Verify we're connected
165
  if ( ! $this->is_connected() ) {
166
  return array();
167
  }
168
 
169
- // first, check our saved transient for a value
170
  $lists = get_transient( 'ctct_lists' );
171
 
172
- // If we passed in our force skip cache flag, we hit the API directly
173
  if ( $force_skip_cache ) {
174
  $lists = false;
175
  }
176
 
177
- // If we didn't get anything, then re-do the API call
178
  if ( false === $lists ) {
179
  try {
180
 
181
- // Get our lists
182
  $lists = $this->cc()->listService->getLists( $this->get_api_token() );
183
 
184
- // If its an array, then set our transient and return it
185
  if ( is_array( $lists ) ) {
186
  set_transient( 'ctct_lists', $lists, 1 * HOUR_IN_SECONDS );
187
  return $lists;
@@ -196,23 +211,23 @@ class ConstantContact_API {
196
 
197
  public function get_list( $id ) {
198
 
199
- // Clean our id
200
  $id = esc_attr( $id );
201
 
202
- // Sanity check that
203
  if ( ! $id ) {
204
  return;
205
  }
206
 
207
- // Verify we're connected
208
  if ( ! $this->is_connected() ) {
209
  return array();
210
  }
211
 
212
- // first, check our saved transient for a value
213
  $list = get_transient( 'ctct_list_' . $id );
214
 
215
- // If we didn't get anything, then re-do the API call
216
  if ( false === $list ) {
217
  try {
218
  $list = $this->cc()->listService->getList( $this->get_api_token(), $id );
@@ -228,27 +243,28 @@ class ConstantContact_API {
228
 
229
 
230
  /**
231
- * Add List to the connected CTCT account
 
 
232
  *
233
- * @since 1.0.0
234
  * @param array $new_list api data for new list.
235
  * @return array current connect ctct lists
236
  */
237
  public function add_list( $new_list = array() ) {
238
 
239
- // Bail out early if we don't have the data we need
240
  if ( empty( $new_list ) || ! isset( $new_list['id'] ) ) {
241
  return;
242
  }
243
 
244
- // Set our return list to empty array
245
  $return_list = array();
246
 
247
  try {
248
- // Try to get the list from the API
249
  $list = $this->cc()->listService->getList( $this->get_api_token(), esc_attr( $new_list['id'] ) );
250
  } catch ( CtctException $ex ) {
251
- // If we get an error, bail out
252
  $this->log_errors( $ex->getErrors() );
253
  }
254
 
@@ -259,37 +275,44 @@ class ConstantContact_API {
259
 
260
  try {
261
 
262
- // Generate a new list
263
  $list = new ContactList();
264
 
265
- // name it our passed in list
266
  $list->name = isset( $new_list['name'] ) ? esc_attr( $new_list['name'] ) : '';
267
 
268
- // Set status to hidden
 
 
 
 
 
 
269
  $list->status = apply_filters( 'constant_contact_list_status', 'HIDDEN' );
270
 
271
- // Push list to API
272
  $return_list = $this->cc()->listService->addList( $this->get_api_token(), $list );
273
 
274
  } catch ( CtctException $ex ) {
275
- // Log an error we get
276
  $this->log_errors( $ex->getErrors() );
277
  }
278
 
279
- // This will either have our data, or be an empty array
280
  return $return_list;
281
  }
282
 
283
  /**
284
- * Update List from the connected CTCT account
 
 
285
  *
286
- * @since 1.0.0
287
  * @param array $updated_list api data for list.
288
  * @return array current connect ctct list
289
  */
290
  public function update_list( $updated_list = array() ) {
291
 
292
- // set our var to do things with
293
  $return_list = false;
294
 
295
  try {
@@ -298,6 +321,14 @@ class ConstantContact_API {
298
 
299
  $list->id = isset( $updated_list['id'] ) ? esc_attr( $updated_list['id'] ) : '';
300
  $list->name = isset( $updated_list['name'] ) ? esc_attr( $updated_list['name'] ) : '';
 
 
 
 
 
 
 
 
301
  $list->status = $list->status = apply_filters( 'constant_contact_list_status', 'HIDDEN' );
302
 
303
  $return_list = $this->cc()->listService->updateList( $this->get_api_token(), $list );
@@ -310,59 +341,55 @@ class ConstantContact_API {
310
  }
311
 
312
  /**
313
- * Delete List from the connected CTCT account
 
 
314
  *
315
- * @since 1.0.0
316
  * @param array $updated_list api data for list.
317
- * @return array current connect ctct list
318
  */
319
  public function delete_list( $updated_list = array() ) {
320
 
321
- // bail early
322
  if ( ! isset( $updated_list['id'] ) ) {
323
  return;
324
  }
325
 
326
- // Set up our potential return var
327
  $list = false;
328
 
329
- // Attempt deletion
330
  try {
331
  $list = $this->cc()->listService->deleteList( $this->get_api_token(), $updated_list['id'] );
332
  } catch ( CtctException $ex ) {
333
  $this->log_errors( $ex->getErrors() );
334
  }
335
 
336
- // Send back the list
337
  return $list;
338
  }
339
 
340
  /**
341
- * Add constact to the connected CTCT account
 
 
342
  *
343
- * @since 1.0.0
344
  * @param array $new_contact New contact data.
345
- * @return array current connect ctct lists
346
  */
347
  public function add_contact( $new_contact = array() ) {
348
 
349
- // Make sure we're passed a full set of data
350
  if ( empty( $new_contact ) ) {
351
  return;
352
  }
353
 
354
- // If we don't get an email, it does us no good
355
  if ( ! isset( $new_contact['email'] ) ) {
356
  return;
357
  }
358
 
359
- // Set our API Token
360
  $api_token = $this->get_api_token();
361
-
362
- // Clean our email address.
363
  $email = sanitize_email( $new_contact['email'] );
364
 
365
- // Set our list data. If we didn't get passed a list and got this far, just generate a random ID
366
  $list = isset( $new_contact['list'] ) ? esc_attr( $new_contact['list'] ) : 'cc_' . wp_generate_password( 15, false );
367
 
368
  $return_contact = false;
@@ -389,29 +416,28 @@ class ConstantContact_API {
389
 
390
 
391
  /**
392
- * Helper method to creat contact
393
  *
394
- * @since 1.0.0
395
- * @param array $response response from api call
396
- * @param string $api_token token
397
- * @param string $list list name
398
- * @param string $email email address
399
- * @param string $f_name first name
400
- * @param string $l_name last name
401
- * @return mixed response from api
402
  */
403
  public function _create_contact( $api_token, $list, $email, $user_data ) {
404
 
405
- // Get a new instance of our contact
406
  $contact = new Contact();
407
 
408
- // Set our email
409
  $contact->addEmail( sanitize_text_field( $email ) );
410
 
411
- // Set our list
412
  $contact->addList( esc_attr( $list ) );
413
 
414
- // Map the rest of our properties to
415
  $contact = $this->set_contact_properties( $contact, $user_data );
416
 
417
  /*
@@ -426,32 +452,34 @@ class ConstantContact_API {
426
  }
427
 
428
  /**
429
- * Helper method to update contact
430
  *
431
- * @since 1.0.0
432
- * @param array $response response from api call
433
- * @param string $api_token token
434
- * @param string $list list name
435
- * @param string $f_name first name
436
- * @param string $l_name last name
437
- * @return mixed response from api
 
 
438
  */
439
  public function _update_contact( $response, $api_token, $list, $user_data ) {
440
 
441
- // Sanity checks on our response
442
  if (
443
  isset( $response->results ) &&
444
  isset( $response->results[0] ) &&
445
  ( $response->results[0] instanceof Contact )
446
  ) {
447
 
448
- // set our returned contact
449
  $contact = $response->results[0];
450
 
451
- // Attach our list
452
  $contact->addList( esc_attr( $list ) );
453
 
454
- // set the rest of our properties
455
  $contact = $this->set_contact_properties( $contact, $user_data );
456
 
457
  /*
@@ -473,18 +501,18 @@ class ConstantContact_API {
473
  * Helper method to push as much data from a form as we can into the
474
  * Constant Contact contact thats in a list
475
  *
476
- * @param object $contact Contact object
477
- * @param array $user_data bunch of user data
478
- * @return object Contact object, with new properties
479
  */
480
  public function set_contact_properties( $contact, $user_data ) {
481
 
482
- // First, verify we have what we need
483
  if ( ! is_object( $contact ) || ! is_array( $user_data ) ) {
484
  return;
485
  }
486
 
487
- // Remove some values we don't need
488
  unset( $user_data['list'] );
489
 
490
  $address = null;
@@ -493,19 +521,23 @@ class ConstantContact_API {
493
  // Loop through each of our values and set it as a property.
494
  foreach ( $user_data as $original => $value ) {
495
 
496
- // Set our key and value to our value's actual key/value
497
  $key = sanitize_text_field( isset( $value['key'] ) ? $value['key'] : false );
498
  $value = sanitize_text_field( isset( $value['val'] ) ? $value['val'] : false );
499
 
500
- // If for some reason, we don't have those, then we'll just skip this one
501
  if ( ! $key || ! $value ) {
502
  continue;
503
  }
504
 
505
- // Based on our key, theres a few different things we should do
506
  switch ( $key ) {
507
  case 'email':
508
- // do nothing, as we already captured
 
 
 
 
509
  break;
510
  case 'company':
511
  $contact->company_name = $value;
@@ -516,12 +548,12 @@ class ConstantContact_API {
516
  case 'state_address':
517
  case 'zip_address':
518
 
519
- // set our global address so we can append more data
520
  if ( is_null( $address ) ) {
521
  $address = new Ctct\Components\Contacts\Address();
522
  }
523
 
524
- // Nested switch to set all our address properties how they should be mapped
525
  switch ( $key ) {
526
  case 'street_address':
527
  $address->address_type = 'PERSONAL';
@@ -549,41 +581,40 @@ class ConstantContact_API {
549
  case 'anniversary_month':
550
  case 'anniversary_year':
551
  case 'custom':
552
- // Dont overload custom fields
553
  if ( 15 >= $count ) {
554
  break;
555
  }
556
 
557
- // Otherwise, set up our custom field
558
  $custom = new Ctct\Components\Contacts\CustomField();
559
 
560
- // Create, name it the way the API needs
561
  $custom = $custom->create( array(
562
  'name' => 'CustomField' . $count,
563
  'value' => $key . ' : ' . $value,
564
  ) );
565
 
566
- // Attach it
567
  $contact->addCustomField( $custom );
568
  break;
569
  default:
570
- // if we got here, try to map our field to the key
571
  try {
572
- // Try it
573
  $contact->$key = $value;
574
  } catch (Exception $e) {
575
- // If we get an exception, then break.
576
  break;
577
  }
578
 
579
- // Otherwise break anyway
580
  break;
581
  }
582
 
583
  $count = $count + 1;
584
  }
585
 
586
- // If we did set address properties, then push it to our contact
587
  if ( ! is_null( $address ) ) {
588
  $contact->addAddress( $address );
589
  }
@@ -594,16 +625,14 @@ class ConstantContact_API {
594
  /**
595
  * Pushes all error to api_error_message
596
  *
597
- * @since 1.0.0
598
- * @param array $errors errors from api
 
599
  * @return void
600
  */
601
  public function log_errors( $errors ) {
602
 
603
- // Make sure we have an array
604
  if ( is_array( $errors ) ) {
605
-
606
- // Loop through all errors
607
  foreach ( $errors as $error ) {
608
  $this->api_error_message( $error );
609
  }
@@ -611,26 +640,26 @@ class ConstantContact_API {
611
  }
612
 
613
  /**
614
- * Process api error response
615
  *
616
- * @since 1.0.0
617
- * @param array $error api error repsonse.
618
  * @return mixed
619
  */
620
  private function api_error_message( $error ) {
621
 
622
- // Make sure we have our expected error key
623
  if ( ! isset( $error->error_key ) ) {
624
  return false;
625
  }
626
 
627
- // If we have our debugging turned on, push that error to the error log
628
  if ( defined( 'CONSTANT_CONTACT_DEBUG' ) && CONSTANT_CONTACT_DEBUG ) {
629
  error_log( $error->error_key . ': ' . $error->error_message );
630
  error_log( serialize( debug_backtrace() ) );
631
  }
632
 
633
- // Otherwise work through our list of error keys we know
634
  switch ( $error->error_key ) {
635
  case 'http.status.authentication.invalid_token':
636
  $this->access_token = false;
@@ -647,10 +676,9 @@ class ConstantContact_API {
647
  }
648
 
649
  /**
650
- * Rate limit ourselves to not bust API call rate limit
651
  *
652
- * @since 1.0.0
653
- * @param string $time amount of time to pause api calls
654
  */
655
  public function pause_api_calls() {
656
  // @TODO
@@ -658,61 +686,58 @@ class ConstantContact_API {
658
  }
659
 
660
  /**
661
- * Make sure we don't over-do API requests, helper method to check if we're connected
662
  *
663
  * @return boolean if connected
664
  */
665
  public function is_connected() {
666
 
667
- // Make sure we only grab our token once during a page load
668
  static $token = null;
669
 
670
- // If we haven't grabbed it yet, grab it
671
  if ( is_null( $token ) ) {
672
  $token = get_option( 'ctct_token', false ) ? true : false;
673
  }
674
 
675
- // Return it
676
  return $token;
677
  }
678
 
679
  /**
680
  * Helper method to output a link for our connect modal
681
  *
682
- * @since 1.0.0
683
- * @param string $type type of link to output
684
  */
685
  public function get_connect_link() {
686
 
687
- // Allow us to re-use the same verification twice on one page load
688
  static $proof = null;
689
 
690
- // If we haven't set a proof yet, generate it
691
  if ( is_null( $proof ) ) {
692
  $proof = constant_contact()->authserver->set_verification_option();
693
  }
694
 
695
- // Send back our connect url
696
  return constant_contact()->authserver->do_connect_url( $proof );
697
  }
698
 
699
  /**
700
- * Helper method to output a link for our connect modal
701
  *
702
- * @since 1.0.0
703
- * @param string $type type of link to output
704
  */
705
  public function get_signup_link() {
706
 
707
- // Allow us to re-use the same verification twice on one page load
708
  static $proof = null;
709
 
710
- // If we haven't set a proof yet, generate it
711
  if ( is_null( $proof ) ) {
712
  $proof = constant_contact()->authserver->set_verification_option();
713
  }
714
 
715
- // Send back our connect url
716
  return constant_contact()->authserver->do_signup_url( $proof );
717
  }
718
 
@@ -721,7 +746,7 @@ class ConstantContact_API {
721
  *
722
  * @since 1.0.0
723
  * @param bool $as_parts If true return an array.
724
- * Array (
725
  * [name] => Business Name
726
  * [address] => 555 Business Place Ln., Beverly Hills, CA, 90210
727
  * ).
@@ -760,7 +785,7 @@ class ConstantContact_API {
760
  $organization_address = array_shift( $account_info->organization_addresses );
761
  $disclosure_address = array();
762
 
763
- // Add in our disclouse address
764
  if ( is_array( $address_fields ) ) {
765
  foreach ( $address_fields as $field ) {
766
  if ( isset( $organization_address[ $field ] ) && strlen( $organization_address[ $field ] ) ) {
1
  <?php
2
  /**
3
+ * Constant Contact API class.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage API
7
  * @author Constant Contact
20
  class ConstantContact_API {
21
 
22
  /**
23
+ * Parent plugin class.
24
  *
25
+ * @var object
26
  * @since 0.0.1
27
  */
28
  protected $plugin = null;
30
  /**
31
  * Constructor
32
  *
33
+ * @since 1.0.0
34
+ *
35
+ * @param object $plugin Parent plugin class.
36
  */
37
  public function __construct( $plugin ) {
38
  $this->plugin = $plugin;
42
  * Get new instance of ConstantContact.
43
  *
44
  * @since 1.0.0
45
+ *
46
  * @return object ConstantContact_API
47
  */
48
  public function cc() {
50
  }
51
 
52
  /**
53
+ * Returns API token string to access API.
54
  *
55
  * @since 1.0.0
56
+ *
57
  * @param string $type api key type.
58
+ * @return string API token.
59
  */
60
  public function get_api_token( $type = '' ) {
61
 
62
  // Depending on our request, we'll try to grab a defined value
63
+ // otherwise we'll grab it from our options.
64
  switch ( $type ) {
65
  case 'CTCT_APIKEY':
66
 
88
  }
89
 
90
  /**
91
+ * Info of the connected CTCT account.
92
  *
93
+ * @since 1.0.0
94
+ *
95
+ * @return array Current connected ctct account info.
96
  */
97
  public function get_account_info() {
98
 
99
+ // If we're not connectd, bail out.
100
  if ( ! $this->is_connected() ) {
101
  return;
102
  }
103
 
104
+ // Get our saved account info.
105
  $acct_data = get_transient( 'constant_contact_acct_info' );
106
 
107
+ /**
108
+ * Filters whether or not to bypass transient with a filter.
109
+ *
110
+ * @since 1.0.0
111
+ *
112
+ * @param bool $value Whether or not to bypass.
113
+ */
114
  $bypass_acct_cache = apply_filters( 'constant_contact_bypass_acct_info_cache', false );
115
 
116
+ // If we dont' have a transient, or we want to bypass, hit our API.
117
  if ( false === $acct_data || $bypass_acct_cache ) {
118
  try {
119
 
120
+ // Grab our account.
121
  $acct_data = $this->cc()->accountService->getAccountInfo( $this->get_api_token() );
122
 
123
+ // Make sure we got a response before trying to save our transient.
124
  if ( $acct_data ) {
125
+ // Save our data to a transient for a day.
126
  set_transient( 'constant_contact_acct_info', $acct_data, 1 * DAY_IN_SECONDS );
127
  }
128
  } catch ( CtctException $ex ) {
130
  }
131
  }
132
 
133
+ // Return our account data.
134
  return $acct_data;
135
  }
136
 
137
  /**
138
+ * Contacts of the connected CTCT account.
139
  *
140
+ * @since 1.0.0
141
+ *
142
+ * @return array Current connect ctct account contacts.
143
  */
144
  public function get_contacts() {
145
 
146
+ // Verify we're connected.
147
  if ( ! $this->is_connected() ) {
148
  return array();
149
  }
150
 
151
+ // First, check our saved transient for a value.
152
  $contacts = get_transient( 'ctct_contact' );
153
 
154
+ // If we didn't get anything, then re-do the API call.
155
  if ( false === $contacts ) {
156
  try {
157
  $contacts = $this->cc()->contactService->getContacts( $this->get_api_token() );
167
  }
168
 
169
  /**
170
+ * Lists of the connected CTCT account.
171
  *
172
+ * @since 1.0.0
173
+ *
174
+ * @param bool $force_skip_cache Whether or not to skip cache.
175
+ * @return array Current connect ctct lists.
176
  */
177
  public function get_lists( $force_skip_cache = false ) {
178
 
179
+ // Verify we're connected.
180
  if ( ! $this->is_connected() ) {
181
  return array();
182
  }
183
 
184
+ // First, check our saved transient for a value.
185
  $lists = get_transient( 'ctct_lists' );
186
 
187
+ // If we passed in our force skip cache flag, we hit the API directly.
188
  if ( $force_skip_cache ) {
189
  $lists = false;
190
  }
191
 
192
+ // If we didn't get anything, then re-do the API call.
193
  if ( false === $lists ) {
194
  try {
195
 
196
+ // Get our lists.
197
  $lists = $this->cc()->listService->getLists( $this->get_api_token() );
198
 
199
+ // If its an array, then set our transient and return it.
200
  if ( is_array( $lists ) ) {
201
  set_transient( 'ctct_lists', $lists, 1 * HOUR_IN_SECONDS );
202
  return $lists;
211
 
212
  public function get_list( $id ) {
213
 
214
+ // Clean our id.
215
  $id = esc_attr( $id );
216
 
217
+ // Sanity check that.
218
  if ( ! $id ) {
219
  return;
220
  }
221
 
222
+ // Verify we're connected.
223
  if ( ! $this->is_connected() ) {
224
  return array();
225
  }
226
 
227
+ // First, check our saved transient for a value.
228
  $list = get_transient( 'ctct_list_' . $id );
229
 
230
+ // If we didn't get anything, then re-do the API call.
231
  if ( false === $list ) {
232
  try {
233
  $list = $this->cc()->listService->getList( $this->get_api_token(), $id );
243
 
244
 
245
  /**
246
+ * Add List to the connected CTCT account.
247
+ *
248
+ * @since 1.0.0
249
  *
 
250
  * @param array $new_list api data for new list.
251
  * @return array current connect ctct lists
252
  */
253
  public function add_list( $new_list = array() ) {
254
 
255
+ // Bail out early if we don't have the data we need.
256
  if ( empty( $new_list ) || ! isset( $new_list['id'] ) ) {
257
  return;
258
  }
259
 
260
+ // Set our return list to empty array.
261
  $return_list = array();
262
 
263
  try {
264
+ // Try to get the list from the API.
265
  $list = $this->cc()->listService->getList( $this->get_api_token(), esc_attr( $new_list['id'] ) );
266
  } catch ( CtctException $ex ) {
267
+ // If we get an error, bail out.
268
  $this->log_errors( $ex->getErrors() );
269
  }
270
 
275
 
276
  try {
277
 
278
+ // Generate a new list.
279
  $list = new ContactList();
280
 
281
+ // Name it our passed in list.
282
  $list->name = isset( $new_list['name'] ) ? esc_attr( $new_list['name'] ) : '';
283
 
284
+ /**
285
+ * Filters the list status to use when adding a list.
286
+ *
287
+ * @since 1.0.0
288
+ *
289
+ * @param string $value List status to use.
290
+ */
291
  $list->status = apply_filters( 'constant_contact_list_status', 'HIDDEN' );
292
 
293
+ // Push list to API.
294
  $return_list = $this->cc()->listService->addList( $this->get_api_token(), $list );
295
 
296
  } catch ( CtctException $ex ) {
297
+ // Log an error we get.
298
  $this->log_errors( $ex->getErrors() );
299
  }
300
 
301
+ // This will either have our data, or be an empty array.
302
  return $return_list;
303
  }
304
 
305
  /**
306
+ * Update List from the connected CTCT account.
307
+ *
308
+ * @since 1.0.0
309
  *
 
310
  * @param array $updated_list api data for list.
311
  * @return array current connect ctct list
312
  */
313
  public function update_list( $updated_list = array() ) {
314
 
315
+ // Set our var to do things with.
316
  $return_list = false;
317
 
318
  try {
321
 
322
  $list->id = isset( $updated_list['id'] ) ? esc_attr( $updated_list['id'] ) : '';
323
  $list->name = isset( $updated_list['name'] ) ? esc_attr( $updated_list['name'] ) : '';
324
+
325
+ /**
326
+ * Filters the list status to use when updating a list.
327
+ *
328
+ * @since 1.0.0
329
+ *
330
+ * @param string $value List status to use.
331
+ */
332
  $list->status = $list->status = apply_filters( 'constant_contact_list_status', 'HIDDEN' );
333
 
334
  $return_list = $this->cc()->listService->updateList( $this->get_api_token(), $list );
341
  }
342
 
343
  /**
344
+ * Delete List from the connected CTCT account.
345
+ *
346
+ * @since 1.0.0
347
  *
 
348
  * @param array $updated_list api data for list.
349
+ * @return array Current connect ctct list.
350
  */
351
  public function delete_list( $updated_list = array() ) {
352
 
 
353
  if ( ! isset( $updated_list['id'] ) ) {
354
  return;
355
  }
356
 
 
357
  $list = false;
358
 
359
+ // Attempt deletion.
360
  try {
361
  $list = $this->cc()->listService->deleteList( $this->get_api_token(), $updated_list['id'] );
362
  } catch ( CtctException $ex ) {
363
  $this->log_errors( $ex->getErrors() );
364
  }
365
 
 
366
  return $list;
367
  }
368
 
369
  /**
370
+ * Add constact to the connected CTCT account.
371
+ *
372
+ * @since 1.0.0
373
  *
 
374
  * @param array $new_contact New contact data.
375
+ * @return array Current connect ctct lists.
376
  */
377
  public function add_contact( $new_contact = array() ) {
378
 
379
+ // Make sure we're passed a full set of data.
380
  if ( empty( $new_contact ) ) {
381
  return;
382
  }
383
 
384
+ // If we don't get an email, it does us no good.
385
  if ( ! isset( $new_contact['email'] ) ) {
386
  return;
387
  }
388
 
 
389
  $api_token = $this->get_api_token();
 
 
390
  $email = sanitize_email( $new_contact['email'] );
391
 
392
+ // Set our list data. If we didn't get passed a list and got this far, just generate a random ID.
393
  $list = isset( $new_contact['list'] ) ? esc_attr( $new_contact['list'] ) : 'cc_' . wp_generate_password( 15, false );
394
 
395
  $return_contact = false;
416
 
417
 
418
  /**
419
+ * Helper method to creat contact.
420
  *
421
+ * @since 1.0.0
422
+ *
423
+ * @param string $api_token Token.
424
+ * @param string $list List name.
425
+ * @param string $email Email address.
426
+ * @param string $user_data User data.
427
+ * @return mixed Response from api.
 
428
  */
429
  public function _create_contact( $api_token, $list, $email, $user_data ) {
430
 
431
+ // Get a new instance of our contact.
432
  $contact = new Contact();
433
 
434
+ // Set our email.
435
  $contact->addEmail( sanitize_text_field( $email ) );
436
 
437
+ // Set our list.
438
  $contact->addList( esc_attr( $list ) );
439
 
440
+ // Map the rest of our properties to.
441
  $contact = $this->set_contact_properties( $contact, $user_data );
442
 
443
  /*
452
  }
453
 
454
  /**
455
+ * Helper method to update contact.
456
  *
457
+ * @since 1.0.0
458
+ *
459
+ * @throws CtctException API exception.
460
+ *
461
+ * @param array $response Response from api call.
462
+ * @param string $api_token Token.
463
+ * @param string $list List name.
464
+ * @param string $user_data User data.
465
+ * @return mixed Response from api.
466
  */
467
  public function _update_contact( $response, $api_token, $list, $user_data ) {
468
 
469
+ // Sanity checks on our response.
470
  if (
471
  isset( $response->results ) &&
472
  isset( $response->results[0] ) &&
473
  ( $response->results[0] instanceof Contact )
474
  ) {
475
 
476
+ // Set our returned contact.
477
  $contact = $response->results[0];
478
 
479
+ // Attach our list.
480
  $contact->addList( esc_attr( $list ) );
481
 
482
+ // Set the rest of our properties.
483
  $contact = $this->set_contact_properties( $contact, $user_data );
484
 
485
  /*
501
  * Helper method to push as much data from a form as we can into the
502
  * Constant Contact contact thats in a list
503
  *
504
+ * @param object $contact Contact object.
505
+ * @param array $user_data Bunch of user data.
506
+ * @return object Contact object, with new properties.
507
  */
508
  public function set_contact_properties( $contact, $user_data ) {
509
 
510
+ // First, verify we have what we need.
511
  if ( ! is_object( $contact ) || ! is_array( $user_data ) ) {
512
  return;
513
  }
514
 
515
+ // Remove some values we don't need.
516
  unset( $user_data['list'] );
517
 
518
  $address = null;
521
  // Loop through each of our values and set it as a property.
522
  foreach ( $user_data as $original => $value ) {
523
 
524
+ // Set our key and value to our value's actual key/value.
525
  $key = sanitize_text_field( isset( $value['key'] ) ? $value['key'] : false );
526
  $value = sanitize_text_field( isset( $value['val'] ) ? $value['val'] : false );
527
 
528
+ // If for some reason, we don't have those, then we'll just skip this one.
529
  if ( ! $key || ! $value ) {
530
  continue;
531
  }
532
 
533
+ // Based on our key, theres a few different things we should do.
534
  switch ( $key ) {
535
  case 'email':
536
+ case 'website':
537
+ // Do nothing, as we already captured.
538
+ break;
539
+ case 'phone_number':
540
+ $contact->cell_phone = $value;
541
  break;
542
  case 'company':
543
  $contact->company_name = $value;
548
  case 'state_address':
549
  case 'zip_address':
550
 
551
+ // Set our global address so we can append more data.
552
  if ( is_null( $address ) ) {
553
  $address = new Ctct\Components\Contacts\Address();
554
  }
555
 
556
+ // Nested switch to set all our address properties how they should be mapped.
557
  switch ( $key ) {
558
  case 'street_address':
559
  $address->address_type = 'PERSONAL';
581
  case 'anniversary_month':
582
  case 'anniversary_year':
583
  case 'custom':
584
+ // Dont overload custom fields.
585
  if ( 15 >= $count ) {
586
  break;
587
  }
588
 
589
+ // Otherwise, set up our custom field.
590
  $custom = new Ctct\Components\Contacts\CustomField();
591
 
592
+ // Create, name it the way the API needs.
593
  $custom = $custom->create( array(
594
  'name' => 'CustomField' . $count,
595
  'value' => $key . ' : ' . $value,
596
  ) );
597
 
598
+ // Attach it.
599
  $contact->addCustomField( $custom );
600
  break;
601
  default:
602
+ // If we got here, try to map our field to the key.
603
  try {
 
604
  $contact->$key = $value;
605
  } catch (Exception $e) {
606
+ // @todo Log the exception.
607
  break;
608
  }
609
 
610
+ // Otherwise break anyway.
611
  break;
612
  }
613
 
614
  $count = $count + 1;
615
  }
616
 
617
+ // If we did set address properties, then push it to our contact.
618
  if ( ! is_null( $address ) ) {
619
  $contact->addAddress( $address );
620
  }
625
  /**
626
  * Pushes all error to api_error_message
627
  *
628
+ * @since 1.0.0
629
+ *
630
+ * @param array $errors Errors from API.
631
  * @return void
632
  */
633
  public function log_errors( $errors ) {
634
 
 
635
  if ( is_array( $errors ) ) {
 
 
636
  foreach ( $errors as $error ) {
637
  $this->api_error_message( $error );
638
  }
640
  }
641
 
642
  /**
643
+ * Process api error response.
644
  *
645
+ * @since 1.0.0
646
+ * @param array $error API error repsonse.
647
  * @return mixed
648
  */
649
  private function api_error_message( $error ) {
650
 
651
+ // Make sure we have our expected error key.
652
  if ( ! isset( $error->error_key ) ) {
653
  return false;
654
  }
655
 
656
+ // If we have our debugging turned on, push that error to the error log.
657
  if ( defined( 'CONSTANT_CONTACT_DEBUG' ) && CONSTANT_CONTACT_DEBUG ) {
658
  error_log( $error->error_key . ': ' . $error->error_message );
659
  error_log( serialize( debug_backtrace() ) );
660
  }
661
 
662
+ // Otherwise work through our list of error keys we know.
663
  switch ( $error->error_key ) {
664
  case 'http.status.authentication.invalid_token':
665
  $this->access_token = false;
676
  }
677
 
678
  /**
679
+ * Rate limit ourselves to not bust API call rate limit.
680
  *
681
+ * @since 1.0.0
 
682
  */
683
  public function pause_api_calls() {
684
  // @TODO
686
  }
687
 
688
  /**
689
+ * Make sure we don't over-do API requests, helper method to check if we're connected.
690
  *
691
  * @return boolean if connected
692
  */
693
  public function is_connected() {
694
 
695
+ // Make sure we only grab our token once during a page load.
696
  static $token = null;
697
 
698
+ // If we haven't grabbed it yet, grab it.
699
  if ( is_null( $token ) ) {
700
  $token = get_option( 'ctct_token', false ) ? true : false;
701
  }
702
 
 
703
  return $token;
704
  }
705
 
706
  /**
707
  * Helper method to output a link for our connect modal
708
  *
709
+ * @since 1.0.0
 
710
  */
711
  public function get_connect_link() {
712
 
713
+ // Allow us to re-use the same verification twice on one page load.
714
  static $proof = null;
715
 
716
+ // If we haven't set a proof yet, generate it.
717
  if ( is_null( $proof ) ) {
718
  $proof = constant_contact()->authserver->set_verification_option();
719
  }
720
 
721
+ // Send back our connect url.
722
  return constant_contact()->authserver->do_connect_url( $proof );
723
  }
724
 
725
  /**
726
+ * Helper method to output a link for our connect modal.
727
  *
728
+ * @since 1.0.0
 
729
  */
730
  public function get_signup_link() {
731
 
732
+ // Allow us to re-use the same verification twice on one page load.
733
  static $proof = null;
734
 
735
+ // If we haven't set a proof yet, generate it.
736
  if ( is_null( $proof ) ) {
737
  $proof = constant_contact()->authserver->set_verification_option();
738
  }
739
 
740
+ // Send back our connect url.
741
  return constant_contact()->authserver->do_signup_url( $proof );
742
  }
743
 
746
  *
747
  * @since 1.0.0
748
  * @param bool $as_parts If true return an array.
749
+ * array (
750
  * [name] => Business Name
751
  * [address] => 555 Business Place Ln., Beverly Hills, CA, 90210
752
  * ).
785
  $organization_address = array_shift( $account_info->organization_addresses );
786
  $disclosure_address = array();
787
 
788
+ // Add in our disclouse address.
789
  if ( is_array( $address_fields ) ) {
790
  foreach ( $address_fields as $field ) {
791
  if ( isset( $organization_address[ $field ] ) && strlen( $organization_address[ $field ] ) ) {
includes/class-auth-redirect.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage AuthRedirect
5
  * @author Constant Contact
@@ -14,7 +16,7 @@ class ConstantContact_Auth_Redirect {
14
  /**
15
  * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
@@ -22,8 +24,9 @@ class ConstantContact_Auth_Redirect {
22
  /**
23
  * Constructor
24
  *
25
- * @since 1.0.0
26
- * @return void
 
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -42,10 +45,12 @@ class ConstantContact_Auth_Redirect {
42
  }
43
 
44
  /**
45
- * Add auth params to query_vars
 
 
46
  *
47
- * @since 1.0.0
48
  * @param array $vars url params.
 
49
  */
50
  function rewrite_add_var( $vars ) {
51
  $vars[] = 'auth';
@@ -55,15 +60,13 @@ class ConstantContact_Auth_Redirect {
55
  }
56
 
57
  /**
58
- * Check for query params and redirect
59
  *
60
- * @since 1.0.0
61
- * @return boolean
62
  */
63
  function rewrite_catch() {
64
  global $wp_query;
65
 
66
- // So many data checks!
67
  if (
68
  current_user_can( 'manage_options' ) &&
69
  ! is_admin() &&
1
  <?php
2
  /**
3
+ * Authentication Redirection.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage AuthRedirect
7
  * @author Constant Contact
16
  /**
17
  * Parent plugin class
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
24
  /**
25
  * Constructor
26
  *
27
+ * @since 1.0.0
28
+ *
29
+ * @param object $plugin Parent plugin.
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
45
  }
46
 
47
  /**
48
+ * Add auth params to query_vars.
49
+ *
50
+ * @since 1.0.0
51
  *
 
52
  * @param array $vars url params.
53
+ * @return array
54
  */
55
  function rewrite_add_var( $vars ) {
56
  $vars[] = 'auth';
60
  }
61
 
62
  /**
63
+ * Check for query params and redirect.
64
  *
65
+ * @since 1.0.0
 
66
  */
67
  function rewrite_catch() {
68
  global $wp_query;
69
 
 
70
  if (
71
  current_user_can( 'manage_options' ) &&
72
  ! is_admin() &&
includes/class-builder-fields.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage BuilderFields
5
  * @author Constant Contact
@@ -20,16 +22,16 @@ class ConstantContact_Builder_Fields {
20
  protected $plugin = null;
21
 
22
  /**
23
- * Prefix for our meta fields / boxes
24
- * @var string
 
25
  */
26
  public $prefix = '_ctct_';
27
 
28
  /**
29
  * Constructor
30
  *
31
- * @since 1.0.0
32
- * @return void
33
  */
34
  public function __construct( $plugin ) {
35
  $this->plugin = $plugin;
@@ -53,18 +55,26 @@ class ConstantContact_Builder_Fields {
53
  public function hooks() {
54
  global $pagenow;
55
 
56
- // Allow filtering the pages to load form build actions
 
 
 
 
 
 
57
  $form_builder_pages = apply_filters(
58
  'constant_contact_form_builder_pages',
59
  array( 'post-new.php', 'post.php' )
60
  );
61
 
62
- // Only load the cmb2 fields on our specified pages
63
  if ( $pagenow && in_array( $pagenow, $form_builder_pages, true ) ) {
64
 
65
  add_action( 'cmb2_admin_init', array( $this, 'description_metabox' ) );
66
  add_action( 'cmb2_admin_init', array( $this, 'opt_ins_metabox' ) );
67
  add_action( 'cmb2_admin_init', array( $this, 'fields_metabox' ) );
 
 
68
  }
69
 
70
  }
@@ -81,12 +91,12 @@ class ConstantContact_Builder_Fields {
81
  * Initiate the $description_metabox
82
  */
83
  $description_metabox = new_cmb2_box( array(
84
- 'id' => 'ctct_0_description_metabox',
85
- 'title' => __( 'Form Description', 'constant-contact-forms' ),
86
- 'object_types' => array( 'ctct_forms' ),
87
- 'context' => 'normal',
88
- 'priority' => 'high',
89
- 'show_names' => true,
90
  ) );
91
 
92
  $description_metabox->add_field( array(
@@ -108,22 +118,23 @@ class ConstantContact_Builder_Fields {
108
  * @return void
109
  */
110
  public function opt_ins_metabox() {
111
- /**
112
- * Only connected users will get the Form Options. This may change
113
- * in the future, leaving the old code here for posterity.
114
- * @todo
115
- * @since 1.0.2
116
- */
117
- if ( constant_contact()->api->is_connected() ) {
118
- $options_metabox = new_cmb2_box( array(
119
- 'id' => 'ctct_1_optin_metabox',
120
- 'title' => __( 'Form Options', 'constant-contact-forms' ),
121
- 'object_types' => array( 'ctct_forms' ),
122
- 'context' => 'normal',
123
- 'priority' => 'high',
124
- 'show_names' => true,
125
- ) );
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  $this->show_optin_connected_fields( $options_metabox );
128
  }/**
129
  * Same as the block above.
@@ -141,13 +152,13 @@ class ConstantContact_Builder_Fields {
141
  */
142
  public function show_optin_connected_fields( $options_metabox ) {
143
 
144
- // Get our lists
145
  $lists = $this->plugin->builder->get_lists();
146
 
147
  // Add field if conncted to API.
148
  if ( $lists ) {
149
 
150
- // Allow choosing a list to add to
151
  $options_metabox->add_field( array(
152
  'name' => __( 'Add subscribers to', 'constant-contact-forms' ),
153
  'id' => $this->prefix . 'list',
@@ -158,10 +169,10 @@ class ConstantContact_Builder_Fields {
158
  ) );
159
  }
160
 
161
- // Show our show/hide checkbox field
162
  $this->show_enable_show_checkbox_field( $options_metabox );
163
 
164
- // Show our affirmation textbox field
165
  $this->show_affirmation_field( $options_metabox );
166
  }
167
 
@@ -184,7 +195,7 @@ class ConstantContact_Builder_Fields {
184
  ),
185
  ) );
186
 
187
- // Show our affirmation textbox field
188
  $this->show_affirmation_field( $options_metabox );
189
  }
190
 
@@ -212,13 +223,12 @@ class ConstantContact_Builder_Fields {
212
  /**
213
  * Helper method to show our affirmation textarea field
214
  *
215
- * @since 1.0.0
216
- * @param object $options_metabox CMB2 options metabox object
217
- * @return void
218
  */
219
  public function show_affirmation_field( $options_metabox ) {
220
 
221
- // Get our site name, and if we don't have it, then use a placeholder
222
  $business_name = get_bloginfo( 'name' );
223
  $business_name ? $business_name : __( 'Your Business Name', 'constant-contact-forms' );
224
 
@@ -233,7 +243,7 @@ class ConstantContact_Builder_Fields {
233
  /**
234
  * Fields builder CMB2 metabox
235
  *
236
- * @since 1.0.0
237
  * @return void
238
  */
239
  public function fields_metabox() {
@@ -242,12 +252,12 @@ class ConstantContact_Builder_Fields {
242
  * Initiate the $fields_metabox
243
  */
244
  $fields_metabox = new_cmb2_box( array(
245
- 'id' => 'ctct_2_fields_metabox',
246
- 'title' => __( 'Form Fields', 'constant-contact-forms' ),
247
- 'object_types' => array( 'ctct_forms' ),
248
- 'context' => 'normal',
249
- 'priority' => 'low',
250
- 'show_names' => true,
251
  ) );
252
 
253
  // Custom CMB2 fields.
@@ -264,7 +274,7 @@ class ConstantContact_Builder_Fields {
264
  'type' => 'title',
265
  ) );
266
 
267
- // Form builder repeater
268
  $custom_group = $fields_metabox->add_field( array(
269
  'id' => 'custom_fields_group',
270
  'type' => 'group',
@@ -277,7 +287,7 @@ class ConstantContact_Builder_Fields {
277
  ),
278
  ) );
279
 
280
- // Add a field label
281
  $fields_metabox->add_group_field( $custom_group, array(
282
  'name' => __( 'Field Label', 'constant-contact-forms' ),
283
  'id' => $this->prefix . 'field_label',
@@ -285,7 +295,7 @@ class ConstantContact_Builder_Fields {
285
  'default' => __( 'Email', 'constant-contact-forms' ),
286
  ) );
287
 
288
- // Add our field description
289
  $fields_metabox->add_group_field( $custom_group, array(
290
  'name' => __( 'Field Description', 'constant-contact-forms' ),
291
  'id' => $this->prefix . 'field_desc',
@@ -293,6 +303,13 @@ class ConstantContact_Builder_Fields {
293
  'default' => 'Ex: Enter email address',
294
  ) );
295
 
 
 
 
 
 
 
 
296
  $default_fields = apply_filters( 'constant_contact_field_types', array(
297
  'email' => __( 'Email (required)', 'constant-contact-forms' ),
298
  'first_name' => __( 'First Name', 'constant-contact-forms' ),
@@ -313,7 +330,7 @@ class ConstantContact_Builder_Fields {
313
  'custom_text_area' => __( 'Custom Text Area', 'constant-contact-forms' ),
314
  ) );
315
 
316
- // Choose which field
317
  $fields_metabox->add_group_field( $custom_group, array(
318
  'name' => __( 'Select a Field', 'constant-contact-forms' ),
319
  'id' => $this->prefix . 'map_select',
@@ -324,7 +341,7 @@ class ConstantContact_Builder_Fields {
324
  'options' => $default_fields,
325
  ) );
326
 
327
- // Allow toggling of required fields
328
  $fields_metabox->add_group_field( $custom_group, array(
329
  'name' => __( 'Required', 'constant-contact-forms' ),
330
  'id' => $this->prefix . 'required_field',
@@ -333,4 +350,32 @@ class ConstantContact_Builder_Fields {
333
  ) );
334
 
335
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  }
1
  <?php
2
  /**
3
+ * Builder fields.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage BuilderFields
7
  * @author Constant Contact
22
  protected $plugin = null;
23
 
24
  /**
25
+ * Prefix for our meta fields / boxes.
26
+ *
27
+ * @var string
28
  */
29
  public $prefix = '_ctct_';
30
 
31
  /**
32
  * Constructor
33
  *
34
+ * @since 1.0.0
 
35
  */
36
  public function __construct( $plugin ) {
37
  $this->plugin = $plugin;
55
  public function hooks() {
56
  global $pagenow;
57
 
58
+ /**
59
+ * Filters the pages to add our form builder content to.
60
+ *
61
+ * @since 1.0.0
62
+ *
63
+ * @param array $value Array of WP admin pages to load builder on.
64
+ */
65
  $form_builder_pages = apply_filters(
66
  'constant_contact_form_builder_pages',
67
  array( 'post-new.php', 'post.php' )
68
  );
69
 
70
+ // Only load the cmb2 fields on our specified pages.
71
  if ( $pagenow && in_array( $pagenow, $form_builder_pages, true ) ) {
72
 
73
  add_action( 'cmb2_admin_init', array( $this, 'description_metabox' ) );
74
  add_action( 'cmb2_admin_init', array( $this, 'opt_ins_metabox' ) );
75
  add_action( 'cmb2_admin_init', array( $this, 'fields_metabox' ) );
76
+ add_action( 'cmb2_admin_init', array( $this, 'generated_shortcode' ) );
77
+ add_filter( 'cmb2_override__ctct_generated_shortcode_meta_save', '__return_empty_string' );
78
  }
79
 
80
  }
91
  * Initiate the $description_metabox
92
  */
93
  $description_metabox = new_cmb2_box( array(
94
+ 'id' => 'ctct_0_description_metabox',
95
+ 'title' => __( 'Form Description', 'constant-contact-forms' ),
96
+ 'object_types' => array( 'ctct_forms' ),
97
+ 'context' => 'normal',
98
+ 'priority' => 'high',
99
+ 'show_names' => true,
100
  ) );
101
 
102
  $description_metabox->add_field( array(
118
  * @return void
119
  */
120
  public function opt_ins_metabox() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
+ $options_metabox = new_cmb2_box( array(
123
+ 'id' => 'ctct_1_optin_metabox',
124
+ 'title' => __( 'Form Options', 'constant-contact-forms' ),
125
+ 'object_types' => array( 'ctct_forms' ),
126
+ 'context' => 'normal',
127
+ 'priority' => 'high',
128
+ 'show_names' => true,
129
+ ) );
130
+
131
+ $options_metabox->add_field( array(
132
+ 'name' => __( 'Button text', 'constant-contact-forms' ),
133
+ 'id' => $this->prefix . 'button_text',
134
+ 'type' => 'text_medium',
135
+ ) );
136
+
137
+ if ( constant_contact()->api->is_connected() ) {
138
  $this->show_optin_connected_fields( $options_metabox );
139
  }/**
140
  * Same as the block above.
152
  */
153
  public function show_optin_connected_fields( $options_metabox ) {
154
 
155
+ // Get our lists.
156
  $lists = $this->plugin->builder->get_lists();
157
 
158
  // Add field if conncted to API.
159
  if ( $lists ) {
160
 
161
+ // Allow choosing a list to add to.
162
  $options_metabox->add_field( array(
163
  'name' => __( 'Add subscribers to', 'constant-contact-forms' ),
164
  'id' => $this->prefix . 'list',
169
  ) );
170
  }
171
 
172
+ // Show our show/hide checkbox field.
173
  $this->show_enable_show_checkbox_field( $options_metabox );
174
 
175
+ // Show our affirmation textbox field.
176
  $this->show_affirmation_field( $options_metabox );
177
  }
178
 
195
  ),
196
  ) );
197
 
198
+ // Show our affirmation textbox field.
199
  $this->show_affirmation_field( $options_metabox );
200
  }
201
 
223
  /**
224
  * Helper method to show our affirmation textarea field
225
  *
226
+ * @since 1.0.0
227
+ * @param object $options_metabox CMB2 options metabox object.
 
228
  */
229
  public function show_affirmation_field( $options_metabox ) {
230
 
231
+ // Get our site name, and if we don't have it, then use a placeholder.
232
  $business_name = get_bloginfo( 'name' );
233
  $business_name ? $business_name : __( 'Your Business Name', 'constant-contact-forms' );
234
 
243
  /**
244
  * Fields builder CMB2 metabox
245
  *
246
+ * @since 1.0.0
247
  * @return void
248
  */
249
  public function fields_metabox() {
252
  * Initiate the $fields_metabox
253
  */
254
  $fields_metabox = new_cmb2_box( array(
255
+ 'id' => 'ctct_2_fields_metabox',
256
+ 'title' => __( 'Form Fields', 'constant-contact-forms' ),
257
+ 'object_types' => array( 'ctct_forms' ),
258
+ 'context' => 'normal',
259
+ 'priority' => 'low',
260
+ 'show_names' => true,
261
  ) );
262
 
263
  // Custom CMB2 fields.
274
  'type' => 'title',
275
  ) );
276
 
277
+ // Form builder repeater.
278
  $custom_group = $fields_metabox->add_field( array(
279
  'id' => 'custom_fields_group',
280
  'type' => 'group',
287
  ),
288
  ) );
289
 
290
+ // Add a field label.
291
  $fields_metabox->add_group_field( $custom_group, array(
292
  'name' => __( 'Field Label', 'constant-contact-forms' ),
293
  'id' => $this->prefix . 'field_label',
295
  'default' => __( 'Email', 'constant-contact-forms' ),
296
  ) );
297
 
298
+ // Add our field description.
299
  $fields_metabox->add_group_field( $custom_group, array(
300
  'name' => __( 'Field Description', 'constant-contact-forms' ),
301
  'id' => $this->prefix . 'field_desc',
303
  'default' => 'Ex: Enter email address',
304
  ) );
305
 
306
+ /**
307
+ * Filters the Constant Contact field types to display as an option.
308
+ *
309
+ * @since 1.0.0
310
+ *
311
+ * @param array $value Array of field types.
312
+ */
313
  $default_fields = apply_filters( 'constant_contact_field_types', array(
314
  'email' => __( 'Email (required)', 'constant-contact-forms' ),
315
  'first_name' => __( 'First Name', 'constant-contact-forms' ),
330
  'custom_text_area' => __( 'Custom Text Area', 'constant-contact-forms' ),
331
  ) );
332
 
333
+ // Choose which field.
334
  $fields_metabox->add_group_field( $custom_group, array(
335
  'name' => __( 'Select a Field', 'constant-contact-forms' ),
336
  'id' => $this->prefix . 'map_select',
341
  'options' => $default_fields,
342
  ) );
343
 
344
+ // Allow toggling of required fields.
345
  $fields_metabox->add_group_field( $custom_group, array(
346
  'name' => __( 'Required', 'constant-contact-forms' ),
347
  'id' => $this->prefix . 'required_field',
350
  ) );
351
 
352
  }
353
+
354
+ /**
355
+ * Show a metabox rendering our shortcode.
356
+ *
357
+ * @since 1.1.0
358
+ */
359
+ public function generated_shortcode() {
360
+ $generated = new_cmb2_box( array(
361
+ 'id' => 'ctct_2_generated_metabox',
362
+ 'title' => __( 'Shortcode', 'constant-contact-forms' ),
363
+ 'object_types' => array( 'ctct_forms' ),
364
+ 'context' => 'side',
365
+ 'priority' => 'low',
366
+ 'show_names' => false,
367
+ ) );
368
+
369
+ $generated->add_field( array(
370
+ 'name' => 'Shortcode to use',
371
+ 'id' => $this->prefix . 'generated_shortcode',
372
+ 'type' => 'text_medium',
373
+ 'desc' => __( 'Shortcode to embed - <em><small>You can copy and paste this in a post to display your form.</small></em>', 'constant-contact-forms' ),
374
+ 'default' => '[ctct form="' . $generated->object_id . '"]',
375
+ 'attributes' => array(
376
+ 'readonly' => 'readonly',
377
+ ),
378
+ ) );
379
+
380
+ }
381
  }
includes/class-builder.php CHANGED
@@ -53,7 +53,7 @@ class ConstantContact_Builder {
53
  public function hooks() {
54
  global $pagenow;
55
 
56
- // Allow filtering the pages to load form build actions
57
  $form_builder_pages = apply_filters(
58
  'constant_contact_form_builder_pages',
59
  array( 'post-new.php', 'post.php' )
53
  public function hooks() {
54
  global $pagenow;
55
 
56
+ /** This filter is documented in includes/class-buider-fields.php */
57
  $form_builder_pages = apply_filters(
58
  'constant_contact_form_builder_pages',
59
  array( 'post-new.php', 'post.php' )
includes/class-check.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Check
5
  * @author Constant Contact
@@ -14,7 +16,7 @@ class ConstantContact_Check {
14
  /**
15
  * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
@@ -23,8 +25,8 @@ class ConstantContact_Check {
23
  /**
24
  * Constructor
25
  *
26
- * @since 1.0.0
27
- * @return void
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
@@ -38,14 +40,12 @@ class ConstantContact_Check {
38
  */
39
  public function maybe_display_debug_info() {
40
 
41
- // Make sure we have our query arg, we're an admin, and we can manage options
42
  if ( isset( $_GET['ctct-debug-server-check'] ) && is_admin() && current_user_can( 'manage_options' ) ) { // Input var okay.
43
  ?>
44
  <div class="ctct-server-requirements">
45
- <p>
46
- <h4><?php esc_attr_e( 'Server Check', 'constant-contact-forms' ); ?></h4>
47
- <?php $this->display_server_checks(); ?>
48
- </p>
49
  </div>
50
  <?php
51
  }
@@ -60,7 +60,13 @@ class ConstantContact_Check {
60
  */
61
  public function get_checks_to_make() {
62
 
63
- // All the functions, classes, etc that we want to check on the server
 
 
 
 
 
 
64
  return apply_filters( 'constant_contact_server_checks', array(
65
  'functions' => array(
66
  'openssl_encrypt',
@@ -78,45 +84,37 @@ class ConstantContact_Check {
78
  * Displays our server check
79
  *
80
  * @since 1.0.0
81
- * @return string html markup
82
  */
83
  public function display_server_checks() {
84
 
85
- // Get everything we should check
86
  $checks = $this->get_checks_to_make();
87
 
88
  echo '<table class="ctct-server-check">';
89
- // If we have a functions array
90
  if (
91
  isset( $checks['functions'] ) &&
92
  is_array( $checks['functions'] ) &&
93
  1 <= count( $checks['functions'] )
94
  ) {
95
-
96
- // Loop through ech function
97
  foreach ( $checks['functions'] as $function ) {
98
-
99
- // Check to see if its available
100
  echo '<tr><td>' . esc_attr( $function ) . '</td><td>' . esc_attr( $this->exists_text( $function, 'f' ) ) . '</td></tr>';
101
  }
102
  }
103
 
104
- // See if we have any classes we should check for
105
  if (
106
  isset( $checks['classes'] ) &&
107
  is_array( $checks['classes'] ) &&
108
  1 <= count( $checks['classes'] )
109
  ) {
110
 
111
- // Loop through em
112
  foreach ( $checks['classes'] as $class ) {
113
-
114
- // check to see if its available
115
  echo '<tr><td>' . esc_attr( $class ) . '</td><td>' . esc_attr( $this->exists_text( $class, 'c' ) ) . '</td></tr>';
116
  }
117
  }
118
 
119
- // Check to see if we can load the encryption library
120
  $crypto = $this->plugin->connect->check_crypto_class();
121
  echo '<tr><td>' . esc_attr_e( 'Encrpytion Library: ', 'constant-contact-forms' ) . '</td><td>' . esc_attr( $this->exists_text( $crypto ) ) . '</td></tr>';
122
 
@@ -126,10 +124,11 @@ class ConstantContact_Check {
126
  /**
127
  * Helper method to give us a display of something exists or not
128
  *
129
- * @since 1.0.0
130
- * @param string $name function/class to check
131
- * @param string $type function or class?
132
- * @return string emoji of checkmark
 
133
  */
134
  public function exists_text( $name, $type = '' ) {
135
  if ( 'f' === $type ) {
@@ -142,8 +141,8 @@ class ConstantContact_Check {
142
 
143
  if ( $exists ) {
144
  return '✅';
145
- } else {
146
- return '🚫';
147
  }
 
 
148
  }
149
  }
1
  <?php
2
  /**
3
+ * Server status checks.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Check
7
  * @author Constant Contact
16
  /**
17
  * Parent plugin class
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
25
  /**
26
  * Constructor
27
  *
28
+ * @since 1.0.0
29
+ * @param object $plugin Parent plugin.
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
40
  */
41
  public function maybe_display_debug_info() {
42
 
43
+ // Make sure we have our query arg, we're an admin, and we can manage options.
44
  if ( isset( $_GET['ctct-debug-server-check'] ) && is_admin() && current_user_can( 'manage_options' ) ) { // Input var okay.
45
  ?>
46
  <div class="ctct-server-requirements">
47
+ <h4><?php esc_attr_e( 'Server Check', 'constant-contact-forms' ); ?></h4>
48
+ <?php $this->display_server_checks(); ?>
 
 
49
  </div>
50
  <?php
51
  }
60
  */
61
  public function get_checks_to_make() {
62
 
63
+ /**
64
+ * Filters the functions, classes, etc that we want to check on to be considered valid.
65
+ *
66
+ * @since 1.0.0
67
+ *
68
+ * @param array $value Array of things to check for.
69
+ */
70
  return apply_filters( 'constant_contact_server_checks', array(
71
  'functions' => array(
72
  'openssl_encrypt',
84
  * Displays our server check
85
  *
86
  * @since 1.0.0
 
87
  */
88
  public function display_server_checks() {
89
 
90
+ // Get everything we should check.
91
  $checks = $this->get_checks_to_make();
92
 
93
  echo '<table class="ctct-server-check">';
94
+ // If we have a functions array.
95
  if (
96
  isset( $checks['functions'] ) &&
97
  is_array( $checks['functions'] ) &&
98
  1 <= count( $checks['functions'] )
99
  ) {
 
 
100
  foreach ( $checks['functions'] as $function ) {
 
 
101
  echo '<tr><td>' . esc_attr( $function ) . '</td><td>' . esc_attr( $this->exists_text( $function, 'f' ) ) . '</td></tr>';
102
  }
103
  }
104
 
105
+ // See if we have any classes we should check for.
106
  if (
107
  isset( $checks['classes'] ) &&
108
  is_array( $checks['classes'] ) &&
109
  1 <= count( $checks['classes'] )
110
  ) {
111
 
 
112
  foreach ( $checks['classes'] as $class ) {
 
 
113
  echo '<tr><td>' . esc_attr( $class ) . '</td><td>' . esc_attr( $this->exists_text( $class, 'c' ) ) . '</td></tr>';
114
  }
115
  }
116
 
117
+ // Check to see if we can load the encryption library.
118
  $crypto = $this->plugin->connect->check_crypto_class();
119
  echo '<tr><td>' . esc_attr_e( 'Encrpytion Library: ', 'constant-contact-forms' ) . '</td><td>' . esc_attr( $this->exists_text( $crypto ) ) . '</td></tr>';
120
 
124
  /**
125
  * Helper method to give us a display of something exists or not
126
  *
127
+ * @since 1.0.0
128
+ *
129
+ * @param string $name Function/class to check.
130
+ * @param string $type Function or class.
131
+ * @return string Emoji of checkmark
132
  */
133
  public function exists_text( $name, $type = '' ) {
134
  if ( 'f' === $type ) {
141
 
142
  if ( $exists ) {
143
  return '✅';
 
 
144
  }
145
+
146
+ return '🚫';
147
  }
148
  }
includes/class-connect.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Connect
5
  * @author Constant Contact
@@ -18,31 +20,31 @@ use Defuse\Crypto\Crypto;
18
  class ConstantContact_Connect {
19
 
20
  /**
21
- * Option key, and option page slug
22
  *
23
  * @var string
24
- * @since 1.0.0
25
  */
26
  private $key = 'ctct_options_connect';
27
 
28
  /**
29
- * CtctOAuth2 object
30
  *
31
  * @var object
32
- * @since 1.0.0
33
  */
34
  private $oauth = '';
35
 
36
  /**
37
- * Api Error message
38
  *
39
  * @var string
40
- * @since 1.0.0
41
  */
42
  public $error_message = '';
43
 
44
  /**
45
- * Current page redirect Url
46
  *
47
  * @var string
48
  * @since 1.0.0
@@ -50,20 +52,24 @@ class ConstantContact_Connect {
50
  private $redirect_url = '';
51
 
52
  /**
53
- * Parent plugin class
54
  *
55
- * @var class
56
  * @since 0.0.1
57
  */
58
  protected $plugin = null;
59
 
 
 
 
 
 
60
  public $should_encrypt = false;
61
 
62
  /**
63
  * Constructor
64
  *
65
- * @since 1.0.0
66
- * @return void
67
  */
68
  public function __construct( $plugin ) {
69
  $this->plugin = $plugin;
@@ -71,10 +77,9 @@ class ConstantContact_Connect {
71
  }
72
 
73
  /**
74
- * Initiate our hooks
75
  *
76
  * @since 1.0.0
77
- * @return void
78
  */
79
  public function hooks() {
80
 
@@ -86,10 +91,9 @@ class ConstantContact_Connect {
86
 
87
  /**
88
  * Watches for our specific $_GET paramaters and if we get a connect request,
89
- * pass it to our auth server class to process
90
  *
91
- * @since 0.0.1
92
- * @return void
93
  */
94
  public function maybe_connect() {
95
 
@@ -97,7 +101,7 @@ class ConstantContact_Connect {
97
  // verify it and potentially process it
98
  if ( isset( $_GET['cc_connect_attempt'] ) && is_user_logged_in() ) { // Input var okay.
99
 
100
- // Call our access token processing
101
  $verified = constant_contact()->authserver->verify_and_save_access_token_return();
102
 
103
  $redirect_args = array(
@@ -109,32 +113,31 @@ class ConstantContact_Connect {
109
  $redirect_args['ctct_connect_error'] = 'true';
110
  }
111
 
112
- // Redirect back to our connection page
113
  wp_redirect( add_query_arg( $redirect_args, admin_url( 'edit.php' ) ) );
114
  die;
115
  }
116
  }
117
 
118
  /**
119
- * Add menu options page
120
  *
121
  * @since 1.0.0
122
  */
123
  public function add_options_page() {
124
 
125
  if ( ! constant_contact()->api->is_connected() ) {
126
- // Set our default title of the connect link
127
  $connect_title = __( 'Connect Now', 'constant-contact-forms' );
128
  $connect_link = 'edit.php?post_type=ctct_forms';
129
 
130
  } else {
131
 
132
- // If we've already been connected, then we can set it to be a disconnect button
133
  $connect_title = __( 'Disconnect', 'constant-contact-forms' );
134
  $connect_link = 'edit.php?post_type=ctct_forms';
135
  }
136
 
137
- // Set up our page
138
  $this->options_page = add_submenu_page(
139
  $connect_link,
140
  $connect_title,
@@ -146,9 +149,9 @@ class ConstantContact_Connect {
146
  }
147
 
148
  /**
149
- * Admin page markup. Mostly handled by CMB2
150
  *
151
- * @since 1.0.0
152
  * @return mixed page markup or false if not admin.
153
  */
154
  public function admin_page_display() {
@@ -162,7 +165,6 @@ class ConstantContact_Connect {
162
 
163
  wp_enqueue_style( 'constant_contact_admin_global_no_connection' );
164
 
165
- // Only run if logged in user can manage site options.
166
  if ( ! current_user_can( 'manage_options' ) ) {
167
  return false;
168
  }
@@ -230,11 +232,11 @@ class ConstantContact_Connect {
230
  </p>
231
  <?php
232
 
233
- // Get our middleware link
234
  $proof = constant_contact()->authserver->set_verification_option();
235
  $auth_link = constant_contact()->authserver->do_connect_url( $proof );
236
 
237
- // If we have a link, then display the connect button
238
  if ( $auth_link ) { ?>
239
  <a href="<?php echo esc_url_raw( $auth_link ); ?>" class="button button-blue ctct-connect">
240
  <?php esc_html_e( 'Connect Plugin', 'constant-contact-forms' ); ?>
@@ -252,20 +254,20 @@ class ConstantContact_Connect {
252
  }
253
 
254
  /**
255
- * Disconnect from api
256
  *
257
- * @since 1.0.0
258
  * @return boolean
259
  */
260
  public function maybe_disconnect() {
261
 
262
- // Make sure we ahve our nonce key
263
- if ( ! isset( $_POST['ctct-admin-disconnect'] ) ) { // Input var okay.
264
  return;
265
  }
266
 
267
- // Make sure we want to disconnect
268
- if ( ! isset( $_POST['ctct-disconnect'] ) ) { // Input var okay.
269
  return;
270
  }
271
 
@@ -274,8 +276,7 @@ class ConstantContact_Connect {
274
  return;
275
  }
276
 
277
- // Verify that nonce
278
- if ( wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ctct-admin-disconnect'] ) ), 'ctct-admin-disconnect' ) ) { // Input var okay.
279
 
280
  // Delete access token and delete our legacy token as well.
281
  delete_option( 'ctct_token' );
@@ -284,10 +285,13 @@ class ConstantContact_Connect {
284
  }
285
 
286
  /**
287
- * Get an encrypted value
288
  *
289
- * @since 1.0.0
290
- * @param string $key key to save to
 
 
 
291
  */
292
  public function e_get( $check_key, $fallback_to_ctct_opt = false ) {
293
 
@@ -295,13 +299,13 @@ class ConstantContact_Connect {
295
  return get_option( $check_key, '' );
296
  }
297
 
298
- // Get our key
299
  $key = $this->get_encrpyt_key();
300
 
301
- // Get our saved token
302
  if ( $fallback_to_ctct_opt ) {
303
 
304
- // if we want to fallback, we'll get the nested option
305
  $options = get_option( 'ctct_options_settings', false );
306
  if ( $options && isset( $options[ $check_key ] ) ) {
307
  $encrypted_token = $options[ $check_key ];
@@ -310,34 +314,36 @@ class ConstantContact_Connect {
310
  }
311
  } else {
312
 
313
- // Otherwise get normal option
314
  $encrypted_token = get_option( $check_key );
315
 
316
- // Make sure we have something
317
  if ( ! $encrypted_token ) {
318
  return false;
319
  }
320
  }
321
 
322
  try {
323
- // Try to decrypt it
324
  $return = Crypto::decrypt( $encrypted_token, $key );
325
  } catch ( Exception $e ) {
326
- // otherwise just return the raw val
327
  $return = '';
328
  }
329
 
330
- // Return data
331
  return $return;
332
 
333
  }
334
 
335
  /**
336
- * Set an encrypted value
337
  *
338
- * @since 1.0.0
339
- * @param string $key key to save to
340
- * @param string $data data to save
 
 
 
341
  */
342
  public function e_set( $check_key, $data, $autoload = false ) {
343
 
@@ -346,67 +352,65 @@ class ConstantContact_Connect {
346
  return $data;
347
  }
348
 
349
- // Get our key
350
  $key = $this->get_encrpyt_key();
351
 
352
- // Encrypt
353
  $saved = Crypto::encrypt( $data, $key );
354
 
355
- // Save option
356
  update_option( $check_key, $saved, $autoload );
357
 
358
- // Return data
359
  return $saved;
360
  }
361
 
362
  /**
363
- * Secure API access token
364
  *
365
- * @since 1.0.0
366
- * @param string $access_token api access token.
367
- * @return void
 
368
  */
369
  public function update_token( $access_token ) {
370
  return $this->e_set( 'ctct_token', $access_token, true );
371
  }
372
 
373
  /**
374
- * Get saved API token
 
 
375
  *
376
- * @since 1.0.0
377
  * @return string token
378
  */
379
  public function get_api_token() {
380
 
381
- // Clean up our old tokens
382
  $this->check_deleted_legacy_token();
383
 
384
  return $this->e_get( 'ctct_token' );
385
  }
386
 
387
  /**
388
- * If we have a legacy token, let's re-save it
389
  *
390
- * @since 1.0.0
391
  */
392
  public function check_deleted_legacy_token() {
393
 
394
- // Get our old token
395
  $legacy = get_option( '_ctct_token' );
396
 
397
- // If we got a legacy value, reencrypt and delete it
398
  if ( $legacy ) {
399
- // Update our token with our legacy data
400
  $this->update_token( $legacy );
401
  delete_option( '_ctct_token' );
402
  }
403
  }
404
 
405
  /**
406
- * Get our encrypt key
407
  *
408
- * @since 1.0.0
409
- * @return string key to use for encrypt
410
  */
411
  public function get_encrpyt_key() {
412
 
@@ -414,23 +418,23 @@ class ConstantContact_Connect {
414
  return 'ctct_key';
415
  }
416
 
417
- // Get our key
418
  $key = get_option( 'ctct_key', false );
419
 
420
- // If we don't have one, make one
421
  if ( ! $key ) {
422
  $key = $this->generate_and_save_key();
423
  }
424
 
425
- // return it
426
  return Key::loadFromAsciiSafeString( $key );
427
  }
428
 
429
  /**
430
- * Generates and saves a new key
431
  *
432
- * @since 1.0.0
433
- * @return object key
 
 
434
  */
435
  public function generate_and_save_key( $first_try = true ) {
436
 
@@ -439,23 +443,22 @@ class ConstantContact_Connect {
439
  return 'ctct_key';
440
  }
441
 
442
- // Generate a random key from our Encryption library
443
  $key = Key::createNewRandomKey();
444
 
445
- // Save our key as a safe string, so we can add it to the DB
446
  $key = $key->saveToAsciiSafeString();
447
 
448
- // Save it as our ctct_key, so that we can use it later
449
  $updated = update_option( 'ctct_key', $key );
450
 
451
- // If we weren't able to update it, try again, but only do it once
452
  if ( ! $updated || $first_try ) {
453
 
454
- // try generating and saving again, but only one more time.
455
  $key = $this->generate_and_save_key( false );
456
  }
457
 
458
- // Send that key back
459
  return $key;
460
  }
461
 
@@ -466,7 +469,7 @@ class ConstantContact_Connect {
466
  *
467
  * @return boolean If we should load/use the encryption libraries.
468
  */
469
- public function is_encryption_ready() {
470
 
471
  // Make sure we have our openssl libraries.
472
  if ( ! function_exists( 'openssl_encrypt' ) || ! function_exists( 'openssl_decrypt' ) ) {
@@ -478,7 +481,6 @@ class ConstantContact_Connect {
478
  return false;
479
  }
480
 
481
- // We should be good.
482
  return true;
483
  }
484
 
1
  <?php
2
  /**
3
+ * Connect
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Connect
7
  * @author Constant Contact
20
  class ConstantContact_Connect {
21
 
22
  /**
23
+ * Option key, and option page slug.
24
  *
25
  * @var string
26
+ * @since 1.0.0
27
  */
28
  private $key = 'ctct_options_connect';
29
 
30
  /**
31
+ * CtctOAuth2 object.
32
  *
33
  * @var object
34
+ * @since 1.0.0
35
  */
36
  private $oauth = '';
37
 
38
  /**
39
+ * Api Error message.
40
  *
41
  * @var string
42
+ * @since 1.0.0
43
  */
44
  public $error_message = '';
45
 
46
  /**
47
+ * Current page redirect Url.
48
  *
49
  * @var string
50
  * @since 1.0.0
52
  private $redirect_url = '';
53
 
54
  /**
55
+ * Parent plugin class.
56
  *
57
+ * @var object
58
  * @since 0.0.1
59
  */
60
  protected $plugin = null;
61
 
62
+ /**
63
+ * Whether or not to encrypt.
64
+ *
65
+ * @var bool
66
+ */
67
  public $should_encrypt = false;
68
 
69
  /**
70
  * Constructor
71
  *
72
+ * @since 1.0.0
 
73
  */
74
  public function __construct( $plugin ) {
75
  $this->plugin = $plugin;
77
  }
78
 
79
  /**
80
+ * Initiate our hooks.
81
  *
82
  * @since 1.0.0
 
83
  */
84
  public function hooks() {
85
 
91
 
92
  /**
93
  * Watches for our specific $_GET paramaters and if we get a connect request,
94
+ * pass it to our auth server class to process.
95
  *
96
+ * @since 0.0.1
 
97
  */
98
  public function maybe_connect() {
99
 
101
  // verify it and potentially process it
102
  if ( isset( $_GET['cc_connect_attempt'] ) && is_user_logged_in() ) { // Input var okay.
103
 
104
+ // Call our access token processing.
105
  $verified = constant_contact()->authserver->verify_and_save_access_token_return();
106
 
107
  $redirect_args = array(
113
  $redirect_args['ctct_connect_error'] = 'true';
114
  }
115
 
 
116
  wp_redirect( add_query_arg( $redirect_args, admin_url( 'edit.php' ) ) );
117
  die;
118
  }
119
  }
120
 
121
  /**
122
+ * Add menu options page.
123
  *
124
  * @since 1.0.0
125
  */
126
  public function add_options_page() {
127
 
128
  if ( ! constant_contact()->api->is_connected() ) {
129
+ // Set our default title of the connect link.
130
  $connect_title = __( 'Connect Now', 'constant-contact-forms' );
131
  $connect_link = 'edit.php?post_type=ctct_forms';
132
 
133
  } else {
134
 
135
+ // If we've already been connected, then we can set it to be a disconnect button.
136
  $connect_title = __( 'Disconnect', 'constant-contact-forms' );
137
  $connect_link = 'edit.php?post_type=ctct_forms';
138
  }
139
 
140
+ // Set up our page.
141
  $this->options_page = add_submenu_page(
142
  $connect_link,
143
  $connect_title,
149
  }
150
 
151
  /**
152
+ * Admin page markup. Mostly handled by CMB2.
153
  *
154
+ * @since 1.0.0
155
  * @return mixed page markup or false if not admin.
156
  */
157
  public function admin_page_display() {
165
 
166
  wp_enqueue_style( 'constant_contact_admin_global_no_connection' );
167
 
 
168
  if ( ! current_user_can( 'manage_options' ) ) {
169
  return false;
170
  }
232
  </p>
233
  <?php
234
 
235
+ // Get our middleware link.
236
  $proof = constant_contact()->authserver->set_verification_option();
237
  $auth_link = constant_contact()->authserver->do_connect_url( $proof );
238
 
239
+ // If we have a link, then display the connect button.
240
  if ( $auth_link ) { ?>
241
  <a href="<?php echo esc_url_raw( $auth_link ); ?>" class="button button-blue ctct-connect">
242
  <?php esc_html_e( 'Connect Plugin', 'constant-contact-forms' ); ?>
254
  }
255
 
256
  /**
257
+ * Disconnect from API.
258
  *
259
+ * @since 1.0.0
260
  * @return boolean
261
  */
262
  public function maybe_disconnect() {
263
 
264
+ // Make sure we ahve our nonce key.
265
+ if ( ! isset( $_POST['ctct-admin-disconnect'] ) ) {
266
  return;
267
  }
268
 
269
+ // Make sure we want to disconnect.
270
+ if ( ! isset( $_POST['ctct-disconnect'] ) ) {
271
  return;
272
  }
273
 
276
  return;
277
  }
278
 
279
+ if ( wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ctct-admin-disconnect'] ) ), 'ctct-admin-disconnect' ) ) {
 
280
 
281
  // Delete access token and delete our legacy token as well.
282
  delete_option( 'ctct_token' );
285
  }
286
 
287
  /**
288
+ * Get an encrypted value.
289
  *
290
+ * @since 1.0.0
291
+ *
292
+ * @param string $check_key key to save to.
293
+ * @param boolean $fallback_to_ctct_opt Fall back maybe.
294
+ * @return boolean|string
295
  */
296
  public function e_get( $check_key, $fallback_to_ctct_opt = false ) {
297
 
299
  return get_option( $check_key, '' );
300
  }
301
 
302
+ // Get our key.
303
  $key = $this->get_encrpyt_key();
304
 
305
+ // Get our saved token.
306
  if ( $fallback_to_ctct_opt ) {
307
 
308
+ // If we want to fallback, we'll get the nested option.
309
  $options = get_option( 'ctct_options_settings', false );
310
  if ( $options && isset( $options[ $check_key ] ) ) {
311
  $encrypted_token = $options[ $check_key ];
314
  }
315
  } else {
316
 
317
+ // Otherwise get normal option.
318
  $encrypted_token = get_option( $check_key );
319
 
320
+ // Make sure we have something.
321
  if ( ! $encrypted_token ) {
322
  return false;
323
  }
324
  }
325
 
326
  try {
327
+ // Try to decrypt it.
328
  $return = Crypto::decrypt( $encrypted_token, $key );
329
  } catch ( Exception $e ) {
330
+ // Otherwise just return the raw val.
331
  $return = '';
332
  }
333
 
 
334
  return $return;
335
 
336
  }
337
 
338
  /**
339
+ * Set an encrypted value.
340
  *
341
+ * @since 1.0.0
342
+ *
343
+ * @param string $check_key Key to save to.
344
+ * @param string $data Data to save.
345
+ * @param boolean $autoload Autoload it.
346
+ * @return string
347
  */
348
  public function e_set( $check_key, $data, $autoload = false ) {
349
 
352
  return $data;
353
  }
354
 
 
355
  $key = $this->get_encrpyt_key();
356
 
 
357
  $saved = Crypto::encrypt( $data, $key );
358
 
 
359
  update_option( $check_key, $saved, $autoload );
360
 
 
361
  return $saved;
362
  }
363
 
364
  /**
365
+ * Secure API access token.
366
  *
367
+ * @since 1.0.0
368
+ *
369
+ * @param string $access_token API access token.
370
+ * @return string
371
  */
372
  public function update_token( $access_token ) {
373
  return $this->e_set( 'ctct_token', $access_token, true );
374
  }
375
 
376
  /**
377
+ * Get saved API token.
378
+ *
379
+ * @since 1.0.0
380
  *
 
381
  * @return string token
382
  */
383
  public function get_api_token() {
384
 
385
+ // Clean up our old tokens.
386
  $this->check_deleted_legacy_token();
387
 
388
  return $this->e_get( 'ctct_token' );
389
  }
390
 
391
  /**
392
+ * If we have a legacy token, let's re-save it.
393
  *
394
+ * @since 1.0.0
395
  */
396
  public function check_deleted_legacy_token() {
397
 
398
+ // Get our old token.
399
  $legacy = get_option( '_ctct_token' );
400
 
401
+ // If we got a legacy value, reencrypt and delete it.
402
  if ( $legacy ) {
403
+ // Update our token with our legacy data.
404
  $this->update_token( $legacy );
405
  delete_option( '_ctct_token' );
406
  }
407
  }
408
 
409
  /**
410
+ * Get our encrypt key.
411
  *
412
+ * @since 1.0.0
413
+ * @return string Key to use for encrypt.
414
  */
415
  public function get_encrpyt_key() {
416
 
418
  return 'ctct_key';
419
  }
420
 
 
421
  $key = get_option( 'ctct_key', false );
422
 
423
+ // If we don't have one, make one.
424
  if ( ! $key ) {
425
  $key = $this->generate_and_save_key();
426
  }
427
 
 
428
  return Key::loadFromAsciiSafeString( $key );
429
  }
430
 
431
  /**
432
+ * Generates and saves a new key.
433
  *
434
+ * @since 1.0.0
435
+ *
436
+ * @param boolean $first_try If first try or not.
437
+ * @return object Key
438
  */
439
  public function generate_and_save_key( $first_try = true ) {
440
 
443
  return 'ctct_key';
444
  }
445
 
446
+ // Generate a random key from our Encryption library.
447
  $key = Key::createNewRandomKey();
448
 
449
+ // Save our key as a safe string, so we can add it to the DB.
450
  $key = $key->saveToAsciiSafeString();
451
 
452
+ // Save it as our ctct_key, so that we can use it later.
453
  $updated = update_option( 'ctct_key', $key );
454
 
455
+ // If we weren't able to update it, try again, but only do it once.
456
  if ( ! $updated || $first_try ) {
457
 
458
+ // Try generating and saving again, but only one more time.
459
  $key = $this->generate_and_save_key( false );
460
  }
461
 
 
462
  return $key;
463
  }
464
 
469
  *
470
  * @return boolean If we should load/use the encryption libraries.
471
  */
472
+ public function is_encryption_ready() {
473
 
474
  // Make sure we have our openssl libraries.
475
  if ( ! function_exists( 'openssl_encrypt' ) || ! function_exists( 'openssl_decrypt' ) ) {
481
  return false;
482
  }
483
 
 
484
  return true;
485
  }
486
 
includes/class-cpts.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage CPTS
5
  * @author Constant Contact
@@ -77,8 +79,8 @@ class ConstantContact_CPTS {
77
  'update_item' => __( 'Update Form', 'constant-contact-forms' ),
78
  'view_item' => __( 'View Form', 'constant-contact-forms' ),
79
  'search_items' => __( 'Search Form', 'constant-contact-forms' ),
80
- 'not_found' => __( 'Not found', 'constant-contact-forms' ),
81
- 'not_found_in_trash' => __( 'Not found in Trash', 'constant-contact-forms' ),
82
  'featured_image' => __( 'Featured Image', 'constant-contact-forms' ),
83
  'set_featured_image' => __( 'Set featured image', 'constant-contact-forms' ),
84
  'remove_featured_image' => __( 'Remove featured image', 'constant-contact-forms' ),
@@ -168,18 +170,18 @@ class ConstantContact_CPTS {
168
  'capability_type' => 'page',
169
  );
170
 
171
- // Only register if we're connected
172
  if ( constantcontact_api()->is_connected() ) {
173
  register_post_type( 'ctct_lists', $args );
174
  }
175
  }
176
 
177
  /**
178
- * Custom post udate messages to match CPT naming
179
  *
180
- * @since 1.0.0
181
- * @param array $messages default update messages.
182
- * @return array appended update messages with custom post types
183
  */
184
  public function post_updated_messages( $messages ) {
185
 
@@ -217,26 +219,25 @@ class ConstantContact_CPTS {
217
  }
218
 
219
  /**
220
- * Customize the "Enter your title" placeholder text for Title field
221
  *
222
- * @since 1.0.0
223
- * @param string $title desired placeholder text.
224
  * @return string $title output string
225
  */
226
  public function change_default_title( $title ) {
227
  global $post;
228
 
229
- // Sanity check
230
  if ( ! isset( $post ) ) {
231
  return $title;
232
  }
233
 
234
- // Check for post type
235
  if ( ! isset( $post->post_type ) ) {
236
  return $title;
237
  }
238
 
239
- // If we're on our forms post type
240
  if ( 'ctct_forms' === $post->post_type ) {
241
  $title = sprintf(
242
  '%s <span class="ctct-admin-title-details">%s</span>',
@@ -253,14 +254,21 @@ class ConstantContact_CPTS {
253
  * Returns array of form ids
254
  *
255
  * @since 1.0.0
 
256
  * @return array
257
  */
258
  public function get_forms( $expanded_data = false, $bust_cache = false ) {
259
 
260
- // Grab our saved transient.
261
  $forms = get_transient( 'constant_contact_shortcode_form_list' );
262
 
263
- // Allow bypassing transient check.
 
 
 
 
 
 
 
264
  $bypass_forms = apply_filters( 'constant_contact_bypass_shotcode_forms', false );
265
 
266
  // If we dont have a transient or we bypass, go through the motions.
@@ -274,7 +282,6 @@ class ConstantContact_CPTS {
274
  'update_post_term_cache' => false,
275
  ) );
276
 
277
- // Grab the posts.
278
  $q_forms = $query->get_posts();
279
 
280
  // If for some reason we got an error, just return a blank array.
@@ -283,15 +290,13 @@ class ConstantContact_CPTS {
283
  }
284
 
285
  // If we're not using this for the shortcode in the admin, just return
286
- // the IDs of our forms
287
  if ( ! $expanded_data ) {
288
  return $q_forms;
289
  }
290
 
291
- // Set up our default array.
292
  $forms = array();
293
 
294
- // Foreach form we have, lets build up our return array.
295
  foreach ( $q_forms as $form ) {
296
 
297
  // Make sure we have the data we want to use.
@@ -302,13 +307,13 @@ class ConstantContact_CPTS {
302
  isset( $form->post_modified )
303
  ) {
304
 
305
- // Get our title
306
  $title = ( $form->post_title ) ? $form->post_title : __( 'No title', 'constant-contact-forms' );
307
 
308
- // Get the last modified time in human text
309
  $last_modified = human_time_diff( strtotime( $form->post_modified ), time() );
310
 
311
- // Build up our title for the shortcode form admin
312
  $title = sprintf(
313
  esc_html__( '%s (last modified %s ago)', 'constant-contact-forms' ),
314
  $title,
@@ -320,7 +325,6 @@ class ConstantContact_CPTS {
320
  }
321
  }
322
 
323
- // Save that.
324
  set_transient( 'constant_contact_shortcode_form_list', $forms, 1 * HOUR_IN_SECONDS );
325
  }
326
 
1
  <?php
2
  /**
3
+ * Custom Post Types
4
+ *
5
  * @package ConstantContact
6
  * @subpackage CPTS
7
  * @author Constant Contact
79
  'update_item' => __( 'Update Form', 'constant-contact-forms' ),
80
  'view_item' => __( 'View Form', 'constant-contact-forms' ),
81
  'search_items' => __( 'Search Form', 'constant-contact-forms' ),
82
+ 'not_found' => __( 'No forms found', 'constant-contact-forms' ),
83
+ 'not_found_in_trash' => __( 'No forms found in Trash', 'constant-contact-forms' ),
84
  'featured_image' => __( 'Featured Image', 'constant-contact-forms' ),
85
  'set_featured_image' => __( 'Set featured image', 'constant-contact-forms' ),
86
  'remove_featured_image' => __( 'Remove featured image', 'constant-contact-forms' ),
170
  'capability_type' => 'page',
171
  );
172
 
173
+ // Only register if we're connected.
174
  if ( constantcontact_api()->is_connected() ) {
175
  register_post_type( 'ctct_lists', $args );
176
  }
177
  }
178
 
179
  /**
180
+ * Custom post udate messages to match CPT naming.
181
  *
182
+ * @since 1.0.0
183
+ * @param array $messages Default update messages.
184
+ * @return array appended update messages with custom post types.
185
  */
186
  public function post_updated_messages( $messages ) {
187
 
219
  }
220
 
221
  /**
222
+ * Customize the "Enter your title" placeholder text for Title field.
223
  *
224
+ * @since 1.0.0
225
+ * @param string $title Desired placeholder text.
226
  * @return string $title output string
227
  */
228
  public function change_default_title( $title ) {
229
  global $post;
230
 
231
+
232
  if ( ! isset( $post ) ) {
233
  return $title;
234
  }
235
 
 
236
  if ( ! isset( $post->post_type ) ) {
237
  return $title;
238
  }
239
 
240
+ // If we're on our forms post type.
241
  if ( 'ctct_forms' === $post->post_type ) {
242
  $title = sprintf(
243
  '%s <span class="ctct-admin-title-details">%s</span>',
254
  * Returns array of form ids
255
  *
256
  * @since 1.0.0
257
+ *
258
  * @return array
259
  */
260
  public function get_forms( $expanded_data = false, $bust_cache = false ) {
261
 
 
262
  $forms = get_transient( 'constant_contact_shortcode_form_list' );
263
 
264
+
265
+ /**
266
+ * Filters whether or not to bypass transient checks.
267
+ *
268
+ * @since 1.0.0
269
+ *
270
+ * @param bool $value Whether or not to bypass.
271
+ */
272
  $bypass_forms = apply_filters( 'constant_contact_bypass_shotcode_forms', false );
273
 
274
  // If we dont have a transient or we bypass, go through the motions.
282
  'update_post_term_cache' => false,
283
  ) );
284
 
 
285
  $q_forms = $query->get_posts();
286
 
287
  // If for some reason we got an error, just return a blank array.
290
  }
291
 
292
  // If we're not using this for the shortcode in the admin, just return
293
+ // the IDs of our forms.
294
  if ( ! $expanded_data ) {
295
  return $q_forms;
296
  }
297
 
 
298
  $forms = array();
299
 
 
300
  foreach ( $q_forms as $form ) {
301
 
302
  // Make sure we have the data we want to use.
307
  isset( $form->post_modified )
308
  ) {
309
 
310
+ // Get our title.
311
  $title = ( $form->post_title ) ? $form->post_title : __( 'No title', 'constant-contact-forms' );
312
 
313
+ // Get the last modified time in human text.
314
  $last_modified = human_time_diff( strtotime( $form->post_modified ), time() );
315
 
316
+ // Build up our title for the shortcode form admin.
317
  $title = sprintf(
318
  esc_html__( '%s (last modified %s ago)', 'constant-contact-forms' ),
319
  $title,
325
  }
326
  }
327
 
 
328
  set_transient( 'constant_contact_shortcode_form_list', $forms, 1 * HOUR_IN_SECONDS );
329
  }
330
 
includes/class-display-shortcode.php CHANGED
@@ -28,6 +28,16 @@ class ConstantContact_Display_Shortcode {
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  /**
@@ -253,4 +263,13 @@ class ConstantContact_Display_Shortcode {
253
 
254
  return '';
255
  }
 
 
 
 
 
 
 
 
 
256
  }
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
31
+ $this->hooks();
32
+ }
33
+
34
+ /**
35
+ * Hooks.
36
+ *
37
+ * @since next
38
+ */
39
+ public function hooks() {
40
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_display_styles' ) );
41
  }
42
 
43
  /**
263
 
264
  return '';
265
  }
266
+
267
+ /**
268
+ * Call the method to enqueue styles for display.
269
+ *
270
+ * @since next
271
+ */
272
+ public function enqueue_display_styles() {
273
+ constant_contact()->display->styles( true );
274
+ }
275
  }
includes/class-display.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Display
5
  * @author Constant Contact
@@ -14,7 +16,7 @@ class ConstantContact_Display {
14
  /**
15
  * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
@@ -22,8 +24,9 @@ class ConstantContact_Display {
22
  /**
23
  * Constructor
24
  *
25
- * @since 1.0.0
26
- * @return void
 
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -32,18 +35,15 @@ class ConstantContact_Display {
32
  /**
33
  * Scripts
34
  *
35
- * @since 1.0.0
36
- * @return void
 
37
  */
38
- public function scripts() {
39
 
40
- // Check if we are in debug mode. allow
41
  $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG === true ? true : false;
42
-
43
- // based on our debug mode, potentially add a min prefix
44
  $suffix = ( true === $debug ) ? '' : '.min';
45
 
46
- // Register our javascript file.
47
  wp_register_script(
48
  'ctct_frontend_forms',
49
  constant_contact()->url() . 'assets/js/ctct-plugin-frontend' . $suffix . '.js',
@@ -51,34 +51,48 @@ class ConstantContact_Display {
51
  constant_contact()->version,
52
  true
53
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
 
56
  /**
57
  * Main wrapper for getting our form display
58
  *
59
- * @since 1.0.0
 
60
  * @return string Form markup
61
  */
62
  public function form( $form_data, $form_id = '', $skip_styles = false ) {
63
 
64
- // Also enqueue our scripts
65
- $this->scripts();
66
-
67
- // Conditionally enqueue our styles
68
  if ( ! $skip_styles ) {
69
-
70
- wp_enqueue_style(
71
- 'ctct_form_styles',
72
- constant_contact()->url() . 'assets/css/style.css',
73
- array(),
74
- constant_contact()->version
75
- );
76
-
77
- // Enqueued script.
78
- wp_enqueue_script( 'ctct_frontend_forms' );
79
  }
80
 
81
- // Start our return markup and some default variables
82
  $return = '';
83
  $form_err_display = '';
84
  $error_message = false;
@@ -91,24 +105,24 @@ class ConstantContact_Display {
91
  // with our error messages.
92
  $response = constant_contact()->process_form->process_wrapper( $form_data, $form_id );
93
 
94
- // submitted values
95
  $old_values = isset( $response['values'] ) ? $response['values'] : '';
96
  $req_errors = isset( $response['errors'] ) ? $response['errors'] : '';
97
 
98
- // Check to see if we got a response, and if it has the fields we expect
99
  if ( $response && isset( $response['message'] ) && isset( $response['status'] ) ) {
100
 
101
- // If we were succesful, then display success message
102
  if ( 'success' === $response['status'] ) {
103
 
104
- // If we were successful, we'll return here so we don't display the entire form again
105
  return $this->message( 'success', $response['message'] );
106
 
107
  } else {
108
 
109
  // If we didn't get a success message, then we want to error.
110
  // We already checked for a messsage response, but we'll force the
111
- // status to error if we're not here
112
  $status = 'error';
113
  $error_message = trim( $response['message'] );
114
  }
@@ -118,107 +132,105 @@ class ConstantContact_Display {
118
  if ( 'error' === $status || $error_message ) {
119
 
120
  if ( ! empty( $error_message ) ) {
121
- // We'll show this error right inside our form
122
  $form_err_display = $this->message( 'error', $error_message );
123
  }
124
  }
125
 
126
- // Force uniqueness of an id for the form
127
  // @todo figure out another way to do this maybe?
128
  $rf_id = 'ctct-form-' . mt_rand();
129
 
130
- // Build out our form
131
  $return .= '<form class="ctct-form" id=' . $rf_id . ' action="' . esc_url( $this->get_current_page() ) . '" method="post">';
132
 
133
- // If we have errors, display them
134
  $return .= $form_err_display;
135
 
136
- // Output our normal form fields
137
  $return .= $this->build_form_fields( $form_data, $old_values, $req_errors );
138
 
139
- // Add our hidden verification fields
140
  $return .= $this->add_verify_fields( $form_data );
141
 
142
- // Add our submit field
143
- $return .= $this->submit();
144
 
145
- // Nonce the field too
146
  $return .= wp_nonce_field( 'ctct_submit_form', 'ctct_form', true, false );
147
 
148
- // add our disclose notice maybe
149
  $return .= wp_kses_post( $this->maybe_add_disclose_note( $form_data ) );
150
 
151
- // Close our form
152
  $return .= '</form>';
153
 
154
  $return .= '<script type="text/javascript">';
155
  $return .= 'var ajaxurl = "' . esc_url( admin_url( 'admin-ajax.php' ) ) . '";';
156
  $return .= '</script>';
157
 
158
- // Return it all
159
  return $return;
160
  }
161
 
162
  /**
163
- * Get our current URL in a somewhat robust way
 
 
164
  *
165
- * @since 1.0.0
166
  * @return string url of current page
167
  */
168
  public function get_current_page() {
169
 
170
- // Grab our global wp objects
171
  global $wp;
172
 
173
- // If we have a request, use that
174
  $request = ( isset( $wp->request ) && $wp->request ) ? $wp->request : null;
175
 
176
- // If we still have a request, lets get our url magically
177
  if ( $request ) {
178
 
179
  $curr_url = untrailingslashit( add_query_arg( '', '', home_url( $request ) ) );
180
 
181
- // if we're not using a custom permalink strucutre, theres a chance the above
182
  // will return the home_url. so we do another check to makesure we're going
183
  // to use the right thing. This check doesn't work on the homepage, but
184
- // that will just get caught with our fallback check correctly anyway
185
  if ( ! is_home() && ( home_url() !== $curr_url ) ) {
186
  return $curr_url;
187
  }
188
  }
189
 
190
- // Otherwise, we'll default to just using add_query_arg, which may throw errors
191
  return untrailingslashit( home_url( add_query_arg( array( '' => '' ) ) ) );
192
  }
193
 
194
  /**
195
- * Adds hidden input fields to our form for form id and verify id
 
 
196
  *
197
- * @since 1.0.0
198
- * @param string $form_data html markup
199
  */
200
  public function add_verify_fields( $form_data ) {
201
 
202
- // Sanity check
203
  if (
204
  isset( $form_data ) &&
205
  isset( $form_data['options'] ) &&
206
  isset( $form_data['options']['form_id'] )
207
  ) {
208
 
209
- // sanitize our form id
210
  $form_id = absint( $form_data['options']['form_id'] );
211
 
212
- // sanity check on our form id
213
  if ( ! $form_id ) {
214
  return false;
215
  }
216
 
217
- // Add hidden field with our form id in it
218
  $return = $this->input( 'hidden', 'ctct-id', 'ctct-id', $form_id, '', '', true );
219
 
220
- // if we have saved a verify value, add that to our field as well. this is to double-check
221
- // that we have the correct form id for processing later
222
  $verify_key = get_post_meta( $form_id, '_ctct_verify_key', true );
223
 
224
  if ( $verify_key ) {
@@ -233,24 +245,25 @@ class ConstantContact_Display {
233
  * Build form fields for shortcode
234
  *
235
  * @since 1.0.0
 
236
  * @param array $form_data formulated cmb2 data for form.
237
- * @return void
238
  */
239
  public function build_form_fields( $form_data, $old_values, $req_errors ) {
240
 
241
- // start our wrapper return var
242
  $return = '';
243
 
244
  // Check to see if we have a form ID for the form, and display our description.
245
  if ( isset( $form_data['options'] ) && isset( $form_data['options']['form_id'] ) ) {
246
 
247
- // Get our description
248
  $desc = isset( $form_data['options']['description'] ) ? $form_data['options']['description'] : '';
249
 
250
- // Clean our form ID
251
  $form_id = absint( $form_data['options']['form_id'] );
252
 
253
- // Add in our Description
254
  $return .= $this->description( $desc, $form_id );
255
  }
256
 
@@ -268,10 +281,11 @@ class ConstantContact_Display {
268
  }
269
 
270
  /**
271
- * Wrapper for single field display
272
  *
273
- * @since 1.0.0
274
- * @param array $field field data
 
275
  * @return string html markup
276
  */
277
  public function field( $field, $old_values = array(), $req_errors = array() ) {
@@ -303,22 +317,22 @@ class ConstantContact_Display {
303
  $map = $map . '___' . md5( serialize( $field ) );
304
  }
305
 
306
- // Default error status
307
  $field_error = false;
308
 
309
- // If we got any errors, then pass them through to the form field
310
  if ( ! empty( $req_errors ) ) {
311
 
312
- // Loop through each error
313
  foreach ( $req_errors as $error ) {
314
 
315
- // Make sure we have a field ID and an actual error
316
  if ( isset( $error['id'] ) && isset( $error['error'] ) ) {
317
 
318
- // If the error matches the field we're rendering
319
  if ( $map === $error['id'] ) {
320
 
321
- // Start our field error return
322
  $field_error = '<span class="ctct-field-error">';
323
 
324
  // Based on the error type, display an error.
@@ -328,17 +342,17 @@ class ConstantContact_Display {
328
  $field_error .= __( ' Error: Please fill out this field.', 'constant-contact-forms' );
329
  }
330
 
331
- // Finish error return
332
  $field_error .= '</span>';
333
  }
334
  }
335
  }
336
  }
337
 
338
- // Potentially replace value with submitted value
339
  $value = $this->get_submitted_value( $value, $map, $field, $old_values );
340
 
341
- // Based on our type, output different things
342
  switch ( $type ) {
343
  case 'custom':
344
  case 'first_name':
@@ -370,7 +384,7 @@ class ConstantContact_Display {
370
  break;
371
  case 'anniversery':
372
  case 'birthday':
373
- // need this to be month / day / year
374
  return $this->dates( $name, $map, $value, $desc, $req, false, $field_error );
375
  break;
376
  default:
@@ -382,45 +396,40 @@ class ConstantContact_Display {
382
  /**
383
  * Gets submitted values
384
  *
385
- * @since 1.0.0
386
- * @param array $field field data
 
387
  * @return string submitted value
388
  */
389
  public function get_submitted_value( $value = '', $map = '', $field = array(), $submitted_vals = array() ) {
390
 
391
- // If we have a value already return it
392
  if ( $value ) {
393
  return $value;
394
  }
395
 
396
- // Sanity check
397
  if ( ! is_array( $submitted_vals ) ) {
398
  return '';
399
  }
400
 
401
- // Possible return this array
402
  $return = array();
403
 
404
- // Loop through each val and try to grab our submitted
405
  foreach ( $submitted_vals as $post ) {
406
 
407
- // Make sure we have some value in the submitted
408
  if ( isset( $post['key'] ) && $post['key'] ) {
409
 
410
- // If we have an address, its a special case
411
  if ( 'address' === $field['name'] ) {
412
 
413
  // If any of our keys contain our address breaker, then add
414
- // it to the array
415
  if ( strpos( $post['key'], '_address___' ) !== false ) {
416
 
417
- // Try to grab the street_address (etc) part of our key
418
  $addr_key = explode( '___', $post['key'] );
419
 
420
- // If we got something, add it to our return array
421
  if ( isset( $addr_key[0] ) && $addr_key[0] ) {
422
 
423
- // Set default
424
  $post_key = '';
425
 
426
  // Validate our data we're about to use
@@ -440,12 +449,12 @@ class ConstantContact_Display {
440
  $post_key = sanitize_text_field( wp_unslash( $_POST[ esc_attr( $post['key'] ) ] ) ); // Input var okay.
441
  }
442
 
443
- // Set our return data
444
  $return[ esc_attr( $addr_key[0] ) ] = $post_key;
445
  }
446
  }
447
 
448
- // Otherwise make sure we have a value
449
  //
450
  // We also flag PHPCS to ignore this line, as we get
451
  // a nonce verification error, but we process the nonce
@@ -454,7 +463,7 @@ class ConstantContact_Display {
454
  // @codingStandardsIgnoreLine
455
  } elseif ( $post['key'] === $map && isset( $_POST[ esc_attr( $map ) ] ) ) { // Input var okay.
456
 
457
- // Clean and return
458
  //
459
  // We also flag PHPCS to ignore this line, as we get
460
  // a nonce verification error, but we process the nonce
@@ -466,99 +475,107 @@ class ConstantContact_Display {
466
  }
467
  }
468
 
469
- // If we did add to our array, send it back
470
- if ( ! empty( $return ) ) {
471
- return $return;
472
- }
473
-
474
- return '';
475
  }
476
 
477
  /**
478
- * Helper method to display in-line for success/error messages
 
 
479
  *
480
- * @since 1.0.0
481
- * @param string $type success / error / etc for class
482
- * @param string $message message to display to user
483
- * @return string html markup
484
  */
485
  public function message( $type, $message ) {
486
  return '<p class="ctct-message ' . esc_attr( $type ) . '">' . esc_attr( $message ) . '</p>';
487
  }
488
 
489
  /**
490
- * Helper method to display form description
 
 
491
  *
492
- * @since 1.0.0
493
- * @param string $description description to outpu
494
- * @return echo echos out form description markup
495
  */
496
  public function description( $desc = '', $form_id = false ) {
497
 
498
- // Set default var
499
  $display = '';
500
 
501
- // if we have the permissions, also display an edit link
502
  if ( current_user_can( 'edit_posts' ) && $form_id ) {
503
 
504
- // get our edit link
505
  $edit_link = get_edit_post_link( absint( $form_id ) );
506
 
507
- // if we got a link, display it
508
  if ( $edit_link ) {
509
  $display .= '<a class="button ctct-button" href="' . esc_url( $edit_link ) . '">' . __( 'Edit Form', 'constant-contact-forms' ) . '</a>';
510
  }
511
  }
512
 
513
- // Display our description
514
  return '<span class="ctct-form-description">' . wpautop( wp_kses_post( $desc ) ) . '</span>' . $display;
515
-
516
  }
517
 
518
  /**
519
- * Helper method to display label for form field + field starting markup
 
 
520
  *
521
- * @since 1.0.0
522
- * @param string $type type of field
523
- * @param string $name name / id of field
524
- * @param string $label label text for field
525
- * @param boolean $req is this field required?
526
- * @return string HTML markup
 
527
  */
528
  public function field_top( $type = '', $name = '', $f_id = '', $label = '', $req = false, $use_label = true ) {
529
 
530
- // Set blank defaults for required info
531
  $req_label = '';
532
 
533
- // If this is required, we output the HMTL5 required att
534
  if ( $req ) {
 
 
 
 
 
 
 
 
535
  $req_label = apply_filters( 'constant_contact_required_label', '<abbr title="required">*</abbr>' );
536
  }
537
 
538
- // Start building our return markup
539
  $markup = '<p class="ctct-form-field ctct-form-field-' . $type . '">';
540
 
541
- // alow skipping label, also don't show for submit buttons
542
  if ( $use_label && ( 'submit' !== $type ) && ( 'hidden' !== $type ) ) {
543
 
544
- // Our field label will be the form name + required asterisk + our label
545
  $markup .= $this->get_label( $f_id, $name . ' ' . $req_label );
546
  }
547
 
548
  // If we're not on submit or hidden, but still doing label on bottom,
549
- // then output a container div
550
  if ( ! $use_label ) {
551
  $markup .= '<div class="ctct-input-container">';
552
  }
553
 
554
- // return it
555
  return $markup;
556
  }
557
 
558
  /**
559
- * Bottom of field markup
560
  *
561
- * @since 1.0.0
 
 
 
562
  * @return string HTML markup
563
  */
564
  public function field_bottom( $name = '', $field_label = '' ) {
@@ -568,37 +585,41 @@ class ConstantContact_Display {
568
  $markup .= $this->get_label( $name, $field_label );
569
  ;
570
  }
571
- // Finish building our markup
572
  return $markup . '</p>';
573
  }
574
 
575
  /**
576
- * Helper method to get form label
 
 
577
  *
578
- * @since 1.0.0
579
- * @param string $name name/id of form field
580
- * @param string $text text to display as label
581
- * @return string HTML markup
582
  */
583
  public function get_label( $f_id, $field_label ) {
584
  return '<label for="' . $f_id . '">' . $field_label . '</label>';
585
  }
586
 
587
  /**
588
- * Wrapper for 'input' form fields
 
 
589
  *
590
- * @since 1.0.0
591
- * @param string $type type of form field
592
- * @param string $name ID of form field
593
- * @param string $value pre-filled value
594
- * @param string $label label text for inpug
595
- * @param boolean $req is this field required?
596
- * @param boolean $f_only should we only return the field itself, with no label?
597
- * @return string HTML markup for field
 
598
  */
599
  public function input( $type = 'text', $name = '', $id = '', $value = '', $label = '', $req = false, $f_only = false, $field_error = false ) {
600
 
601
- // Sanitize our stuff / set values
602
  $name = sanitize_text_field( $name );
603
  $f_id = sanitize_title( $id );
604
  $type = sanitize_text_field( $type );
@@ -606,192 +627,207 @@ class ConstantContact_Display {
606
  $label = sanitize_text_field( $label );
607
  $req_text = $req ? 'required' : '';
608
 
609
- // Start our markup
610
  $markup = $this->field_top( $type, $name, $f_id, $label, $req );
611
 
612
- // Set our field as as seprate var, because we allow for only returning that
613
  $field = '<input ' . $req_text . ' type="' . $type . '" name="' . $f_id . '" id="' . $f_id . '" value="' . $value . '" placeholder="' . $label . '"';
614
 
615
- // If we have an error
616
  if ( $field_error ) {
617
 
618
- // Tack that sucker on to the end of our input
619
  $field .= 'class="ctct-invalid"';
620
  }
621
 
622
- // Finish the markup for our field itself
623
  $field .= '/>';
624
 
625
- // Add our field to our markup
626
  $markup .= $field;
627
 
628
- // If we got an error, add it to the bottom label
629
  if ( $field_error ) {
630
  $markup .= $this->field_bottom( $id, $field_error );
631
  } else {
632
  $markup .= $this->field_bottom();
633
  }
634
 
635
- // If we passed in a flag for only the field, just return that
636
  if ( $f_only ) {
637
  return $field;
638
  }
639
 
640
- // Otherwise all the markup
641
  return $markup;
642
  }
643
 
644
  /**
645
- * Checkbox field helper method
646
  *
647
- * @since 1.0.0
648
- * @param string $name name/it of field
649
- * @param string $value value of field
650
- * @param string $label label / desc text
651
- * @return string html markup for checkbox
 
 
652
  */
653
  public function checkbox( $name = '', $f_id = '', $value = '', $label = '' ) {
654
 
655
- // Clean our inputs
656
  $name = sanitize_text_field( $name );
657
  $f_id = sanitize_title( $f_id );
658
  $value = sanitize_text_field( $value );
659
  $label = esc_attr( $label );
660
  $type = 'checkbox';
661
 
662
- // Build up our markup
663
  $markup = $this->field_top( $type, $name, $f_id, $label, false, false );
664
  $markup .= '<input type="' . $type . '" name="' . $f_id . '" id="' . $f_id . '" value="' . $value . '" />';
665
  $markup .= $this->field_bottom( $name, ' ' . $label );
666
 
667
- // return it
668
  return $markup;
669
  }
670
 
671
  /**
672
- * Helper method for submit button
673
  *
674
- * @since 1.0.0
675
- * @return string html markup
 
 
 
676
  */
677
- public function submit() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
678
  return $this->field( array(
679
  'type' => 'submit',
680
  'name' => 'ctct-submitted',
681
  'map_to' => 'ctct-submitted',
682
- 'value' => __( 'Send', 'constant-contact-forms' ),
683
  ) );
684
  }
685
 
686
  /**
687
- * Build markup for opt_in form
 
 
688
  *
689
- * @since 1.0.0
690
- * @param array $form_data form data structure
691
- * @return string markup of optin form
692
  */
693
  public function opt_in( $form_data ) {
694
 
695
- // Make sure we have our optin data
696
  if ( ! isset( $form_data['optin'] ) ) {
697
  return;
698
  }
699
 
700
- // Set up our defaults
701
  $optin = wp_parse_args( $form_data['optin'], array(
702
  'list' => false,
703
  'show' => false,
704
  'instructions' => '',
705
  ) );
706
 
707
- // Make sure we have our opt in set, as well as an associated list
708
  if ( isset( $optin['list'] ) && $optin['list'] ) {
709
  return $this->optin_display( $optin );
710
  }
711
  }
712
 
713
  /**
714
- * Internal method to display checkbox
715
  *
716
- * @since 1.0.0
717
- * @param array $optin optin data
718
- * @return string html markup
 
719
  */
720
  public function optin_display( $optin ) {
721
 
722
- // Clean our inputs, set defaults
723
  $label = sanitize_text_field( isset( $optin['instructions'] ) ? $optin['instructions'] : '' );
724
  $value = sanitize_text_field( isset( $optin['list'] ) ? $optin['list'] : '' );
725
 
726
- // Set our $show var
727
  $show = false;
728
  if ( isset( $optin['show'] ) && 'on' === $optin['show'] ) {
729
  $show = true;
730
  }
731
 
732
- // Start our markup return
733
  $markup = '';
734
 
735
- // If we set to hide the field, then hide it inline
736
  if ( ! $show ) {
737
  $markup = '<div class="ctct-optin-hide" style="display:none;">';
738
  }
739
 
740
- // Grab our markup
741
  $markup .= $this->get_optin_markup( $label, $value, $show );
742
 
743
- // If we set to hide, close our open div
744
  if ( ! $show ) {
745
  $markup .= '</div><!--.ctct-optin-hide -->';
746
  }
747
 
748
- // return it
749
  return $markup;
750
  }
751
 
752
  /**
753
  * Helper method to get optin markup
754
  *
755
- * @since 1.0.0
756
- * @param string $label label for field
757
- * @param string $value value of opt in field
758
- * @param string $show whether or not we are showing the field
759
- * @return string HTML markup
 
760
  */
761
  public function get_optin_markup( $label, $value, $show ) {
762
 
763
- // If we aren't showing the field, then we default our checkbox to checked
764
  $checked = $show ? '' : 'checked';
765
 
766
- // Build up our markup
767
  $markup = $this->field_top( 'checkbox', 'ctct-opt-in', 'ctct-opt-in', $label, false, false );
768
  $markup .= '<input type="checkbox" ' . $checked . ' name="ctct-opt-in" id="ctct-opt-in" value="' . $value . '" />';
769
  $markup .= $this->field_bottom( 'ctct-opt-in', ' ' . wp_kses_post( $label ) ) . '</div>';
770
 
771
- // Send it back
772
  return $markup;
773
  }
774
 
775
  /**
776
  * Builds a fancy address field group
777
  *
778
- * @since 1.0.0
779
- * @param string $name name of fields
780
- * @param string $f_id form id name
781
- * @param array $value values of each field
782
- * @param string $desc label of field
783
- * @return string html markup of field
 
 
 
784
  */
785
  public function address( $name = '', $f_id = '', $value = array(), $desc = '', $req = false, $field_error = '' ) {
786
 
787
- // Set up our text strings
788
  $street = __( 'Street Address', 'constant-contact-forms' );
789
  $line_2 = __( 'Address Line 2', 'constant-contact-forms' );
790
  $city = __( 'City', 'constant-contact-forms' );
791
  $state = __( 'State', 'constant-contact-forms' );
792
  $zip = __( 'ZIP Code', 'constant-contact-forms' );
793
 
794
- // Set our values
795
  $v_street = isset( $value['street_address'] ) ? $value['street_address'] : '';
796
  $v_line_2 = isset( $value['line_2_address'] ) ? $value['line_2_address'] : '';
797
  $v_city = isset( $value['city_address'] ) ? $value['city_address'] : '';
@@ -800,16 +836,17 @@ class ConstantContact_Display {
800
 
801
  $req = $req ? ' required ' : '';
802
 
803
- // Build our field
804
  $return = '<p class="ctct-address"><fieldset>';
805
  $return .= ' <legend>' . esc_attr( $name ) . '</legend>';
806
  $return .= ' <div class="ctct-form-field ctct-field-full address-line-1">';
807
  $return .= ' <label for="street_' . esc_attr( $f_id ) . '">' . esc_attr( $street ) . '</label>';
808
  $return .= ' <input ' . $req . 'type="text" name="street_' . esc_attr( $f_id ) . '" id="street_' . esc_attr( $f_id ) . '" value="' . esc_attr( $v_street ) . '">';
809
  $return .= ' </div>';
 
810
  $return .= ' <div class="ctct-form-field ctct-field-full address-line-2" id="input_2_1_2_container">';
811
  $return .= ' <label for="line_2_' . esc_attr( $f_id ) . '">' . esc_attr( $line_2 ) . '</label>';
812
- $return .= ' <input ' . $req . 'type="text" name="line_2_' . esc_attr( $f_id ) . '" id="line_2_' . esc_attr( $f_id ) . '" value="' . esc_attr( $v_line_2 ) . '">';
813
  $return .= ' </div>';
814
  $return .= ' <div class="ctct-form-field ctct-field-third address-city" id="input_2_1_3_container">';
815
  $return .= ' <label for="city_' . esc_attr( $f_id ) . '">' . esc_attr( $city ) . '</label>';
@@ -831,29 +868,30 @@ class ConstantContact_Display {
831
  /**
832
  * Gets and return a 3-part date selector
833
  *
834
- * @since 1.0.0
835
- * @param string $name name of field
836
- * @param string $f_id field id
837
- * @param array $value values to pre-fill
838
- * @param string $desc description of fields
839
- * @param boolean $req is required?
840
- * @param string $field_error field error text
841
- * @return string html markup of fields
 
842
  */
843
  public function dates( $name = '', $f_id = '', $value = array(), $desc = '', $req = false, $field_error = '' ) {
844
 
845
- // Set our field lables
846
  $month = __( 'Month', 'constant-contact-forms' );
847
  $day = __( 'Day', 'constant-contact-forms' );
848
  $year = __( 'Year', 'constant-contact-forms' );
849
 
850
- // @TODO these need to get set correctly
851
- // Set our values
852
  $v_month = isset( $value['month'] ) ? $value['month'] : '';
853
  $v_day = isset( $value['day'] ) ? $value['day'] : '';
854
  $v_year = isset( $value['year'] ) ? $value['year'] : '';
855
 
856
- // Build our field
857
  $return = '<p class="ctct-date"><fieldset>';
858
  $return .= ' <legend>' . esc_attr( $name ) . '</legend>';
859
  $return .= ' <div class="ctct-form-field ctct-field-inline month">';
@@ -874,88 +912,97 @@ class ConstantContact_Display {
874
  /**
875
  * Gets actual dropdowns for date selector
876
  *
877
- * @since 1.0.0
878
- * @param string $text text for default option
879
- * @param string $f_id field id
880
- * @param string $type type of dropdown (day, month, year)
881
- * @param string $selected_value previous value
882
- * @param boolean $req is require?
883
- * @return string markup of field
 
884
  */
885
  public function get_date_dropdown( $text = '', $f_id = '', $type = '', $selected_value = '', $req = false ) {
886
 
887
- // Account for our weird IDs
888
  $f_id = str_replace( 'birthday', 'birthday_' . $type, $f_id );
889
  $f_id = str_replace( 'anniversary', 'anniversary_' . $type, $f_id );
890
 
891
- // Start our field
892
  $return = '<select name="' . esc_attr( $f_id ) . '" class="ctct-date-select ctct-date-select-' . esc_attr( $type ) . '">';
893
 
894
  if ( $req ) {
895
  $return = str_replace( '">', '" required>', $return );
896
  }
897
 
898
- // Grab all of our options based on the field type
899
  $return .= $this->get_date_options( $text, $this->get_date_values( $type ), $selected_value );
900
 
901
- // Close our field
902
  $return .= '</select>';
903
 
904
- // Send it back
905
  return $return;
906
  }
907
 
908
  /**
909
- * Gets option markup for a date selector
 
 
910
  *
911
- * @since 1.0.0
912
- * @param string $text default first option
913
- * @param array $values values to use
914
- * @param array $prev_selected_values previous selected values
915
- * @return string html markup
916
  */
917
  public function get_date_options( $text = '', $values = array(), $prev_selected_values = array() ) {
918
 
919
- // First, we'll want
920
  $return = '<option value="">' . sanitize_text_field( $text ) . '</option>';
921
 
922
- // If we don't have a values array, bail out
923
  if ( ! is_array( $values ) ) {
924
  return $return;
925
  }
926
 
927
- // Loop through each of our values
928
  foreach ( $values as $key => $value ) {
929
 
930
- // Sanitize and make sure our key is set
931
  $key = sanitize_text_field( isset( $key ) ? $key : '' );
932
 
933
- // Sanitize and make sure our value is set
934
  $value = sanitize_text_field( isset( $value ) ? $value : '' );
935
 
936
- // Build out our option value
937
  $return .= '<option value="' . $key . '">' . $value . '</option>';
938
  }
939
 
940
- // Send it back
941
  return $return;
942
  }
943
 
944
  /**
945
- * Gets array of data for a date dropdown type
946
  *
947
- * @since 1.0.0
948
- * @param string $type day,month,or,year
949
- * @return array array of data
 
950
  */
951
  public function get_date_values( $type ) {
952
 
953
- // Based on $type, we'll send back an array of either days, months, or years
954
  switch ( $type ) {
955
  case 'day':
 
 
 
 
 
 
 
 
956
  $return = apply_filters( 'constant_contact_dates_day', $this->get_days() );
957
  break;
958
  case 'month':
 
 
 
 
 
 
 
 
959
  $return = apply_filters( 'constant_contact_dates_month', array(
960
  'january' => __( 'January', 'contantcontact' ),
961
  'february' => __( 'February', 'contantcontact' ),
@@ -972,6 +1019,14 @@ class ConstantContact_Display {
972
  ) );
973
  break;
974
  case 'year':
 
 
 
 
 
 
 
 
975
  $return = apply_filters( 'constant_contact_dates_year', $this->get_years() );
976
  break;
977
  }
@@ -980,19 +1035,19 @@ class ConstantContact_Display {
980
  }
981
 
982
  /**
983
- * Helper method to get all years
984
  *
985
- * @since 1.0.0
986
  * @return array years from 1910-current year
987
  */
988
  public function get_years() {
989
 
990
- // Get all of our years
991
  $year_range = range( 1910, date( 'Y' ) );
992
 
993
  $year_range = array_reverse( $year_range );
994
 
995
- // Loop through each of the years we have
996
  foreach ( $year_range as $year ) {
997
  $years[ $year ] = $year;
998
  }
@@ -1003,15 +1058,15 @@ class ConstantContact_Display {
1003
  /**
1004
  * Gets array of 1-31
1005
  *
1006
- * @since 1.0.0
1007
  * @return array array of days
1008
  */
1009
  public function get_days() {
1010
 
1011
- // Get all of our day
1012
  $day_range = range( 1, 31 );
1013
 
1014
- // Loop through each of the days we have
1015
  foreach ( $day_range as $day ) {
1016
  $days[ $day ] = $day;
1017
  }
@@ -1022,88 +1077,97 @@ class ConstantContact_Display {
1022
  /**
1023
  * Displays text area field
1024
  *
1025
- * @param string $name name of field
1026
- * @param string $map id of field
1027
- * @param string $value previous value of field
1028
- * @param string $desc description/label of field
1029
- * @param boolean $req is required?
1030
- * @param string $field_error error from field
1031
- * @return string html markup
1032
  */
1033
  public function textarea( $name = '', $map = '', $value = '', $desc = '', $req = false, $field_error = '' ) {
1034
- // Set our required text
1035
  $req_text = $req ? 'required' : '';
1036
 
1037
- // If required, get our label
1038
  $req_label = '';
1039
  if ( $req ) {
 
 
 
 
 
 
 
 
1040
  $req_label = apply_filters( 'constant_contact_required_label', '<abbr title="required">*</abbr>' );
1041
  }
1042
 
1043
- // Build up our field markup
1044
  $return = '<p><label for="' . esc_attr( $map ) . '">' . esc_attr( $name ) . ' ' . $req_label . '</label><textarea ' . $req_text . ' name="' . esc_attr( $map ) . '" placeholder="' . esc_attr( $desc ) . '">' . esc_html( $value ) . '</textarea>';
1045
 
1046
- // IF we have an error, add it to our markup
1047
  if ( $field_error ) {
1048
  $return .= '<span class="ctct-field-error"><label for="' . esc_attr( $map ) . '">' . esc_attr( __( 'Error: Please correct your entry.', 'constant-contact-forms' ) ) . '</label></span>';
1049
  }
1050
 
1051
- // Send it back
1052
  return $return . '</p>';
1053
  }
1054
 
1055
  /**
1056
- * Maybe display the disclourse notice
1057
  *
1058
- * @since 1.0.0
1059
- * @param array $form_data form data
1060
- * @return string html markup
 
1061
  */
1062
  public function maybe_add_disclose_note( $form_data ) {
1063
 
1064
- // Get out our form options
1065
  $opts = isset( $form_data['options'] ) ? $form_data['options'] : false;
1066
 
1067
- // Bail if they're not set
1068
  if ( ! $opts ) {
1069
  return;
1070
  }
1071
 
1072
- // Get our optin data
1073
  $optin = isset( $opts['optin'] ) ? $opts['optin'] : false;
1074
 
1075
- // Bail if not set
1076
  if ( ! $optin ) {
1077
  return false;
1078
  }
1079
 
1080
- // Get our list
1081
  $list = isset( $optin['list'] ) ? $optin['list'] : false;
1082
 
1083
- // Bail if not set
1084
  if ( ! $list ) {
1085
  return false;
1086
  }
1087
 
1088
- // finally, send back our text
1089
  return $this->get_disclose_text();
1090
  }
1091
 
1092
  /**
1093
- * Get our disclose markup
1094
  *
1095
- * @since 1.0.0
1096
- * @return string html markup
 
1097
  */
1098
  public function get_disclose_text() {
 
 
 
 
 
 
 
 
1099
  return apply_filters( 'constant_contact_disclose', '<hr><sub>' . $this->get_inner_disclose_text() . '</sub>' );
1100
  }
1101
 
1102
  /**
1103
- * Get our disclose text
 
 
1104
  *
1105
- * @since 1.0.0
1106
- * @return string text
1107
  */
1108
  public function get_inner_disclose_text() {
1109
  return sprintf( __( 'By submitting this form, you are granting: %s, permission to email you. You may unsubscribe via the link found at the bottom of every email. (See our Email Privacy Policy (http://constantcontact.com/legal/privacy-statement) for details.) Emails are serviced by Constant Contact.', 'constant-contact-forms' ), $this->plugin->api->get_disclosure_info() );
1
  <?php
2
  /**
3
+ * Display.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Display
7
  * @author Constant Contact
16
  /**
17
  * Parent plugin class
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
24
  /**
25
  * Constructor
26
  *
27
+ * @since 1.0.0
28
+ *
29
+ * @param object $plugin Parent plugin.
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
35
  /**
36
  * Scripts
37
  *
38
+ * @since 1.0.0
39
+ * @param bool $enqueue Set true to enqueue the scripts after registering.
40
+ * @since next
41
  */
42
+ public function scripts( $enqueue = false ) {
43
 
 
44
  $debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG === true ? true : false;
 
 
45
  $suffix = ( true === $debug ) ? '' : '.min';
46
 
 
47
  wp_register_script(
48
  'ctct_frontend_forms',
49
  constant_contact()->url() . 'assets/js/ctct-plugin-frontend' . $suffix . '.js',
51
  constant_contact()->version,
52
  true
53
  );
54
+
55
+ if ( $enqueue ) {
56
+ wp_enqueue_script( 'ctct_frontend_forms' );
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Register and (maybe) enqueue styles.
62
+ *
63
+ * @since next
64
+ * @param bool $enqueue Set true to enqueue the scripts after registering.
65
+ */
66
+ public function styles( $enqueue = false ) {
67
+ wp_register_style(
68
+ 'ctct_form_styles',
69
+ constant_contact()->url() . 'assets/css/style.css',
70
+ array(),
71
+ constant_contact()->version
72
+ );
73
+
74
+ if ( $enqueue ) {
75
+ wp_enqueue_style( 'ctct_form_styles' );
76
+ }
77
  }
78
 
79
  /**
80
  * Main wrapper for getting our form display
81
  *
82
+ * @since 1.0.0
83
+ *
84
  * @return string Form markup
85
  */
86
  public function form( $form_data, $form_id = '', $skip_styles = false ) {
87
 
88
+ // Enqueue some things.
 
 
 
89
  if ( ! $skip_styles ) {
90
+ $this->styles( true );
91
+ $this->scripts( true );
92
+ } else {
93
+ $this->scripts();
 
 
 
 
 
 
94
  }
95
 
 
96
  $return = '';
97
  $form_err_display = '';
98
  $error_message = false;
105
  // with our error messages.
106
  $response = constant_contact()->process_form->process_wrapper( $form_data, $form_id );
107
 
108
+ // Submitted values.
109
  $old_values = isset( $response['values'] ) ? $response['values'] : '';
110
  $req_errors = isset( $response['errors'] ) ? $response['errors'] : '';
111
 
112
+ // Check to see if we got a response, and if it has the fields we expect.
113
  if ( $response && isset( $response['message'] ) && isset( $response['status'] ) ) {
114
 
115
+ // If we were succesful, then display success message.
116
  if ( 'success' === $response['status'] ) {
117
 
118
+ // If we were successful, we'll return here so we don't display the entire form again.
119
  return $this->message( 'success', $response['message'] );
120
 
121
  } else {
122
 
123
  // If we didn't get a success message, then we want to error.
124
  // We already checked for a messsage response, but we'll force the
125
+ // status to error if we're not here.
126
  $status = 'error';
127
  $error_message = trim( $response['message'] );
128
  }
132
  if ( 'error' === $status || $error_message ) {
133
 
134
  if ( ! empty( $error_message ) ) {
135
+ // We'll show this error right inside our form.
136
  $form_err_display = $this->message( 'error', $error_message );
137
  }
138
  }
139
 
140
+ // Force uniqueness of an id for the form.
141
  // @todo figure out another way to do this maybe?
142
  $rf_id = 'ctct-form-' . mt_rand();
143
 
144
+ // Build out our form.
145
  $return .= '<form class="ctct-form" id=' . $rf_id . ' action="' . esc_url( $this->get_current_page() ) . '" method="post">';
146
 
147
+ // If we have errors, display them.
148
  $return .= $form_err_display;
149
 
150
+ // Output our normal form fields.
151
  $return .= $this->build_form_fields( $form_data, $old_values, $req_errors );
152
 
153
+ // Add our hidden verification fields.
154
  $return .= $this->add_verify_fields( $form_data );
155
 
156
+ // Add our submit field.
157
+ $return .= $this->submit( $form_id );
158
 
159
+ // Nonce the field too.
160
  $return .= wp_nonce_field( 'ctct_submit_form', 'ctct_form', true, false );
161
 
162
+ // Add our disclose notice maybe.
163
  $return .= wp_kses_post( $this->maybe_add_disclose_note( $form_data ) );
164
 
 
165
  $return .= '</form>';
166
 
167
  $return .= '<script type="text/javascript">';
168
  $return .= 'var ajaxurl = "' . esc_url( admin_url( 'admin-ajax.php' ) ) . '";';
169
  $return .= '</script>';
170
 
 
171
  return $return;
172
  }
173
 
174
  /**
175
+ * Get our current URL in a somewhat robust way.
176
+ *
177
+ * @since 1.0.0
178
  *
 
179
  * @return string url of current page
180
  */
181
  public function get_current_page() {
182
 
183
+ // Grab our global wp objects.
184
  global $wp;
185
 
186
+ // If we have a request, use that.
187
  $request = ( isset( $wp->request ) && $wp->request ) ? $wp->request : null;
188
 
189
+ // If we still have a request, lets get our url magically.
190
  if ( $request ) {
191
 
192
  $curr_url = untrailingslashit( add_query_arg( '', '', home_url( $request ) ) );
193
 
194
+ // If we're not using a custom permalink strucutre, theres a chance the above
195
  // will return the home_url. so we do another check to makesure we're going
196
  // to use the right thing. This check doesn't work on the homepage, but
197
+ // that will just get caught with our fallback check correctly anyway.
198
  if ( ! is_home() && ( home_url() !== $curr_url ) ) {
199
  return $curr_url;
200
  }
201
  }
202
 
203
+ // Otherwise, we'll default to just using add_query_arg, which may throw errors.
204
  return untrailingslashit( home_url( add_query_arg( array( '' => '' ) ) ) );
205
  }
206
 
207
  /**
208
+ * Adds hidden input fields to our form for form id and verify id.
209
+ *
210
+ * @since 1.0.0
211
  *
212
+ * @param string $form_data html markup.
213
+ * @return mixed.
214
  */
215
  public function add_verify_fields( $form_data ) {
216
 
 
217
  if (
218
  isset( $form_data ) &&
219
  isset( $form_data['options'] ) &&
220
  isset( $form_data['options']['form_id'] )
221
  ) {
222
 
 
223
  $form_id = absint( $form_data['options']['form_id'] );
224
 
 
225
  if ( ! $form_id ) {
226
  return false;
227
  }
228
 
229
+ // Add hidden field with our form id in it.
230
  $return = $this->input( 'hidden', 'ctct-id', 'ctct-id', $form_id, '', '', true );
231
 
232
+ // If we have saved a verify value, add that to our field as well. this is to double-check
233
+ // that we have the correct form id for processing later.
234
  $verify_key = get_post_meta( $form_id, '_ctct_verify_key', true );
235
 
236
  if ( $verify_key ) {
245
  * Build form fields for shortcode
246
  *
247
  * @since 1.0.0
248
+ *
249
  * @param array $form_data formulated cmb2 data for form.
250
+ * @return string
251
  */
252
  public function build_form_fields( $form_data, $old_values, $req_errors ) {
253
 
254
+ // Start our wrapper return var.
255
  $return = '';
256
 
257
  // Check to see if we have a form ID for the form, and display our description.
258
  if ( isset( $form_data['options'] ) && isset( $form_data['options']['form_id'] ) ) {
259
 
260
+ // Get our description.
261
  $desc = isset( $form_data['options']['description'] ) ? $form_data['options']['description'] : '';
262
 
263
+ // Clean our form ID.
264
  $form_id = absint( $form_data['options']['form_id'] );
265
 
266
+ // Add in our Description.
267
  $return .= $this->description( $desc, $form_id );
268
  }
269
 
281
  }
282
 
283
  /**
284
+ * Wrapper for single field display.
285
  *
286
+ * @since 1.0.0
287
+ *
288
+ * @param array $field field data.
289
  * @return string html markup
290
  */
291
  public function field( $field, $old_values = array(), $req_errors = array() ) {
317
  $map = $map . '___' . md5( serialize( $field ) );
318
  }
319
 
320
+ // Default error status.
321
  $field_error = false;
322
 
323
+ // If we got any errors, then pass them through to the form field.
324
  if ( ! empty( $req_errors ) ) {
325
 
326
+ // Loop through each error.
327
  foreach ( $req_errors as $error ) {
328
 
329
+ // Make sure we have a field ID and an actual error.
330
  if ( isset( $error['id'] ) && isset( $error['error'] ) ) {
331
 
332
+ // If the error matches the field we're rendering.
333
  if ( $map === $error['id'] ) {
334
 
335
+ // Start our field error return.
336
  $field_error = '<span class="ctct-field-error">';
337
 
338
  // Based on the error type, display an error.
342
  $field_error .= __( ' Error: Please fill out this field.', 'constant-contact-forms' );
343
  }
344
 
345
+ // Finish error return.
346
  $field_error .= '</span>';
347
  }
348
  }
349
  }
350
  }
351
 
352
+ // Potentially replace value with submitted value.
353
  $value = $this->get_submitted_value( $value, $map, $field, $old_values );
354
 
355
+ // Based on our type, output different things.
356
  switch ( $type ) {
357
  case 'custom':
358
  case 'first_name':
384
  break;
385
  case 'anniversery':
386
  case 'birthday':
387
+ // Need this to be month / day / year.
388
  return $this->dates( $name, $map, $value, $desc, $req, false, $field_error );
389
  break;
390
  default:
396
  /**
397
  * Gets submitted values
398
  *
399
+ * @since 1.0.0
400
+ *
401
+ * @param array $field field data.
402
  * @return string submitted value
403
  */
404
  public function get_submitted_value( $value = '', $map = '', $field = array(), $submitted_vals = array() ) {
405
 
 
406
  if ( $value ) {
407
  return $value;
408
  }
409
 
 
410
  if ( ! is_array( $submitted_vals ) ) {
411
  return '';
412
  }
413
 
 
414
  $return = array();
415
 
 
416
  foreach ( $submitted_vals as $post ) {
417
 
 
418
  if ( isset( $post['key'] ) && $post['key'] ) {
419
 
420
+ // If we have an address, its a special case.
421
  if ( 'address' === $field['name'] ) {
422
 
423
  // If any of our keys contain our address breaker, then add
424
+ // it to the array.
425
  if ( strpos( $post['key'], '_address___' ) !== false ) {
426
 
427
+ // Try to grab the street_address (etc) part of our key.
428
  $addr_key = explode( '___', $post['key'] );
429
 
430
+ // If we got something, add it to our return array.
431
  if ( isset( $addr_key[0] ) && $addr_key[0] ) {
432
 
 
433
  $post_key = '';
434
 
435
  // Validate our data we're about to use
449
  $post_key = sanitize_text_field( wp_unslash( $_POST[ esc_attr( $post['key'] ) ] ) ); // Input var okay.
450
  }
451
 
452
+ // Set our return data.
453
  $return[ esc_attr( $addr_key[0] ) ] = $post_key;
454
  }
455
  }
456
 
457
+ // Otherwise make sure we have a value.
458
  //
459
  // We also flag PHPCS to ignore this line, as we get
460
  // a nonce verification error, but we process the nonce
463
  // @codingStandardsIgnoreLine
464
  } elseif ( $post['key'] === $map && isset( $_POST[ esc_attr( $map ) ] ) ) { // Input var okay.
465
 
466
+ // Clean and return.
467
  //
468
  // We also flag PHPCS to ignore this line, as we get
469
  // a nonce verification error, but we process the nonce
475
  }
476
  }
477
 
478
+ return $return;
 
 
 
 
 
479
  }
480
 
481
  /**
482
+ * Helper method to display in-line for success/error messages.
483
+ *
484
+ * @since 1.0.0
485
  *
486
+ * @param string $type Success / error / etc for class.
487
+ * @param string $message Message to display to user.
488
+ * @return string HTML markup.
 
489
  */
490
  public function message( $type, $message ) {
491
  return '<p class="ctct-message ' . esc_attr( $type ) . '">' . esc_attr( $message ) . '</p>';
492
  }
493
 
494
  /**
495
+ * Helper method to display form description.
496
+ *
497
+ * @since 1.0.0
498
  *
499
+ * @param string $desc Description to output.
500
+ * @param int|boolean $form_id Form ID.
501
+ * @return string Form description markup.
502
  */
503
  public function description( $desc = '', $form_id = false ) {
504
 
 
505
  $display = '';
506
 
507
+ // If we have the permissions, also display an edit link.
508
  if ( current_user_can( 'edit_posts' ) && $form_id ) {
509
 
510
+ // Get our edit link.
511
  $edit_link = get_edit_post_link( absint( $form_id ) );
512
 
513
+ // If we got a link, display it.
514
  if ( $edit_link ) {
515
  $display .= '<a class="button ctct-button" href="' . esc_url( $edit_link ) . '">' . __( 'Edit Form', 'constant-contact-forms' ) . '</a>';
516
  }
517
  }
518
 
 
519
  return '<span class="ctct-form-description">' . wpautop( wp_kses_post( $desc ) ) . '</span>' . $display;
 
520
  }
521
 
522
  /**
523
+ * Helper method to display label for form field + field starting markup.
524
+ *
525
+ * @since 1.0.0
526
  *
527
+ * @param string $type Type of field.
528
+ * @param string $name Name / id of field.
529
+ * @param string $f_id Field ID.
530
+ * @param string $label Label text for field.
531
+ * @param boolean $req If this field required.
532
+ * @param boolean $use_label Whether or not to use label.
533
+ * @return string HTML markup.
534
  */
535
  public function field_top( $type = '', $name = '', $f_id = '', $label = '', $req = false, $use_label = true ) {
536
 
537
+ // Set blank defaults for required info.
538
  $req_label = '';
539
 
540
+ // If this is required, we output the HMTL5 required att.
541
  if ( $req ) {
542
+
543
+ /**
544
+ * Filters the markup used for the required indicator.
545
+ *
546
+ * @since 1.0.0
547
+ *
548
+ * @param string $value An `<abbr>` tag with an asterisk indicating required status.
549
+ */
550
  $req_label = apply_filters( 'constant_contact_required_label', '<abbr title="required">*</abbr>' );
551
  }
552
 
553
+ // Start building our return markup.
554
  $markup = '<p class="ctct-form-field ctct-form-field-' . $type . '">';
555
 
556
+ // Allow skipping label, also don't show for submit buttons.
557
  if ( $use_label && ( 'submit' !== $type ) && ( 'hidden' !== $type ) ) {
558
 
559
+ // Our field label will be the form name + required asterisk + our label.
560
  $markup .= $this->get_label( $f_id, $name . ' ' . $req_label );
561
  }
562
 
563
  // If we're not on submit or hidden, but still doing label on bottom,
564
+ // then output a container div.
565
  if ( ! $use_label ) {
566
  $markup .= '<div class="ctct-input-container">';
567
  }
568
 
 
569
  return $markup;
570
  }
571
 
572
  /**
573
+ * Bottom of field markup.
574
  *
575
+ * @since 1.0.0
576
+ *
577
+ * @param string $name Field name.
578
+ * @param string $field_label Field label.
579
  * @return string HTML markup
580
  */
581
  public function field_bottom( $name = '', $field_label = '' ) {
585
  $markup .= $this->get_label( $name, $field_label );
586
  ;
587
  }
588
+ // Finish building our markup.
589
  return $markup . '</p>';
590
  }
591
 
592
  /**
593
+ * Helper method to get form label.
594
+ *
595
+ * @since 1.0.0
596
  *
597
+ * @param string $f_id Name/id of form field.
598
+ * @param string $field_label Text to display as label.
599
+ * @return string HTML markup
 
600
  */
601
  public function get_label( $f_id, $field_label ) {
602
  return '<label for="' . $f_id . '">' . $field_label . '</label>';
603
  }
604
 
605
  /**
606
+ * Wrapper for 'input' form fields.
607
+ *
608
+ * @since 1.0.0
609
  *
610
+ * @param string $type Type of form field.
611
+ * @param string $name ID of form field.
612
+ * @param string $id ID attribute value.
613
+ * @param string $value pre-filled value.
614
+ * @param string $label label text for inpug.
615
+ * @param boolean $req If field required.
616
+ * @param boolean $f_only If we only return the field itself, with no label.
617
+ * @param boolean $field_error Field error.
618
+ * @return string HTML markup for field.
619
  */
620
  public function input( $type = 'text', $name = '', $id = '', $value = '', $label = '', $req = false, $f_only = false, $field_error = false ) {
621
 
622
+ // Sanitize our stuff / set values.
623
  $name = sanitize_text_field( $name );
624
  $f_id = sanitize_title( $id );
625
  $type = sanitize_text_field( $type );
627
  $label = sanitize_text_field( $label );
628
  $req_text = $req ? 'required' : '';
629
 
630
+ // Start our markup.
631
  $markup = $this->field_top( $type, $name, $f_id, $label, $req );
632
 
633
+ // Set our field as as seprate var, because we allow for only returning that.
634
  $field = '<input ' . $req_text . ' type="' . $type . '" name="' . $f_id . '" id="' . $f_id . '" value="' . $value . '" placeholder="' . $label . '"';
635
 
636
+ // If we have an error.
637
  if ( $field_error ) {
638
 
639
+ // Tack that sucker on to the end of our input.
640
  $field .= 'class="ctct-invalid"';
641
  }
642
 
643
+ // Finish the markup for our field itself.
644
  $field .= '/>';
645
 
646
+ // Add our field to our markup.
647
  $markup .= $field;
648
 
649
+ // If we got an error, add it to the bottom label.
650
  if ( $field_error ) {
651
  $markup .= $this->field_bottom( $id, $field_error );
652
  } else {
653
  $markup .= $this->field_bottom();
654
  }
655
 
656
+ // If we passed in a flag for only the field, just return that.
657
  if ( $f_only ) {
658
  return $field;
659
  }
660
 
 
661
  return $markup;
662
  }
663
 
664
  /**
665
+ * Checkbox field helper method.
666
  *
667
+ * @since 1.0.0
668
+ *
669
+ * @param string $name Name/it of field.
670
+ * @param string $f_id Field ID.
671
+ * @param string $value Value of field.
672
+ * @param string $label Label / desc text.
673
+ * @return string HTML markup for checkbox.
674
  */
675
  public function checkbox( $name = '', $f_id = '', $value = '', $label = '' ) {
676
 
 
677
  $name = sanitize_text_field( $name );
678
  $f_id = sanitize_title( $f_id );
679
  $value = sanitize_text_field( $value );
680
  $label = esc_attr( $label );
681
  $type = 'checkbox';
682
 
 
683
  $markup = $this->field_top( $type, $name, $f_id, $label, false, false );
684
  $markup .= '<input type="' . $type . '" name="' . $f_id . '" id="' . $f_id . '" value="' . $value . '" />';
685
  $markup .= $this->field_bottom( $name, ' ' . $label );
686
 
 
687
  return $markup;
688
  }
689
 
690
  /**
691
+ * Helper method for submit button.
692
  *
693
+ * @since 1.0.0
694
+ * @since 1.1.0 Added form ID parameter.
695
+ *
696
+ * @param int $form_id Rendered form ID.
697
+ * @return string HTML markup.
698
  */
699
+ public function submit( $form_id = 0 ) {
700
+ $button_text = get_post_meta( $form_id, '_ctct_button_text', true );
701
+ $button_text =
702
+ ( ! empty( $button_text ) ) ?
703
+ $button_text :
704
+ /**
705
+ * Filters the text that appears on the submit button.
706
+ *
707
+ * @since 1.1.0
708
+ *
709
+ * @param string $value Submit button text.
710
+ */
711
+ apply_filters( 'constant_contact_submit_text', __( 'Send', 'constant-contact-forms' )
712
+ );
713
+
714
  return $this->field( array(
715
  'type' => 'submit',
716
  'name' => 'ctct-submitted',
717
  'map_to' => 'ctct-submitted',
718
+ 'value' => $button_text,
719
  ) );
720
  }
721
 
722
  /**
723
+ * Build markup for opt_in form.
724
+ *
725
+ * @since 1.0.0
726
  *
727
+ * @param array $form_data Form data structure.
728
+ * @return string Markup of optin form.
 
729
  */
730
  public function opt_in( $form_data ) {
731
 
732
+ // Make sure we have our optin data.
733
  if ( ! isset( $form_data['optin'] ) ) {
734
  return;
735
  }
736
 
737
+ // Set up our defaults.
738
  $optin = wp_parse_args( $form_data['optin'], array(
739
  'list' => false,
740
  'show' => false,
741
  'instructions' => '',
742
  ) );
743
 
744
+ // Make sure we have our opt in set, as well as an associated list.
745
  if ( isset( $optin['list'] ) && $optin['list'] ) {
746
  return $this->optin_display( $optin );
747
  }
748
  }
749
 
750
  /**
751
+ * Internal method to display checkbox.
752
  *
753
+ * @since 1.0.0
754
+ *
755
+ * @param array $optin Optin data.
756
+ * @return string HTML markup.
757
  */
758
  public function optin_display( $optin ) {
759
 
 
760
  $label = sanitize_text_field( isset( $optin['instructions'] ) ? $optin['instructions'] : '' );
761
  $value = sanitize_text_field( isset( $optin['list'] ) ? $optin['list'] : '' );
762
 
 
763
  $show = false;
764
  if ( isset( $optin['show'] ) && 'on' === $optin['show'] ) {
765
  $show = true;
766
  }
767
 
 
768
  $markup = '';
769
 
770
+ // If we set to hide the field, then hide it inline.
771
  if ( ! $show ) {
772
  $markup = '<div class="ctct-optin-hide" style="display:none;">';
773
  }
774
 
775
+ // Grab our markup.
776
  $markup .= $this->get_optin_markup( $label, $value, $show );
777
 
778
+ // If we set to hide, close our open div.
779
  if ( ! $show ) {
780
  $markup .= '</div><!--.ctct-optin-hide -->';
781
  }
782
 
 
783
  return $markup;
784
  }
785
 
786
  /**
787
  * Helper method to get optin markup
788
  *
789
+ * @since 1.0.0
790
+ *
791
+ * @param string $label Label for field.
792
+ * @param string $value Value of opt in field.
793
+ * @param string $show Whether or not we are showing the field.
794
+ * @return string HTML markup
795
  */
796
  public function get_optin_markup( $label, $value, $show ) {
797
 
798
+ // If we aren't showing the field, then we default our checkbox to checked.
799
  $checked = $show ? '' : 'checked';
800
 
 
801
  $markup = $this->field_top( 'checkbox', 'ctct-opt-in', 'ctct-opt-in', $label, false, false );
802
  $markup .= '<input type="checkbox" ' . $checked . ' name="ctct-opt-in" id="ctct-opt-in" value="' . $value . '" />';
803
  $markup .= $this->field_bottom( 'ctct-opt-in', ' ' . wp_kses_post( $label ) ) . '</div>';
804
 
 
805
  return $markup;
806
  }
807
 
808
  /**
809
  * Builds a fancy address field group
810
  *
811
+ * @since 1.0.0
812
+ *
813
+ * @param string $name Name of fields.
814
+ * @param string $f_id Form ID name.
815
+ * @param array $value Values of each field.
816
+ * @param string $desc Label of field.
817
+ * @param boolean $req Whether or not required.
818
+ * @param string $field_error Field error value.
819
+ * @return string field HTML markup.
820
  */
821
  public function address( $name = '', $f_id = '', $value = array(), $desc = '', $req = false, $field_error = '' ) {
822
 
823
+ // Set up our text strings.
824
  $street = __( 'Street Address', 'constant-contact-forms' );
825
  $line_2 = __( 'Address Line 2', 'constant-contact-forms' );
826
  $city = __( 'City', 'constant-contact-forms' );
827
  $state = __( 'State', 'constant-contact-forms' );
828
  $zip = __( 'ZIP Code', 'constant-contact-forms' );
829
 
830
+ // Set our values.
831
  $v_street = isset( $value['street_address'] ) ? $value['street_address'] : '';
832
  $v_line_2 = isset( $value['line_2_address'] ) ? $value['line_2_address'] : '';
833
  $v_city = isset( $value['city_address'] ) ? $value['city_address'] : '';
836
 
837
  $req = $req ? ' required ' : '';
838
 
839
+ // Build our field.
840
  $return = '<p class="ctct-address"><fieldset>';
841
  $return .= ' <legend>' . esc_attr( $name ) . '</legend>';
842
  $return .= ' <div class="ctct-form-field ctct-field-full address-line-1">';
843
  $return .= ' <label for="street_' . esc_attr( $f_id ) . '">' . esc_attr( $street ) . '</label>';
844
  $return .= ' <input ' . $req . 'type="text" name="street_' . esc_attr( $f_id ) . '" id="street_' . esc_attr( $f_id ) . '" value="' . esc_attr( $v_street ) . '">';
845
  $return .= ' </div>';
846
+ // Address Line 2 is not required, note the missing $req inclusion.
847
  $return .= ' <div class="ctct-form-field ctct-field-full address-line-2" id="input_2_1_2_container">';
848
  $return .= ' <label for="line_2_' . esc_attr( $f_id ) . '">' . esc_attr( $line_2 ) . '</label>';
849
+ $return .= ' <input type="text" name="line_2_' . esc_attr( $f_id ) . '" id="line_2_' . esc_attr( $f_id ) . '" value="' . esc_attr( $v_line_2 ) . '">';
850
  $return .= ' </div>';
851
  $return .= ' <div class="ctct-form-field ctct-field-third address-city" id="input_2_1_3_container">';
852
  $return .= ' <label for="city_' . esc_attr( $f_id ) . '">' . esc_attr( $city ) . '</label>';
868
  /**
869
  * Gets and return a 3-part date selector
870
  *
871
+ * @since 1.0.0
872
+ *
873
+ * @param string $name Name of field.
874
+ * @param string $f_id Field ID.
875
+ * @param array $value Values to pre-fill.
876
+ * @param string $desc Description of fields.
877
+ * @param boolean $req If is required.
878
+ * @param string $field_error Field error text.
879
+ * @return string Fields HTML markup.
880
  */
881
  public function dates( $name = '', $f_id = '', $value = array(), $desc = '', $req = false, $field_error = '' ) {
882
 
883
+ // Set our field lables.
884
  $month = __( 'Month', 'constant-contact-forms' );
885
  $day = __( 'Day', 'constant-contact-forms' );
886
  $year = __( 'Year', 'constant-contact-forms' );
887
 
888
+ // @TODO these need to get set correctly.
889
+ // Set our values.
890
  $v_month = isset( $value['month'] ) ? $value['month'] : '';
891
  $v_day = isset( $value['day'] ) ? $value['day'] : '';
892
  $v_year = isset( $value['year'] ) ? $value['year'] : '';
893
 
894
+ // Build our field.
895
  $return = '<p class="ctct-date"><fieldset>';
896
  $return .= ' <legend>' . esc_attr( $name ) . '</legend>';
897
  $return .= ' <div class="ctct-form-field ctct-field-inline month">';
912
  /**
913
  * Gets actual dropdowns for date selector
914
  *
915
+ * @since 1.0.0
916
+ *
917
+ * @param string $text Text for default option.
918
+ * @param string $f_id Field ID.
919
+ * @param string $type Type of dropdown (day, month, year).
920
+ * @param string $selected_value Previous value.
921
+ * @param boolean $req If is require.
922
+ * @return string field markup.
923
  */
924
  public function get_date_dropdown( $text = '', $f_id = '', $type = '', $selected_value = '', $req = false ) {
925
 
926
+ // Account for our weird IDs.
927
  $f_id = str_replace( 'birthday', 'birthday_' . $type, $f_id );
928
  $f_id = str_replace( 'anniversary', 'anniversary_' . $type, $f_id );
929
 
 
930
  $return = '<select name="' . esc_attr( $f_id ) . '" class="ctct-date-select ctct-date-select-' . esc_attr( $type ) . '">';
931
 
932
  if ( $req ) {
933
  $return = str_replace( '">', '" required>', $return );
934
  }
935
 
936
+ // Grab all of our options based on the field type.
937
  $return .= $this->get_date_options( $text, $this->get_date_values( $type ), $selected_value );
938
 
 
939
  $return .= '</select>';
940
 
 
941
  return $return;
942
  }
943
 
944
  /**
945
+ * Gets option markup for a date selector.
946
+ *
947
+ * @since 1.0.0
948
  *
949
+ * @param string $text Default first option.
950
+ * @param array $values Values to use.
951
+ * @param array $prev_selected_values Previous selected values.
952
+ * @return string HTML markup.
 
953
  */
954
  public function get_date_options( $text = '', $values = array(), $prev_selected_values = array() ) {
955
 
 
956
  $return = '<option value="">' . sanitize_text_field( $text ) . '</option>';
957
 
 
958
  if ( ! is_array( $values ) ) {
959
  return $return;
960
  }
961
 
 
962
  foreach ( $values as $key => $value ) {
963
 
 
964
  $key = sanitize_text_field( isset( $key ) ? $key : '' );
965
 
 
966
  $value = sanitize_text_field( isset( $value ) ? $value : '' );
967
 
 
968
  $return .= '<option value="' . $key . '">' . $value . '</option>';
969
  }
970
 
 
971
  return $return;
972
  }
973
 
974
  /**
975
+ * Gets array of data for a date dropdown type.
976
  *
977
+ * @since 1.0.0
978
+ *
979
+ * @param string $type Day, month, or year.
980
+ * @return array Array of data
981
  */
982
  public function get_date_values( $type ) {
983
 
984
+ // Based on $type, we'll send back an array of either days, months, or years.
985
  switch ( $type ) {
986
  case 'day':
987
+
988
+ /**
989
+ * Filters the array of numbers used to indicate day of the month in numerals.
990
+ *
991
+ * @since 1.0.0
992
+ *
993
+ * @param array $value Array of numbers ranging from 1 to 31.
994
+ */
995
  $return = apply_filters( 'constant_contact_dates_day', $this->get_days() );
996
  break;
997
  case 'month':
998
+
999
+ /**
1000
+ * Filters the array of months used for dropdown.
1001
+ *
1002
+ * @since 1.0.0
1003
+ *
1004
+ * @param array $value Array of months from calendar.
1005
+ */
1006
  $return = apply_filters( 'constant_contact_dates_month', array(
1007
  'january' => __( 'January', 'contantcontact' ),
1008
  'february' => __( 'February', 'contantcontact' ),
1019
  ) );
1020
  break;
1021
  case 'year':
1022
+
1023
+ /**
1024
+ * Filters the array of years, starting from 1910 to present.
1025
+ *
1026
+ * @since 1.0.0
1027
+ *
1028
+ * @param array $value Array of years.
1029
+ */
1030
  $return = apply_filters( 'constant_contact_dates_year', $this->get_years() );
1031
  break;
1032
  }
1035
  }
1036
 
1037
  /**
1038
+ * Helper method to get all years.
1039
  *
1040
+ * @since 1.0.0
1041
  * @return array years from 1910-current year
1042
  */
1043
  public function get_years() {
1044
 
1045
+ // Get all of our years.
1046
  $year_range = range( 1910, date( 'Y' ) );
1047
 
1048
  $year_range = array_reverse( $year_range );
1049
 
1050
+ // Loop through each of the years we have.
1051
  foreach ( $year_range as $year ) {
1052
  $years[ $year ] = $year;
1053
  }
1058
  /**
1059
  * Gets array of 1-31
1060
  *
1061
+ * @since 1.0.0
1062
  * @return array array of days
1063
  */
1064
  public function get_days() {
1065
 
1066
+ // Get all of our day.
1067
  $day_range = range( 1, 31 );
1068
 
1069
+ // Loop through each of the days we have.
1070
  foreach ( $day_range as $day ) {
1071
  $days[ $day ] = $day;
1072
  }
1077
  /**
1078
  * Displays text area field
1079
  *
1080
+ * @param string $name Name of field.
1081
+ * @param string $map ID of field.
1082
+ * @param string $value Previous value of field.
1083
+ * @param string $desc Description/label of field.
1084
+ * @param boolean $req If is required.
1085
+ * @param string $field_error Error from field.
1086
+ * @return string HTML markup.
1087
  */
1088
  public function textarea( $name = '', $map = '', $value = '', $desc = '', $req = false, $field_error = '' ) {
1089
+ // Set our required text.
1090
  $req_text = $req ? 'required' : '';
1091
 
1092
+ // If required, get our label.
1093
  $req_label = '';
1094
  if ( $req ) {
1095
+
1096
+ /**
1097
+ * Filters the markup used for the required indicator.
1098
+ *
1099
+ * @since 1.0.0
1100
+ *
1101
+ * @param string $value An `<abbr>` tag with an asterisk indicating required status.
1102
+ */
1103
  $req_label = apply_filters( 'constant_contact_required_label', '<abbr title="required">*</abbr>' );
1104
  }
1105
 
 
1106
  $return = '<p><label for="' . esc_attr( $map ) . '">' . esc_attr( $name ) . ' ' . $req_label . '</label><textarea ' . $req_text . ' name="' . esc_attr( $map ) . '" placeholder="' . esc_attr( $desc ) . '">' . esc_html( $value ) . '</textarea>';
1107
 
 
1108
  if ( $field_error ) {
1109
  $return .= '<span class="ctct-field-error"><label for="' . esc_attr( $map ) . '">' . esc_attr( __( 'Error: Please correct your entry.', 'constant-contact-forms' ) ) . '</label></span>';
1110
  }
1111
 
 
1112
  return $return . '</p>';
1113
  }
1114
 
1115
  /**
1116
+ * Maybe display the disclourse notice.
1117
  *
1118
+ * @since 1.0.0
1119
+ *
1120
+ * @param array $form_data Form data.
1121
+ * @return string HTML markup
1122
  */
1123
  public function maybe_add_disclose_note( $form_data ) {
1124
 
 
1125
  $opts = isset( $form_data['options'] ) ? $form_data['options'] : false;
1126
 
 
1127
  if ( ! $opts ) {
1128
  return;
1129
  }
1130
 
 
1131
  $optin = isset( $opts['optin'] ) ? $opts['optin'] : false;
1132
 
 
1133
  if ( ! $optin ) {
1134
  return false;
1135
  }
1136
 
 
1137
  $list = isset( $optin['list'] ) ? $optin['list'] : false;
1138
 
 
1139
  if ( ! $list ) {
1140
  return false;
1141
  }
1142
 
 
1143
  return $this->get_disclose_text();
1144
  }
1145
 
1146
  /**
1147
+ * Get our disclose markup.
1148
  *
1149
+ * @since 1.0.0
1150
+ *
1151
+ * @return string HTML markup.
1152
  */
1153
  public function get_disclose_text() {
1154
+
1155
+ /**
1156
+ * Filters the content used to display the disclose text.
1157
+ *
1158
+ * @since 1.0.0
1159
+ *
1160
+ * @param string $value HTML and disclose text.
1161
+ */
1162
  return apply_filters( 'constant_contact_disclose', '<hr><sub>' . $this->get_inner_disclose_text() . '</sub>' );
1163
  }
1164
 
1165
  /**
1166
+ * Get our disclose text.
1167
+ *
1168
+ * @since 1.0.0
1169
  *
1170
+ * @return string text
 
1171
  */
1172
  public function get_inner_disclose_text() {
1173
  return sprintf( __( 'By submitting this form, you are granting: %s, permission to email you. You may unsubscribe via the link found at the bottom of every email. (See our Email Privacy Policy (http://constantcontact.com/legal/privacy-statement) for details.) Emails are serviced by Constant Contact.', 'constant-contact-forms' ), $this->plugin->api->get_disclosure_info() );
includes/class-lists.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Lists
5
  * @author Constant Contact
@@ -17,7 +19,7 @@ class ConstantContact_Lists {
17
  /**
18
  * Parent plugin class
19
  *
20
- * @var class
21
  * @since 0.0.1
22
  */
23
  protected $plugin = null;
@@ -25,8 +27,7 @@ class ConstantContact_Lists {
25
  /**
26
  * Constructor
27
  *
28
- * @since 1.0.0
29
- * @return void
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
@@ -34,7 +35,7 @@ class ConstantContact_Lists {
34
  }
35
 
36
  /**
37
- * Returns the running object
38
  *
39
  * @since 1.0.0
40
  * @return ConstantContact_Lists
@@ -54,29 +55,29 @@ class ConstantContact_Lists {
54
  */
55
  public function hooks() {
56
 
57
- // Hook in our CMB2 fields / functionality
58
  add_action( 'cmb2_admin_init', array( $this, 'sync_lists' ) );
59
  add_action( 'cmb2_admin_init', array( $this, 'add_lists_metabox' ) );
60
 
61
- // On save, process a list
62
  add_action( 'save_post_ctct_lists', array( $this, 'save_or_update_list' ), 10, 1 );
63
  add_action( 'transition_post_status', array( $this, 'post_status_transition' ), 11, 3 );
64
 
65
- // Show duplicate notices for lists
66
  add_action( 'admin_notices', array( $this, 'show_duplicate_list_message' ) );
67
 
68
- // On deletion, verify the list is handled correctly
69
  add_action( 'wp_trash_post', array( $this, 'delete_list' ) );
70
 
71
- // Add some CMB2 goodness
72
  add_action( 'cmb2_after_post_form_ctct_list_metabox', array( $this, 'add_form_css' ) );
73
  add_action( 'cmb2_render_constant_contact_list_information', array( $this, 'list_info_metabox' ), 10, 5 );
74
 
75
- // Add a force sync button to the admin
76
  add_filter( 'views_edit-ctct_lists', array( $this, 'add_force_sync_button' ) );
77
  add_action( 'admin_init', array( $this, 'check_for_list_sync_request' ) );
78
 
79
- // Remove quick edit
80
  add_filter( 'post_row_actions', array( $this, 'remove_quick_edit_from_lists' ) );
81
  }
82
 
@@ -110,7 +111,6 @@ class ConstantContact_Lists {
110
  */
111
  public function list_info_metabox( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
112
 
113
- // Sanity check
114
  if ( ! $object_id ) {
115
  echo wp_kses_post( $this->get_list_info_no_data() );
116
  return;
@@ -123,38 +123,38 @@ class ConstantContact_Lists {
123
  return;
124
  }
125
 
126
- // Get our list
127
  $list_info = constant_contact()->api->get_list( esc_attr( $list_id ) );
128
 
129
- // Make sure we have an actual list
130
  if ( ! isset( $list_info->id ) ) {
131
  echo wp_kses_post( $this->get_list_info_no_data() );
132
  return;
133
  }
134
 
135
- // Cast our list to an array, so we can easily display it
136
  $list_info = (array) $list_info;
137
 
138
  echo '<ul>';
139
 
140
- // Unset non-cust facing details
141
  unset( $list_info['id'] );
142
  unset( $list_info['status'] );
143
 
144
- // Convert our time/dates to a better format
145
  if ( isset( $list_info['created_date'] ) && $list_info['created_date'] ) {
146
  $list_info['created_date'] = date( 'l, F jS, Y g:i A', strtotime( $list_info['created_date'] ) );
147
  }
148
 
149
- // Convert our time/dates to a better format
150
  if ( isset( $list_info['modified_date'] ) && $list_info['modified_date'] ) {
151
  $list_info['modified_date'] = date( 'l, F jS, Y g:i A', strtotime( $list_info['modified_date'] ) );
152
  }
153
 
154
- // Loop through each property of the list object
155
  foreach ( $list_info as $key => $value ) {
156
 
157
- // Clean up our property name
158
  $key = sanitize_text_field( $key );
159
  $key = str_replace( '_', ' ', $key );
160
  $key = ucwords( $key );
@@ -166,7 +166,7 @@ class ConstantContact_Lists {
166
  }
167
 
168
  /**
169
- * Gets our no list info data
170
  *
171
  * @return string
172
  */
@@ -175,23 +175,24 @@ class ConstantContact_Lists {
175
  }
176
 
177
  /**
178
- * Style our form stuff
179
  *
180
- * @since 1.0.0
181
  */
182
  public function add_form_css() {
183
  wp_enqueue_style( 'constant-contact-forms' );
184
  }
185
 
186
  /**
187
- * Syncs list cpt with lists on CTCT
188
  *
189
  * @since 1.0.0
 
190
  * @return void
191
  */
192
  public function sync_lists( $force = false ) {
193
 
194
- // Make sure we're on the correct page
195
  global $pagenow;
196
  if ( ! $pagenow || ( ! in_array( $pagenow, array( 'edit.php' ), true ) ) ) {
197
  return;
@@ -209,36 +210,50 @@ class ConstantContact_Lists {
209
  // Currently, the rate limit for this is a refresh every 2 minutes. This can be filtered to be
210
  // less or more time.
211
  $last_synced = get_option( 'constant_contact_lists_last_synced', time() - DAY_IN_SECONDS );
 
 
 
 
 
 
 
 
212
  $sync_rate_limit_time = apply_filters( 'constant_contact_list_sync_rate_limit', 15 * MINUTE_IN_SECONDS );
213
 
214
  // If our last synced time plus our rate limit is less than or equal to right now,
215
  // then we don't want to refresh. If we refreshed less than 15 minutes ago, we do not want to
216
- // redo it. Also allow forcing a bypass of this check
217
  if ( ( ! $force ) && ( $last_synced + $sync_rate_limit_time ) >= time() ) {
218
  return;
219
  }
220
 
221
- // If we can't edit and delete posts, get out of here
222
  if ( ! current_user_can( 'edit_posts' ) || ! current_user_can( 'delete_posts' ) ) {
223
  return;
224
  }
225
 
226
- // If we don't have an api token, leave
227
  if ( ! constantcontact_api()->get_api_token() ) {
228
  return;
229
  }
230
 
231
- // Make sure we're on the edit page
232
- if ( ! isset( $_GET['post_type'] ) ) { // Input var okay.
233
  return;
234
  }
235
 
236
- // Make sure we're on our cpt page
237
- if ( 'ctct_lists' !== esc_attr( sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) ) ) { // Input var okay.
238
  return;
239
  }
240
 
241
- // Grab all our lists that we have
 
 
 
 
 
 
242
  $query = new WP_Query( apply_filters( 'constant_contact_lists_query_for_sync', array(
243
  'post_type' => 'ctct_lists',
244
  'posts_per_page' => 150,
@@ -247,72 +262,77 @@ class ConstantContact_Lists {
247
  'fields' => 'ids',
248
  ) ) );
249
 
250
- // Grab our posts
251
  $potentially_remove_list = $query->get_posts();
252
 
253
- // Make sure we didn't get an error and that it is an array
254
  if ( is_wp_error( $potentially_remove_list ) || ! is_array( $potentially_remove_list ) ) {
255
  return;
256
  }
257
 
258
- // Make our lists to delete array
259
  $lists_to_delete = array();
260
 
261
- // Loop through each of our lists
262
  foreach ( $potentially_remove_list as $post_id ) {
263
 
264
- // make sure we have a post ied
265
  if ( isset( $post_id ) ) {
266
 
267
- // grab our list id
268
  $list_id = get_post_meta( $post_id, '_ctct_list_id', true );
269
 
270
  if ( ! $list_id ) {
271
 
272
  // If we didn't get a list id, we'll want to generate a random string
273
  // so that we'll still delete it, rather than automatically giving it a
274
- // numerical value in our array
275
  $list_id = 'delete_' . wp_generate_password( 20, false );
276
  }
277
 
278
- // set the key of our array to the list id, value to our post ID
279
  $lists_to_delete[ esc_attr( $list_id ) ] = absint( $post_id );
280
  }
281
  }
282
 
283
- // Grab the lists we'll want to update/insert
284
  $lists_to_insert = constantcontact_api()->get_lists( true );
285
 
286
- // verify our data before continuing
287
  if ( $lists_to_insert && is_array( $lists_to_insert ) ) {
288
 
289
- // If we get too many lists, surface an error
290
  if ( count( $lists_to_insert ) >= 150 ) {
291
 
292
- // Set a notification of this
293
  $this->plugin->updates->add_notification( 'too_many_lists' );
294
 
295
- // Break the list into just 100 items
296
  $lists_to_insert = array_chunk( $lists_to_insert, 100 );
297
  if ( isset( $lists_to_insert[0] ) ) {
298
  $lists_to_insert = $lists_to_insert[0];
299
  }
300
  }
301
 
302
- // Loop through our lists to insert
303
  foreach ( $lists_to_insert as $list ) {
304
 
305
- // If we dont' have an idea, bail out of this one
306
  if ( ! isset( $list->id ) ) {
307
  continue;
308
  }
309
 
310
- // sanitize our data
311
  $list_id = esc_attr( $list->id );
312
 
313
- // Build up our insertion args
 
 
 
 
 
 
314
  $new_post = apply_filters( 'constant_contact_list_insert_args', array(
315
- 'post_title' => isset( $list->name ) ? esc_attr( $list->name ) : '',
316
  'post_status' => 'publish',
317
  'post_type' => 'ctct_lists',
318
  ) );
@@ -320,61 +340,60 @@ class ConstantContact_Lists {
320
  // By default, we'll attempt to update post meta for everything
321
  $update_meta = true;
322
 
323
- // if our list that we want to insert is in our delete array,
324
- // just update it, instead of deleting and re-adding
325
  if ( isset( $lists_to_delete[ $list_id ] ) ) {
326
 
327
- // tack on the id to our new post array, so that we
328
- // will force an update, rather that re-inserting
329
  $new_post['ID'] = $lists_to_delete[ $list_id ];
330
 
331
- // Remove it from our list of lists to delete
332
  unset( $lists_to_delete[ $list_id ] );
333
 
334
  // If we already have it, no need to update our meta,
335
- // might as well save a query
336
  $update_meta = false;
337
  }
338
 
339
- // Insert or update our list
340
  $post = wp_insert_post( $new_post );
341
 
342
- // If we added / inserted it correctly, and we need to update our meta
343
  if ( ! is_wp_error( $post ) && $post && $update_meta ) {
344
 
345
- // Update with our list id
346
  update_post_meta( $post, '_ctct_list_id', $list_id );
347
  }
348
  }
349
  }
350
 
351
  // Loop through each of the lists we didn't touch with the update/insert
352
- // and double check them, then delete
353
  foreach ( $lists_to_delete as $post_id ) {
354
 
355
- // force our post ID to be an int
356
  $post_id = absint( $post_id );
357
 
358
- // If we have an ID and the post type is a list, and is published
359
  if (
360
  $post_id &&
361
  ( 'ctct_lists' === get_post_type( $post_id ) ) &&
362
  ( 'publish' === get_post_status( $post_id ) )
363
  ) {
364
-
365
- // remove that post
366
  wp_delete_post( $post_id, true );
367
  }
368
  }
369
 
370
- // Update our last synced option to prevent doing this too often
371
  update_option( 'constant_contact_lists_last_synced', time() );
372
 
373
  /**
374
  * Hook when a ctct list is updated.
375
  *
376
  * @since 1.0.0
377
- * @param array $list ctct returned list data
 
378
  */
379
  do_action( 'ctct_sync_lists', $lists_to_insert );
380
  }
@@ -382,57 +401,56 @@ class ConstantContact_Lists {
382
  /**
383
  * Wrapper function to handle saving and updating our lists
384
  *
385
- * @since 1.0.0
386
- * @param int $post_id wp post id
387
- * @return bool whether or not it worked
388
  */
389
  public function save_or_update_list( $post_id ) {
390
 
391
- // Make sure we're on the new post page
392
  global $pagenow;
393
 
394
- // Verify we're on the correct page
395
  if ( ! $pagenow || ( ! in_array( $pagenow, array( 'post.php', 'post-new.php' ), true ) ) ) {
396
  return false;
397
  }
398
- // If we can't edit posts, get out of here
399
  if ( ! current_user_can( 'edit_posts' ) ) {
400
  return false;
401
  }
402
 
403
- // Grab the post we're using
404
  $ctct_list = get_post( $post_id );
405
 
406
- // If we didn't get data, bail
407
  if ( ! $ctct_list ) {
408
  return false;
409
  }
410
 
411
- // If we don't have a post status, bail
412
  if ( ! isset( $ctct_list->post_status ) ) {
413
  return false;
414
  }
415
 
416
- // If we're an autodraft, bail out
417
  if ( 'auto-draft' === $ctct_list->post_status ) {
418
  return false;
419
  }
420
 
421
- // if we didn't get an ID, return
422
  if ( ! isset( $ctct_list->ID ) ) {
423
  return false;
424
  }
425
 
426
- // Verify we don't mark things as duplicate if they aren't
427
  delete_post_meta( $ctct_list->ID, 'ctct_duplicate_list' );
428
 
429
- // Set our placeholder return var
430
  $return = false;
431
 
432
- // When we're adding a list, make sure we don't have one of the same name
433
  if ( $this->check_if_list_exists_by_title( $ctct_list->post_title ) ) {
434
 
435
- // If it does exist, flag it in our post meta
436
  add_post_meta( $ctct_list->ID, 'ctct_duplicate_list', true );
437
 
438
  if ( 'draft' !== $ctct_list->post_status ) {
@@ -442,10 +460,10 @@ class ConstantContact_Lists {
442
  ) );
443
  }
444
  } else {
445
- // Try to grab our list id from our post meta
446
  $list_id = get_post_meta( $ctct_list->ID, '_ctct_list_id', true );
447
 
448
- // If we got a list id, let's update that list, other wise add it
449
  if ( ! empty( $list_id ) ) {
450
  $return = $this->_update_list( $ctct_list, $list_id );
451
  } else {
@@ -453,13 +471,13 @@ class ConstantContact_Lists {
453
  }
454
  }
455
 
456
- // Remove our saved transient of our lists
457
  delete_transient( 'ctct_lists' );
458
 
459
- // Force re-syncing our lists right after deletion
460
  $this->sync_lists( true );
461
 
462
- // Set our last synced time to now, so we don't re-add our new/removed list right away
463
  update_option( 'constant_contact_lists_last_synced', time() );
464
 
465
  return $return;
@@ -510,9 +528,10 @@ class ConstantContact_Lists {
510
  * Hook when a ctct list is saved.
511
  *
512
  * @since 1.0.0
513
- * @param integer $post_id cpt post id
514
- * @param integer $list_id ctct list id
515
- * @param array $list ctct returned list data
 
516
  */
517
  do_action( 'ctct_update_list', $ctct_list->ID, $list_id, $list );
518
 
@@ -686,9 +705,9 @@ class ConstantContact_Lists {
686
  * Hook when a ctct list is updated.
687
  *
688
  * @since 1.0.0
689
- * @param integer $post_id cpt post id
690
- * @param integer $list_id ctct list id
691
- * @param array $list ctct returned list data
692
  */
693
  do_action( 'ctct_update_list', $ctct_list->ID, $list_id, $list );
694
 
@@ -737,8 +756,9 @@ class ConstantContact_Lists {
737
  * Hook when a ctct list is deleted.
738
  *
739
  * @since 1.0.0
740
- * @param integer $post_id
741
- * @param integer $list_id
 
742
  */
743
  do_action( 'ctct_delete_list', $post_id, $list_id );
744
 
1
  <?php
2
  /**
3
+ * Lists.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Lists
7
  * @author Constant Contact
19
  /**
20
  * Parent plugin class
21
  *
22
+ * @var object
23
  * @since 0.0.1
24
  */
25
  protected $plugin = null;
27
  /**
28
  * Constructor
29
  *
30
+ * @since 1.0.0
 
31
  */
32
  public function __construct( $plugin ) {
33
  $this->plugin = $plugin;
35
  }
36
 
37
  /**
38
+ * Returns the running object.
39
  *
40
  * @since 1.0.0
41
  * @return ConstantContact_Lists
55
  */
56
  public function hooks() {
57
 
58
+ // Hook in our CMB2 fields / functionality.
59
  add_action( 'cmb2_admin_init', array( $this, 'sync_lists' ) );
60
  add_action( 'cmb2_admin_init', array( $this, 'add_lists_metabox' ) );
61
 
62
+ // On save, process a list.
63
  add_action( 'save_post_ctct_lists', array( $this, 'save_or_update_list' ), 10, 1 );
64
  add_action( 'transition_post_status', array( $this, 'post_status_transition' ), 11, 3 );
65
 
66
+ // Show duplicate notices for lists.
67
  add_action( 'admin_notices', array( $this, 'show_duplicate_list_message' ) );
68
 
69
+ // On deletion, verify the list is handled correctly.
70
  add_action( 'wp_trash_post', array( $this, 'delete_list' ) );
71
 
72
+ // Add some CMB2 goodness.
73
  add_action( 'cmb2_after_post_form_ctct_list_metabox', array( $this, 'add_form_css' ) );
74
  add_action( 'cmb2_render_constant_contact_list_information', array( $this, 'list_info_metabox' ), 10, 5 );
75
 
76
+ // Add a force sync button to the admin.
77
  add_filter( 'views_edit-ctct_lists', array( $this, 'add_force_sync_button' ) );
78
  add_action( 'admin_init', array( $this, 'check_for_list_sync_request' ) );
79
 
80
+ // Remove quick edit.
81
  add_filter( 'post_row_actions', array( $this, 'remove_quick_edit_from_lists' ) );
82
  }
83
 
111
  */
112
  public function list_info_metabox( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
113
 
 
114
  if ( ! $object_id ) {
115
  echo wp_kses_post( $this->get_list_info_no_data() );
116
  return;
123
  return;
124
  }
125
 
126
+ // Get our list.
127
  $list_info = constant_contact()->api->get_list( esc_attr( $list_id ) );
128
 
129
+ // Make sure we have an actual list.
130
  if ( ! isset( $list_info->id ) ) {
131
  echo wp_kses_post( $this->get_list_info_no_data() );
132
  return;
133
  }
134
 
135
+ // Cast our list to an array, so we can easily display it.
136
  $list_info = (array) $list_info;
137
 
138
  echo '<ul>';
139
 
140
+ // Unset non-cust facing details.
141
  unset( $list_info['id'] );
142
  unset( $list_info['status'] );
143
 
144
+ // Convert our time/dates to a better format.
145
  if ( isset( $list_info['created_date'] ) && $list_info['created_date'] ) {
146
  $list_info['created_date'] = date( 'l, F jS, Y g:i A', strtotime( $list_info['created_date'] ) );
147
  }
148
 
149
+ // Convert our time/dates to a better format.
150
  if ( isset( $list_info['modified_date'] ) && $list_info['modified_date'] ) {
151
  $list_info['modified_date'] = date( 'l, F jS, Y g:i A', strtotime( $list_info['modified_date'] ) );
152
  }
153
 
154
+ // Loop through each property of the list object.
155
  foreach ( $list_info as $key => $value ) {
156
 
157
+ // Clean up our property name.
158
  $key = sanitize_text_field( $key );
159
  $key = str_replace( '_', ' ', $key );
160
  $key = ucwords( $key );
166
  }
167
 
168
  /**
169
+ * Gets our no list info data.
170
  *
171
  * @return string
172
  */
175
  }
176
 
177
  /**
178
+ * Style our form stuff.
179
  *
180
+ * @since 1.0.0
181
  */
182
  public function add_form_css() {
183
  wp_enqueue_style( 'constant-contact-forms' );
184
  }
185
 
186
  /**
187
+ * Syncs list cpt with lists on CTCT.
188
  *
189
  * @since 1.0.0
190
+ *
191
  * @return void
192
  */
193
  public function sync_lists( $force = false ) {
194
 
195
+ // Make sure we're on the correct page.
196
  global $pagenow;
197
  if ( ! $pagenow || ( ! in_array( $pagenow, array( 'edit.php' ), true ) ) ) {
198
  return;
210
  // Currently, the rate limit for this is a refresh every 2 minutes. This can be filtered to be
211
  // less or more time.
212
  $last_synced = get_option( 'constant_contact_lists_last_synced', time() - DAY_IN_SECONDS );
213
+
214
+ /**
215
+ * Filters the rate limit to use for syncing lists.
216
+ *
217
+ * @since 1.0.0
218
+ *
219
+ * @param int $value Amount o time to wait between syncs. Default 15 minutes.
220
+ */
221
  $sync_rate_limit_time = apply_filters( 'constant_contact_list_sync_rate_limit', 15 * MINUTE_IN_SECONDS );
222
 
223
  // If our last synced time plus our rate limit is less than or equal to right now,
224
  // then we don't want to refresh. If we refreshed less than 15 minutes ago, we do not want to
225
+ // redo it. Also allow forcing a bypass of this check.
226
  if ( ( ! $force ) && ( $last_synced + $sync_rate_limit_time ) >= time() ) {
227
  return;
228
  }
229
 
230
+ // If we can't edit and delete posts, get out of here.
231
  if ( ! current_user_can( 'edit_posts' ) || ! current_user_can( 'delete_posts' ) ) {
232
  return;
233
  }
234
 
235
+ // If we don't have an api token, leave.
236
  if ( ! constantcontact_api()->get_api_token() ) {
237
  return;
238
  }
239
 
240
+ // Make sure we're on the edit page.
241
+ if ( ! isset( $_GET['post_type'] ) ) {
242
  return;
243
  }
244
 
245
+ // Make sure we're on our cpt page.
246
+ if ( 'ctct_lists' !== esc_attr( sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) ) ) {
247
  return;
248
  }
249
 
250
+ /**
251
+ * Filters the arguments used to grab the lists to sync.
252
+ *
253
+ * @since 1.0.0
254
+ *
255
+ * @param array $value Array of WP_Query arguments.
256
+ */
257
  $query = new WP_Query( apply_filters( 'constant_contact_lists_query_for_sync', array(
258
  'post_type' => 'ctct_lists',
259
  'posts_per_page' => 150,
262
  'fields' => 'ids',
263
  ) ) );
264
 
265
+ // Grab our posts.
266
  $potentially_remove_list = $query->get_posts();
267
 
268
+ // Make sure we didn't get an error and that it is an array.
269
  if ( is_wp_error( $potentially_remove_list ) || ! is_array( $potentially_remove_list ) ) {
270
  return;
271
  }
272
 
273
+ // Make our lists to delete array.
274
  $lists_to_delete = array();
275
 
276
+ // Loop through each of our lists.
277
  foreach ( $potentially_remove_list as $post_id ) {
278
 
279
+ // Make sure we have a post ID.
280
  if ( isset( $post_id ) ) {
281
 
282
+ // Grab our list id.
283
  $list_id = get_post_meta( $post_id, '_ctct_list_id', true );
284
 
285
  if ( ! $list_id ) {
286
 
287
  // If we didn't get a list id, we'll want to generate a random string
288
  // so that we'll still delete it, rather than automatically giving it a
289
+ // numerical value in our array.
290
  $list_id = 'delete_' . wp_generate_password( 20, false );
291
  }
292
 
293
+ // Set the key of our array to the list id, value to our post ID.
294
  $lists_to_delete[ esc_attr( $list_id ) ] = absint( $post_id );
295
  }
296
  }
297
 
298
+ // Grab the lists we'll want to update/insert.
299
  $lists_to_insert = constantcontact_api()->get_lists( true );
300
 
301
+ // Verify our data before continuing.
302
  if ( $lists_to_insert && is_array( $lists_to_insert ) ) {
303
 
304
+ // If we get too many lists, surface an error.
305
  if ( count( $lists_to_insert ) >= 150 ) {
306
 
307
+ // Set a notification of this.
308
  $this->plugin->updates->add_notification( 'too_many_lists' );
309
 
310
+ // Break the list into just 100 items.
311
  $lists_to_insert = array_chunk( $lists_to_insert, 100 );
312
  if ( isset( $lists_to_insert[0] ) ) {
313
  $lists_to_insert = $lists_to_insert[0];
314
  }
315
  }
316
 
317
+ // Loop through our lists to insert.
318
  foreach ( $lists_to_insert as $list ) {
319
 
320
+ // If we dont' have an idea, bail out of this one.
321
  if ( ! isset( $list->id ) ) {
322
  continue;
323
  }
324
 
 
325
  $list_id = esc_attr( $list->id );
326
 
327
+ /**
328
+ * Filters the arguments used for inserting new lists from a fresh sync.
329
+ *
330
+ * @since 1.0.0
331
+ *
332
+ * @param array $value Array of arguments for a new list to be inserted into database.
333
+ */
334
  $new_post = apply_filters( 'constant_contact_list_insert_args', array(
335
+ 'post_title' => isset( $list->name ) ? esc_attr( $list->name ) : '',
336
  'post_status' => 'publish',
337
  'post_type' => 'ctct_lists',
338
  ) );
340
  // By default, we'll attempt to update post meta for everything
341
  $update_meta = true;
342
 
343
+ // If our list that we want to insert is in our delete array,
344
+ // just update it, instead of deleting and re-adding.
345
  if ( isset( $lists_to_delete[ $list_id ] ) ) {
346
 
347
+ // Tack on the id to our new post array, so that we
348
+ // will force an update, rather that re-inserting.
349
  $new_post['ID'] = $lists_to_delete[ $list_id ];
350
 
351
+ // Remove it from our list of lists to delete.
352
  unset( $lists_to_delete[ $list_id ] );
353
 
354
  // If we already have it, no need to update our meta,
355
+ // might as well save a query.
356
  $update_meta = false;
357
  }
358
 
359
+ // Insert or update our list.
360
  $post = wp_insert_post( $new_post );
361
 
362
+ // If we added / inserted it correctly, and we need to update our meta.
363
  if ( ! is_wp_error( $post ) && $post && $update_meta ) {
364
 
365
+ // Update with our list id.
366
  update_post_meta( $post, '_ctct_list_id', $list_id );
367
  }
368
  }
369
  }
370
 
371
  // Loop through each of the lists we didn't touch with the update/insert
372
+ // and double check them, then delete.
373
  foreach ( $lists_to_delete as $post_id ) {
374
 
375
+ // Force our post ID to be an int.
376
  $post_id = absint( $post_id );
377
 
378
+ // If we have an ID and the post type is a list, and is published.
379
  if (
380
  $post_id &&
381
  ( 'ctct_lists' === get_post_type( $post_id ) ) &&
382
  ( 'publish' === get_post_status( $post_id ) )
383
  ) {
 
 
384
  wp_delete_post( $post_id, true );
385
  }
386
  }
387
 
388
+ // Update our last synced option to prevent doing this too often.
389
  update_option( 'constant_contact_lists_last_synced', time() );
390
 
391
  /**
392
  * Hook when a ctct list is updated.
393
  *
394
  * @since 1.0.0
395
+ *
396
+ * @param array $lists_to_insert CTCT returned list data.
397
  */
398
  do_action( 'ctct_sync_lists', $lists_to_insert );
399
  }
401
  /**
402
  * Wrapper function to handle saving and updating our lists
403
  *
404
+ * @since 1.0.0
405
+ * @param int $post_id wp post id.
406
+ * @return bool Whether or not it worked.
407
  */
408
  public function save_or_update_list( $post_id ) {
409
 
410
+ // Make sure we're on the new post page.
411
  global $pagenow;
412
 
413
+ // Verify we're on the correct page.
414
  if ( ! $pagenow || ( ! in_array( $pagenow, array( 'post.php', 'post-new.php' ), true ) ) ) {
415
  return false;
416
  }
417
+ // If we can't edit posts, get out of here.
418
  if ( ! current_user_can( 'edit_posts' ) ) {
419
  return false;
420
  }
421
 
 
422
  $ctct_list = get_post( $post_id );
423
 
424
+ // If we didn't get data, bail.
425
  if ( ! $ctct_list ) {
426
  return false;
427
  }
428
 
429
+ // If we don't have a post status, bail.
430
  if ( ! isset( $ctct_list->post_status ) ) {
431
  return false;
432
  }
433
 
434
+ // If we're an autodraft, bail out.
435
  if ( 'auto-draft' === $ctct_list->post_status ) {
436
  return false;
437
  }
438
 
439
+ // If we didn't get an ID, return.
440
  if ( ! isset( $ctct_list->ID ) ) {
441
  return false;
442
  }
443
 
444
+ // Verify we don't mark things as duplicate if they aren't.
445
  delete_post_meta( $ctct_list->ID, 'ctct_duplicate_list' );
446
 
447
+ // Set our placeholder return var.
448
  $return = false;
449
 
450
+ // When we're adding a list, make sure we don't have one of the same name.
451
  if ( $this->check_if_list_exists_by_title( $ctct_list->post_title ) ) {
452
 
453
+ // If it does exist, flag it in our post meta.
454
  add_post_meta( $ctct_list->ID, 'ctct_duplicate_list', true );
455
 
456
  if ( 'draft' !== $ctct_list->post_status ) {
460
  ) );
461
  }
462
  } else {
463
+ // Try to grab our list id from our post meta.
464
  $list_id = get_post_meta( $ctct_list->ID, '_ctct_list_id', true );
465
 
466
+ // If we got a list id, let's update that list, other wise add it.
467
  if ( ! empty( $list_id ) ) {
468
  $return = $this->_update_list( $ctct_list, $list_id );
469
  } else {
471
  }
472
  }
473
 
474
+ // Remove our saved transient of our lists.
475
  delete_transient( 'ctct_lists' );
476
 
477
+ // Force re-syncing our lists right after deletion.
478
  $this->sync_lists( true );
479
 
480
+ // Set our last synced time to now, so we don't re-add our new/removed list right away.
481
  update_option( 'constant_contact_lists_last_synced', time() );
482
 
483
  return $return;
528
  * Hook when a ctct list is saved.
529
  *
530
  * @since 1.0.0
531
+ *
532
+ * @param integer $post_id CPT post id.
533
+ * @param integer $list_id Ctct list id.
534
+ * @param array $list Ctct returned list data.
535
  */
536
  do_action( 'ctct_update_list', $ctct_list->ID, $list_id, $list );
537
 
705
  * Hook when a ctct list is updated.
706
  *
707
  * @since 1.0.0
708
+ * @param integer $post_id CPT post id.
709
+ * @param integer $list_id Ctct list id.
710
+ * @param array $list Ctct returned list data.
711
  */
712
  do_action( 'ctct_update_list', $ctct_list->ID, $list_id, $list );
713
 
756
  * Hook when a ctct list is deleted.
757
  *
758
  * @since 1.0.0
759
+ *
760
+ * @param integer $post_id Form list ID that was deleted.
761
+ * @param integer $list_id Constant Contact list ID.
762
  */
763
  do_action( 'ctct_delete_list', $post_id, $list_id );
764
 
includes/class-mail.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Mail
5
  * @author Constant Contact
@@ -23,7 +25,6 @@ class ConstantContact_Mail {
23
  * Constructor
24
  *
25
  * @since 1.0.0
26
- * @return void
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -47,34 +48,35 @@ class ConstantContact_Mail {
47
  */
48
  public function submit_form_values( $values = array(), $add_to_opt_in = false ) {
49
 
50
- // Sanity check
51
  if ( ! is_array( $values ) ) {
52
  return;
53
  }
54
 
55
- // Clean our values
56
  $values = constant_contact()->process_form->clean_values( $values );
57
 
58
- // If a user opted-in and we're still connected, push their data to CC
59
  if ( $add_to_opt_in && constant_contact()->api->is_connected() ) {
 
60
  /**
61
- * Delay the scheduling of the opt-in e-mail event.
 
 
62
  *
63
- * @since 1.0.2
64
- * @param int $schedule_delay The time to add to `time()` for the event.
65
- * @return int
66
  */
67
  $schedule_delay = apply_filters( 'constant_contact_opt_in_delay', MINUTE_IN_SECONDS );
68
  wp_schedule_single_event( time() + absint( $schedule_delay ), 'ctct_schedule_form_opt_in', array( $values ) );
69
  }
70
 
71
- // pretty our values
72
  $values = constant_contact()->process_form->pretty_values( $values );
73
 
74
- // Format them
75
  $email_values = $this->format_values_for_email( $values );
76
 
77
- // Send the mail
78
  return $this->mail( $this->get_email(), $email_values );
79
  }
80
 
@@ -87,37 +89,37 @@ class ConstantContact_Mail {
87
  */
88
  public function opt_in_user( $values ) {
89
 
90
- // go through all our fields
91
  foreach ( $values as $key => $val ) {
92
 
93
- // Clean up our data that we'll be using
94
  $key = sanitize_text_field( isset( $val['key'] ) ? $val['key'] : '' );
95
  $orig = sanitize_text_field( isset( $val['orig_key'] ) ? $val['orig_key'] : '' );
96
  $val = sanitize_text_field( isset( $val['value'] ) ? $val['value'] : '' );
97
 
98
- // Make sure we have a key that we can use
99
  if ( $key && ( 'ctct-opt-in' !== $key ) && ( 'ctct-id' !== $key ) ) {
100
 
101
- // Set our args that we'll pass to our API
102
  $args[ $orig ] = array(
103
  'key' => $key,
104
  'val' => $val,
105
  );
106
 
107
- // If we have an email, make sure we keep it safe
108
  if ( 'email' === $key ) {
109
  $args['email'] = $val;
110
  }
111
  }
112
  }
113
 
114
- // Make sure we have an email set
115
  if ( isset( $values['ctct-opt-in'] ) && isset( $values['ctct-opt-in']['value'] ) ) {
116
 
117
- // Make sure that our list is a top level
118
  $args['list'] = sanitize_text_field( $values['ctct-opt-in']['value'] );
119
 
120
- // Send that to our API
121
  return constantcontact_api()->add_contact( $args );
122
  }
123
  }
@@ -134,15 +136,13 @@ class ConstantContact_Mail {
134
  $return = '';
135
  foreach ( $pretty_vals as $val ) {
136
 
137
- // force vars to exist
138
  $label = isset( $val['orig_key'] ) ? $val['orig_key'] : false;
139
 
140
- // If we have a label
141
  if ( $label ) {
142
- // break out our unique key
143
  $label = explode( '___', $label );
144
 
145
- // Uppercase and format to be human readable
146
  $label = ucwords( str_replace( '_', ' ', $label[0] ) );
147
  }
148
  $value = isset( $val['post'] ) ? $val['post'] : '&nbsp;';
@@ -161,12 +161,12 @@ class ConstantContact_Mail {
161
  */
162
  public function get_email() {
163
 
164
- // Eventually we'll make this configurable
165
  return get_option( 'admin_email' );
166
  }
167
 
168
  /**
169
- * Sends our mail out
170
  *
171
  * @since 1.0.0
172
  * @param string $destination_email email address
@@ -179,7 +179,7 @@ class ConstantContact_Mail {
179
  static $last_sent = false;
180
 
181
  $screen = '';
182
- // Sanity check for get_current_screen, as we may run too early
183
  if ( function_exists( 'get_current_screen' ) ) {
184
  $screen = get_current_screen();
185
  }
@@ -196,33 +196,29 @@ class ConstantContact_Mail {
196
  }
197
 
198
  // If we didn't get passed in a sanitized email, we know something is
199
- // wonky here, so bail out
200
  if ( sanitize_email( $destination_email ) !== $destination_email ) {
201
  return false;
202
  }
203
 
204
- // Filter to allow sending HTML for our message body
205
  add_filter( 'wp_mail_content_type', array( $this, 'set_email_type' ) );
206
 
207
- // Before text for content
208
  $content_before = __( 'Congratulations! Your Constant Contact Forms plugin has successfully captured new information:', 'constant-contact-forms' );
209
 
210
- // After text for content
211
- $content_after = __( "Don't forget: Email marketing is a great way to stay connected with visitors after they’ve left your site. To make the most of the information you collect, connect the plugin to an active Constant Contact account. Just go to the Connect page from the Plugin console view.", 'constant-contact-forms' );
212
 
213
- // Tie our contents together
214
  $content = $content_before . $content . $content_after;
215
 
216
- // Send that mail
217
  $mail_status = wp_mail(
218
  $destination_email,
219
- __( 'New submission' ),
220
  $content
221
  );
222
 
223
  $this->maybe_log_mail_status( $mail_status, $destination_email, $content );
224
 
225
- // Clean up, remove the filter we had set
226
  remove_filter( 'wp_mail_content_type', array( $this, 'set_email_type' ) );
227
 
228
  // Store this for later.
@@ -230,7 +226,6 @@ class ConstantContact_Mail {
230
  $last_sent = $mail_key;
231
  }
232
 
233
- // Return the mail status
234
  return $mail_status;
235
  }
236
 
@@ -247,20 +242,19 @@ class ConstantContact_Mail {
247
  * If our mail debugging is set, then log mail statuses to the error log
248
  *
249
  * @since 1.0.0
250
- * @param string $status status from wp_mai
251
- * @param string $dest_email destination email
252
- * @param string $content content of email
253
  * @return void
254
  */
255
  public function maybe_log_mail_status( $status, $dest_email, $content ) {
256
 
257
- // If we have our debugging turned on
258
  if ( defined( 'CONSTANT_CONTACT_DEBUG_MAIL' ) && CONSTANT_CONTACT_DEBUG_MAIL ) {
259
 
260
- // Log status of mail
261
  error_log( 'mail attempted for ' . $dest_email . ': ' . $status );
262
 
263
- // Log content too just in case
264
  error_log( print_r( $content, true ) );
265
  }
266
 
1
  <?php
2
  /**
3
+ * Mail
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Mail
7
  * @author Constant Contact
25
  * Constructor
26
  *
27
  * @since 1.0.0
 
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
48
  */
49
  public function submit_form_values( $values = array(), $add_to_opt_in = false ) {
50
 
51
+ // Sanity check.
52
  if ( ! is_array( $values ) ) {
53
  return;
54
  }
55
 
56
+ // Clean our values.
57
  $values = constant_contact()->process_form->clean_values( $values );
58
 
59
+ // If a user opted-in and we're still connected, push their data to CC.
60
  if ( $add_to_opt_in && constant_contact()->api->is_connected() ) {
61
+
62
  /**
63
+ * Filters the delay between scheduling of the opt-in e-mail event.
64
+ *
65
+ * @since 1.0.2
66
  *
67
+ * @param int $schedule_delay The time to add to `time()` for the event.
 
 
68
  */
69
  $schedule_delay = apply_filters( 'constant_contact_opt_in_delay', MINUTE_IN_SECONDS );
70
  wp_schedule_single_event( time() + absint( $schedule_delay ), 'ctct_schedule_form_opt_in', array( $values ) );
71
  }
72
 
73
+ // Pretty our values.
74
  $values = constant_contact()->process_form->pretty_values( $values );
75
 
76
+ // Format them.
77
  $email_values = $this->format_values_for_email( $values );
78
 
79
+ // Send the mail.
80
  return $this->mail( $this->get_email(), $email_values );
81
  }
82
 
89
  */
90
  public function opt_in_user( $values ) {
91
 
92
+ // Go through all our fields.
93
  foreach ( $values as $key => $val ) {
94
 
95
+ // Clean up our data that we'll be using.
96
  $key = sanitize_text_field( isset( $val['key'] ) ? $val['key'] : '' );
97
  $orig = sanitize_text_field( isset( $val['orig_key'] ) ? $val['orig_key'] : '' );
98
  $val = sanitize_text_field( isset( $val['value'] ) ? $val['value'] : '' );
99
 
100
+ // Make sure we have a key that we can use.
101
  if ( $key && ( 'ctct-opt-in' !== $key ) && ( 'ctct-id' !== $key ) ) {
102
 
103
+ // Set our args that we'll pass to our API.
104
  $args[ $orig ] = array(
105
  'key' => $key,
106
  'val' => $val,
107
  );
108
 
109
+ // If we have an email, make sure we keep it safe.
110
  if ( 'email' === $key ) {
111
  $args['email'] = $val;
112
  }
113
  }
114
  }
115
 
116
+ // Make sure we have an email set.
117
  if ( isset( $values['ctct-opt-in'] ) && isset( $values['ctct-opt-in']['value'] ) ) {
118
 
119
+ // Make sure that our list is a top level.
120
  $args['list'] = sanitize_text_field( $values['ctct-opt-in']['value'] );
121
 
122
+ // Send that to our API.
123
  return constantcontact_api()->add_contact( $args );
124
  }
125
  }
136
  $return = '';
137
  foreach ( $pretty_vals as $val ) {
138
 
 
139
  $label = isset( $val['orig_key'] ) ? $val['orig_key'] : false;
140
 
 
141
  if ( $label ) {
142
+ // Break out our unique key.
143
  $label = explode( '___', $label );
144
 
145
+ // Uppercase and format to be human readable.
146
  $label = ucwords( str_replace( '_', ' ', $label[0] ) );
147
  }
148
  $value = isset( $val['post'] ) ? $val['post'] : '&nbsp;';
161
  */
162
  public function get_email() {
163
 
164
+ // Eventually we'll make this configurable.
165
  return get_option( 'admin_email' );
166
  }
167
 
168
  /**
169
+ * Sends our mail out.
170
  *
171
  * @since 1.0.0
172
  * @param string $destination_email email address
179
  static $last_sent = false;
180
 
181
  $screen = '';
182
+ // Sanity check for get_current_screen, as we may run too early.
183
  if ( function_exists( 'get_current_screen' ) ) {
184
  $screen = get_current_screen();
185
  }
196
  }
197
 
198
  // If we didn't get passed in a sanitized email, we know something is
199
+ // wonky here, so bail out.
200
  if ( sanitize_email( $destination_email ) !== $destination_email ) {
201
  return false;
202
  }
203
 
204
+ // Filter to allow sending HTML for our message body.
205
  add_filter( 'wp_mail_content_type', array( $this, 'set_email_type' ) );
206
 
 
207
  $content_before = __( 'Congratulations! Your Constant Contact Forms plugin has successfully captured new information:', 'constant-contact-forms' );
208
 
209
+ $content_after = __( "Don't forget: Email marketing is a great way to stay connected and engage with visitors after they’ve left your site. When you connect to a Constant Contact account, all new subscribers are automatically synced so you can keep the interaction going through emails and more. Sign up for a Free Trial on the Connect page in the Plugin console view.", 'constant-contact-forms' );
 
210
 
 
211
  $content = $content_before . $content . $content_after;
212
 
 
213
  $mail_status = wp_mail(
214
  $destination_email,
215
+ __( 'Great News: You just captured a new visitor submission', 'constant-contact-forms' ),
216
  $content
217
  );
218
 
219
  $this->maybe_log_mail_status( $mail_status, $destination_email, $content );
220
 
221
+ // Clean up, remove the filter we had set.
222
  remove_filter( 'wp_mail_content_type', array( $this, 'set_email_type' ) );
223
 
224
  // Store this for later.
226
  $last_sent = $mail_key;
227
  }
228
 
 
229
  return $mail_status;
230
  }
231
 
242
  * If our mail debugging is set, then log mail statuses to the error log
243
  *
244
  * @since 1.0.0
245
+ * @param string $status status from wp_mail.
246
+ * @param string $dest_email destination email.
247
+ * @param string $content content of email.
248
  * @return void
249
  */
250
  public function maybe_log_mail_status( $status, $dest_email, $content ) {
251
 
 
252
  if ( defined( 'CONSTANT_CONTACT_DEBUG_MAIL' ) && CONSTANT_CONTACT_DEBUG_MAIL ) {
253
 
254
+ // Log status of mail.
255
  error_log( 'mail attempted for ' . $dest_email . ': ' . $status );
256
 
257
+ // Log content too just in case.
258
  error_log( print_r( $content, true ) );
259
  }
260
 
includes/class-middleware.php CHANGED
@@ -25,7 +25,6 @@ class ConstantContact_Middleware {
25
  *
26
  * @since 1.0.1
27
  * @param object $plugin Main plugin object.
28
- * @return void
29
  */
30
  public function __construct( $plugin ) {
31
  $this->plugin = $plugin;
@@ -39,15 +38,15 @@ class ConstantContact_Middleware {
39
  */
40
  public function do_connect_url( $proof = '', $extra_args = array() ) {
41
 
42
- // Get our main link
43
  $auth_server_link = $this->get_auth_server_link();
44
 
45
- // If we don't have that, then bail
46
  if ( ! $auth_server_link ) {
47
  return;
48
  }
49
 
50
- // Add our query args to our middleware link, and return it
51
  return $this->add_query_args_to_link( $auth_server_link, $proof, $extra_args );
52
  }
53
 
@@ -60,15 +59,17 @@ class ConstantContact_Middleware {
60
  */
61
  public function do_signup_url( $proof = '' ) {
62
 
63
- // Just a wrapper for the connect url, but with the signup param we'll be passing
64
  return $this->do_connect_url( $proof, array( 'new_signup' => true ) );
65
  }
66
 
67
  /**
68
- * Add our query args for proof and site callback to our auth server link
69
  *
70
  * @since 1.0.1
71
- * @param string $link auth server link
 
 
72
  */
73
  public function add_query_args_to_link( $link, $proof, $extra_args = array() ) {
74
  $return = add_query_arg( array(
@@ -78,12 +79,12 @@ class ConstantContact_Middleware {
78
  ),
79
  $link );
80
 
81
- // If got passed other args, tack them on as query args to the link that we were going to be using
82
  if ( ! empty( $extra_args ) ) {
83
  $return = add_query_arg( $extra_args, $return );
84
  }
85
 
86
- // Send it back
87
  return $return;
88
  }
89
 
@@ -105,16 +106,16 @@ class ConstantContact_Middleware {
105
  */
106
  public function set_verification_option() {
107
 
108
- // Allow re-use of our $proof on a page load
109
  static $proof = null;
110
 
111
- // If its null, then generate it
112
  if ( is_null( $proof ) ) {
113
  $proof = esc_attr( wp_generate_password( 35, false, false ) );
114
  update_option( 'ctct_connect_verification', $proof );
115
  }
116
 
117
- // Send it back
118
  return $proof;
119
  }
120
 
@@ -133,17 +134,17 @@ class ConstantContact_Middleware {
133
  $token = isset( $_GET['token'] ) ? sanitize_text_field( wp_unslash( $_GET['token'] ) ) : false; // Input var okay.
134
  $key = isset( $_GET['key'] ) ? sanitize_text_field( wp_unslash( $_GET['key'] ) ) : false; // Input var okay.
135
 
136
- // If we're missing any piece of data, we failed
137
  if ( ! $proof || ! $token || ! $key ) {
138
  return false;
139
  }
140
 
141
- // We'll want to verify our proof before we continue
142
  if ( ! $this->verify_proof( $proof ) ) {
143
  return false;
144
  }
145
 
146
- // Save our token / key into the DB
147
  constant_contact()->connect->update_token( sanitize_text_field( $token ) );
148
  constant_contact()->connect->e_set( '_ctct_api_key', sanitize_text_field( $key ) );
149
  return true;
@@ -158,13 +159,13 @@ class ConstantContact_Middleware {
158
  */
159
  public function verify_proof( $proof ) {
160
 
161
- // Get our saved option that we set for our proof
162
  $expected_proof = get_option( 'ctct_connect_verification' );
163
 
164
- // Clean up after ourselves
165
  delete_option( 'ctct_connect_verification' );
166
 
167
- // Send back a bool of whether they match or not
168
  return ( $proof === $expected_proof );
169
 
170
  }
25
  *
26
  * @since 1.0.1
27
  * @param object $plugin Main plugin object.
 
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
38
  */
39
  public function do_connect_url( $proof = '', $extra_args = array() ) {
40
 
41
+ // Get our main link.
42
  $auth_server_link = $this->get_auth_server_link();
43
 
44
+ // If we don't have that, then bail.
45
  if ( ! $auth_server_link ) {
46
  return;
47
  }
48
 
49
+ // Add our query args to our middleware link, and return it.
50
  return $this->add_query_args_to_link( $auth_server_link, $proof, $extra_args );
51
  }
52
 
59
  */
60
  public function do_signup_url( $proof = '' ) {
61
 
62
+ // Just a wrapper for the connect url, but with the signup param we'll be passing.
63
  return $this->do_connect_url( $proof, array( 'new_signup' => true ) );
64
  }
65
 
66
  /**
67
+ * Add our query args for proof and site callback to our auth server link.
68
  *
69
  * @since 1.0.1
70
+ *
71
+ * @param string $link auth server link.
72
+ * @return string
73
  */
74
  public function add_query_args_to_link( $link, $proof, $extra_args = array() ) {
75
  $return = add_query_arg( array(
79
  ),
80
  $link );
81
 
82
+ // If got passed other args, tack them on as query args to the link that we were going to be using.
83
  if ( ! empty( $extra_args ) ) {
84
  $return = add_query_arg( $extra_args, $return );
85
  }
86
 
87
+ // Send it back.
88
  return $return;
89
  }
90
 
106
  */
107
  public function set_verification_option() {
108
 
109
+ // Allow re-use of our $proof on a page load.
110
  static $proof = null;
111
 
112
+ // If its null, then generate it.
113
  if ( is_null( $proof ) ) {
114
  $proof = esc_attr( wp_generate_password( 35, false, false ) );
115
  update_option( 'ctct_connect_verification', $proof );
116
  }
117
 
118
+ // Send it back.
119
  return $proof;
120
  }
121
 
134
  $token = isset( $_GET['token'] ) ? sanitize_text_field( wp_unslash( $_GET['token'] ) ) : false; // Input var okay.
135
  $key = isset( $_GET['key'] ) ? sanitize_text_field( wp_unslash( $_GET['key'] ) ) : false; // Input var okay.
136
 
137
+ // If we're missing any piece of data, we failed.
138
  if ( ! $proof || ! $token || ! $key ) {
139
  return false;
140
  }
141
 
142
+ // We'll want to verify our proof before we continue.
143
  if ( ! $this->verify_proof( $proof ) ) {
144
  return false;
145
  }
146
 
147
+ // Save our token / key into the DB.
148
  constant_contact()->connect->update_token( sanitize_text_field( $token ) );
149
  constant_contact()->connect->e_set( '_ctct_api_key', sanitize_text_field( $key ) );
150
  return true;
159
  */
160
  public function verify_proof( $proof ) {
161
 
162
+ // Get our saved option that we set for our proof.
163
  $expected_proof = get_option( 'ctct_connect_verification' );
164
 
165
+ // Clean up after ourselves.
166
  delete_option( 'ctct_connect_verification' );
167
 
168
+ // Send back a bool of whether they match or not.
169
  return ( $proof === $expected_proof );
170
 
171
  }
includes/class-notification-content.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Notifications_Content
5
  * @author Constant Contact
@@ -23,7 +25,6 @@ class ConstantContact_Notification_Content {
23
  * Constructor
24
  *
25
  * @since 1.0.0
26
- * @return void
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -36,7 +37,6 @@ class ConstantContact_Notification_Content {
36
  */
37
  public static function activation() {
38
 
39
- // Start our output buffer
40
  ob_start();
41
 
42
  ?>
@@ -58,7 +58,6 @@ class ConstantContact_Notification_Content {
58
  </p>
59
  <?php
60
 
61
- // Get our output and send it back
62
  $output = ob_get_clean();
63
  return $output;
64
  }
@@ -77,7 +76,7 @@ class ConstantContact_Notification_Content {
77
  * Sample update notification for updating to 1.0.1
78
  *
79
  * @since 1.0.0
80
- * @return string notification text
81
  */
82
  public static function v1_0_1() {
83
 
1
  <?php
2
  /**
3
+ * Notification content.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Notifications_Content
7
  * @author Constant Contact
25
  * Constructor
26
  *
27
  * @since 1.0.0
 
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
37
  */
38
  public static function activation() {
39
 
 
40
  ob_start();
41
 
42
  ?>
58
  </p>
59
  <?php
60
 
 
61
  $output = ob_get_clean();
62
  return $output;
63
  }
76
  * Sample update notification for updating to 1.0.1
77
  *
78
  * @since 1.0.0
79
+ * @return string notification text Text.
80
  */
81
  public static function v1_0_1() {
82
 
includes/class-notifications.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Notifications
5
  * @author Constant Contact
@@ -23,7 +25,6 @@ class ConstantContact_Notifications {
23
  * Constructor
24
  *
25
  * @since 1.0.0
26
- * @return void
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -38,7 +39,7 @@ class ConstantContact_Notifications {
38
  */
39
  public function hooks() {
40
 
41
- // Add activation message
42
  add_action( 'admin_notices', array( $this, 'main' ) );
43
 
44
  }
@@ -50,7 +51,13 @@ class ConstantContact_Notifications {
50
  */
51
  public function get_notifications() {
52
 
53
- // Return all our notifications
 
 
 
 
 
 
54
  return apply_filters( 'constant_contact_notifications', array(
55
  array(
56
  'ID' => 'activation',
@@ -78,17 +85,17 @@ class ConstantContact_Notifications {
78
  public function main() {
79
 
80
  // If we have our query args where we're attempting to dismiss the notice
81
- // Get our potentically dismissed notif ID
82
  $notif_id = $this->get_dismissal_id();
83
 
84
- // First, we want to check if we should save any dismissals
85
  if ( $this->check_dismissal_nonce() && $notif_id ) {
86
 
87
- // Then save that we dismissed it
88
  $this->save_dismissed_notification( $notif_id );
89
  }
90
 
91
- // Get all our notifications
92
  $notifications = $this->get_notifications();
93
  $update_notifications = $this->get_update_notifications();
94
 
@@ -111,44 +118,44 @@ class ConstantContact_Notifications {
111
  */
112
  public function maybe_show_notification( $notif ) {
113
 
114
- // If our notification isn't an array, skip it
115
  if ( ! is_array( $notif ) ) {
116
  return;
117
  }
118
 
119
- // Save our notification data to a helper var
120
  $notif_id = isset( $notif['ID'] ) ? esc_attr( $notif['ID'] ) : false;
121
  $callback = isset( $notif['callback'] ) ? $notif['callback'] : false;
122
  $require_cb = isset( $notif['require_cb'] ) ? $notif['require_cb'] : false;
123
 
124
- // If we don't have an ID or callback set, bail
125
  if ( ! $notif_id || ! $callback ) {
126
  return;
127
  }
128
 
129
- // Don't show if it was dismissed
130
  if ( $this->was_notification_dismissed( $notif_id ) ) {
131
  return;
132
  }
133
 
134
- // If we don have requirements set up for a notif, then check them
135
  if ( $require_cb ) {
136
 
137
- // Check to make sure the requirements defined for a notification evalulate to true
138
  $requirements_passed = ( $this->check_requirements_callback_for_notif( $require_cb ) );
139
 
140
- // If we didnt' pass, then return
141
  if ( ! $requirements_passed ) {
142
  return;
143
  }
144
  }
145
 
146
- // If we cant call our notification callback, bail
147
  if ( ! is_callable( $callback ) ) {
148
  return false;
149
  }
150
 
151
- // Get our notifictaion content from our callback
152
  $notif_content = call_user_func( $callback );
153
 
154
  $this->show_notice( $notif_id, $notif_content );
@@ -161,26 +168,22 @@ class ConstantContact_Notifications {
161
  * Call and return results of executing a callback for a notificaion
162
  *
163
  * @since 1.0.0
164
- * @param mixed $require_cb valid callback
165
  * @return boolean boolean results of callback
166
  */
167
  public function check_requirements_callback_for_notif( $require_cb ) {
168
 
169
- // Make sure we can call our require callback
170
  if ( is_callable( $require_cb ) ) {
171
-
172
- // Call it
173
  return ( call_user_func( $require_cb ) );
174
  }
175
 
176
- // Otherwise false
177
  return false;
178
  }
179
 
180
  /**
181
- * Checks to see if we have a dismissal nonce, and if it is valid
182
  *
183
- * @since 1.0.0
184
  * @return boolean whether or not nonce is verified
185
  */
186
  public function check_dismissal_nonce() {
@@ -193,7 +196,7 @@ class ConstantContact_Notifications {
193
  // Save our nonce
194
  $nonce = sanitize_text_field( wp_unslash( $_GET['ctct-dismiss'] ) ); // Input var okay.
195
 
196
- // If our nonce fails, then we don't want to dismiss it
197
  return ( wp_verify_nonce( $nonce, 'ctct-user-is-dismissing' ) );
198
  }
199
 
@@ -210,20 +213,20 @@ class ConstantContact_Notifications {
210
  return false;
211
  }
212
 
213
- // if we don't have our dismiss query arg, bail
214
  if ( ! isset( $_GET['ctct-dismiss-action'] ) ) { // Input var okay.
215
  return false;
216
  }
217
 
218
- // Get what notification we're attempting to dismiss
219
  $dismissing_notif = sanitize_text_field( wp_unslash( $_GET['ctct-dismiss-action'] ) ); // Input var okay.
220
 
221
- // If we don't have an action set for our dismiss action, bail
222
  if ( ! $dismissing_notif ) {
223
  return false;
224
  }
225
 
226
- // Send back our notification type
227
  return $dismissing_notif;
228
  }
229
 
@@ -235,7 +238,7 @@ class ConstantContact_Notifications {
235
  */
236
  public function save_dismissed_notification( $key ) {
237
 
238
- // Call our save option helper
239
  return $this->save_dismissed_option( $key, true );
240
  }
241
 
@@ -243,12 +246,12 @@ class ConstantContact_Notifications {
243
  * Set a specific notificaion saved state to false
244
  *
245
  * @since 1.0.0
246
- * @param strin $key ID of notificaion
247
  * @return boolean update succeeded?
248
  */
249
  public function delete_dismissed_notification( $key ) {
250
 
251
- // Call our save option helper
252
  return $this->save_dismissed_option( $key, false );
253
  }
254
 
@@ -283,18 +286,18 @@ class ConstantContact_Notifications {
283
  */
284
  public function save_dismissed_option( $key, $value ) {
285
 
286
- // Get all of our options we have saved
287
  $options = $this->get_dismissed_options();
288
 
289
- // If for some reason, we didn't get an array, then clear it out
290
  if ( ! is_array( $options ) ) {
291
  $options = array();
292
  }
293
 
294
- // Save our keyed notification to be saved
295
  $options[ esc_attr( $key ) ] = esc_attr( $value );
296
 
297
- // Save all the options
298
  return $this->save_dismissed_options( $options );
299
  }
300
 
@@ -307,13 +310,13 @@ class ConstantContact_Notifications {
307
  */
308
  public function was_notification_dismissed( $key = '' ) {
309
 
310
- // Get all our options
311
  $option = $this->get_dismissed_option( $key );
312
 
313
- // If we have 'true' or '1' saved, then its true
314
  $is_true = ( ( 'true' === $option ) || ( '1' === $option ) );
315
 
316
- // Cast to boolean and send it back
317
  return ( $is_true ? true : false );
318
  }
319
 
@@ -326,17 +329,17 @@ class ConstantContact_Notifications {
326
  */
327
  public function get_dismissed_option( $key = '' ) {
328
 
329
- // Get all our dismissed notifications
330
  $options = $this->get_dismissed_options();
331
 
332
- // If we have the notification saved in our options array
333
  if ( isset( $options[ esc_attr( $key ) ] ) ) {
334
 
335
- // Return the option of whatever it is
336
  return $options[ esc_attr( $key ) ];
337
  }
338
 
339
- // Otherwise, we'll just return false and bail
340
  return false;
341
  }
342
 
@@ -347,15 +350,15 @@ class ConstantContact_Notifications {
347
  */
348
  public function show_notice( $key, $content = '' ) {
349
 
350
- // If we don't have any content, bail
351
  if ( ! $content ) {
352
  return;
353
  }
354
 
355
- // Show our styles
356
  $this->do_styles();
357
 
358
- // Wrap our content in our markup
359
  ?>
360
  <div id="ctct-admin-notice-<?php echo esc_attr( $key ); ?>" class="ctct-admin-notice updated notice">
361
  <?php echo wp_kses_post( $content ); ?>
@@ -371,13 +374,12 @@ class ConstantContact_Notifications {
371
  */
372
  public function do_styles() {
373
 
374
- // Set our flag about notice being shown, so we don't re-enqueue styles
375
  static $have_styles = false;
376
 
377
- // If we haven't shown styles yet, enqueue em
378
  if ( ! $have_styles ) {
379
 
380
- // Style it up
381
  wp_enqueue_style(
382
  'constant-contact-admin-notices',
383
  constant_contact()->url() . 'assets/css/admin-notices.css',
@@ -385,7 +387,6 @@ class ConstantContact_Notifications {
385
  constant_contact()->version
386
  );
387
 
388
- // Set to true
389
  $have_styles = true;
390
  }
391
  }
@@ -413,10 +414,9 @@ class ConstantContact_Notifications {
413
  */
414
  public function get_activation_dismiss_url( $type ) {
415
 
416
- // Set a link with our current url and desired action
417
  $link = add_query_arg( array( 'ctct-dismiss-action' => esc_attr( $type ) ) );
418
 
419
- // Also nonce it and return it
420
  return wp_nonce_url( $link, 'ctct-user-is-dismissing', 'ctct-dismiss' );
421
  }
422
  }
1
  <?php
2
  /**
3
+ * Notifications.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Notifications
7
  * @author Constant Contact
25
  * Constructor
26
  *
27
  * @since 1.0.0
 
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
39
  */
40
  public function hooks() {
41
 
42
+ // Add activation message.
43
  add_action( 'admin_notices', array( $this, 'main' ) );
44
 
45
  }
51
  */
52
  public function get_notifications() {
53
 
54
+ /**
55
+ * Filters our notifications.
56
+ *
57
+ * @since 1.0.0
58
+ *
59
+ * @param array $value Array of notification details.
60
+ */
61
  return apply_filters( 'constant_contact_notifications', array(
62
  array(
63
  'ID' => 'activation',
85
  public function main() {
86
 
87
  // If we have our query args where we're attempting to dismiss the notice
88
+ // Get our potentically dismissed notif ID.
89
  $notif_id = $this->get_dismissal_id();
90
 
91
+ // First, we want to check if we should save any dismissals.
92
  if ( $this->check_dismissal_nonce() && $notif_id ) {
93
 
94
+ // Then save that we dismissed it.
95
  $this->save_dismissed_notification( $notif_id );
96
  }
97
 
98
+ // Get all our notifications.
99
  $notifications = $this->get_notifications();
100
  $update_notifications = $this->get_update_notifications();
101
 
118
  */
119
  public function maybe_show_notification( $notif ) {
120
 
121
+ // If our notification isn't an array, skip it.
122
  if ( ! is_array( $notif ) ) {
123
  return;
124
  }
125
 
126
+ // Save our notification data to a helper var.
127
  $notif_id = isset( $notif['ID'] ) ? esc_attr( $notif['ID'] ) : false;
128
  $callback = isset( $notif['callback'] ) ? $notif['callback'] : false;
129
  $require_cb = isset( $notif['require_cb'] ) ? $notif['require_cb'] : false;
130
 
131
+ // If we don't have an ID or callback set, bail.
132
  if ( ! $notif_id || ! $callback ) {
133
  return;
134
  }
135
 
136
+ // Don't show if it was dismissed.
137
  if ( $this->was_notification_dismissed( $notif_id ) ) {
138
  return;
139
  }
140
 
141
+ // If we don have requirements set up for a notif, then check them.
142
  if ( $require_cb ) {
143
 
144
+ // Check to make sure the requirements defined for a notification evalulate to true.
145
  $requirements_passed = ( $this->check_requirements_callback_for_notif( $require_cb ) );
146
 
147
+ // If we didnt' pass, then return.
148
  if ( ! $requirements_passed ) {
149
  return;
150
  }
151
  }
152
 
153
+ // If we cant call our notification callback, bail.
154
  if ( ! is_callable( $callback ) ) {
155
  return false;
156
  }
157
 
158
+ // Get our notifictaion content from our callback.
159
  $notif_content = call_user_func( $callback );
160
 
161
  $this->show_notice( $notif_id, $notif_content );
168
  * Call and return results of executing a callback for a notificaion
169
  *
170
  * @since 1.0.0
171
+ * @param mixed $require_cb valid callback.
172
  * @return boolean boolean results of callback
173
  */
174
  public function check_requirements_callback_for_notif( $require_cb ) {
175
 
 
176
  if ( is_callable( $require_cb ) ) {
 
 
177
  return ( call_user_func( $require_cb ) );
178
  }
179
 
 
180
  return false;
181
  }
182
 
183
  /**
184
+ * Checks to see if we have a dismissal nonce, and if it is valid.
185
  *
186
+ * @since 1.0.0
187
  * @return boolean whether or not nonce is verified
188
  */
189
  public function check_dismissal_nonce() {
196
  // Save our nonce
197
  $nonce = sanitize_text_field( wp_unslash( $_GET['ctct-dismiss'] ) ); // Input var okay.
198
 
199
+ // If our nonce fails, then we don't want to dismiss it.
200
  return ( wp_verify_nonce( $nonce, 'ctct-user-is-dismissing' ) );
201
  }
202
 
213
  return false;
214
  }
215
 
216
+ // If we don't have our dismiss query arg, bail.
217
  if ( ! isset( $_GET['ctct-dismiss-action'] ) ) { // Input var okay.
218
  return false;
219
  }
220
 
221
+ // Get what notification we're attempting to dismiss.
222
  $dismissing_notif = sanitize_text_field( wp_unslash( $_GET['ctct-dismiss-action'] ) ); // Input var okay.
223
 
224
+ // If we don't have an action set for our dismiss action, bail.
225
  if ( ! $dismissing_notif ) {
226
  return false;
227
  }
228
 
229
+ // Send back our notification type.
230
  return $dismissing_notif;
231
  }
232
 
238
  */
239
  public function save_dismissed_notification( $key ) {
240
 
241
+ // Call our save option helper.
242
  return $this->save_dismissed_option( $key, true );
243
  }
244
 
246
  * Set a specific notificaion saved state to false
247
  *
248
  * @since 1.0.0
249
+ * @param strin $key ID of notificaion.
250
  * @return boolean update succeeded?
251
  */
252
  public function delete_dismissed_notification( $key ) {
253
 
254
+ // Call our save option helper.
255
  return $this->save_dismissed_option( $key, false );
256
  }
257
 
286
  */
287
  public function save_dismissed_option( $key, $value ) {
288
 
289
+ // Get all of our options we have saved.
290
  $options = $this->get_dismissed_options();
291
 
292
+ // If for some reason, we didn't get an array, then clear it out.
293
  if ( ! is_array( $options ) ) {
294
  $options = array();
295
  }
296
 
297
+ // Save our keyed notification to be saved.
298
  $options[ esc_attr( $key ) ] = esc_attr( $value );
299
 
300
+ // Save all the options.
301
  return $this->save_dismissed_options( $options );
302
  }
303
 
310
  */
311
  public function was_notification_dismissed( $key = '' ) {
312
 
313
+ // Get all our options.
314
  $option = $this->get_dismissed_option( $key );
315
 
316
+ // If we have 'true' or '1' saved, then its true.
317
  $is_true = ( ( 'true' === $option ) || ( '1' === $option ) );
318
 
319
+ // Cast to boolean and send it back.
320
  return ( $is_true ? true : false );
321
  }
322
 
329
  */
330
  public function get_dismissed_option( $key = '' ) {
331
 
332
+ // Get all our dismissed notifications.
333
  $options = $this->get_dismissed_options();
334
 
335
+ // If we have the notification saved in our options array.
336
  if ( isset( $options[ esc_attr( $key ) ] ) ) {
337
 
338
+ // Return the option of whatever it is.
339
  return $options[ esc_attr( $key ) ];
340
  }
341
 
342
+ // Otherwise, we'll just return false and bail.
343
  return false;
344
  }
345
 
350
  */
351
  public function show_notice( $key, $content = '' ) {
352
 
353
+ // If we don't have any content, bail.
354
  if ( ! $content ) {
355
  return;
356
  }
357
 
358
+ // Show our styles.
359
  $this->do_styles();
360
 
361
+ // Wrap our content in our markup.
362
  ?>
363
  <div id="ctct-admin-notice-<?php echo esc_attr( $key ); ?>" class="ctct-admin-notice updated notice">
364
  <?php echo wp_kses_post( $content ); ?>
374
  */
375
  public function do_styles() {
376
 
377
+ // Set our flag about notice being shown, so we don't re-enqueue styles.
378
  static $have_styles = false;
379
 
380
+ // If we haven't shown styles yet, enqueue em.
381
  if ( ! $have_styles ) {
382
 
 
383
  wp_enqueue_style(
384
  'constant-contact-admin-notices',
385
  constant_contact()->url() . 'assets/css/admin-notices.css',
387
  constant_contact()->version
388
  );
389
 
 
390
  $have_styles = true;
391
  }
392
  }
414
  */
415
  public function get_activation_dismiss_url( $type ) {
416
 
417
+ // Set a link with our current url and desired action.
418
  $link = add_query_arg( array( 'ctct-dismiss-action' => esc_attr( $type ) ) );
419
 
 
420
  return wp_nonce_url( $link, 'ctct-user-is-dismissing', 'ctct-dismiss' );
421
  }
422
  }
includes/class-process-form.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage ProcessForm
5
  * @author Constant Contact
@@ -14,7 +16,7 @@ class ConstantContact_Process_Form {
14
  /**
15
  * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
@@ -23,7 +25,6 @@ class ConstantContact_Process_Form {
23
  * Constructor
24
  *
25
  * @since 1.0.0
26
- * @return void
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -60,13 +61,13 @@ class ConstantContact_Process_Form {
60
  // @codingStandardsIgnoreLine
61
  $data = explode( '&', $_POST['data'] );
62
 
63
- // Finish converting that ajax data to something we can use
64
  $json_data = array();
65
 
66
- // Make sure we have an array of data
67
  if ( is_array( $data ) ) {
68
 
69
- // Loop through each of our fields
70
  foreach ( $data as $field ) {
71
 
72
  // @codingStandardsIgnoreStart
@@ -80,27 +81,27 @@ class ConstantContact_Process_Form {
80
  // in case there is an = in the actual form value
81
  $exp_fields = explode( '=', $field, 2 );
82
 
83
- // Sanity check
84
  if ( isset( $exp_fields[0] ) && $exp_fields[0] ) {
85
- // Set up our data structure if we have the data
86
  $value = urldecode( isset( $exp_fields[1] ) ? $exp_fields[1] : '' );
87
  $json_data[ esc_attr( $exp_fields[0] ) ] = sanitize_text_field( $value );
88
  }
89
  }
90
  }
91
 
92
- // Send it to our process form method
93
  $response = $this->process_form( $json_data, true );
94
 
95
- // We don't need the original values for the ajax check
96
  if ( isset( $response['values'] ) ) {
97
  unset( $response['values'] );
98
  }
99
 
100
- // Send back our response
101
  wp_send_json( $response );
102
 
103
- // die out of the ajax request
104
  wp_die();
105
  }
106
  }
@@ -109,47 +110,47 @@ class ConstantContact_Process_Form {
109
  * Process submitted form data
110
  *
111
  * @since 1.0.0
112
- * @return void
113
  */
114
  public function process_form( $data = array(), $is_ajax = false ) {
115
 
116
- // Set our data var to $_POST if we dont get it passed in
117
  if ( empty( $data ) ) {
118
 
119
  $data = $_POST; // @codingStandardsIgnoreLine
120
  }
121
 
122
- // Don't check for submitted if we are doing it over ajax
123
  if ( ! $is_ajax ) {
124
- // If we don't have our submitted action, just bail out
125
  if ( ! isset( $data['ctct-submitted'] ) ) {
126
  return;
127
  }
128
  }
129
 
130
- // If we don't have our submitted form id, just bail out
131
  if ( ! isset( $data['ctct-id'] ) ) {
132
  return;
133
  }
134
 
135
- // If we don't have our submitted form verify, just bail out
136
  if ( ! isset( $data['ctct-verify'] ) ) {
137
  return;
138
  }
139
 
140
- // Verify our nonce first
141
  if (
142
  ! isset( $data['ctct_form'] ) ||
143
  ! wp_verify_nonce( $data['ctct_form'], 'ctct_submit_form' )
144
  ) {
145
- // figure out a way to pass errors back
146
  return array(
147
  'status' => 'named_error',
148
  'error' => __( 'We had trouble processing your submission. Please review your entries and try again.', 'constant-contact-forms' ),
149
  );
150
  }
151
 
152
- // Make sure we have an original form id
153
  $orig_form_id = absint( $data['ctct-id'] );
154
  if ( ! $orig_form_id ) {
155
  return array(
@@ -158,7 +159,7 @@ class ConstantContact_Process_Form {
158
  );
159
  }
160
 
161
- // Make sure we have a verify value
162
  $form_verify = esc_attr( $data['ctct-verify'] );
163
  if ( ! $form_verify ) {
164
  return array(
@@ -167,7 +168,7 @@ class ConstantContact_Process_Form {
167
  );
168
  }
169
 
170
- // Make sure our verify key matches our saved one
171
  $orig_verify = get_post_meta( $orig_form_id, '_ctct_verify_key', true );
172
  if ( $orig_verify !== $form_verify ) {
173
  return array(
@@ -176,18 +177,18 @@ class ConstantContact_Process_Form {
176
  );
177
  }
178
 
 
 
 
 
 
 
 
 
179
  // If the submit button is clicked, send the email.
180
  foreach ( $data as $key => $value ) {
181
 
182
- // Allow ignoring of certain keys, like our nonce.
183
- $ignored_keys = apply_filters( 'constant_contact_ignored_post_form_values', array(
184
- 'ctct-submitted',
185
- 'ctct_form',
186
- '_wp_http_referer',
187
- 'ctct-verify',
188
- ) );
189
-
190
- // if our key we're processing is in our array, ignore it
191
  if ( in_array( $key, $ignored_keys, true ) ) {
192
  continue;
193
  }
@@ -203,13 +204,13 @@ class ConstantContact_Process_Form {
203
  return;
204
  }
205
 
206
- // Check for specific validation errors
207
  $field_errors = $this->get_field_errors( $this->clean_values( $return['values'] ), $is_ajax );
208
 
209
- // If we got errors
210
  if ( is_array( $field_errors ) && ! empty( $field_errors ) ) {
211
 
212
- // Send back an error status, a message, the errors we found, and all orig values
213
  return array(
214
  'status' => 'req_error',
215
  'errors' => $field_errors,
@@ -217,12 +218,12 @@ class ConstantContact_Process_Form {
217
  );
218
  }
219
 
220
- // if we're not processing the opt-in stuff, we can just return our data here
221
  if ( ! isset( $data['ctct-opt-in'] ) ) {
222
 
223
  if ( ! $is_ajax ) {
224
 
225
- // at this point we can process all of our submitted values
226
  constant_contact()->mail->submit_form_values( $return['values'] );
227
  }
228
 
@@ -232,7 +233,7 @@ class ConstantContact_Process_Form {
232
 
233
  if ( ! $is_ajax ) {
234
 
235
- // at this point we can process all of our submitted values
236
  constant_contact()->mail->submit_form_values( $return['values'], true );
237
  }
238
 
@@ -246,28 +247,28 @@ class ConstantContact_Process_Form {
246
  * Pretty our values up
247
  *
248
  * @since 1.0.0
249
- * @param array $values values
250
  * @return array values but better
251
  */
252
  public function pretty_values( $values = array() ) {
253
 
254
- // Sanity check
255
  if ( ! is_array( $values ) ) {
256
  return '';
257
  }
258
 
259
- // Loop through once to get our form ID
260
  $form_id = 0;
261
  foreach ( $values as $key => $value ) {
262
 
263
  // Sanity check and check to see if we get our form ID
264
- // when we find it, break out
265
  if ( isset( $value['key'] ) && isset( $value['value'] ) ) {
266
 
267
- // if we match our form ID, perfect
268
  if ( 'ctct-id' === $value['key'] ) {
269
 
270
- // set our form id, unset, and break out
271
  $form_id = absint( $value['value'] );
272
  unset( $values['ctct-id'] );
273
  break;
@@ -275,49 +276,49 @@ class ConstantContact_Process_Form {
275
  }
276
  }
277
 
278
- // If we didn't get a form ID, bail out
279
  if ( ! $form_id ) {
280
  return '';
281
  }
282
 
283
- // Get our original fields
284
  $orig_fields = $this->get_original_fields( $form_id );
285
 
286
- // if its not an array, bail out
287
  if ( ! is_array( $orig_fields ) ) {
288
  return;
289
  }
290
 
291
- // this is what we'll use
292
  $pretty_values = array();
293
 
294
- // Loop through each field again
295
  foreach ( $values as $key => $value ) {
296
 
297
- // make sure we have a value
298
  if ( empty( $value ) ) {
299
  continue;
300
  }
301
 
302
- // make sure we have a value
303
  if ( ! isset( $value['key'] ) ) {
304
  continue;
305
  }
306
 
307
- // Make sure we have an orig field with the same key
308
  if ( ! isset( $orig_fields[ $key ] ) ) {
309
  continue;
310
  }
311
 
312
- // Make sure we have the orig mapping key
313
  if ( ! isset( $orig_fields[ $key ]['map_to'] ) ) {
314
  continue;
315
  }
316
 
317
- // force value to be set
318
  $value['value'] = isset( $value['value'] ) ? $value['value'] : '';
319
 
320
- // Send back our data
321
  $pretty_values[] = array(
322
  'orig' => $orig_fields[ $key ],
323
  'post' => $value['value'],
@@ -326,7 +327,7 @@ class ConstantContact_Process_Form {
326
 
327
  }
328
 
329
- // Send it back
330
  return $pretty_values;
331
  }
332
 
@@ -334,36 +335,36 @@ class ConstantContact_Process_Form {
334
  * Gets our original field from a form id
335
  *
336
  * @since 1.0.0
337
- * @param int $form_id form id
338
  * @return array array of form data
339
  */
340
  public function get_original_fields( $form_id ) {
341
 
342
- // Sanity check
343
  if ( ! $form_id ) {
344
  return false;
345
  }
346
 
347
- // Get our fields post meta
348
  $fields = get_post_meta( $form_id, 'custom_fields_group', true );
349
 
350
- // Sanity check again
351
  if ( ! is_array( $fields ) ) {
352
  return false;
353
  }
354
 
355
- // Start our return array
356
  $return = array();
357
 
358
- // Loop through fields to expand some multi-field groups
359
  foreach ( $fields as $field ) {
360
 
361
- // if we don't have a map, skip this loop
362
  if ( ! isset( $field['_ctct_map_select'] ) ) {
363
  continue;
364
  }
365
 
366
- // set our key field thing
367
  $field_key = array(
368
  'name' => isset( $field['_ctct_field_label'] ) ? $field['_ctct_field_label'] : '',
369
  'map_to' => isset( $field['_ctct_map_select'] ) ? $field['_ctct_map_select'] : '',
@@ -415,25 +416,25 @@ class ConstantContact_Process_Form {
415
  * Get field requirement errors
416
  *
417
  * @since 1.0.0
418
- * @param array $values values
419
  * @return array return error code stuff
420
  */
421
  public function get_field_errors( $values, $is_ajax = false ) {
422
 
423
- // get our values with full orig field comparisons
424
  $values = $this->pretty_values( $values );
425
 
426
- // Sanity check
427
  if ( ! is_array( $values ) ) {
428
  return array();
429
  }
430
 
431
- // set up an array to populate with errors
432
  $err_returns = array();
433
 
434
- // Loop through each value
435
  foreach ( $values as $value ) {
436
- // Sanity check
437
  if (
438
  ! isset( $value['orig'] ) ||
439
  ! isset( $value['post'] ) ||
@@ -442,13 +443,14 @@ class ConstantContact_Process_Form {
442
  continue;
443
  }
444
 
445
- // Do a check for if field was required
446
  if (
447
  isset( $value['orig']['required'] ) &&
448
  $value['orig']['required'] &&
449
- $value['orig']['required']
 
450
  ) {
451
- // If it was required, check for a value
452
  if ( ! $value['post'] ) {
453
  $err_returns[] = array(
454
  'map' => $value['orig']['map_to'],
@@ -478,30 +480,30 @@ class ConstantContact_Process_Form {
478
  * Clean our values from form submission
479
  *
480
  * @since 1.0.0
481
- * @param array $values values to clean
482
  * @return array cleaned values
483
  */
484
  public function clean_values( $values ) {
485
 
486
- // Sanity check that
487
  if ( ! is_array( $values ) ) {
488
  return $values;
489
  }
490
 
491
  $return_values = array();
492
 
493
- // Loop through each of our values
494
  foreach ( $values as $value ) {
495
 
496
- // if we don't have a key and value set, skip it
497
  if ( ! isset( $value['key'] ) || ! isset( $value['value'] ) ) {
498
  continue;
499
  }
500
 
501
- // we made our fields look like first_name___435fajiosdf to force unique
502
  $key_break = explode( '___', $value['key'] );
503
 
504
- // Make sure we actually got something for that
505
  if ( ! isset( $key_break[0] ) || ! $key_break[0] ) {
506
  continue;
507
  }
@@ -520,43 +522,42 @@ class ConstantContact_Process_Form {
520
  * Form submit success/error messages.
521
  *
522
  * @since 1.0.0
523
- * @return void
524
  */
525
  public function process_wrapper( $form_data = array(), $form_id = '' ) {
526
 
527
  // Process our data, and get our response.
528
  $processed = $this->process_form();
529
 
530
- // set up our default error
531
  $default_error = __( 'There was an error sending your form.', 'constant-contact-forms' );
532
 
533
- // default to no status
534
  $status = false;
535
 
536
- // If we got a status back, check that in our list of returns
537
  if ( isset( $processed['status'] ) && $processed['status'] ) {
538
  $status = $processed['status'];
539
  }
540
 
541
- // switch based on our status code
542
  switch ( $status ) {
543
 
544
- // yay success
545
  case 'success':
546
  $message = __( 'Your information has been submitted.', 'constant-contact-forms' );
547
  break;
548
 
549
- // generic error
550
  case 'error':
551
  $message = $default_error;
552
  break;
553
 
554
- // named error from our process
555
  case 'named_error':
556
  $message = isset( $processed['error'] ) ? $processed['error'] : $default_error;
557
  break;
558
 
559
- // required field errors
560
  case 'req_error':
561
  return array(
562
  'status' => 'error',
@@ -565,7 +566,7 @@ class ConstantContact_Process_Form {
565
  'values' => isset( $processed['values'] ) ? $processed['values'] : '',
566
  );
567
 
568
- // all else fails, then we'll just use the default
569
  default:
570
  $message = '';
571
  break;
1
  <?php
2
  /**
3
+ * Process form.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage ProcessForm
7
  * @author Constant Contact
16
  /**
17
  * Parent plugin class
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
25
  * Constructor
26
  *
27
  * @since 1.0.0
 
28
  */
29
  public function __construct( $plugin ) {
30
  $this->plugin = $plugin;
61
  // @codingStandardsIgnoreLine
62
  $data = explode( '&', $_POST['data'] );
63
 
64
+ // Finish converting that ajax data to something we can use.
65
  $json_data = array();
66
 
67
+ // Make sure we have an array of data.
68
  if ( is_array( $data ) ) {
69
 
70
+ // Loop through each of our fields.
71
  foreach ( $data as $field ) {
72
 
73
  // @codingStandardsIgnoreStart
81
  // in case there is an = in the actual form value
82
  $exp_fields = explode( '=', $field, 2 );
83
 
84
+ // Sanity check.
85
  if ( isset( $exp_fields[0] ) && $exp_fields[0] ) {
86
+ // Set up our data structure if we have the data.
87
  $value = urldecode( isset( $exp_fields[1] ) ? $exp_fields[1] : '' );
88
  $json_data[ esc_attr( $exp_fields[0] ) ] = sanitize_text_field( $value );
89
  }
90
  }
91
  }
92
 
93
+ // Send it to our process form method.
94
  $response = $this->process_form( $json_data, true );
95
 
96
+ // We don't need the original values for the ajax check.
97
  if ( isset( $response['values'] ) ) {
98
  unset( $response['values'] );
99
  }
100
 
101
+ // Send back our response.
102
  wp_send_json( $response );
103
 
104
+ // Die out of the ajax request.
105
  wp_die();
106
  }
107
  }
110
  * Process submitted form data
111
  *
112
  * @since 1.0.0
113
+ * @return array
114
  */
115
  public function process_form( $data = array(), $is_ajax = false ) {
116
 
117
+ // Set our data var to $_POST if we dont get it passed in.
118
  if ( empty( $data ) ) {
119
 
120
  $data = $_POST; // @codingStandardsIgnoreLine
121
  }
122
 
123
+ // Don't check for submitted if we are doing it over ajax.
124
  if ( ! $is_ajax ) {
125
+ // If we don't have our submitted action, just bail out.
126
  if ( ! isset( $data['ctct-submitted'] ) ) {
127
  return;
128
  }
129
  }
130
 
131
+ // If we don't have our submitted form id, just bail out.
132
  if ( ! isset( $data['ctct-id'] ) ) {
133
  return;
134
  }
135
 
136
+ // If we don't have our submitted form verify, just bail out.
137
  if ( ! isset( $data['ctct-verify'] ) ) {
138
  return;
139
  }
140
 
141
+ // Verify our nonce first.
142
  if (
143
  ! isset( $data['ctct_form'] ) ||
144
  ! wp_verify_nonce( $data['ctct_form'], 'ctct_submit_form' )
145
  ) {
146
+ // Figure out a way to pass errors back.
147
  return array(
148
  'status' => 'named_error',
149
  'error' => __( 'We had trouble processing your submission. Please review your entries and try again.', 'constant-contact-forms' ),
150
  );
151
  }
152
 
153
+ // Make sure we have an original form id.
154
  $orig_form_id = absint( $data['ctct-id'] );
155
  if ( ! $orig_form_id ) {
156
  return array(
159
  );
160
  }
161
 
162
+ // Make sure we have a verify value.
163
  $form_verify = esc_attr( $data['ctct-verify'] );
164
  if ( ! $form_verify ) {
165
  return array(
168
  );
169
  }
170
 
171
+ // Make sure our verify key matches our saved one.
172
  $orig_verify = get_post_meta( $orig_form_id, '_ctct_verify_key', true );
173
  if ( $orig_verify !== $form_verify ) {
174
  return array(
177
  );
178
  }
179
 
180
+ // Allow ignoring of certain keys, like our nonce.
181
+ $ignored_keys = apply_filters( 'constant_contact_ignored_post_form_values', array(
182
+ 'ctct-submitted',
183
+ 'ctct_form',
184
+ '_wp_http_referer',
185
+ 'ctct-verify',
186
+ ) );
187
+
188
  // If the submit button is clicked, send the email.
189
  foreach ( $data as $key => $value ) {
190
 
191
+ // If our key we're processing is in our array, ignore it.
 
 
 
 
 
 
 
 
192
  if ( in_array( $key, $ignored_keys, true ) ) {
193
  continue;
194
  }
204
  return;
205
  }
206
 
207
+ // Check for specific validation errors.
208
  $field_errors = $this->get_field_errors( $this->clean_values( $return['values'] ), $is_ajax );
209
 
210
+ // If we got errors.
211
  if ( is_array( $field_errors ) && ! empty( $field_errors ) ) {
212
 
213
+ // Send back an error status, a message, the errors we found, and all orig values.
214
  return array(
215
  'status' => 'req_error',
216
  'errors' => $field_errors,
218
  );
219
  }
220
 
221
+ // If we're not processing the opt-in stuff, we can just return our data here.
222
  if ( ! isset( $data['ctct-opt-in'] ) ) {
223
 
224
  if ( ! $is_ajax ) {
225
 
226
+ // At this point we can process all of our submitted values.
227
  constant_contact()->mail->submit_form_values( $return['values'] );
228
  }
229
 
233
 
234
  if ( ! $is_ajax ) {
235
 
236
+ // At this point we can process all of our submitted values.
237
  constant_contact()->mail->submit_form_values( $return['values'], true );
238
  }
239
 
247
  * Pretty our values up
248
  *
249
  * @since 1.0.0
250
+ * @param array $values values.
251
  * @return array values but better
252
  */
253
  public function pretty_values( $values = array() ) {
254
 
255
+ // Sanity check.
256
  if ( ! is_array( $values ) ) {
257
  return '';
258
  }
259
 
260
+ // Loop through once to get our form ID.
261
  $form_id = 0;
262
  foreach ( $values as $key => $value ) {
263
 
264
  // Sanity check and check to see if we get our form ID
265
+ // when we find it, break out.
266
  if ( isset( $value['key'] ) && isset( $value['value'] ) ) {
267
 
268
+ // If we match our form ID, perfect.
269
  if ( 'ctct-id' === $value['key'] ) {
270
 
271
+ // Set our form id, unset, and break out.
272
  $form_id = absint( $value['value'] );
273
  unset( $values['ctct-id'] );
274
  break;
276
  }
277
  }
278
 
279
+ // If we didn't get a form ID, bail out.
280
  if ( ! $form_id ) {
281
  return '';
282
  }
283
 
284
+ // Get our original fields.
285
  $orig_fields = $this->get_original_fields( $form_id );
286
 
287
+ // If its not an array, bail out.
288
  if ( ! is_array( $orig_fields ) ) {
289
  return;
290
  }
291
 
292
+ // This is what we'll use.
293
  $pretty_values = array();
294
 
295
+ // Loop through each field again.
296
  foreach ( $values as $key => $value ) {
297
 
298
+ // Make sure we have a value.
299
  if ( empty( $value ) ) {
300
  continue;
301
  }
302
 
303
+ // Make sure we have a value.
304
  if ( ! isset( $value['key'] ) ) {
305
  continue;
306
  }
307
 
308
+ // Make sure we have an orig field with the same key.
309
  if ( ! isset( $orig_fields[ $key ] ) ) {
310
  continue;
311
  }
312
 
313
+ // Make sure we have the orig mapping key.
314
  if ( ! isset( $orig_fields[ $key ]['map_to'] ) ) {
315
  continue;
316
  }
317
 
318
+ // Force value to be set.
319
  $value['value'] = isset( $value['value'] ) ? $value['value'] : '';
320
 
321
+ // Send back our data.
322
  $pretty_values[] = array(
323
  'orig' => $orig_fields[ $key ],
324
  'post' => $value['value'],
327
 
328
  }
329
 
330
+ // Send it back.
331
  return $pretty_values;
332
  }
333
 
335
  * Gets our original field from a form id
336
  *
337
  * @since 1.0.0
338
+ * @param int $form_id form id.
339
  * @return array array of form data
340
  */
341
  public function get_original_fields( $form_id ) {
342
 
343
+ // Sanity check.
344
  if ( ! $form_id ) {
345
  return false;
346
  }
347
 
348
+ // Get our fields post meta.
349
  $fields = get_post_meta( $form_id, 'custom_fields_group', true );
350
 
351
+ // Sanity check again.
352
  if ( ! is_array( $fields ) ) {
353
  return false;
354
  }
355
 
356
+ // Start our return array.
357
  $return = array();
358
 
359
+ // Loop through fields to expand some multi-field groups.
360
  foreach ( $fields as $field ) {
361
 
362
+ // If we don't have a map, skip this loop.
363
  if ( ! isset( $field['_ctct_map_select'] ) ) {
364
  continue;
365
  }
366
 
367
+ // Set our key field thing.
368
  $field_key = array(
369
  'name' => isset( $field['_ctct_field_label'] ) ? $field['_ctct_field_label'] : '',
370
  'map_to' => isset( $field['_ctct_map_select'] ) ? $field['_ctct_map_select'] : '',
416
  * Get field requirement errors
417
  *
418
  * @since 1.0.0
419
+ * @param array $values values.
420
  * @return array return error code stuff
421
  */
422
  public function get_field_errors( $values, $is_ajax = false ) {
423
 
424
+ // Get our values with full orig field comparisons.
425
  $values = $this->pretty_values( $values );
426
 
427
+ // Sanity check.
428
  if ( ! is_array( $values ) ) {
429
  return array();
430
  }
431
 
432
+ // Set up an array to populate with errors.
433
  $err_returns = array();
434
 
435
+ // Loop through each value.
436
  foreach ( $values as $value ) {
437
+ // Sanity check.
438
  if (
439
  ! isset( $value['orig'] ) ||
440
  ! isset( $value['post'] ) ||
443
  continue;
444
  }
445
 
446
+ // Do a check for if field was required.
447
  if (
448
  isset( $value['orig']['required'] ) &&
449
  $value['orig']['required'] &&
450
+ // Skip Address Line 2.
451
+ 'line_2' !== $value['orig']['_ctct_map_select']
452
  ) {
453
+ // If it was required, check for a value.
454
  if ( ! $value['post'] ) {
455
  $err_returns[] = array(
456
  'map' => $value['orig']['map_to'],
480
  * Clean our values from form submission
481
  *
482
  * @since 1.0.0
483
+ * @param array $values values to clean.
484
  * @return array cleaned values
485
  */
486
  public function clean_values( $values ) {
487
 
488
+ // Sanity check that.
489
  if ( ! is_array( $values ) ) {
490
  return $values;
491
  }
492
 
493
  $return_values = array();
494
 
495
+ // Loop through each of our values.
496
  foreach ( $values as $value ) {
497
 
498
+ // If we don't have a key and value set, skip it.
499
  if ( ! isset( $value['key'] ) || ! isset( $value['value'] ) ) {
500
  continue;
501
  }
502
 
503
+ // We made our fields look like first_name___435fajiosdf to force unique.
504
  $key_break = explode( '___', $value['key'] );
505
 
506
+ // Make sure we actually got something for that.
507
  if ( ! isset( $key_break[0] ) || ! $key_break[0] ) {
508
  continue;
509
  }
522
  * Form submit success/error messages.
523
  *
524
  * @since 1.0.0
525
+ * @return array
526
  */
527
  public function process_wrapper( $form_data = array(), $form_id = '' ) {
528
 
529
  // Process our data, and get our response.
530
  $processed = $this->process_form();
531
 
532
+ // Set up our default error.
533
  $default_error = __( 'There was an error sending your form.', 'constant-contact-forms' );
534
 
535
+ // Default to no status.
536
  $status = false;
537
 
538
+ // If we got a status back, check that in our list of returns.
539
  if ( isset( $processed['status'] ) && $processed['status'] ) {
540
  $status = $processed['status'];
541
  }
542
 
543
+ // Switch based on our status code.
544
  switch ( $status ) {
545
 
 
546
  case 'success':
547
  $message = __( 'Your information has been submitted.', 'constant-contact-forms' );
548
  break;
549
 
550
+ // Generic error.
551
  case 'error':
552
  $message = $default_error;
553
  break;
554
 
555
+ // Named error from our process.
556
  case 'named_error':
557
  $message = isset( $processed['error'] ) ? $processed['error'] : $default_error;
558
  break;
559
 
560
+ // Required field errors.
561
  case 'req_error':
562
  return array(
563
  'status' => 'error',
566
  'values' => isset( $processed['values'] ) ? $processed['values'] : '',
567
  );
568
 
569
+ // All else fails, then we'll just use the default.
570
  default:
571
  $message = '';
572
  break;
includes/class-settings.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Settings
5
  * @author Constant Contact
@@ -56,7 +58,6 @@ class ConstantContact_Settings {
56
  *
57
  * @since 1.0.0
58
  * @param object $plugin parent plugin instance.
59
- * @return void
60
  */
61
  public function __construct( $plugin ) {
62
  $this->plugin = $plugin;
@@ -70,10 +71,10 @@ class ConstantContact_Settings {
70
  */
71
  public function hooks() {
72
 
73
- // Kick it off / register our settings
74
  add_action( 'admin_init', array( $this, 'init' ) );
75
 
76
- // Add our options menu + options page
77
  add_action( 'admin_menu', array( $this, 'add_options_page' ) );
78
  add_action( 'cmb2_admin_init', array( $this, 'add_options_page_metabox' ) );
79
 
@@ -83,10 +84,10 @@ class ConstantContact_Settings {
83
  // Override CMB's setter.
84
  add_filter( 'cmb2_override_option_save_' . $this->key, array( $this, 'update_override' ), 10, 2 );
85
 
86
- // Hook in all our form opt-in injects, decide to show or not when we are at the display point
87
  $this->inject_optin_form_hooks();
88
 
89
- // Process our opt-ins
90
  add_filter( 'preprocess_comment', array( $this, 'process_optin_comment_form' ) );
91
  add_filter( 'authenticate', array( $this, 'process_optin_login_form' ), 10, 3 );
92
  }
@@ -98,13 +99,13 @@ class ConstantContact_Settings {
98
  */
99
  public function inject_optin_form_hooks() {
100
 
101
- // Login form
102
  add_action( 'login_form', array( $this, 'optin_form_field_login' ) );
103
 
104
- // Comment Form
105
  add_action( 'comment_form_after_fields', array( $this, 'optin_form_field_comment' ) );
106
 
107
- // Registration form
108
  add_action( 'register_form', array( $this, 'optin_form_field_registration' ) );
109
  add_action( 'signup_extra_fields', array( $this, 'optin_form_field_registration' ) );
110
  }
@@ -125,7 +126,7 @@ class ConstantContact_Settings {
125
  */
126
  public function add_options_page() {
127
 
128
- // Only show our settings page if we're connected to CC
129
  if ( constant_contact()->api->is_connected() ) {
130
 
131
  $this->options_page = add_submenu_page(
@@ -156,7 +157,7 @@ class ConstantContact_Settings {
156
  cmb2_metabox_form( $this->metabox_id, $this->key );
157
  }
158
 
159
- // add 'ctct-debug-server-check' to query args to display server debug
160
  $this->plugin->check->maybe_display_debug_info();
161
  ?>
162
  </div>
@@ -171,7 +172,7 @@ class ConstantContact_Settings {
171
  */
172
  public function on_settings_page() {
173
 
174
- // Get our current page
175
  global $pagenow;
176
 
177
  // Check if we're on edit.php, and if we're on our options page, cast to bool and return
@@ -188,10 +189,10 @@ class ConstantContact_Settings {
188
  // Hook in our save notices.
189
  add_action( "cmb2_save_options-page_fields_{$this->metabox_id}", array( $this, 'settings_notices' ), 10, 2 );
190
 
191
- // Only do the settings fields if we're on the options settings page of edit.php
192
  if ( $this->on_settings_page() ) {
193
 
194
- // Start our new field
195
  $cmb = new_cmb2_box( array(
196
  'id' => $this->metabox_id,
197
  'hookup' => false,
@@ -202,7 +203,7 @@ class ConstantContact_Settings {
202
  ),
203
  ) );
204
 
205
- // Get our lists fields
206
  $this->do_lists_field( $cmb );
207
  }
208
  }
@@ -211,11 +212,11 @@ class ConstantContact_Settings {
211
  * Helper to show our lists field for settings
212
  *
213
  * @since 1.0.0
214
- * @param object $cmb CMB fields object
215
  */
216
  public function do_lists_field( $cmb ) {
217
 
218
- // Get our lists
219
  $lists = constant_contact()->builder->get_lists();
220
 
221
  if ( $lists && is_array( $lists ) ) {
@@ -228,7 +229,7 @@ class ConstantContact_Settings {
228
  'options' => $this->get_optin_show_options(),
229
  ) );
230
 
231
- // Tack on 'select a list' to our lists array
232
  $lists[0] = __( 'Select a list', 'constant-contact-forms' );
233
 
234
  $cmb->add_field( array(
@@ -287,18 +288,18 @@ class ConstantContact_Settings {
287
  */
288
  public function get_optin_show_options() {
289
 
290
- // Set up our default options
291
  $optin_options = array(
292
  'comment_form' => __( 'Add a checkbox to the comment field in your posts', 'constant-contact-forms' ),
293
  'login_form' => __( 'Add a checkbox to the main WordPress login page', 'constant-contact-forms' ),
294
  );
295
 
296
- // If users can register, then allow this option as well
297
  if ( get_option( 'users_can_register' ) ) {
298
  $optin_options['reg_form'] = __( 'Add a checkbox to the WordPress user registration page', 'constant-contact-forms' );
299
  }
300
 
301
- // Send em back
302
  return $optin_options;
303
  }
304
 
@@ -307,20 +308,20 @@ class ConstantContact_Settings {
307
  * for that form is checked or not in the admin
308
  *
309
  * @since 1.0.0
310
- * @param string $type allowed values: 'login_form', 'comment_form', 'reg_form'
311
  * @return boolean if should show or not
312
  */
313
  public function check_if_optin_should_show( $type ) {
314
 
315
- // Get all our settings
316
  $available_areas = ctct_get_settings_option( '_ctct_optin_forms' );
317
 
318
- // If our settings aren't an array, bail out
319
  if ( ! is_array( $available_areas ) ) {
320
  return false;
321
  }
322
 
323
- // Otherwise, check to see if our check is in the array
324
  return in_array( $type, $available_areas, true );
325
  }
326
 
@@ -335,7 +336,7 @@ class ConstantContact_Settings {
335
  */
336
  public function optin_form_field_login() {
337
 
338
- // If we should show it this field, then show it
339
  if ( $this->check_if_optin_should_show( 'login_form' ) ) {
340
  $this->optin_form_field();
341
  }
@@ -349,7 +350,7 @@ class ConstantContact_Settings {
349
  */
350
  public function optin_form_field_comment() {
351
 
352
- // If we should show it this field, then show it
353
  if ( $this->check_if_optin_should_show( 'comment_form' ) ) {
354
  $this->optin_form_field();
355
  }
@@ -363,7 +364,7 @@ class ConstantContact_Settings {
363
  */
364
  public function optin_form_field_registration() {
365
 
366
- // If we should show it this field, then show it
367
  if ( $this->check_if_optin_should_show( 'reg_form' ) ) {
368
  $this->optin_form_field();
369
  }
@@ -377,16 +378,16 @@ class ConstantContact_Settings {
377
  */
378
  public function optin_form_field() {
379
 
380
- // Only show this if we're connected
381
  if ( ! constant_contact()->api->is_connected() ) {
382
  return;
383
  }
384
 
385
- // Get our label, based on our settings if they're available
386
  $saved_label = ctct_get_settings_option( '_ctct_optin_label' );
387
  $list = ctct_get_settings_option( '_ctct_optin_list' );
388
 
389
- // Otherwise, use our default
390
  $label = $saved_label ? $saved_label : __( 'Sign up to our newsletter.', 'constant-contact-forms' );
391
 
392
  ?><p class="ctct-optin-wrapper" style="padding: 0 0 1em 0;">
@@ -408,22 +409,22 @@ class ConstantContact_Settings {
408
  */
409
  public function process_optin_comment_form( $comment_data ) {
410
 
411
- // Sanity check
412
  if ( ! isset( $_POST['ctct_optin_list'] ) ) { // Input var okay.
413
  return $comment_data;
414
  }
415
 
416
- // nonce sanity check
417
  if ( ! isset( $_POST['ct_ct_optin'] ) ) { // Input var okay.
418
  return $comment_data;
419
  }
420
 
421
- // Check our nonce
422
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ct_ct_optin'] ) ), 'ct_ct_add_to_optin' ) ) { // Input var okay.
423
  return $comment_data;
424
  }
425
 
426
- // Send our data to be processed, send back original comment data
427
  return $this->_process_comment_data_for_optin( $comment_data );
428
  }
429
 
@@ -431,21 +432,21 @@ class ConstantContact_Settings {
431
  * Process our comment data and send to CC
432
  *
433
  * @since 1.0.0
434
- * @param array $comment_data array of comment data
435
  * @return array passed in comment data
436
  */
437
  public function _process_comment_data_for_optin( $comment_data ) {
438
 
439
- // finally, if we have at least an email, then add it to the api
440
  if ( isset( $comment_data['comment_author_email'] ) && $comment_data['comment_author_email'] ) {
441
 
442
- // If we can grab a name, try to use it
443
  $name = isset( $comment_data['comment_author'] ) ? $comment_data['comment_author'] : '';
444
 
445
- // If we can get a website, use it
446
  $website = isset( $comment_data['comment_author_url'] ) ? $comment_data['comment_author_url'] : '';
447
 
448
- // Check for our list
449
  //
450
  // We also flag PHPCS to ignore this line, as we get
451
  // a nonce verification error, but we process the nonce
@@ -465,7 +466,7 @@ class ConstantContact_Settings {
465
  // @codingStandardsIgnoreLine
466
  $list = sanitize_text_field( wp_unslash( $_POST['ctct_optin_list'] ) ); // Input var okay.
467
 
468
- // Build up our data array
469
  $args = array(
470
  'list' => $list,
471
  'email' => sanitize_email( $comment_data['comment_author_email'] ),
@@ -474,11 +475,11 @@ class ConstantContact_Settings {
474
  'website' => sanitize_text_field( $website ),
475
  );
476
 
477
- // Add the contact, based on our whitelist of information we have from above
478
  constantcontact_api()->add_contact( $args );
479
  }
480
 
481
- // Send back original comment data
482
  return $comment_data;
483
  }
484
 
@@ -486,34 +487,34 @@ class ConstantContact_Settings {
486
  * Sends contact to CTCT if optin checked
487
  *
488
  * @since 1.0.0
489
- * @param array $user
490
  * @param string $username login name.
491
  * @param string $password user password.
492
  * @return object CTCT return API for contact
493
  */
494
  public function process_optin_login_form( $user, $username, $password ) {
495
 
496
- // Sanity check
497
  if ( ! isset( $_POST['ctct_optin_list'] ) ) { // Input var okay.
498
  return $user;
499
  }
500
 
501
- // nonce sanity check
502
  if ( ! isset( $_POST['ct_ct_optin'] ) ) { // Input var okay.
503
  return $user;
504
  }
505
 
506
- // Check our nonce
507
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ct_ct_optin'] ) ), 'ct_ct_add_to_optin' ) ) { // Input var okay.
508
  return $user;
509
  }
510
 
511
- // Check username
512
  if ( empty( $username ) ) {
513
  return $user;
514
  }
515
 
516
- // Send data to CC and send back our passed in user object
517
  return $this->_process_user_data_for_optin( $user, $username );
518
  }
519
 
@@ -521,23 +522,23 @@ class ConstantContact_Settings {
521
  * Sends user data to CC
522
  *
523
  * @since 1.0.0
524
- * @param object $user WP user object
525
- * @param string $username username
526
- * @return object passed in $user object
527
  */
528
  public function _process_user_data_for_optin( $user, $username ) {
529
 
530
- // Get user
531
  $user_data = get_user_by( 'login', $username );
532
 
533
- // Get email
534
  if ( $user_data && isset( $user_data->data ) && isset( $user_data->data->user_email ) ) {
535
  $email = sanitize_email( $user_data->data->user_email );
536
  } else {
537
  $email = '';
538
  }
539
 
540
- // Get name
541
  if ( $user_data && isset( $user_data->data ) && isset( $user_data->data->display_name ) ) {
542
  $name = sanitize_text_field( $user_data->data->display_name );
543
  } else {
@@ -560,7 +561,7 @@ class ConstantContact_Settings {
560
  // @codingStandardsIgnoreLine
561
  $list = sanitize_text_field( wp_unslash( $_POST['ctct_optin_list'] ) );
562
 
563
- // If we have one or the other, try it
564
  if ( $email ) {
565
  $args = array(
566
  'email' => $email,
@@ -573,7 +574,7 @@ class ConstantContact_Settings {
573
  constantcontact_api()->add_contact( $args );
574
  }
575
 
576
- // Send back our passed in user object
577
  return $user;
578
  }
579
 
@@ -581,8 +582,8 @@ class ConstantContact_Settings {
581
  * Register settings notices for display
582
  *
583
  * @since 1.0.0
584
- * @param int $object_id Option key
585
- * @param array $updated Array of updated fields
586
  * @return void
587
  */
588
  public function settings_notices( $object_id, $updated ) {
@@ -592,7 +593,7 @@ class ConstantContact_Settings {
592
  return;
593
  }
594
 
595
- // Output any errors / notices we need
596
  add_settings_error( $this->key . '-notices', '', __( 'Settings updated.', 'constant-contact-forms' ), 'updated' );
597
  settings_errors( $this->key . '-notices' );
598
  }
@@ -601,6 +602,9 @@ class ConstantContact_Settings {
601
  * Replaces get_option with get_site_option
602
  *
603
  * @since 1.0.0
 
 
 
604
  * @return mixed site option
605
  */
606
  public function get_override( $test, $default = false ) {
@@ -611,6 +615,8 @@ class ConstantContact_Settings {
611
  * Replaces update_option with update_site_option
612
  *
613
  * @since 1.0.0
 
 
614
  * @return mixed site option
615
  */
616
  public function update_override( $test, $option_value ) {
@@ -618,14 +624,17 @@ class ConstantContact_Settings {
618
  }
619
 
620
  /**
621
- * Public getter method for retrieving protected/private variables
622
  *
623
- * @since 1.0.0
624
- * @param string $field Field to retrieve.
 
 
 
625
  * @return mixed Field value or exception is thrown
626
  */
627
  public function __get( $field ) {
628
- // Allowed fields to retrieve
629
  if ( in_array( $field, array( 'key', 'metabox_id', 'title', 'options_page' ), true ) ) {
630
  if ( isset( $this->{$field} ) ) {
631
  return $this->{$field};
@@ -639,7 +648,7 @@ class ConstantContact_Settings {
639
  }
640
 
641
  /**
642
- * Wrapper function around cmb2_get_option
643
  *
644
  * @since 1.0.0
645
  * @param string $key Options array key.
1
  <?php
2
  /**
3
+ * Constant Contact Settings class.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Settings
7
  * @author Constant Contact
58
  *
59
  * @since 1.0.0
60
  * @param object $plugin parent plugin instance.
 
61
  */
62
  public function __construct( $plugin ) {
63
  $this->plugin = $plugin;
71
  */
72
  public function hooks() {
73
 
74
+ // Kick it off / register our settings.
75
  add_action( 'admin_init', array( $this, 'init' ) );
76
 
77
+ // Add our options menu + options page.
78
  add_action( 'admin_menu', array( $this, 'add_options_page' ) );
79
  add_action( 'cmb2_admin_init', array( $this, 'add_options_page_metabox' ) );
80
 
84
  // Override CMB's setter.
85
  add_filter( 'cmb2_override_option_save_' . $this->key, array( $this, 'update_override' ), 10, 2 );
86
 
87
+ // Hook in all our form opt-in injects, decide to show or not when we are at the display point.
88
  $this->inject_optin_form_hooks();
89
 
90
+ // Process our opt-ins.
91
  add_filter( 'preprocess_comment', array( $this, 'process_optin_comment_form' ) );
92
  add_filter( 'authenticate', array( $this, 'process_optin_login_form' ), 10, 3 );
93
  }
99
  */
100
  public function inject_optin_form_hooks() {
101
 
102
+ // Login form.
103
  add_action( 'login_form', array( $this, 'optin_form_field_login' ) );
104
 
105
+ // Comment Form.
106
  add_action( 'comment_form_after_fields', array( $this, 'optin_form_field_comment' ) );
107
 
108
+ // Registration form.
109
  add_action( 'register_form', array( $this, 'optin_form_field_registration' ) );
110
  add_action( 'signup_extra_fields', array( $this, 'optin_form_field_registration' ) );
111
  }
126
  */
127
  public function add_options_page() {
128
 
129
+ // Only show our settings page if we're connected to CC.
130
  if ( constant_contact()->api->is_connected() ) {
131
 
132
  $this->options_page = add_submenu_page(
157
  cmb2_metabox_form( $this->metabox_id, $this->key );
158
  }
159
 
160
+ // Add 'ctct-debug-server-check' to query args to display server debug.
161
  $this->plugin->check->maybe_display_debug_info();
162
  ?>
163
  </div>
172
  */
173
  public function on_settings_page() {
174
 
175
+ // Get our current page.
176
  global $pagenow;
177
 
178
  // Check if we're on edit.php, and if we're on our options page, cast to bool and return
189
  // Hook in our save notices.
190
  add_action( "cmb2_save_options-page_fields_{$this->metabox_id}", array( $this, 'settings_notices' ), 10, 2 );
191
 
192
+ // Only do the settings fields if we're on the options settings page of edit.php.
193
  if ( $this->on_settings_page() ) {
194
 
195
+ // Start our new field.
196
  $cmb = new_cmb2_box( array(
197
  'id' => $this->metabox_id,
198
  'hookup' => false,
203
  ),
204
  ) );
205
 
206
+ // Get our lists fields.
207
  $this->do_lists_field( $cmb );
208
  }
209
  }
212
  * Helper to show our lists field for settings
213
  *
214
  * @since 1.0.0
215
+ * @param object $cmb CMB fields object.
216
  */
217
  public function do_lists_field( $cmb ) {
218
 
219
+ // Get our lists.
220
  $lists = constant_contact()->builder->get_lists();
221
 
222
  if ( $lists && is_array( $lists ) ) {
229
  'options' => $this->get_optin_show_options(),
230
  ) );
231
 
232
+ // Tack on 'select a list' to our lists array.
233
  $lists[0] = __( 'Select a list', 'constant-contact-forms' );
234
 
235
  $cmb->add_field( array(
288
  */
289
  public function get_optin_show_options() {
290
 
291
+ // Set up our default options.
292
  $optin_options = array(
293
  'comment_form' => __( 'Add a checkbox to the comment field in your posts', 'constant-contact-forms' ),
294
  'login_form' => __( 'Add a checkbox to the main WordPress login page', 'constant-contact-forms' ),
295
  );
296
 
297
+ // If users can register, then allow this option as well.
298
  if ( get_option( 'users_can_register' ) ) {
299
  $optin_options['reg_form'] = __( 'Add a checkbox to the WordPress user registration page', 'constant-contact-forms' );
300
  }
301
 
302
+ // Send em back.
303
  return $optin_options;
304
  }
305
 
308
  * for that form is checked or not in the admin
309
  *
310
  * @since 1.0.0
311
+ * @param string $type Allowed values: 'login_form', 'comment_form', 'reg_form'.
312
  * @return boolean if should show or not
313
  */
314
  public function check_if_optin_should_show( $type ) {
315
 
316
+ // Get all our settings.
317
  $available_areas = ctct_get_settings_option( '_ctct_optin_forms' );
318
 
319
+ // If our settings aren't an array, bail out.
320
  if ( ! is_array( $available_areas ) ) {
321
  return false;
322
  }
323
 
324
+ // Otherwise, check to see if our check is in the array.
325
  return in_array( $type, $available_areas, true );
326
  }
327
 
336
  */
337
  public function optin_form_field_login() {
338
 
339
+ // If we should show it this field, then show it.
340
  if ( $this->check_if_optin_should_show( 'login_form' ) ) {
341
  $this->optin_form_field();
342
  }
350
  */
351
  public function optin_form_field_comment() {
352
 
353
+ // If we should show it this field, then show it.
354
  if ( $this->check_if_optin_should_show( 'comment_form' ) ) {
355
  $this->optin_form_field();
356
  }
364
  */
365
  public function optin_form_field_registration() {
366
 
367
+ // If we should show it this field, then show it.
368
  if ( $this->check_if_optin_should_show( 'reg_form' ) ) {
369
  $this->optin_form_field();
370
  }
378
  */
379
  public function optin_form_field() {
380
 
381
+ // Only show this if we're connected.
382
  if ( ! constant_contact()->api->is_connected() ) {
383
  return;
384
  }
385
 
386
+ // Get our label, based on our settings if they're available.
387
  $saved_label = ctct_get_settings_option( '_ctct_optin_label' );
388
  $list = ctct_get_settings_option( '_ctct_optin_list' );
389
 
390
+ // Otherwise, use our default.
391
  $label = $saved_label ? $saved_label : __( 'Sign up to our newsletter.', 'constant-contact-forms' );
392
 
393
  ?><p class="ctct-optin-wrapper" style="padding: 0 0 1em 0;">
409
  */
410
  public function process_optin_comment_form( $comment_data ) {
411
 
412
+ // Sanity check.
413
  if ( ! isset( $_POST['ctct_optin_list'] ) ) { // Input var okay.
414
  return $comment_data;
415
  }
416
 
417
+ // Nonce sanity check.
418
  if ( ! isset( $_POST['ct_ct_optin'] ) ) { // Input var okay.
419
  return $comment_data;
420
  }
421
 
422
+ // Check our nonce.
423
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ct_ct_optin'] ) ), 'ct_ct_add_to_optin' ) ) { // Input var okay.
424
  return $comment_data;
425
  }
426
 
427
+ // Send our data to be processed, send back original comment data.
428
  return $this->_process_comment_data_for_optin( $comment_data );
429
  }
430
 
432
  * Process our comment data and send to CC
433
  *
434
  * @since 1.0.0
435
+ * @param array $comment_data Array of comment data.
436
  * @return array passed in comment data
437
  */
438
  public function _process_comment_data_for_optin( $comment_data ) {
439
 
440
+ // Finally, if we have at least an email, then add it to the api.
441
  if ( isset( $comment_data['comment_author_email'] ) && $comment_data['comment_author_email'] ) {
442
 
443
+ // If we can grab a name, try to use it.
444
  $name = isset( $comment_data['comment_author'] ) ? $comment_data['comment_author'] : '';
445
 
446
+ // If we can get a website, use it.
447
  $website = isset( $comment_data['comment_author_url'] ) ? $comment_data['comment_author_url'] : '';
448
 
449
+ // Check for our list.
450
  //
451
  // We also flag PHPCS to ignore this line, as we get
452
  // a nonce verification error, but we process the nonce
466
  // @codingStandardsIgnoreLine
467
  $list = sanitize_text_field( wp_unslash( $_POST['ctct_optin_list'] ) ); // Input var okay.
468
 
469
+ // Build up our data array.
470
  $args = array(
471
  'list' => $list,
472
  'email' => sanitize_email( $comment_data['comment_author_email'] ),
475
  'website' => sanitize_text_field( $website ),
476
  );
477
 
478
+ // Add the contact, based on our whitelist of information we have from above.
479
  constantcontact_api()->add_contact( $args );
480
  }
481
 
482
+ // Send back original comment data.
483
  return $comment_data;
484
  }
485
 
487
  * Sends contact to CTCT if optin checked
488
  *
489
  * @since 1.0.0
490
+ * @param array $user User.
491
  * @param string $username login name.
492
  * @param string $password user password.
493
  * @return object CTCT return API for contact
494
  */
495
  public function process_optin_login_form( $user, $username, $password ) {
496
 
497
+ // Sanity check.
498
  if ( ! isset( $_POST['ctct_optin_list'] ) ) { // Input var okay.
499
  return $user;
500
  }
501
 
502
+ // nonce sanity check.
503
  if ( ! isset( $_POST['ct_ct_optin'] ) ) { // Input var okay.
504
  return $user;
505
  }
506
 
507
+ // Check our nonce.
508
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['ct_ct_optin'] ) ), 'ct_ct_add_to_optin' ) ) { // Input var okay.
509
  return $user;
510
  }
511
 
512
+ // Check username.
513
  if ( empty( $username ) ) {
514
  return $user;
515
  }
516
 
517
+ // Send data to CC and send back our passed in user object.
518
  return $this->_process_user_data_for_optin( $user, $username );
519
  }
520
 
522
  * Sends user data to CC
523
  *
524
  * @since 1.0.0
525
+ * @param object $user WP user object.
526
+ * @param string $username Username.
527
+ * @return object Passed in $user object.
528
  */
529
  public function _process_user_data_for_optin( $user, $username ) {
530
 
531
+ // Get user.
532
  $user_data = get_user_by( 'login', $username );
533
 
534
+ // Get email.
535
  if ( $user_data && isset( $user_data->data ) && isset( $user_data->data->user_email ) ) {
536
  $email = sanitize_email( $user_data->data->user_email );
537
  } else {
538
  $email = '';
539
  }
540
 
541
+ // Get name.
542
  if ( $user_data && isset( $user_data->data ) && isset( $user_data->data->display_name ) ) {
543
  $name = sanitize_text_field( $user_data->data->display_name );
544
  } else {
561
  // @codingStandardsIgnoreLine
562
  $list = sanitize_text_field( wp_unslash( $_POST['ctct_optin_list'] ) );
563
 
564
+ // If we have one or the other, try it.
565
  if ( $email ) {
566
  $args = array(
567
  'email' => $email,
574
  constantcontact_api()->add_contact( $args );
575
  }
576
 
577
+ // Send back our passed in user object.
578
  return $user;
579
  }
580
 
582
  * Register settings notices for display
583
  *
584
  * @since 1.0.0
585
+ * @param int $object_id Option key.
586
+ * @param array $updated Array of updated fields.
587
  * @return void
588
  */
589
  public function settings_notices( $object_id, $updated ) {
593
  return;
594
  }
595
 
596
+ // Output any errors / notices we need.
597
  add_settings_error( $this->key . '-notices', '', __( 'Settings updated.', 'constant-contact-forms' ), 'updated' );
598
  settings_errors( $this->key . '-notices' );
599
  }
602
  * Replaces get_option with get_site_option
603
  *
604
  * @since 1.0.0
605
+ *
606
+ * @param string $test Something.
607
+ * @param bool $default Default to return.
608
  * @return mixed site option
609
  */
610
  public function get_override( $test, $default = false ) {
615
  * Replaces update_option with update_site_option
616
  *
617
  * @since 1.0.0
618
+ * @param string $test Key.
619
+ * @param mixed $option_value Value to update to.
620
  * @return mixed site option
621
  */
622
  public function update_override( $test, $option_value ) {
624
  }
625
 
626
  /**
627
+ * Public getter method for retrieving protected/private variables.
628
  *
629
+ * @since 1.0.0
630
+ *
631
+ * @throws Exception Invalid property.
632
+ *
633
+ * @param string $field Field to retrieve.
634
  * @return mixed Field value or exception is thrown
635
  */
636
  public function __get( $field ) {
637
+ // Allowed fields to retrieve.
638
  if ( in_array( $field, array( 'key', 'metabox_id', 'title', 'options_page' ), true ) ) {
639
  if ( isset( $this->{$field} ) ) {
640
  return $this->{$field};
648
  }
649
 
650
  /**
651
+ * Wrapper function around cmb2_get_option.
652
  *
653
  * @since 1.0.0
654
  * @param string $key Options array key.
includes/class-shortcode-admin.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  /**
3
- * @package ConstantContact
 
 
4
  * @subpackage ShortcodeAdmin
5
  * @author Constant Contact
6
  * @since 1.0.0
@@ -36,6 +38,13 @@ if ( class_exists( 'WDS_Shortcodes', false ) && ! class_exists( 'ConstantContact
36
  */
37
  public function js_button_data() {
38
 
 
 
 
 
 
 
 
39
  return apply_filters( 'constant_contact_shortcode_button_settings', array(
40
  'qt_button_text' => __( 'Add Constant Contact Form', 'constant-contact-forms' ),
41
  'button_tooltip' => __( 'Add Constant Contact Form', 'constant-contact-forms' ),
1
  <?php
2
  /**
3
+ * Shortcode admin button.
4
+ *
5
+ * @package ConstantContact
6
  * @subpackage ShortcodeAdmin
7
  * @author Constant Contact
8
  * @since 1.0.0
38
  */
39
  public function js_button_data() {
40
 
41
+ /**
42
+ * Filters our shortcode button settings for WDS_Shortcode class.
43
+ *
44
+ * @since 1.0.0
45
+ *
46
+ * @param array $value Array of properties to use with shortcode popup.
47
+ */
48
  return apply_filters( 'constant_contact_shortcode_button_settings', array(
49
  'qt_button_text' => __( 'Add Constant Contact Form', 'constant-contact-forms' ),
50
  'button_tooltip' => __( 'Add Constant Contact Form', 'constant-contact-forms' ),
includes/class-shortcode.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Shortcode
5
  * @author Constant Contact
@@ -42,7 +44,7 @@ if ( class_exists( 'WDS_Shortcodes', false ) && ! class_exists( 'ConstantContact
42
  // Attributes.
43
  $atts = shortcode_atts( array( 'form' => '' ), $this->shortcode_object->atts );
44
 
45
- // Use our helper class to display the shortcode
46
  return constant_contact()->display_shortcode->shortcode_wrapper( $atts );
47
  }
48
 
@@ -55,7 +57,7 @@ if ( class_exists( 'WDS_Shortcodes', false ) && ! class_exists( 'ConstantContact
55
  * @see WDS_Shortcode::att
56
  *
57
  * @since 1.0.0
58
- * @param string $att Attribute to override.
59
  * @param string|null $default Default value.
60
  * @return string
61
  */
1
  <?php
2
  /**
3
+ * Shortcode button.
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Shortcode
7
  * @author Constant Contact
44
  // Attributes.
45
  $atts = shortcode_atts( array( 'form' => '' ), $this->shortcode_object->atts );
46
 
47
+ // Use our helper class to display the shortcode.
48
  return constant_contact()->display_shortcode->shortcode_wrapper( $atts );
49
  }
50
 
57
  * @see WDS_Shortcode::att
58
  *
59
  * @since 1.0.0
60
+ * @param string $att Attribute to override.
61
  * @param string|null $default Default value.
62
  * @return string
63
  */
includes/class-updates.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
  /**
 
 
3
  * @package ConstantContact
4
  * @subpackage Updates
5
  * @author Constant Contact
@@ -14,7 +16,7 @@ class ConstantContact_Updates {
14
  /**
15
  * Parent plugin class
16
  *
17
- * @var class
18
  * @since 0.0.1
19
  */
20
  protected $plugin = null;
@@ -23,7 +25,8 @@ class ConstantContact_Updates {
23
  * Constructor
24
  *
25
  * @since 1.0.0
26
- * @return void
 
27
  */
28
  public function __construct( $plugin ) {
29
  $this->plugin = $plugin;
@@ -38,7 +41,7 @@ class ConstantContact_Updates {
38
  */
39
  public function hooks() {
40
 
41
- // Check to make sure we don't need to run any update functionality, but only in the admin
42
  if ( is_admin() ) {
43
  add_action( 'plugins_loaded', array( $this, 'check_for_update_needed' ) );
44
  }
@@ -52,26 +55,26 @@ class ConstantContact_Updates {
52
  */
53
  public function check_for_update_needed() {
54
 
55
- // Grab what our current version in the DB is saved as
56
  $installed = get_option( 'ctct_plugin_version', '0.0.0' );
57
  $current = esc_attr( $this->plugin->version );
58
 
59
  if ( ! version_compare( $current, $installed, '<' ) ) {
60
 
61
- // Update our DB option to the current plugin version
62
  update_option( 'ctct_plugin_version', $current, true );
63
 
64
  // Convert our installed / current version to something we can use
65
- // in a function name
66
  $installed = sanitize_title( str_replace( '.', '_', $installed ) );
67
  $current = sanitize_title( str_replace( '.', '_', $current ) );
68
 
69
  // Build up an update method function to call if we need it
70
  // this will create something like: run_update_v0_0_0_to_v1_0_1
71
- // which will then get run if it needs to
72
  $method_to_call = array( $this, esc_attr( 'run_update_v' . $installed . '_to_v' . $current ) );
73
 
74
- // If we can call our update function, then call it, passing in 'v1_0_0' as argument
75
  if ( is_callable( $method_to_call ) ) {
76
  call_user_func_array( $method_to_call, array( 'v' . $current ) );
77
  }
@@ -82,30 +85,31 @@ class ConstantContact_Updates {
82
  * If we have an update that requires surfacing a notification to the user,
83
  * let queue it up for display later at some point
84
  *
85
- * @since 1.0.0
86
- * @param string $notif_id update key to use for version
 
87
  */
88
  public function add_notification( $update_id ) {
89
 
90
- // Get our current saved update notifications
91
  $current_notifs = get_option( 'ctct_update_notifications' );
92
  $compare_notifs = $current_notifs;
93
 
94
- // If its not an array, cast it as one
95
  if ( ! is_array( $current_notifs ) ) {
96
  $current_notifs = array();
97
  }
98
 
99
- // Set up our update notif ID to use
100
  $notif_id = 'update-' . str_replace( '_', '-', esc_attr( $update_id ) );
101
 
102
- // Tack on our new update notifications
103
  $current_notifs[ $notif_id ] = array(
104
  'ID' => $notif_id,
105
  'callback' => array( 'ConstantContact_Notification_Content', esc_attr( $update_id ) ),
106
  );
107
 
108
- // Re-save it if we actually did add one
109
  if ( $compare_notifs !== $current_notifs ) {
110
  update_option( 'ctct_update_notifications', $current_notifs );
111
  }
@@ -113,24 +117,30 @@ class ConstantContact_Updates {
113
 
114
 
115
  /**
116
- * Sample update scaffolding for 1.0.0 -> 1.0.1 update
 
 
 
 
117
  */
118
  public function run_update_v1_0_0_to_v1_0_1( $version ) {
119
 
120
- // If we need a notification, then we add it in this way
121
-
122
  // Example of adding a notification to an update. The @codingStand.. line
123
  // can be removed as this is to suppress commented code warnings in PHPCS
124
  // @codingStandardsIgnoreLine
125
  // $this->add_notification( $version );
126
-
127
- // Here we would run any other necessary update code
128
  }
129
 
130
  /**
131
  * For 0.0.0 to 1.0.1, we just run our 1.0.0 to 1.0.1.
132
  * We currently need this in place for the above method, as a user
133
  * doesn't always update 0.0.0->1.0.0->1.0.1, might be 0.0.0->1.0.1
 
 
 
 
134
  */
135
  public function run_update_v0_0_0_to_v1_0_1( $version ) {
136
  $this->run_update_v1_0_0_to_v1_0_1( $version );
1
  <?php
2
  /**
3
+ * Updates
4
+ *
5
  * @package ConstantContact
6
  * @subpackage Updates
7
  * @author Constant Contact
16
  /**
17
  * Parent plugin class
18
  *
19
+ * @var object
20
  * @since 0.0.1
21
  */
22
  protected $plugin = null;
25
  * Constructor
26
  *
27
  * @since 1.0.0
28
+ *
29
+ * @param object $plugin Plugin to store.
30
  */
31
  public function __construct( $plugin ) {
32
  $this->plugin = $plugin;
41
  */
42
  public function hooks() {
43
 
44
+ // Check to make sure we don't need to run any update functionality, but only in the admin.
45
  if ( is_admin() ) {
46
  add_action( 'plugins_loaded', array( $this, 'check_for_update_needed' ) );
47
  }
55
  */
56
  public function check_for_update_needed() {
57
 
58
+ // Grab what our current version in the DB is saved as.
59
  $installed = get_option( 'ctct_plugin_version', '0.0.0' );
60
  $current = esc_attr( $this->plugin->version );
61
 
62
  if ( ! version_compare( $current, $installed, '<' ) ) {
63
 
64
+ // Update our DB option to the current plugin version.
65
  update_option( 'ctct_plugin_version', $current, true );
66
 
67
  // Convert our installed / current version to something we can use
68
+ // in a function name.
69
  $installed = sanitize_title( str_replace( '.', '_', $installed ) );
70
  $current = sanitize_title( str_replace( '.', '_', $current ) );
71
 
72
  // Build up an update method function to call if we need it
73
  // this will create something like: run_update_v0_0_0_to_v1_0_1
74
+ // which will then get run if it needs to.
75
  $method_to_call = array( $this, esc_attr( 'run_update_v' . $installed . '_to_v' . $current ) );
76
 
77
+ // If we can call our update function, then call it, passing in 'v1_0_0' as argument.
78
  if ( is_callable( $method_to_call ) ) {
79
  call_user_func_array( $method_to_call, array( 'v' . $current ) );
80
  }
85
  * If we have an update that requires surfacing a notification to the user,
86
  * let queue it up for display later at some point
87
  *
88
+ * @since 1.0.0
89
+ *
90
+ * @param string $update_id Update key to use for version.
91
  */
92
  public function add_notification( $update_id ) {
93
 
94
+ // Get our current saved update notifications.
95
  $current_notifs = get_option( 'ctct_update_notifications' );
96
  $compare_notifs = $current_notifs;
97
 
98
+ // If its not an array, cast it as one.
99
  if ( ! is_array( $current_notifs ) ) {
100
  $current_notifs = array();
101
  }
102
 
103
+ // Set up our update notif ID to use.
104
  $notif_id = 'update-' . str_replace( '_', '-', esc_attr( $update_id ) );
105
 
106
+ // Tack on our new update notifications.
107
  $current_notifs[ $notif_id ] = array(
108
  'ID' => $notif_id,
109
  'callback' => array( 'ConstantContact_Notification_Content', esc_attr( $update_id ) ),
110
  );
111
 
112
+ // Re-save it if we actually did add one.
113
  if ( $compare_notifs !== $current_notifs ) {
114
  update_option( 'ctct_update_notifications', $current_notifs );
115
  }
117
 
118
 
119
  /**
120
+ * Sample update scaffolding for 1.0.0 -> 1.0.1 update.
121
+ *
122
+ * @since 1.0.0
123
+ *
124
+ * @param string $version Version updating to.
125
  */
126
  public function run_update_v1_0_0_to_v1_0_1( $version ) {
127
 
128
+ // If we need a notification, then we add it in this way.
 
129
  // Example of adding a notification to an update. The @codingStand.. line
130
  // can be removed as this is to suppress commented code warnings in PHPCS
131
  // @codingStandardsIgnoreLine
132
  // $this->add_notification( $version );
133
+ // Here we would run any other necessary update code.
 
134
  }
135
 
136
  /**
137
  * For 0.0.0 to 1.0.1, we just run our 1.0.0 to 1.0.1.
138
  * We currently need this in place for the above method, as a user
139
  * doesn't always update 0.0.0->1.0.0->1.0.1, might be 0.0.0->1.0.1
140
+ *
141
+ * @since 1.0.0
142
+ *
143
+ * @param string $version Version updating to.
144
  */
145
  public function run_update_v0_0_0_to_v1_0_1( $version ) {
146
  $this->run_update_v1_0_0_to_v1_0_1( $version );
includes/helper-functions.php CHANGED
@@ -30,8 +30,8 @@ function constant_contact_is_not_connected() {
30
  /**
31
  * Get a form's markup without using a shortcode
32
  *
33
- * @since 1.0.0
34
- * @param int $form_id form post ID to grab
35
  * @return string HTML markup
36
  */
37
  function constant_contact_get_form( $form_id ) {
@@ -41,8 +41,8 @@ function constant_contact_get_form( $form_id ) {
41
  /**
42
  * Get a form and display it without using a shortcode
43
  *
44
- * @since 1.0.0
45
- * @param int $form_id form post ID to grab
46
  */
47
  function constant_contact_display_form( $form_id ) {
48
  constant_contact()->display_shortcode->display_form( $form_id );
@@ -52,7 +52,7 @@ function constant_contact_display_form( $form_id ) {
52
  * Get an array of forms
53
  *
54
  * @since 1.0.0
55
- * @return array WP Query results of forms
56
  */
57
  function constant_contact_get_forms() {
58
  return constant_contact()->cpts->get_forms( false, true );
30
  /**
31
  * Get a form's markup without using a shortcode
32
  *
33
+ * @since 1.0.0
34
+ * @param int $form_id Form post ID to grab.
35
  * @return string HTML markup
36
  */
37
  function constant_contact_get_form( $form_id ) {
41
  /**
42
  * Get a form and display it without using a shortcode
43
  *
44
+ * @since 1.0.0
45
+ * @param int $form_id Form post ID to grab.
46
  */
47
  function constant_contact_display_form( $form_id ) {
48
  constant_contact()->display_shortcode->display_form( $form_id );
52
  * Get an array of forms
53
  *
54
  * @since 1.0.0
55
+ * @return array WP_Query results of forms.
56
  */
57
  function constant_contact_get_forms() {
58
  return constant_contact()->cpts->get_forms( false, true );
includes/widgets/contact-form-select.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Constant Contact Form Widget.
4
+ *
5
+ * @package ConstantContactForms
6
+ * @author Constant Contact
7
+ * @since 1.1.0
8
+ */
9
+
10
+ /**
11
+ * Constant Contact Form Display Widget
12
+ *
13
+ * @since 1.1.0
14
+ */
15
+ class ConstantContactWidget extends WP_Widget {
16
+
17
+ /**
18
+ * ConstantContactWidget constructor.
19
+ */
20
+ public function __construct() {
21
+ $widget_ops = array(
22
+ 'classname' => '',
23
+ 'description' => __( 'Display a Constant Contact form.', 'constant-contact-forms' ),
24
+ );
25
+ parent::__construct(
26
+ 'ctct_form',
27
+ __( 'Constant Contact Form', 'constant-contact-forms' ),
28
+ $widget_ops
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Form method.
34
+ *
35
+ * @since 1.1.0
36
+ *
37
+ * @param array $instance Widget instance.
38
+ * @return void
39
+ */
40
+ public function form( $instance ) {
41
+ $defaults = array(
42
+ 'ctct_title' => '',
43
+ 'ctct_form_id' => 0,
44
+ );
45
+ $instance = wp_parse_args( (array) $instance, $defaults );
46
+
47
+ $title = strip_tags( $instance['ctct_title'] );
48
+ $form_id = absint( $instance['ctct_form_id'] );
49
+
50
+ $this->form_input_text( array(
51
+ 'label_text' => __( 'Title', 'constant-contact-forms' ),
52
+ 'name' => $this->get_field_name( 'ctct_title' ),
53
+ 'id' => $this->get_field_id( 'ctct_title' ),
54
+ 'value' => $title,
55
+ ) );
56
+
57
+ $this->form_input_select( array(
58
+ 'label_text' => __( 'Form', 'constant-contact-forms' ),
59
+ 'name' => $this->get_field_name( 'ctct_form_id' ),
60
+ 'id' => $this->get_field_id( 'ctct_form_id' ),
61
+ 'options' => $this->get_forms(),
62
+ 'value' => $form_id,
63
+ ) );
64
+ }
65
+
66
+ /**
67
+ * Update method.
68
+ *
69
+ * @since 1.1.0
70
+ *
71
+ * @param array $new_instance New data.
72
+ * @param array $old_instance Original data.
73
+ * @return array Updated data
74
+ */
75
+ public function update( $new_instance, $old_instance ) {
76
+ $instance = $old_instance;
77
+ $instance['ctct_title'] = trim( strip_tags( $new_instance['ctct_title'] ) );
78
+ $instance['ctct_form_id'] = trim( strip_tags( $new_instance['ctct_form_id'] ) );
79
+
80
+ return $instance;
81
+ }
82
+
83
+ /**
84
+ * Widget method.
85
+ *
86
+ * @since 1.1.0
87
+ *
88
+ * @param array $args Widget args.
89
+ * @param array $instance Widget instance.
90
+ */
91
+ public function widget( $args, $instance ) {
92
+ $title = trim( strip_tags( $instance['ctct_title'] ) );
93
+ $form_id = absint( $instance['ctct_form_id'] );
94
+
95
+ echo $args['before_widget'];
96
+
97
+ if ( $title ) {
98
+ echo $args['before_title'] . $title . $args['after_title'];
99
+ }
100
+
101
+ echo do_shortcode( sprintf( '[ctct form="%s"]', $form_id ) );
102
+
103
+ echo $args['after_widget'];
104
+ }
105
+
106
+ /**
107
+ * Get all available forms to display.
108
+ *
109
+ * @since 1.1.0
110
+ *
111
+ * @return array
112
+ */
113
+ public function get_forms() {
114
+ $args = array(
115
+ 'post_type' => 'ctct_forms',
116
+ 'posts_per_page' => - 1,
117
+ 'orderby' => 'title',
118
+ );
119
+ $forms = new WP_Query( $args );
120
+ if ( $forms->have_posts() ) {
121
+ return array_map( function( $post ) {
122
+ return array( $post->ID => $post->post_title );
123
+ }, $forms->posts );
124
+ }
125
+
126
+ return array();
127
+ }
128
+
129
+ /**
130
+ * Return a text input.
131
+ *
132
+ * @since 1.1.0
133
+ *
134
+ * @param array $args Arguments for text input.
135
+ * @return void
136
+ */
137
+ public function form_input_text( $args = array() ) {
138
+
139
+ if ( ! empty( $args ) ) {
140
+ $label_text = esc_attr( $args['label_text'] );
141
+ $name = esc_attr( $args['name'] );
142
+ $id = esc_attr( $args['id'] );
143
+ $value = esc_attr( $args['value'] );
144
+
145
+ printf(
146
+ '<p><label for="%s">%s</label><input type="text" class="widefat" name="%s" id="%s" value="%s" /></p>',
147
+ $id,
148
+ $label_text,
149
+ $name,
150
+ $id,
151
+ $value
152
+ );
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Return a select input.
158
+ *
159
+ * @since 1.1.0
160
+ *
161
+ * @param array $args Arguments for select input.
162
+ * @return void
163
+ */
164
+ public function form_input_select( $args = array() ) {
165
+ if ( ! empty( $args ) ) {
166
+ $label_text = esc_attr( $args['label_text'] );
167
+ $name = esc_attr( $args['name'] );
168
+ $id = esc_attr( $args['id'] );
169
+ $options = $args['options'];
170
+ $value = esc_attr( $args['value'] );
171
+
172
+ $selects = '';
173
+ foreach ( $options as $option ) {
174
+ foreach ( $option as $key => $title ) {
175
+ $selects .= sprintf(
176
+ '<option value="%s" %s>%s</option>',
177
+ $key,
178
+ selected( $value, $key, false ),
179
+ $title
180
+ );
181
+ }
182
+ }
183
+ printf(
184
+ '<p><label for="%s">%s</label><select class="widefat" name="%s" id="%s">%s</select>',
185
+ $id,
186
+ $label_text,
187
+ $name,
188
+ $id,
189
+ $selects
190
+ );
191
+ }
192
+ }
193
+ }
languages/constant-contact-forms.pot CHANGED
@@ -5,7 +5,7 @@ msgstr ""
5
  "Project-Id-Version: Constant Contact Forms for WordPress 1.0.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/constant-contact-"
7
  "forms\n"
8
- "POT-Creation-Date: 2016-10-07 13:25:47+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
@@ -257,135 +257,135 @@ msgid ""
257
  "coupons, and more."
258
  msgstr ""
259
 
260
- #: includes/class-builder-fields.php:120
261
  msgid "Form Options"
262
  msgstr ""
263
 
264
- #: includes/class-builder-fields.php:152 includes/class-settings.php:235
265
  msgid "Add subscribers to"
266
  msgstr ""
267
 
268
- #: includes/class-builder-fields.php:155
269
  msgid "No List Selected"
270
  msgstr ""
271
 
272
- #: includes/class-builder-fields.php:178
273
  msgid "Enable email subscriber opt-in"
274
  msgstr ""
275
 
276
- #: includes/class-builder-fields.php:180
277
  msgid "Adds an opt-in to the bottom of your form."
278
  msgstr ""
279
 
280
- #: includes/class-builder-fields.php:200
281
  msgid "Show opt-in checkbox to allow visitors to opt-in to your email list."
282
  msgstr ""
283
 
284
- #: includes/class-builder-fields.php:202
285
  msgid "(usually used with a Contact Us type form)"
286
  msgstr ""
287
 
288
- #: includes/class-builder-fields.php:205
289
  msgid "Show Opt-in checkbox"
290
  msgstr ""
291
 
292
- #: includes/class-builder-fields.php:223
293
  msgid "Your Business Name"
294
  msgstr ""
295
 
296
- #: includes/class-builder-fields.php:226 includes/class-settings.php:256
297
  msgid "Opt-in Affirmation"
298
  msgstr ""
299
 
300
- #: includes/class-builder-fields.php:229
301
  msgid ""
302
  "Example: Yes, I would like to receive emails from %s. (You can unsubscribe "
303
  "anytime)"
304
  msgstr ""
305
 
306
- #: includes/class-builder-fields.php:246
307
  msgid "Form Fields"
308
  msgstr ""
309
 
310
- #: includes/class-builder-fields.php:255
311
  msgid "Add Fields"
312
  msgstr ""
313
 
314
- #: includes/class-builder-fields.php:262
315
  msgid ""
316
  "Create a field for each piece of information you want to collect. Good "
317
  "basics include email address, first name, and last name."
318
  msgstr ""
319
 
320
- #: includes/class-builder-fields.php:273
321
  msgid "Field {#}"
322
  msgstr ""
323
 
324
- #: includes/class-builder-fields.php:274
325
  msgid "Add Another Field"
326
  msgstr ""
327
 
328
- #: includes/class-builder-fields.php:275
329
  msgid "Remove Field"
330
  msgstr ""
331
 
332
- #: includes/class-builder-fields.php:282
333
  msgid "Field Label"
334
  msgstr ""
335
 
336
- #: includes/class-builder-fields.php:285
337
  msgid "Email"
338
  msgstr ""
339
 
340
- #: includes/class-builder-fields.php:290
341
  msgid "Field Description"
342
  msgstr ""
343
 
344
- #: includes/class-builder-fields.php:297
345
  msgid "Email (required)"
346
  msgstr ""
347
 
348
- #: includes/class-builder-fields.php:298
349
  msgid "First Name"
350
  msgstr ""
351
 
352
- #: includes/class-builder-fields.php:299
353
  msgid "Last Name"
354
  msgstr ""
355
 
356
- #: includes/class-builder-fields.php:300
357
  msgid "Phone Number"
358
  msgstr ""
359
 
360
- #: includes/class-builder-fields.php:301
361
  msgid "Address"
362
  msgstr ""
363
 
364
- #: includes/class-builder-fields.php:302
365
  msgid "Job Title"
366
  msgstr ""
367
 
368
- #: includes/class-builder-fields.php:303
369
  msgid "Company"
370
  msgstr ""
371
 
372
- #: includes/class-builder-fields.php:304
373
  msgid "Website"
374
  msgstr ""
375
 
376
- #: includes/class-builder-fields.php:312
377
  msgid "Custom Text Field"
378
  msgstr ""
379
 
380
- #: includes/class-builder-fields.php:313
381
  msgid "Custom Text Area"
382
  msgstr ""
383
 
384
- #: includes/class-builder-fields.php:318
385
  msgid "Select a Field"
386
  msgstr ""
387
 
388
- #: includes/class-builder-fields.php:329
389
  msgid "Required"
390
  msgstr ""
391
 
5
  "Project-Id-Version: Constant Contact Forms for WordPress 1.0.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/constant-contact-"
7
  "forms\n"
8
+ "POT-Creation-Date: 2016-10-03 14:05:32+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
257
  "coupons, and more."
258
  msgstr ""
259
 
260
+ #: includes/class-builder-fields.php:115
261
  msgid "Form Options"
262
  msgstr ""
263
 
264
+ #: includes/class-builder-fields.php:147 includes/class-settings.php:235
265
  msgid "Add subscribers to"
266
  msgstr ""
267
 
268
+ #: includes/class-builder-fields.php:150
269
  msgid "No List Selected"
270
  msgstr ""
271
 
272
+ #: includes/class-builder-fields.php:173
273
  msgid "Enable email subscriber opt-in"
274
  msgstr ""
275
 
276
+ #: includes/class-builder-fields.php:175
277
  msgid "Adds an opt-in to the bottom of your form."
278
  msgstr ""
279
 
280
+ #: includes/class-builder-fields.php:195
281
  msgid "Show opt-in checkbox to allow visitors to opt-in to your email list."
282
  msgstr ""
283
 
284
+ #: includes/class-builder-fields.php:197
285
  msgid "(usually used with a Contact Us type form)"
286
  msgstr ""
287
 
288
+ #: includes/class-builder-fields.php:200
289
  msgid "Show Opt-in checkbox"
290
  msgstr ""
291
 
292
+ #: includes/class-builder-fields.php:218
293
  msgid "Your Business Name"
294
  msgstr ""
295
 
296
+ #: includes/class-builder-fields.php:221 includes/class-settings.php:256
297
  msgid "Opt-in Affirmation"
298
  msgstr ""
299
 
300
+ #: includes/class-builder-fields.php:224
301
  msgid ""
302
  "Example: Yes, I would like to receive emails from %s. (You can unsubscribe "
303
  "anytime)"
304
  msgstr ""
305
 
306
+ #: includes/class-builder-fields.php:241
307
  msgid "Form Fields"
308
  msgstr ""
309
 
310
+ #: includes/class-builder-fields.php:250
311
  msgid "Add Fields"
312
  msgstr ""
313
 
314
+ #: includes/class-builder-fields.php:257
315
  msgid ""
316
  "Create a field for each piece of information you want to collect. Good "
317
  "basics include email address, first name, and last name."
318
  msgstr ""
319
 
320
+ #: includes/class-builder-fields.php:268
321
  msgid "Field {#}"
322
  msgstr ""
323
 
324
+ #: includes/class-builder-fields.php:269
325
  msgid "Add Another Field"
326
  msgstr ""
327
 
328
+ #: includes/class-builder-fields.php:270
329
  msgid "Remove Field"
330
  msgstr ""
331
 
332
+ #: includes/class-builder-fields.php:277
333
  msgid "Field Label"
334
  msgstr ""
335
 
336
+ #: includes/class-builder-fields.php:280
337
  msgid "Email"
338
  msgstr ""
339
 
340
+ #: includes/class-builder-fields.php:285
341
  msgid "Field Description"
342
  msgstr ""
343
 
344
+ #: includes/class-builder-fields.php:292
345
  msgid "Email (required)"
346
  msgstr ""
347
 
348
+ #: includes/class-builder-fields.php:293
349
  msgid "First Name"
350
  msgstr ""
351
 
352
+ #: includes/class-builder-fields.php:294
353
  msgid "Last Name"
354
  msgstr ""
355
 
356
+ #: includes/class-builder-fields.php:295
357
  msgid "Phone Number"
358
  msgstr ""
359
 
360
+ #: includes/class-builder-fields.php:296
361
  msgid "Address"
362
  msgstr ""
363
 
364
+ #: includes/class-builder-fields.php:297
365
  msgid "Job Title"
366
  msgstr ""
367
 
368
+ #: includes/class-builder-fields.php:298
369
  msgid "Company"
370
  msgstr ""
371
 
372
+ #: includes/class-builder-fields.php:299
373
  msgid "Website"
374
  msgstr ""
375
 
376
+ #: includes/class-builder-fields.php:307
377
  msgid "Custom Text Field"
378
  msgstr ""
379
 
380
+ #: includes/class-builder-fields.php:308
381
  msgid "Custom Text Area"
382
  msgstr ""
383
 
384
+ #: includes/class-builder-fields.php:313
385
  msgid "Select a Field"
386
  msgstr ""
387
 
388
+ #: includes/class-builder-fields.php:324
389
  msgid "Required"
390
  msgstr ""
391
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: constantcontact
3
  Tags:
4
  Requires at least: 4.0.0
5
  Tested up to: 4.6.1
6
- Stable tag: 1.0.1
7
  License: GPLv2
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -13,6 +13,8 @@ Add a contact form to your WordPress site and quickly capture information from v
13
 
14
  **Constant Contact Forms** makes it fast and easy to capture visitor information right from your WordPress site. Whether you’re looking to collect email addresses, contact info, event sign-ups, or visitor feedback, you can customize your forms with data fields that work best for you. Best of all, this plugin is available to all WordPress users, even if you don’t have a Constant Contact account.
15
 
 
 
16
  **Constant Contact Forms** allows you to:
17
 
18
  * Create forms that are clear, simple, and mobile-optimized for every device.
@@ -31,6 +33,20 @@ BONUS: If you have a Constant Contact account, all new email addresses that you
31
 
32
  == Changelog ==
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  = 1.0.2 =
35
  * Update copyright information.
36
  * Remove Form Options for users who aren't connected to Constant Contact.
3
  Tags:
4
  Requires at least: 4.0.0
5
  Tested up to: 4.6.1
6
+ Stable tag: 1.1.0
7
  License: GPLv2
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
13
 
14
  **Constant Contact Forms** makes it fast and easy to capture visitor information right from your WordPress site. Whether you’re looking to collect email addresses, contact info, event sign-ups, or visitor feedback, you can customize your forms with data fields that work best for you. Best of all, this plugin is available to all WordPress users, even if you don’t have a Constant Contact account.
15
 
16
+ https://www.youtube.com/watch?v=MhxtAlpZzJw
17
+
18
  **Constant Contact Forms** allows you to:
19
 
20
  * Create forms that are clear, simple, and mobile-optimized for every device.
33
 
34
  == Changelog ==
35
 
36
+ = 1.1.0 =
37
+ * Added: Widget that allows you to select a form to display.
38
+ * Added: Small metabox in form editor showing shortcode to use for current form.
39
+ * Added: Field and filter for text shown on the rendered submit button.
40
+ * Added: Developers: Inline documentation of actions and filters.
41
+ * Fixed: Loading position of Constant Contact stylesheet. Should now load in `<head>`.
42
+ * Fixed: Removed redundant "Add form" button on Constant Contact form editor TinyMCE.
43
+ * Fixed: Removed required attribute for Address line 2 when line 1 is required.
44
+ * Updated: Labels in Constant Contact Form list around none available and none in trash.
45
+
46
+ = 1.0.3 =
47
+ * Fixed: Improperly placed content for Constant Contact API requests for phone and website fields.
48
+ * Updated: Default text for admin email subject line and email footer copy.
49
+
50
  = 1.0.2 =
51
  * Update copyright information.
52
  * Remove Form Options for users who aren't connected to Constant Contact.