Call Now Button - Version 0.5.0

Version Description

= * Button enablement is back in the creation view * Small UI improvements * Backend improvements

Download this release

Release Info

Developer jasperroel
Plugin Icon 128x128 Call Now Button
Version 0.5.0
Comparing to
See all releases

Code changes from version 0.4.7 to 0.5.0

Files changed (40) hide show
  1. call-now-button.php +3 -2
  2. readme.txt +6 -1
  3. resources/images/button-new-full.png +0 -0
  4. resources/images/button-new-multi.png +0 -0
  5. resources/images/button-new-single.png +0 -0
  6. resources/js/call-now-button.js +125 -3
  7. resources/js/dismiss.js +17 -0
  8. resources/style/call-now-button.css +68 -0
  9. src/admin/action-edit.php +32 -36
  10. src/admin/action-overview.php +140 -107
  11. src/admin/admin-ajax.php +38 -3
  12. src/admin/api/CnbAdminCloud.php +107 -104
  13. src/admin/api/CnbAppRemote.php +162 -109
  14. src/admin/api/RemoteTrace.php +1 -1
  15. src/admin/api/RemoteTracer.php +1 -1
  16. src/admin/apikey-overview.php +42 -57
  17. src/admin/button-edit.php +92 -93
  18. src/admin/button-overview.php +156 -121
  19. src/admin/condition-edit.php +98 -38
  20. src/admin/condition-overview.php +85 -90
  21. src/admin/domain-edit.php +151 -163
  22. src/admin/domain-overview.php +70 -65
  23. src/admin/domain-upgrade.php +130 -132
  24. src/admin/legacy-edit.php +118 -84
  25. src/admin/models/CnbAction.class.php +28 -0
  26. src/admin/models/CnbButton.class.php +68 -0
  27. src/admin/models/CnbCondition.class.php +11 -0
  28. src/admin/models/CnbDomain.class.php +81 -0
  29. src/admin/partials/admin-footer.php +12 -5
  30. src/admin/partials/admin-functions.php +6 -4
  31. src/admin/partials/admin-header.php +31 -29
  32. src/admin/settings.php +296 -276
  33. src/call-now-button.php +73 -13
  34. src/renderers/classic/wp_head.php +1 -1
  35. src/renderers/cloud/wp_head.php +2 -2
  36. src/renderers/modern/wp_head.php +1 -4
  37. src/utils/CnbAdminNotices.class.php +193 -0
  38. src/utils/notices.php +140 -53
  39. src/utils/utils.php +101 -22
  40. uninstall.php +21 -6
call-now-button.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Call Now Button
4
  Plugin URI: https://callnowbutton.com
5
  Description: Mobile visitors will see a <strong>Call Now Button</strong> on your website. Easy to use but flexible to meet more demanding requirements. Change placement and color, hide on specific pages, track how many people click them or conversions of your Google Ads campaigns. It's all optional but possible.
6
- Version: 0.4.7
7
  Author: Jerry Rietveld
8
  Author URI: https://www.callnowbutton.com
9
  GitHub Plugin URI: https://github.com/callnowbutton/wp-plugin
@@ -26,12 +26,13 @@ License: GPL2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
- define('CNB_VERSION', '0.4.7');
30
  define('CNB_NAME', 'Call Now Button');
31
  define('CNB_BASENAME', plugin_basename(__FILE__));
32
  define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
33
  define('CNB_FILENAME', str_replace(CNB_BASEFOLDER . '/', '', CNB_BASENAME));
34
  define('CNB_WEBSITE', 'https://callnowbutton.com/');
35
  define('CNB_SUPPORT', CNB_WEBSITE . 'support/');
 
36
 
37
  require_once dirname( __FILE__ ) . '/src/call-now-button.php';
3
  Plugin Name: Call Now Button
4
  Plugin URI: https://callnowbutton.com
5
  Description: Mobile visitors will see a <strong>Call Now Button</strong> on your website. Easy to use but flexible to meet more demanding requirements. Change placement and color, hide on specific pages, track how many people click them or conversions of your Google Ads campaigns. It's all optional but possible.
6
+ Version: 0.5.0
7
  Author: Jerry Rietveld
8
  Author URI: https://www.callnowbutton.com
9
  GitHub Plugin URI: https://github.com/callnowbutton/wp-plugin
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
+ define('CNB_VERSION', '0.5.0');
30
  define('CNB_NAME', 'Call Now Button');
31
  define('CNB_BASENAME', plugin_basename(__FILE__));
32
  define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
33
  define('CNB_FILENAME', str_replace(CNB_BASEFOLDER . '/', '', CNB_BASENAME));
34
  define('CNB_WEBSITE', 'https://callnowbutton.com/');
35
  define('CNB_SUPPORT', CNB_WEBSITE . 'support/');
36
+ define('CNB_SLUG', sanitize_title(CNB_NAME));
37
 
38
  require_once dirname( __FILE__ ) . '/src/call-now-button.php';
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: call button, click to call, convert, call now button, contact button
5
  Requires at least: 3.9
6
  Requires PHP: 5.4
7
  Tested up to: 5.8
8
- Stable tag: 0.4.7
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -110,6 +110,11 @@ This is coming before the end of this year. We're currently looking for testers
110
 
111
 
112
  == Changelog ==
 
 
 
 
 
113
  = 0.4.7 =
114
  * Added notice bar for live buttons without a phone number entered
115
 
5
  Requires at least: 3.9
6
  Requires PHP: 5.4
7
  Tested up to: 5.8
8
+ Stable tag: 0.5.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
110
 
111
 
112
  == Changelog ==
113
+ = 0.5.0 =
114
+ * Button enablement is back in the creation view
115
+ * Small UI improvements
116
+ * Backend improvements
117
+
118
  = 0.4.7 =
119
  * Added notice bar for live buttons without a phone number entered
120
 
resources/images/button-new-full.png CHANGED
Binary file
resources/images/button-new-multi.png CHANGED
Binary file
resources/images/button-new-single.png CHANGED
Binary file
resources/js/call-now-button.js CHANGED
@@ -69,14 +69,21 @@ function cnb_hide_on_show_always() {
69
  return false;
70
  }
71
 
 
 
 
 
72
  function cnb_disable_api_key_when_cloud_hosting_is_disabled() {
73
- jQuery('.when-cloud-enabled :input').prop('disabled', !jQuery('#cloud_enabled').is(':checked'));
 
 
 
74
  }
75
 
76
  let cnb_add_condition_counter = 0;
77
  function cnb_add_condition() {
78
  let template = `
79
- <th scope="row">Condition: <div class="cnb_font_normal cnb_font_90">new/unsaved</div></th>
80
  <td>
81
  <input type="hidden" name="condition[${cnb_add_condition_counter}][id]" value="" />
82
  <input type="hidden" name="condition[${cnb_add_condition_counter}][conditionType]" value="URL" />
@@ -267,6 +274,117 @@ function cnb_strip_beta_from_referrer() {
267
  }
268
  }
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  jQuery( document ).ready(function() {
271
  cnb_setup_colors();
272
  cnb_setup_sliders();
@@ -285,4 +403,8 @@ jQuery( document ).ready(function() {
285
  if (typeof show_advanced_view_only_set !== 'undefined' && show_advanced_view_only_set && show_advanced_view_only_set === 1) {
286
  show_advanced_view_only()
287
  }
288
- });
 
 
 
 
69
  return false;
70
  }
71
 
72
+ /**
73
+ * Disable the Cloud inputs when it is disabled (but only on the settings screen,
74
+ * where that checkbox is actually visible)
75
+ */
76
  function cnb_disable_api_key_when_cloud_hosting_is_disabled() {
77
+ const ele = jQuery('#cnb_cloud_enabled');
78
+ if (ele.length) {
79
+ jQuery('.when-cloud-enabled :input').prop('disabled', !ele.is(':checked'));
80
+ }
81
  }
82
 
83
  let cnb_add_condition_counter = 0;
84
  function cnb_add_condition() {
85
  let template = `
86
+ <th scope="row">Condition <div class="cnb_font_normal cnb_font_90">new/unsaved</div></th>
87
  <td>
88
  <input type="hidden" name="condition[${cnb_add_condition_counter}][id]" value="" />
89
  <input type="hidden" name="condition[${cnb_add_condition_counter}][conditionType]" value="URL" />
274
  }
275
  }
276
 
277
+ function cnb_delete_action() {
278
+ jQuery('.cnb-button-edit-action-table tbody[data-wp-lists="list:cnb_list_action"]#the-list span.delete a[data-ajax="true"]').click(function(){
279
+ // Prep data
280
+ const id = jQuery(this).data('id');
281
+ const bid = jQuery(this).data('bid');
282
+ const data = {
283
+ 'action': 'cnb_delete_action',
284
+ 'id': id,
285
+ 'bid': bid,
286
+ '_ajax_nonce': jQuery(this).data('wpnonce'),
287
+ };
288
+
289
+ // Send remove request
290
+ jQuery.post(ajaxurl, data);
291
+
292
+ // Remove container
293
+ const action_row = jQuery(this).closest('tr');
294
+ jQuery(action_row).css("background-color", "#ff726f");
295
+ jQuery(action_row).fadeOut(function() {
296
+ jQuery(action_row).css("background-color", "");
297
+ jQuery(action_row).remove();
298
+
299
+ // Special case: if this is the last item, show a "no items" row
300
+ const remaining_items = jQuery('#the-list tr').length;
301
+ if (!remaining_items) {
302
+ // Add row
303
+ jQuery('#the-list').html('<tr class="no-items"><td class="colspanchange" colspan="3">This button has no actions yet. Let\'s add one!</td></tr>');
304
+ }
305
+ });
306
+
307
+ return false;
308
+ });
309
+ }
310
+
311
+ /**
312
+ * function for the button type selection in the New button modal
313
+ */
314
+ function cnb_button_overview_modal() {
315
+ jQuery(".cnb_type_selector_item").click(function(){
316
+ jQuery(".cnb_type_selector_item").removeClass('cnb_type_selector_active');
317
+ jQuery(this).addClass("cnb_type_selector_active");
318
+ var cnbType = jQuery(this).attr("data-cnb-selection");
319
+ jQuery('#cnb_type').val(cnbType);
320
+ });
321
+ }
322
+
323
+ /**
324
+ * function for the currency selector on the Upgrade page
325
+ */
326
+ function cnb_domain_upgrade_currency() {
327
+ jQuery(".cnb-currency-select").click(function(){
328
+ jQuery(".cnb-currency-select").removeClass('nav-tab-active');
329
+ jQuery(".currency-box").removeClass('currency-box-active');
330
+ jQuery(this).addClass("nav-tab-active");
331
+ var currencyType = jQuery(this).attr("data-cnb-currency");
332
+ var currencySelector = 'currency-box-' + currencyType;
333
+ jQuery('.' + currencySelector).addClass('currency-box-active');
334
+ });
335
+ }
336
+
337
+
338
+ /**
339
+ * Request a Stripe Checkout Session ID for a given domain and a selected plan
340
+ *
341
+ * Used on the Domain upgrade page.
342
+ * @param planId
343
+ */
344
+ function cnb_get_checkout(planId) {
345
+ const data = {
346
+ 'action': 'cnb_get_checkout',
347
+ 'planId': planId,
348
+ 'domainId': jQuery('#cnb_domain_id').val()
349
+ };
350
+ const cnb_notice = jQuery('.cnb-message');
351
+
352
+ cnb_notice.hide();
353
+ jQuery('.cnb-error-message').text('Processing your request, please wait...');
354
+ cnb_notice.addClass('notice notice-success');
355
+ cnb_notice.removeClass('notice-warning');
356
+ cnb_notice.show();
357
+
358
+ console.log(cnb_notice);
359
+
360
+ jQuery.post(ajaxurl, data, function(response) {
361
+ cnb_goto_checkout(response)
362
+ });
363
+ }
364
+
365
+ /**
366
+ * The callback function once an API response for a Stripe Checkout Session ID is received.
367
+ * @param response
368
+ */
369
+ function cnb_goto_checkout(response) {
370
+ const cnb_notice = jQuery('.cnb-message');
371
+
372
+ if (response.status === 'success') {
373
+ jQuery('.cnb-error-message').text('Redirecting you...');
374
+ cnb_notice.addClass('notice notice-success');
375
+ cnb_notice.removeClass('notice-warning');
376
+ cnb_notice.show();
377
+
378
+ stripe.redirectToCheckout({sessionId: response.message});
379
+ }
380
+ if (response.status === 'error') {
381
+ jQuery('.cnb-error-message').text(response.message);
382
+ cnb_notice.addClass('notice notice-warning');
383
+ cnb_notice.removeClass('notice-success');
384
+ cnb_notice.show();
385
+ }
386
+ }
387
+
388
  jQuery( document ).ready(function() {
389
  cnb_setup_colors();
390
  cnb_setup_sliders();
403
  if (typeof show_advanced_view_only_set !== 'undefined' && show_advanced_view_only_set && show_advanced_view_only_set === 1) {
404
  show_advanced_view_only()
405
  }
406
+
407
+ cnb_delete_action();
408
+ cnb_button_overview_modal();
409
+ cnb_domain_upgrade_currency();
410
+ });
resources/js/dismiss.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Admin code for dismissing notifications.
3
+ *
4
+ */
5
+ (function( $ ) {
6
+ 'use strict';
7
+ $( function() {
8
+ const plugin_slug = 'call-now-button';
9
+ $( '.notice-' + plugin_slug ).on( 'click', '.notice-dismiss', function( event, el ) {
10
+ const $notice = $(this).parent('.notice.is-dismissible');
11
+ const dismiss_url = $notice.attr('data-dismiss-url');
12
+ if ( dismiss_url ) {
13
+ $.get( dismiss_url );
14
+ }
15
+ });
16
+ } );
17
+ })( jQuery );
resources/style/call-now-button.css CHANGED
@@ -113,6 +113,11 @@ table.form-table.nav-tab-active,
113
  .notice table.form-table {
114
  display: initial;
115
  }
 
 
 
 
 
116
  #TB_window .cnb-button-name-field,
117
  .cnb-button-name-field.nav-tab-active {
118
  display: block;
@@ -246,3 +251,66 @@ input[type='range'] {
246
  .cnb-version {
247
  font-weight: 200;
248
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  .notice table.form-table {
114
  display: initial;
115
  }
116
+ .notice > form {
117
+ margin: .5em 0;
118
+ padding: 2px;
119
+ }
120
+
121
  #TB_window .cnb-button-name-field,
122
  .cnb-button-name-field.nav-tab-active {
123
  display: block;
251
  .cnb-version {
252
  font-weight: 200;
253
  }
254
+ .cnb_type_selector .cnb_type_selector_item {
255
+ transition: all 0.5s;
256
+ opacity: 0.3;
257
+ filter: grayscale(1);
258
+ cursor: pointer;
259
+ }
260
+ .cnb_type_selector .cnb_type_selector_active {
261
+ opacity: 1;
262
+ filter: grayscale(0);
263
+ }
264
+ .cnb-flexbox {
265
+ display: flex;
266
+ justify-content:center;
267
+ }
268
+ .cnb-flexbox > * {
269
+ flex: 1 1 0px;
270
+ }
271
+ /* Pricing page */
272
+ .cnb-price-plans {
273
+ max-width:1000px;
274
+ margin: 0 auto 50px;
275
+ }
276
+ .cnb-price-plans .pricebox {
277
+ text-align:center;
278
+ padding:10px;
279
+ margin:10px;
280
+ }
281
+ .cnb-price-plans .pricebox h3 {
282
+ border-bottom:2px solid #ccc;
283
+ margin-bottom:0.5em;
284
+ padding-bottom:0.5em
285
+ }
286
+ .cnb-price-plans .pricebox .benefit {
287
+ padding-bottom: 1em;
288
+ }
289
+ .cnb-price-plans .pricebox h3.yearly {
290
+ border-bottom:2px solid #2271b1;
291
+ }
292
+ .cnb-price-plans .plan-amount {
293
+ margin:20px 0;
294
+ font-weight:700;
295
+ }
296
+ .cnb-price-plans .euros {
297
+ font-size:4em;
298
+ }
299
+ .cnb-price-plans .billingprice,
300
+ .cnb-price-plans .timeframe {
301
+ margin: 20px 0;
302
+ color:#999;
303
+ font-size:80%;
304
+ font-weight: normal;
305
+ }
306
+ .cnb-price-plans .currency {
307
+ font-size:150%;
308
+ color:#444;
309
+ font-weight: normal;
310
+ }
311
+ .cnb-price-plans .currency-box {
312
+ display:none;
313
+ }
314
+ .cnb-price-plans .currency-box.currency-box-active {
315
+ display: flex;
316
+ }
src/admin/action-edit.php CHANGED
@@ -5,6 +5,7 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
8
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
9
  require_once dirname( __FILE__ ) . '/button-edit.php';
10
 
@@ -130,7 +131,7 @@ function cnb_admin_page_action_create_process() {
130
  }
131
 
132
  /**
133
- * @param $action
134
  *
135
  * @return array
136
  */
@@ -241,11 +242,11 @@ function cnb_action_edit_create_tab_url($button, $tab) {
241
  }
242
 
243
  /**
244
- * @param $action
245
- * @param object? $button
246
- * @param bool $show_table
247
  */
248
- function cnb_render_form($action, $button=null, $show_table=true) {
249
  /**
250
  * @global WP_Locale $wp_locale WordPress date and time locale object.
251
  */
@@ -282,7 +283,7 @@ function cnb_render_form($action, $button=null, $show_table=true) {
282
  <td></td>
283
  </tr>
284
  <tr class="cnb_hide_on_modal">
285
- <th scope="row"><label for="cnb_action_type">Button type:</label></th>
286
  <td>
287
  <select id="cnb_action_type" name="actions[<?php esc_attr_e($action->id) ?>][actionType]">
288
  <?php foreach (cnb_get_action_types() as $action_type_key => $action_type_value) { ?>
@@ -296,7 +297,7 @@ function cnb_render_form($action, $button=null, $show_table=true) {
296
  <th scope="row">
297
  <label for="cnb_action_value_input">
298
  <span id="cnb_action_value">Action value</span>
299
- </label>:
300
  <a href="<?php echo CNB_SUPPORT; ?>phone-number/<?php cnb_utm_params("question-mark", "phone-number"); ?>"
301
  target="_blank" class="cnb-nounderscore">
302
  <span class="dashicons dashicons-editor-help"></span>
@@ -317,7 +318,7 @@ function cnb_render_form($action, $button=null, $show_table=true) {
317
  </td>
318
  </tr>
319
  <tr class="button-text cnb_hide_on_modal">
320
- <th scope="row"><label for="buttonTextField">Button label:</label><a
321
  href="<?php echo CNB_SUPPORT; ?>using-text-buttons/<?php cnb_utm_params("question-mark", "using-text-buttons"); ?>"
322
  target="_blank" class="cnb-nounderscore">
323
  <span class="dashicons dashicons-editor-help"></span>
@@ -428,7 +429,7 @@ function cnb_render_form($action, $button=null, $show_table=true) {
428
  <input id="actions_schedule_show_always" name="actions[<?php esc_attr_e($action->id) ?>][schedule][showAlways]" type="hidden" value="true" />
429
  <label title="Show always" for="actions_schedule_show_always">Show always.
430
  <?php
431
- if ($button->domain->type !== 'PROPLUS') {
432
  echo '<a href="' . $upgrade_url . '">Upgrade!</a>';
433
  }
434
  ?>
@@ -464,13 +465,16 @@ function cnb_render_form($action, $button=null, $show_table=true) {
464
  <th><label for="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]">Timezone</label></th>
465
  <td>
466
  <select name="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]" id="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]">
467
- <?php if (isset($action->schedule)) { echo wp_timezone_choice($action->schedule->timezone); } ?>
 
 
 
468
  </select>
469
  <p class="description" id="domain_timezone-description">
470
- <?php if (empty($action->schedule->timezone)) { ?>
471
  Please select your timezone.
472
  <?php } else { ?>
473
- Currently set to <code><?php esc_html_e($action->schedule->timezone)?></code>.
474
  <?php } ?>
475
  </p>
476
  </td>
@@ -490,6 +494,11 @@ function cnb_render_form($action, $button=null, $show_table=true) {
490
  <?php
491
  }
492
 
 
 
 
 
 
493
  function cnb_admin_page_action_edit_render_main($action, $button, $show_table=true) {
494
  $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
495
  // Set some sane defaults
@@ -510,17 +519,12 @@ function cnb_admin_page_action_edit_render_main($action, $button, $show_table=tr
510
  <input type="hidden" name="action_id" value="<?php echo $action->id ?>" />
511
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('cnb-action-edit')?>" />
512
  <?php
513
- cnb_render_form($action, $button, $show_table);
514
  }
515
 
516
  function cnb_admin_page_action_edit_render() {
517
- global $cnb_options, $cnb_settings;
518
-
519
- $cnb_notices = cnb_get_notices();
520
- $cnb_changelog = cnb_get_changelog();
521
-
522
  $action_id = cnb_get_button_id();
523
- $action = new stdClass();
524
  $action->id = 'new';
525
  $action->actionType = 'PHONE';
526
  $action->actionValue = null;
@@ -530,15 +534,15 @@ function cnb_admin_page_action_edit_render() {
530
  $action = CnbAppRemote::cnb_remote_get_action( $action_id );
531
  }
532
 
 
 
 
 
533
  $button = null;
534
  $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
535
  if ($bid !== null) {
536
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
537
 
538
- add_action('cnb_header', function() use($button) {
539
- cnb_add_header_button_edit($button);
540
- });
541
-
542
  // Create back link
543
  $url = admin_url('admin.php');
544
  $redirect_link = esc_url(
@@ -550,15 +554,9 @@ function cnb_admin_page_action_edit_render() {
550
  $url ));
551
 
552
  $action_verb = $action->id === 'new' ? 'adding' : 'editing';
553
- $cnb_notice = '<div class="notice notice-info">
554
- <p><strong>You are '.$action_verb.' an Action</strong>. Click <a href="'.$redirect_link.'">here</a> to go back to editing the button.</p></div>';
555
-
556
- $cnb_notices[] = $cnb_notice;
557
-
558
- } else {
559
- add_action('cnb_header', function() use($action) {
560
- cnb_add_header_action_edit($action);
561
- });
562
  }
563
 
564
  $url = admin_url('admin-post.php');
@@ -570,9 +568,8 @@ function cnb_admin_page_action_edit_render() {
570
  $form_action
571
  );
572
 
 
573
  ?>
574
- <div class="wrap">
575
- <?php cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog); ?>
576
 
577
  <?php if ($bid !== null) { ?>
578
  <h2 class="nav-tab-wrapper">
@@ -592,6 +589,5 @@ function cnb_admin_page_action_edit_render() {
592
  submit_button();
593
  ?>
594
  </form>
595
- <?php cnb_admin_footer();
596
- echo '</div>';
597
  }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/models/CnbAction.class.php';
9
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
10
  require_once dirname( __FILE__ ) . '/button-edit.php';
11
 
131
  }
132
 
133
  /**
134
+ * @param $action CnbAction
135
  *
136
  * @return array
137
  */
242
  }
243
 
244
  /**
245
+ * @param $action CnbAction
246
+ * @param $button CnbButton
247
+ * @param $show_table boolean
248
  */
249
+ function cnb_render_form_action($action, $button=null, $show_table=true) {
250
  /**
251
  * @global WP_Locale $wp_locale WordPress date and time locale object.
252
  */
283
  <td></td>
284
  </tr>
285
  <tr class="cnb_hide_on_modal">
286
+ <th scope="row"><label for="cnb_action_type">Button type</label></th>
287
  <td>
288
  <select id="cnb_action_type" name="actions[<?php esc_attr_e($action->id) ?>][actionType]">
289
  <?php foreach (cnb_get_action_types() as $action_type_key => $action_type_value) { ?>
297
  <th scope="row">
298
  <label for="cnb_action_value_input">
299
  <span id="cnb_action_value">Action value</span>
300
+ </label>
301
  <a href="<?php echo CNB_SUPPORT; ?>phone-number/<?php cnb_utm_params("question-mark", "phone-number"); ?>"
302
  target="_blank" class="cnb-nounderscore">
303
  <span class="dashicons dashicons-editor-help"></span>
318
  </td>
319
  </tr>
320
  <tr class="button-text cnb_hide_on_modal">
321
+ <th scope="row"><label for="buttonTextField">Button label</label><a
322
  href="<?php echo CNB_SUPPORT; ?>using-text-buttons/<?php cnb_utm_params("question-mark", "using-text-buttons"); ?>"
323
  target="_blank" class="cnb-nounderscore">
324
  <span class="dashicons dashicons-editor-help"></span>
429
  <input id="actions_schedule_show_always" name="actions[<?php esc_attr_e($action->id) ?>][schedule][showAlways]" type="hidden" value="true" />
430
  <label title="Show always" for="actions_schedule_show_always">Show always.
431
  <?php
432
+ if ($button->domain->type !== 'PRO') {
433
  echo '<a href="' . $upgrade_url . '">Upgrade!</a>';
434
  }
435
  ?>
465
  <th><label for="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]">Timezone</label></th>
466
  <td>
467
  <select name="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]" id="actions[<?php esc_attr_e($action->id) ?>][schedule][timezone]">
468
+ <?php
469
+ $timezone = (isset($action->schedule) && isset($action->schedule->timezone)) ? $action->schedule->timezone : null;
470
+ echo wp_timezone_choice($timezone);
471
+ ?>
472
  </select>
473
  <p class="description" id="domain_timezone-description">
474
+ <?php if (empty($timezone)) { ?>
475
  Please select your timezone.
476
  <?php } else { ?>
477
+ Currently set to <code><?php esc_html_e($timezone)?></code>.
478
  <?php } ?>
479
  </p>
480
  </td>
494
  <?php
495
  }
496
 
497
+ /**
498
+ * @param $action CnbAction
499
+ * @param $button CnbButton
500
+ * @param $show_table boolean
501
+ */
502
  function cnb_admin_page_action_edit_render_main($action, $button, $show_table=true) {
503
  $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
504
  // Set some sane defaults
519
  <input type="hidden" name="action_id" value="<?php echo $action->id ?>" />
520
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('cnb-action-edit')?>" />
521
  <?php
522
+ cnb_render_form_action($action, $button, $show_table);
523
  }
524
 
525
  function cnb_admin_page_action_edit_render() {
 
 
 
 
 
526
  $action_id = cnb_get_button_id();
527
+ $action = new CnbAction();
528
  $action->id = 'new';
529
  $action->actionType = 'PHONE';
530
  $action->actionValue = null;
534
  $action = CnbAppRemote::cnb_remote_get_action( $action_id );
535
  }
536
 
537
+ add_action('cnb_header_name', function() use($action) {
538
+ cnb_add_header_action_edit($action);
539
+ });
540
+
541
  $button = null;
542
  $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
543
  if ($bid !== null) {
544
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
545
 
 
 
 
 
546
  // Create back link
547
  $url = admin_url('admin.php');
548
  $redirect_link = esc_url(
554
  $url ));
555
 
556
  $action_verb = $action->id === 'new' ? 'adding' : 'editing';
557
+ $mesage = '<strong>You are '.$action_verb.' an Action</strong>.
558
+ Click <a href="'.$redirect_link.'">here</a> to go back to continue configuring the Button.';
559
+ CnbAdminNotices::get_instance()->renderInfo($mesage);
 
 
 
 
 
 
560
  }
561
 
562
  $url = admin_url('admin-post.php');
568
  $form_action
569
  );
570
 
571
+ do_action('cnb_header');
572
  ?>
 
 
573
 
574
  <?php if ($bid !== null) { ?>
575
  <h2 class="nav-tab-wrapper">
589
  submit_button();
590
  ?>
591
  </form>
592
+ <?php do_action('cnb_footer');
 
593
  }
src/admin/action-overview.php CHANGED
@@ -5,6 +5,7 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
8
 
9
  if(!class_exists('WP_List_Table')) {
10
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
@@ -14,6 +15,28 @@ function cnb_add_header_action_overview() {
14
  echo 'Actions ';
15
  }
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  class Cnb_Action_List_Table extends WP_List_Table {
18
 
19
  /**
@@ -27,7 +50,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
27
  /**
28
  * Constructor, we override the parent to pass our own arguments
29
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
30
- * @param array $args (show contain at least a single key called 'button')
31
  */
32
  function __construct( $args = array() ) {
33
  if (isset($args['button'])) {
@@ -37,7 +60,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
37
  parent::__construct(array(
38
  'singular' => 'cnb_list_action', //Singular label
39
  'plural' => 'cnb_list_actions', //plural label, also this well be one of the table css class
40
- 'ajax' => false //We won't support Ajax for this table
41
  ));
42
  }
43
 
@@ -192,7 +215,8 @@ class Cnb_Action_List_Table extends WP_List_Table {
192
  * Custom action for `cb` columns (checkboxes)
193
  *
194
  * @param array|object $item
195
- * @return string|void
 
196
  */
197
  function column_cb($item) {
198
  return sprintf(
@@ -207,6 +231,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
207
  $bid = $this->button !== null ? $this->button->id : null;
208
  $tab = $this->button !== null ? 'actions' : null;
209
 
 
210
  // Let's build a link
211
  $url = admin_url('admin.php');
212
  $edit_link =
@@ -219,26 +244,38 @@ class Cnb_Action_List_Table extends WP_List_Table {
219
  'tab' => $tab),
220
  $url );
221
  $edit_url = esc_url( $edit_link );
222
- $actions = array(
223
- 'edit' => '<a href="'.$edit_url.'">Edit</a>',
224
- );
225
 
226
- $delete_link = wp_nonce_url(
227
- add_query_arg( array(
228
- 'page' => 'call-now-button-actions',
229
- 'action' => 'delete',
 
230
  'id' => $item['id'],
231
- 'bid' => $bid ),
232
- $url ),
233
- 'cnb_delete_action' );
234
- $delete_url = esc_url( $delete_link );
235
- $actions['delete'] = '<a href="'.$delete_url.'">Delete</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
  $actionTypes = cnb_get_action_types();
238
  $value = !empty($item[$column_name]) ? esc_html($actionTypes[$item[$column_name]]) : '<em>No value</em>';
239
  return sprintf(
240
  '%1$s %2$s',
241
- '<a href="'.$edit_url.'">'.$value . '</a>',
242
  $this->row_actions($actions)
243
  );
244
  }
@@ -264,33 +301,83 @@ class Cnb_Action_List_Table extends WP_List_Table {
264
  $action = array('id' => $actionId);
265
  CnbAppRemote::cnb_remote_delete_action( $action );
266
  }
267
- echo '<div class="notice-success notice"><p>' . count($actionIds) . ' Action(s) deleted</p></div>';
268
  break;
269
  }
270
  }
271
  }
272
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  }
274
 
275
- function cnb_action_after_header() {
276
- // Only add the "Add new" action in the overview part
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
278
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
279
- $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
280
- if ($id === null || ($action != 'new' && $action != 'edit')) {
 
 
 
 
281
  // Create link
282
  $url = admin_url('admin.php');
283
  $new_link =
284
  add_query_arg(
285
  array(
286
- 'page' => 'call-now-button-actions',
287
- 'action' => 'new',
288
- 'id' => 'new',
289
- 'bid' => $bid),
290
  $url);
291
- $new_url = esc_url($new_link);
292
 
293
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
 
 
 
 
 
 
 
294
  }
295
  }
296
 
@@ -299,113 +386,59 @@ function cnb_action_after_header() {
299
  */
300
  function cnb_admin_page_action_overview_render() {
301
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
302
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
303
  if ($id === null) {
304
  cnb_admin_page_action_overview_render_list();
305
- } else {
306
- switch ($action) {
307
- case 'new':
308
- case 'edit':
309
- require_once dirname( __FILE__ ) . '/action-edit.php';
310
- cnb_admin_page_action_edit_render();
311
- break;
312
- case 'delete':
313
- if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
314
- $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
315
- $action = 'cnb_delete_action';
316
-
317
- if (wp_verify_nonce($nonce, $action)) {
318
- $cnb_cloud_notifications = array();
319
- // If a button is set, remove this ID from the actions array
320
- $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
321
- if ($bid !== null) {
322
- // Get the button
323
- $button = CnbAppRemote::cnb_remote_get_button( $bid );
324
-
325
- // Remove the current Action
326
- $pos = array_search($id, $button->actions);
327
- unset($button->actions[$pos]);
328
-
329
- // Convert to array and update
330
- $button_array = json_decode(json_encode($button), true);
331
- CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button_array );
332
- }
333
-
334
- CnbAdminCloud::cnb_delete_action( $cnb_cloud_notifications, $id );
335
 
336
- foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
337
- echo $cnb_cloud_notification;
338
- }
339
- if ($bid !== null) {
340
- // Create link
341
- // Create link
342
- $url = admin_url('admin.php');
343
- $new_link =
344
- add_query_arg(
345
- array(
346
- 'page' => 'call-now-button',
347
- 'action' => 'edit',
348
- 'id' => $bid,
349
- ),
350
- $url);
351
- $new_url = esc_url_raw($new_link);
352
- echo '<div class="notice-success notice"><p>';
353
- echo '<p>You will be redirected back to the Button overview in 5 seconds...</p><p>Or click here to go immediately: <a href="'.$new_url.'">'.$new_url.'</a></p>';
354
- echo '<script type="text/javascript">setTimeout(function(){location.href="' . $new_url .'"} , 5000); </script>';
355
- echo '</p></div>';
356
- } else {
357
- cnb_admin_page_action_overview_render_list();
358
- }
359
- }
360
- }
361
- break;
362
- }
363
  }
364
  }
365
 
366
- function cnb_admin_page_action_overview_bid(&$cnb_notices) {
367
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
368
- $args = array();
369
- $button = null;
370
  if ($bid !== null) {
371
- $button = CnbAppRemote::cnb_remote_get_button( $bid );
372
- }
373
 
374
- if ($button && !($button instanceof WP_Error)) {
375
- $args['button'] = $button;
376
- $cnb_notices[] = '<div class="notice notice-info"><p>Only actions for Button ID <code>'.esc_html($button->id).'</code> (<strong>'.esc_html($button->name).'</strong>) are shown</p></div>';
 
377
  }
378
- return $args;
379
  }
380
- function cnb_admin_page_action_overview_render_list() {
381
- global $cnb_options, $cnb_settings;
382
 
383
- add_action('cnb_header', 'cnb_add_header_action_overview');
384
-
385
- $cnb_notices = cnb_get_notices();
386
- $cnb_changelog = cnb_get_changelog();
387
 
388
- $args = cnb_admin_page_action_overview_bid($cnb_notices);
389
  //Prepare Table of elements
390
  $wp_list_table = new Cnb_Action_List_Table($args);
391
  $data = $wp_list_table->prepare_items();
392
 
393
  if ($data instanceof WP_Error) {
394
- $cnb_notices[] = cnb_admin_header_get_cloud_error($data);
395
  } else {
396
  add_action('cnb_after_header', 'cnb_action_after_header');
397
  }
398
 
399
- echo '<div class="wrap">';
400
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
401
 
402
  echo '<form id="wp_list_event" method="post">';
403
 
404
  //Table of elements
405
  $wp_list_table->display();
406
  echo '</form>';
407
- cnb_admin_footer();
408
- echo '</div>';
409
  }
410
 
411
  /**
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/action-edit.php';
9
 
10
  if(!class_exists('WP_List_Table')) {
11
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
15
  echo 'Actions ';
16
  }
17
 
18
+ function cnb_action_after_header() {
19
+ // Only add the "Add new" action in the overview part
20
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
21
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
22
+ $bid = !empty($_GET["bid"]) ? sanitize_text_field($_GET["bid"]) : null;
23
+ if ($id === null || ($action != 'new' && $action != 'edit')) {
24
+ // Create link
25
+ $url = admin_url('admin.php');
26
+ $new_link =
27
+ add_query_arg(
28
+ array(
29
+ 'page' => 'call-now-button-actions',
30
+ 'action' => 'new',
31
+ 'id' => 'new',
32
+ 'bid' => $bid),
33
+ $url);
34
+ $new_url = esc_url($new_link);
35
+
36
+ echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
37
+ }
38
+ }
39
+
40
  class Cnb_Action_List_Table extends WP_List_Table {
41
 
42
  /**
50
  /**
51
  * Constructor, we override the parent to pass our own arguments
52
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
53
+ * @param $args array (can contain at least a single key called 'button')
54
  */
55
  function __construct( $args = array() ) {
56
  if (isset($args['button'])) {
60
  parent::__construct(array(
61
  'singular' => 'cnb_list_action', //Singular label
62
  'plural' => 'cnb_list_actions', //plural label, also this well be one of the table css class
63
+ 'ajax' => true // We support it, see _js_vars()
64
  ));
65
  }
66
 
215
  * Custom action for `cb` columns (checkboxes)
216
  *
217
  * @param array|object $item
218
+ *
219
+ * @return string
220
  */
221
  function column_cb($item) {
222
  return sprintf(
231
  $bid = $this->button !== null ? $this->button->id : null;
232
  $tab = $this->button !== null ? 'actions' : null;
233
 
234
+ $actions = array();
235
  // Let's build a link
236
  $url = admin_url('admin.php');
237
  $edit_link =
244
  'tab' => $tab),
245
  $url );
246
  $edit_url = esc_url( $edit_link );
247
+ $actions['edit'] = '<a href="'.$edit_url.'">Edit</a>';
 
 
248
 
249
+ if ($this->button) {
250
+ $nonce = wp_create_nonce('cnb_delete_action');
251
+ $screen = get_current_screen();
252
+ $args = array(
253
+ 'action' => 'cnb_delete_action',
254
  'id' => $item['id'],
255
+ 'bid' => $bid,
256
+ '_wpnonce' => $nonce,
257
+ 'refer' => $screen->parent_file
258
+ );
259
+ $delete_url = esc_url(add_query_arg($args, admin_url('admin-ajax.php')));
260
+ $actions['delete'] = '<a data-ajax="true" data-id="' . $item['id'] . '" data-bid="' . $bid . '" data-wpnonce="' . $nonce . '" href="' . $delete_url . '">Delete</a>';
261
+ } else {
262
+ $delete_link = wp_nonce_url(
263
+ add_query_arg(array(
264
+ 'page' => 'call-now-button-actions',
265
+ 'action' => 'delete',
266
+ 'id' => $item['id'],
267
+ 'bid' => $bid),
268
+ $url),
269
+ 'cnb_delete_action');
270
+ $delete_url = esc_url($delete_link);
271
+ $actions['delete'] = '<a href="' . $delete_url . '">Delete</a>';
272
+ }
273
 
274
  $actionTypes = cnb_get_action_types();
275
  $value = !empty($item[$column_name]) ? esc_html($actionTypes[$item[$column_name]]) : '<em>No value</em>';
276
  return sprintf(
277
  '%1$s %2$s',
278
+ '<strong><a class="row-title" href="'.$edit_url.'">'.$value . '</a></strong>',
279
  $this->row_actions($actions)
280
  );
281
  }
301
  $action = array('id' => $actionId);
302
  CnbAppRemote::cnb_remote_delete_action( $action );
303
  }
304
+ CnbAdminNotices::get_instance()->renderSuccess(count($actionIds) . ' Action(s) deleted.');
305
  break;
306
  }
307
  }
308
  }
309
  }
310
+
311
+ public function _js_vars() {
312
+ $args = array(
313
+ 'class' => get_class( $this ),
314
+ 'screen' => array(
315
+ 'id' => $this->screen->id,
316
+ 'base' => $this->screen->base,
317
+ ),
318
+ 'button' => $this->button,
319
+ 'data' => $this->get_data(),
320
+ );
321
+
322
+ printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
323
+ }
324
+
325
+ function no_items() {
326
+ _e( 'No actions found.' );
327
+ }
328
  }
329
 
330
+ function cnb_delete_action_real($action_id, $button_id = null, &$cnb_cloud_notifications = array()) {
331
+ if (cnb_check_ajax_referer('cnb_delete_action')) {
332
+ // If a button is set, remove this ID from the actions array
333
+ if ($button_id !== null) {
334
+ // Get the button
335
+ $button = CnbAppRemote::cnb_remote_get_button($button_id);
336
+
337
+ // Remove the current Action
338
+ $pos = array_search($action_id, $button->actions);
339
+ unset($button->actions[$pos]);
340
+
341
+ // Convert to array and update
342
+ $button_array = json_decode(json_encode($button), true);
343
+ CnbAdminCloud::cnb_update_button($cnb_cloud_notifications, $button_array);
344
+ }
345
+
346
+ return CnbAdminCloud::cnb_delete_action($cnb_cloud_notifications, $action_id);
347
+ }
348
+ return false;
349
+ }
350
+
351
+ function cnb_delete_action() {
352
+ // Action ID
353
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
354
+ $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
355
+
356
+ $cnb_cloud_notifications = array();
357
+ cnb_delete_action_real($id, $bid, $cnb_cloud_notifications);
358
+
359
+ $adminNotices = CnbAdminNotices::get_instance();
360
+ if ($bid !== null) {
361
  // Create link
362
  $url = admin_url('admin.php');
363
  $new_link =
364
  add_query_arg(
365
  array(
366
+ 'page' => 'call-now-button',
367
+ 'action' => 'edit',
368
+ 'id' => $bid,
369
+ ),
370
  $url);
371
+ $new_url = esc_url_raw($new_link);
372
 
373
+ $message = '<p>You will be redirected back to the Button overview in 1 second...</p><p>Or click here to go back immediately: <a href="'.$new_url.'">'.$new_url.'</a></p>';
374
+ $message .= '<script type="text/javascript">setTimeout(function(){location.href="' . $new_url .'"} , 1000); </script>';
375
+ $notice = new CnbNotice('success', $message);
376
+ CnbAdminNotices::get_instance()->renderNotice($notice);
377
+ } else {
378
+ foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
379
+ $adminNotices->renderNotice($cnb_cloud_notification);
380
+ }
381
  }
382
  }
383
 
386
  */
387
  function cnb_admin_page_action_overview_render() {
388
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
 
389
  if ($id === null) {
390
  cnb_admin_page_action_overview_render_list();
391
+ return;
392
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
 
394
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
395
+ switch ($action) {
396
+ case 'new':
397
+ case 'edit':
398
+ cnb_admin_page_action_edit_render();
399
+ break;
400
+ case 'delete':
401
+ cnb_delete_action();
402
+ cnb_admin_page_action_overview_render_list();
403
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  }
405
  }
406
 
407
+ function cnb_admin_page_action_overview_bid() {
408
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
 
 
409
  if ($bid !== null) {
410
+ $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
 
411
 
412
+ if ( $button && ! ( $button instanceof WP_Error ) ) {
413
+ CnbAdminNotices::get_instance()->renderInfo( 'Only actions for Button ID <code>' . esc_html( $button->id ) . '</code> (<strong>' . esc_html( $button->name ) . '</strong>) are shown.' );
414
+ return array( 'button' => $button );
415
+ }
416
  }
417
+ return array();
418
  }
 
 
419
 
420
+ function cnb_admin_page_action_overview_render_list() {
421
+ add_action('cnb_header_name', 'cnb_add_header_action_overview');
 
 
422
 
423
+ $args = cnb_admin_page_action_overview_bid();
424
  //Prepare Table of elements
425
  $wp_list_table = new Cnb_Action_List_Table($args);
426
  $data = $wp_list_table->prepare_items();
427
 
428
  if ($data instanceof WP_Error) {
429
+ cnb_api_key_invalid_notice($data);
430
  } else {
431
  add_action('cnb_after_header', 'cnb_action_after_header');
432
  }
433
 
434
+ do_action('cnb_header');
 
435
 
436
  echo '<form id="wp_list_event" method="post">';
437
 
438
  //Table of elements
439
  $wp_list_table->display();
440
  echo '</form>';
441
+ do_action('cnb_footer');
 
442
  }
443
 
444
  /**
src/admin/admin-ajax.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  require_once dirname( __FILE__ ) . '/api/CnbAppRemotePayment.php';
3
  require_once dirname( __FILE__ ) . '/api/CnbAppRemote.php';
 
4
 
5
  // part of domain-upgrade
6
  function cnb_admin_page_domain_upgrade_get_checkout($arg) {
@@ -18,12 +19,46 @@ function cnb_admin_page_domain_upgrade_get_checkout($arg) {
18
  $url );
19
  $callbackUri = esc_url_raw( $redirect_link );
20
  $checkoutSession = CnbAppRemotePayment::cnb_remote_post_subscription( $planId, $domainId, $callbackUri );
21
- if ($checkoutSession instanceof WP_Error) {
22
- return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  } else {
24
  // Get link based on Stripe checkoutSessionId
25
- esc_html_e($checkoutSession->checkoutSessionId);
 
 
 
26
  }
27
  wp_die();
28
  }
29
  add_action( 'wp_ajax_cnb_get_checkout', 'cnb_admin_page_domain_upgrade_get_checkout' );
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  require_once dirname( __FILE__ ) . '/api/CnbAppRemotePayment.php';
3
  require_once dirname( __FILE__ ) . '/api/CnbAppRemote.php';
4
+ require_once dirname( __FILE__ ) . '/action-overview.php';
5
 
6
  // part of domain-upgrade
7
  function cnb_admin_page_domain_upgrade_get_checkout($arg) {
19
  $url );
20
  $callbackUri = esc_url_raw( $redirect_link );
21
  $checkoutSession = CnbAppRemotePayment::cnb_remote_post_subscription( $planId, $domainId, $callbackUri );
22
+
23
+ if (is_wp_error($checkoutSession)) {
24
+ $custom_message_data = $checkoutSession->get_error_data('CNB_ERROR');
25
+ if (!empty($custom_message_data)) {
26
+ $custom_message_obj = json_decode( $custom_message_data );
27
+ $message = $custom_message_obj->message;
28
+ // Strip "request_id"
29
+ if (stripos($message, '; request-id') !== 0) {
30
+ $message = preg_replace('/; request-id.*/i', '', $message);
31
+ }
32
+ // Replace "customer" with "domain"
33
+ $message = str_replace('customer', 'domain', $message);
34
+ wp_send_json( array(
35
+ 'status' => 'error',
36
+ 'message' => $message
37
+ ) );
38
+ } else {
39
+ wp_send_json( array(
40
+ 'status' => 'error',
41
+ 'message' => $checkoutSession->get_error_message()
42
+ ) );
43
+ }
44
  } else {
45
  // Get link based on Stripe checkoutSessionId
46
+ wp_send_json( array(
47
+ 'status' => 'success',
48
+ 'message' => $checkoutSession->checkoutSessionId
49
+ ) );
50
  }
51
  wp_die();
52
  }
53
  add_action( 'wp_ajax_cnb_get_checkout', 'cnb_admin_page_domain_upgrade_get_checkout' );
54
+
55
+ function cnb_admin_button_delete_actions() {
56
+ // Action ID
57
+ $action_id = !empty($_REQUEST['id']) ? sanitize_text_field($_REQUEST['id']) : null;
58
+ $button_id = !empty($_REQUEST['bid']) ? sanitize_text_field($_REQUEST['bid']) : null;
59
+
60
+ $result = cnb_delete_action_real($action_id, $button_id);
61
+ wp_send_json($result);
62
+ }
63
+
64
+ add_action( 'wp_ajax_cnb_delete_action', 'cnb_admin_button_delete_actions' );
src/admin/api/CnbAdminCloud.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  class CnbAdminCloud {
4
 
5
  /**
@@ -12,25 +14,24 @@ class CnbAdminCloud {
12
  * @return string The ID to use for the Cloud Button
13
  */
14
  public static function cnb_set_default_option_for_cloud( $options ) {
15
- global $cnb_options;
16
- if ( isset( $cnb_options['cloud_use_id'] ) && ! empty( $cnb_options['cloud_use_id'] ) ) {
17
- return $cnb_options['cloud_use_id'];
18
- }
19
- if ( ! isset( $cnb_options['api_key'] ) || empty( $cnb_options['api_key'] ) ) {
20
- $cnb_options['api_key'] = $options['api_key'];
21
  }
 
 
22
  $user_info = CnbAppRemote::cnb_remote_get_user_info();
23
- if ( $user_info instanceof WP_Error ) {
24
- return '';
25
  }
26
 
27
- return $user_info->id;
28
  }
29
 
30
  /**
31
- * @param $button
32
- * @param array $actions Should ONLY contain Ids, not full objects
33
- * @param array $conditions
34
  *
35
  * @return array
36
  */
@@ -89,11 +90,10 @@ class CnbAdminCloud {
89
  $result = CnbAppRemote::cnb_remote_update_wp_button( $button, $actions, $conditions );
90
  if ( $result instanceof WP_Error ) {
91
  $message = self::cnb_admin_get_error_message( 'update', 'button', $result );
92
- array_push( $cnb_cloud_notifications, $message );
93
  } else {
94
- $message = self::cnb_admin_get_success_message( 'updated', 'button', $result->id );
95
- array_push( $cnb_cloud_notifications, $message );
96
  }
 
97
 
98
  return $result;
99
  }
@@ -102,11 +102,10 @@ class CnbAdminCloud {
102
  $result = CnbAppRemote::cnb_remote_update_button( $button );
103
  if ( $result instanceof WP_Error ) {
104
  $message = self::cnb_admin_get_error_message( 'update', 'button', $result );
105
- array_push( $cnb_cloud_notifications, $message );
106
  } else {
107
- $message = self::cnb_admin_get_success_message( 'updated', 'button', $result->id );
108
- array_push( $cnb_cloud_notifications, $message );
109
  }
 
110
 
111
  return $result;
112
  }
@@ -116,9 +115,6 @@ class CnbAdminCloud {
116
  if ( $result instanceof WP_Error ) {
117
  $message = self::cnb_admin_get_error_message( 'update', 'action', $result );
118
  array_push( $cnb_cloud_notifications, $message );
119
- } else {
120
- $message = self::cnb_admin_get_success_message( 'updated', 'action', $result->id );
121
- array_push( $cnb_cloud_notifications, $message );
122
  }
123
 
124
  return $result;
@@ -129,9 +125,6 @@ class CnbAdminCloud {
129
  if ( $result instanceof WP_Error ) {
130
  $message = self::cnb_admin_get_error_message( 'update', 'condition', $result );
131
  array_push( $cnb_cloud_notifications, $message );
132
- } else {
133
- $message = self::cnb_admin_get_success_message( 'updated', 'condition', $result->id );
134
- array_push( $cnb_cloud_notifications, $message );
135
  }
136
 
137
  return $result;
@@ -141,11 +134,10 @@ class CnbAdminCloud {
141
  $result = CnbAppRemote::cnb_remote_update_domain( $domain );
142
  if ( $result instanceof WP_Error ) {
143
  $message = self::cnb_admin_get_error_message( 'update', 'domain', $result );
144
- array_push( $cnb_cloud_notifications, $message );
145
  } else {
146
- $message = self::cnb_admin_get_success_message( 'updated', 'domain', $result->id );
147
- array_push( $cnb_cloud_notifications, $message );
148
  }
 
149
 
150
  return $result;
151
  }
@@ -154,17 +146,16 @@ class CnbAdminCloud {
154
  * @param $cnb_cloud_notifications
155
  * @param $button array Single Button object
156
  *
157
- * @return object|WP_Error The created Button
158
  */
159
  public static function cnb_create_button( &$cnb_cloud_notifications, $button ) {
160
  $result = CnbAppRemote::cnb_remote_create_button( $button );
161
  if ( $result instanceof WP_Error ) {
162
  $message = self::cnb_admin_get_error_message( 'create', 'button', $result );
163
- array_push( $cnb_cloud_notifications, $message );
164
  } else {
165
- $message = self::cnb_admin_get_success_message( 'created', 'button', $result->id );
166
- array_push( $cnb_cloud_notifications, $message );
167
  }
 
168
 
169
  return $result;
170
  }
@@ -179,11 +170,11 @@ class CnbAdminCloud {
179
  $result = CnbAppRemote::cnb_remote_delete_button( array( 'id' => $button_id ) );
180
  if ( $result instanceof WP_Error ) {
181
  $message = self::cnb_admin_get_error_message( 'delete', 'button', $result, 'with ID <code>' . esc_html( $button_id ) . '</code>' );
182
- array_push( $cnb_cloud_notifications, $message );
183
  } else {
184
- $message = self::cnb_admin_get_success_message( 'deleted', 'button', $button_id );
185
- array_push( $cnb_cloud_notifications, $message );
186
  }
 
187
 
188
  return $result;
189
  }
@@ -198,11 +189,10 @@ class CnbAdminCloud {
198
  $result = CnbAppRemote::cnb_remote_delete_domain( array( 'id' => $domain_id ) );
199
  if ( $result instanceof WP_Error ) {
200
  $message = self::cnb_admin_get_error_message( 'delete', 'domain', $result, 'with ID <code>' . esc_html( $domain_id ) . '</code>' );
201
- array_push( $cnb_cloud_notifications, $message );
202
  } else {
203
  $message = self::cnb_admin_get_success_message( 'deleted', 'domain', $domain_id );
204
- array_push( $cnb_cloud_notifications, $message );
205
  }
 
206
 
207
  return $result;
208
  }
@@ -218,9 +208,6 @@ class CnbAdminCloud {
218
  if ( $result instanceof WP_Error ) {
219
  $message = self::cnb_admin_get_error_message( 'delete', 'action', $result, 'with ID <code>' . esc_html( $action_id ) . '</code>' );
220
  array_push( $cnb_cloud_notifications, $message );
221
- } else {
222
- $message = self::cnb_admin_get_success_message( 'deleted', 'action', $action_id );
223
- array_push( $cnb_cloud_notifications, $message );
224
  }
225
 
226
  return $result;
@@ -237,9 +224,6 @@ class CnbAdminCloud {
237
  if ( $result instanceof WP_Error ) {
238
  $message = self::cnb_admin_get_error_message( 'delete', 'condition', $result, 'with ID <code>' . esc_html( $condition_id ) . '</code>' );
239
  array_push( $cnb_cloud_notifications, $message );
240
- } else {
241
- $message = self::cnb_admin_get_success_message( 'deleted', 'condition', $condition_id );
242
- array_push( $cnb_cloud_notifications, $message );
243
  }
244
 
245
  return $result;
@@ -255,11 +239,10 @@ class CnbAdminCloud {
255
  $result = CnbAppRemote::cnb_remote_delete_apikey( array( 'id' => $apikey_id ) );
256
  if ( $result instanceof WP_Error ) {
257
  $message = self::cnb_admin_get_error_message( 'delete', 'apikey', $result, 'with ID <code>' . esc_html( $apikey_id ) . '</code>' );
258
- array_push( $cnb_cloud_notifications, $message );
259
  } else {
260
  $message = self::cnb_admin_get_success_message( 'deleted', 'apikey', $apikey_id );
261
- array_push( $cnb_cloud_notifications, $message );
262
  }
 
263
 
264
  return $result;
265
  }
@@ -268,11 +251,10 @@ class CnbAdminCloud {
268
  $result = CnbAppRemote::cnb_remote_create_domain( $domain );
269
  if ( $result instanceof WP_Error ) {
270
  $message = self::cnb_admin_get_error_message( 'create', 'domain', $result );
271
- array_push( $cnb_cloud_notifications, $message );
272
  } else {
273
  $message = self::cnb_admin_get_success_message( 'created', 'domain', $result->name );
274
- array_push( $cnb_cloud_notifications, $message );
275
  }
 
276
 
277
  return $result;
278
  }
@@ -283,8 +265,7 @@ class CnbAdminCloud {
283
  $message = self::cnb_admin_get_error_message( 'create', 'action', $result );
284
  array_push( $cnb_cloud_notifications, $message );
285
  } else {
286
- $message = self::cnb_admin_get_success_message( 'created', 'action', $result->id );
287
- array_push( $cnb_cloud_notifications, $message );
288
  }
289
 
290
  return $result;
@@ -296,8 +277,7 @@ class CnbAdminCloud {
296
  $message = self::cnb_admin_get_error_message( 'create', 'condition', $result );
297
  array_push( $cnb_cloud_notifications, $message );
298
  } else if ( $result !== null ) {
299
- $message = self::cnb_admin_get_success_message( 'created', 'condition', $result->id );
300
- array_push( $cnb_cloud_notifications, $message );
301
  }
302
 
303
  return $result;
@@ -309,31 +289,13 @@ class CnbAdminCloud {
309
  $message = self::cnb_admin_get_error_message( 'create', 'apikey', $result );
310
  array_push( $cnb_cloud_notifications, $message );
311
  } else if ( $result !== null ) {
312
- $message = self::cnb_admin_get_success_message( 'created', 'apikey', $result->id );
313
- array_push( $cnb_cloud_notifications, $message );
314
-
315
- $key_msg = '<div class="notice-success notice"><p>' .
316
- 'Your API key is <strong><code>' . esc_html( $result->key ) . '</code></strong>. This will not be shown again!' .
317
- '</p></div>';
318
- array_push( $cnb_cloud_notifications, $key_msg );
319
  }
320
 
321
  return $result;
322
  }
323
 
324
- /**
325
- * @param $verb string one of created, updated, deleted
326
- * @param $type string one of button, action, condition
327
- * @param $id string The identifier of the $type (could be an actual ID, a name, etc)
328
- *
329
- * @return string A Wordpress success notice with all details filled out
330
- */
331
- public static function cnb_admin_get_success_message( $verb, $type, $id ) {
332
- return '<div class="notice-success notice is-dismissible"><p>
333
- Your ' . $type . ' <strong>' . esc_html( $id ) . '</strong> has been ' . $verb . ' at <strong>' . CnbAppRemote::cnb_get_api_base() . '</strong>!
334
- </p></div>';
335
- }
336
-
337
  /**
338
  * @param $result WP_Error The WP_Error that was thrown
339
  *
@@ -343,7 +305,7 @@ class CnbAdminCloud {
343
  if (!($result instanceof WP_Error)) { return ''; }
344
 
345
  $error_codes = $result->get_error_codes();
346
- $codes = 'Technical details: <br />';
347
  foreach ($error_codes as $error_code) {
348
  if ( $result->get_error_message( $error_code ) === '' ) {
349
  $codes .= '<p>Error code: <code>' . esc_html( $error_code ) . '.</code></p>';
@@ -366,7 +328,7 @@ class CnbAdminCloud {
366
  }
367
  }
368
 
369
- return '<p>' . $codes . $additional_details . '</p>';
370
 
371
  }
372
 
@@ -377,35 +339,52 @@ class CnbAdminCloud {
377
  * @param $extra_info string Allows for some extra details to be added to the error message.
378
  * This contains HTML and should be escaped already when passed through.
379
  *
380
- * @return string A Wordpress error notice with all details filled out (Content has been escaped already)
381
  */
382
  public static function cnb_admin_get_error_message( $verb, $type, $result, $extra_info = '' ) {
383
  $error_details = self::cnb_admin_get_error_message_details( $result );
 
 
 
384
 
385
- return '<div class="notice-error notice"><p>We could not ' . $verb . ' the ' . $type . ' ' . $extra_info . ' :-(.</p>
386
- ' . $error_details . '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  }
388
 
389
  /**
390
  *
391
- * Update the CallNowButton Cloud with a domain matching the Wordpress Domain
392
  *
393
  * @param $cnb_user
394
  *
395
- * @return array Array of Notifications
396
  */
397
  public static function cnb_wp_create_domain( $cnb_user ) {
398
  $cnb_cloud_notifications = array();
399
 
400
  if ( $cnb_user instanceof WP_Error ) {
401
- array_push( $cnb_cloud_notifications,
402
- '<div class="notice-error notice"><p>Cloud hosting is enabled, but needs to be configured.</p></div>' );
403
-
404
  return $cnb_cloud_notifications;
405
  }
406
 
407
- array_push( $cnb_cloud_notifications,
408
- '<div class="notice-success notice is-dismissible"><p>Cloud hosting is successfully connected.</p></div>' );
409
 
410
  $cnb_cloud_create_domain_check = CnbAppRemote::cnb_remote_get_wp_domain();
411
  if ( $cnb_cloud_create_domain_check instanceof WP_Error ) {
@@ -425,8 +404,9 @@ class CnbAdminCloud {
425
  */
426
  public static function cnb_remote_create_wp_domain( &$cnb_cloud_notifications ) {
427
  global $cnb_options;
 
428
  $domain = array(
429
- 'name' => CnbAppRemote::cnb_clean_site_url(),
430
  'timezone' => wp_timezone_string(),
431
  'trackGA' => isset($cnb_options['tracking'] ) && $cnb_options['tracking'] != 0,
432
  'trackConversion' => isset($cnb_options['conversions'] ) && $cnb_options['conversions'] != 0,
@@ -443,17 +423,36 @@ class CnbAdminCloud {
443
  /**
444
  * Update the CallNowButton Cloud with the current settings
445
  *
446
- * @return array Array of Notifications
447
  */
448
  public static function cnb_wp_migrate_button() {
449
  global $cnb_options;
450
-
451
  $cnb_cloud_notifications = array();
452
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
454
  if ( $cnb_user instanceof WP_Error ) {
455
- array_push( $cnb_cloud_notifications,
456
- '<div class="notice-error notice"><p>Cloud hosting is enabled, but needs to be configured.</p></div>' );
457
 
458
  return $cnb_cloud_notifications;
459
  }
@@ -461,18 +460,22 @@ class CnbAdminCloud {
461
  // Initialize the cloud
462
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
463
  if ( $domain instanceof WP_Error ) {
464
- array_push( $cnb_cloud_notifications,
465
- '<div class="notice-error notice"><p>Cloud hosting is enabled, but there is no domain matching ' . CnbAppRemote::cnb_clean_site_url() . '</p></div>' );
466
  }
467
 
 
 
 
 
468
  // 1: Create action
469
- $action = self::cnb_wp_create_action( $cnb_cloud_notifications, $cnb_options );
470
 
471
  // 2: Create condition
472
- $condition = self::cnb_wp_create_condition( $cnb_cloud_notifications, $cnb_options );
473
 
474
  // 3: Create button
475
- $button = self::cnb_wp_create_button( $cnb_cloud_notifications, $domain, $action, $condition, $cnb_options );
476
 
477
  if ( ! ( $button instanceof WP_Error ) ) {
478
  $url = admin_url( 'admin.php' );
@@ -486,10 +489,10 @@ class CnbAdminCloud {
486
  $url );
487
  $button_edit_url = esc_url( $button_edit_link );
488
 
489
- array_push( $cnb_cloud_notifications,
490
- '<div class="notice notice-success"><p><span class="dashicons dashicons-cloud-saved"></span>
491
- Congratulations, you have successfully migrated your Button to the cloud version!
492
- Click <a href="' . $button_edit_url . '">here</a> to edit your button.</p></div>' );
493
  }
494
 
495
  return $cnb_cloud_notifications;
@@ -501,7 +504,7 @@ class CnbAdminCloud {
501
  'actionValue' => $options['number'],
502
  'labelText' => $options['text'],
503
  'backgroundColor' => $options['color'],
504
- 'iconcolor' => $options['iconcolor'],
505
  'iconEnabled' => isset( $options['hideIcon'] ) && $options['hideIcon'] == 1 ? false : true,
506
  'schedule' => array(
507
  'showAlways' => true
@@ -518,7 +521,7 @@ class CnbAdminCloud {
518
  }
519
 
520
  $condition = array(
521
- 'conditionType' => 'url',
522
  'filterType' => 'EXCLUDE',
523
  'matchType' => 'EXACT',
524
  'matchValue' => get_home_url(),
@@ -529,13 +532,13 @@ class CnbAdminCloud {
529
 
530
  /**
531
  *
532
- * @param $cnb_cloud_notifications
533
  * @param $domain
534
  * @param $action
535
  * @param $condition
536
  * @param $options
537
  *
538
- * @return mixed|WP_Error
539
  */
540
  public static function cnb_wp_create_button( &$cnb_cloud_notifications, $domain, $action, $condition, $options ) {
541
  $appearance = 'default';
@@ -599,7 +602,7 @@ class CnbAdminCloud {
599
  $button = array(
600
  'name' => 'Button created via Wordpress plugin',
601
  'domain' => $domain->id,
602
- 'active' => true,
603
  'actions' => $actions,
604
  'conditions' => $conditions,
605
  'type' => $type,
@@ -616,8 +619,8 @@ class CnbAdminCloud {
616
  /**
617
  * NOTE: Currently only be called via button-overview, for a specific listing use case
618
  *
619
- * @param array $button The button array as created by the button-overview table class
620
- * @param int $max (optional) The maximum amount of Actions to retrieve
621
  *
622
  * @return array Array of Action objects, between 0 and $max items
623
  */
@@ -637,4 +640,4 @@ class CnbAdminCloud {
637
  }
638
 
639
  return $result;
640
- }}
1
  <?php
2
 
3
+ require_once dirname( __FILE__ ) . '/../../utils/CnbAdminNotices.class.php';
4
+
5
  class CnbAdminCloud {
6
 
7
  /**
14
  * @return string The ID to use for the Cloud Button
15
  */
16
  public static function cnb_set_default_option_for_cloud( $options ) {
17
+ // Check if an ID has already been set. If so, use if and continue
18
+ if ( isset( $options['cloud_use_id'] ) && ! empty( $options['cloud_use_id'] ) ) {
19
+ return null;
 
 
 
20
  }
21
+
22
+ // Check if we can talk to the API via a key. If so, use the current user to be safe
23
  $user_info = CnbAppRemote::cnb_remote_get_user_info();
24
+ if ( !is_wp_error($user_info)) {
25
+ return $user_info->id;
26
  }
27
 
28
+ return null;
29
  }
30
 
31
  /**
32
+ * @param $button array
33
+ * @param $actions array Should ONLY contain Ids, not full objects
34
+ * @param $conditions array
35
  *
36
  * @return array
37
  */
90
  $result = CnbAppRemote::cnb_remote_update_wp_button( $button, $actions, $conditions );
91
  if ( $result instanceof WP_Error ) {
92
  $message = self::cnb_admin_get_error_message( 'update', 'button', $result );
 
93
  } else {
94
+ $message = self::cnb_admin_get_success_message( 'updated', 'button', $result->name );
 
95
  }
96
+ array_push( $cnb_cloud_notifications, $message );
97
 
98
  return $result;
99
  }
102
  $result = CnbAppRemote::cnb_remote_update_button( $button );
103
  if ( $result instanceof WP_Error ) {
104
  $message = self::cnb_admin_get_error_message( 'update', 'button', $result );
 
105
  } else {
106
+ $message = self::cnb_admin_get_success_message( 'updated', 'button', $result->name );
 
107
  }
108
+ array_push( $cnb_cloud_notifications, $message );
109
 
110
  return $result;
111
  }
115
  if ( $result instanceof WP_Error ) {
116
  $message = self::cnb_admin_get_error_message( 'update', 'action', $result );
117
  array_push( $cnb_cloud_notifications, $message );
 
 
 
118
  }
119
 
120
  return $result;
125
  if ( $result instanceof WP_Error ) {
126
  $message = self::cnb_admin_get_error_message( 'update', 'condition', $result );
127
  array_push( $cnb_cloud_notifications, $message );
 
 
 
128
  }
129
 
130
  return $result;
134
  $result = CnbAppRemote::cnb_remote_update_domain( $domain );
135
  if ( $result instanceof WP_Error ) {
136
  $message = self::cnb_admin_get_error_message( 'update', 'domain', $result );
 
137
  } else {
138
+ $message = self::cnb_admin_get_success_message( 'updated', 'domain', $result->name );
 
139
  }
140
+ array_push( $cnb_cloud_notifications, $message );
141
 
142
  return $result;
143
  }
146
  * @param $cnb_cloud_notifications
147
  * @param $button array Single Button object
148
  *
149
+ * @return CnbButton|WP_Error The created Button
150
  */
151
  public static function cnb_create_button( &$cnb_cloud_notifications, $button ) {
152
  $result = CnbAppRemote::cnb_remote_create_button( $button );
153
  if ( $result instanceof WP_Error ) {
154
  $message = self::cnb_admin_get_error_message( 'create', 'button', $result );
 
155
  } else {
156
+ $message = self::cnb_admin_get_success_message( 'created', 'button', $result->name );
 
157
  }
158
+ array_push( $cnb_cloud_notifications, $message );
159
 
160
  return $result;
161
  }
170
  $result = CnbAppRemote::cnb_remote_delete_button( array( 'id' => $button_id ) );
171
  if ( $result instanceof WP_Error ) {
172
  $message = self::cnb_admin_get_error_message( 'delete', 'button', $result, 'with ID <code>' . esc_html( $button_id ) . '</code>' );
 
173
  } else {
174
+ $button = $result->object;
175
+ $message = self::cnb_admin_get_success_message( 'deleted', 'button', $button->name );
176
  }
177
+ array_push( $cnb_cloud_notifications, $message );
178
 
179
  return $result;
180
  }
189
  $result = CnbAppRemote::cnb_remote_delete_domain( array( 'id' => $domain_id ) );
190
  if ( $result instanceof WP_Error ) {
191
  $message = self::cnb_admin_get_error_message( 'delete', 'domain', $result, 'with ID <code>' . esc_html( $domain_id ) . '</code>' );
 
192
  } else {
193
  $message = self::cnb_admin_get_success_message( 'deleted', 'domain', $domain_id );
 
194
  }
195
+ array_push( $cnb_cloud_notifications, $message );
196
 
197
  return $result;
198
  }
208
  if ( $result instanceof WP_Error ) {
209
  $message = self::cnb_admin_get_error_message( 'delete', 'action', $result, 'with ID <code>' . esc_html( $action_id ) . '</code>' );
210
  array_push( $cnb_cloud_notifications, $message );
 
 
 
211
  }
212
 
213
  return $result;
224
  if ( $result instanceof WP_Error ) {
225
  $message = self::cnb_admin_get_error_message( 'delete', 'condition', $result, 'with ID <code>' . esc_html( $condition_id ) . '</code>' );
226
  array_push( $cnb_cloud_notifications, $message );
 
 
 
227
  }
228
 
229
  return $result;
239
  $result = CnbAppRemote::cnb_remote_delete_apikey( array( 'id' => $apikey_id ) );
240
  if ( $result instanceof WP_Error ) {
241
  $message = self::cnb_admin_get_error_message( 'delete', 'apikey', $result, 'with ID <code>' . esc_html( $apikey_id ) . '</code>' );
 
242
  } else {
243
  $message = self::cnb_admin_get_success_message( 'deleted', 'apikey', $apikey_id );
 
244
  }
245
+ array_push( $cnb_cloud_notifications, $message );
246
 
247
  return $result;
248
  }
251
  $result = CnbAppRemote::cnb_remote_create_domain( $domain );
252
  if ( $result instanceof WP_Error ) {
253
  $message = self::cnb_admin_get_error_message( 'create', 'domain', $result );
 
254
  } else {
255
  $message = self::cnb_admin_get_success_message( 'created', 'domain', $result->name );
 
256
  }
257
+ array_push( $cnb_cloud_notifications, $message );
258
 
259
  return $result;
260
  }
265
  $message = self::cnb_admin_get_error_message( 'create', 'action', $result );
266
  array_push( $cnb_cloud_notifications, $message );
267
  } else {
268
+ self::cnb_admin_get_success_message( 'created', 'action', $result->actionType );
 
269
  }
270
 
271
  return $result;
277
  $message = self::cnb_admin_get_error_message( 'create', 'condition', $result );
278
  array_push( $cnb_cloud_notifications, $message );
279
  } else if ( $result !== null ) {
280
+ self::cnb_admin_get_success_message( 'created', 'condition', $result->filterType );
 
281
  }
282
 
283
  return $result;
289
  $message = self::cnb_admin_get_error_message( 'create', 'apikey', $result );
290
  array_push( $cnb_cloud_notifications, $message );
291
  } else if ( $result !== null ) {
292
+ $notice = new CnbNotice('success', '<p>Your new API key for <strong>'.esc_html( $result->name ).'</strong> is <strong><code>' . esc_html( $result->key ) . '</code></strong>. This will not be shown again!</p>');
293
+ array_push( $cnb_cloud_notifications, $notice );
 
 
 
 
 
294
  }
295
 
296
  return $result;
297
  }
298
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  /**
300
  * @param $result WP_Error The WP_Error that was thrown
301
  *
305
  if (!($result instanceof WP_Error)) { return ''; }
306
 
307
  $error_codes = $result->get_error_codes();
308
+ $codes = '<p>Technical details:</p>';
309
  foreach ($error_codes as $error_code) {
310
  if ( $result->get_error_message( $error_code ) === '' ) {
311
  $codes .= '<p>Error code: <code>' . esc_html( $error_code ) . '.</code></p>';
328
  }
329
  }
330
 
331
+ return $codes . $additional_details;
332
 
333
  }
334
 
339
  * @param $extra_info string Allows for some extra details to be added to the error message.
340
  * This contains HTML and should be escaped already when passed through.
341
  *
342
+ * @return CnbNotice A Wordpress error notice with all details filled out (Content has been escaped already)
343
  */
344
  public static function cnb_admin_get_error_message( $verb, $type, $result, $extra_info = '' ) {
345
  $error_details = self::cnb_admin_get_error_message_details( $result );
346
+ $message = '<p>We could not ' . $verb . ' the ' . $type . ' ' . $extra_info . ' :-(.</p>' . $error_details;
347
+ return new CnbNotice('error', $message);
348
+ }
349
 
350
+ /**
351
+ * @param $verb string one of created, updated, deleted
352
+ * @param $type string one of button, action, condition
353
+ * @param $id string The identifier of the $type (could be an actual ID, a name, etc)
354
+ *
355
+ * @return CnbNotice A WordPress success notice with all details filled out
356
+ */
357
+ public static function cnb_admin_get_success_message( $verb, $type, $id ) {
358
+ global $cnb_options;
359
+ $advanced = '';
360
+ if (isset($cnb_options['advanced_view']) && $cnb_options['advanced_view'] == 1) {
361
+ $advanced = ' at <strong>' . CnbAppRemote::cnb_get_api_base() . '</strong>';
362
+ }
363
+ $message = '<p>Your ' . $type . ' <strong>' . esc_html( $id ) . '</strong> has been ' . $verb . $advanced . '!</p>';
364
+ $notice = new CnbNotice('success', $message);
365
+ $notice->dismissable = true;
366
+ return $notice;
367
  }
368
 
369
  /**
370
  *
371
+ * Update the CallNowButton Cloud with a domain matching the WordPress Domain
372
  *
373
  * @param $cnb_user
374
  *
375
+ * @return array Array of CnbNotice
376
  */
377
  public static function cnb_wp_create_domain( $cnb_user ) {
378
  $cnb_cloud_notifications = array();
379
 
380
  if ( $cnb_user instanceof WP_Error ) {
381
+ $notice = new CnbNotice('error', 'Cloud hosting is enabled, but needs to be configured.');
382
+ array_push( $cnb_cloud_notifications, $notice);
 
383
  return $cnb_cloud_notifications;
384
  }
385
 
386
+ $notice = new CnbNotice('success', '<p>Successfully connected to your Call Now Button account.</p>', true);
387
+ array_push( $cnb_cloud_notifications,$notice);
388
 
389
  $cnb_cloud_create_domain_check = CnbAppRemote::cnb_remote_get_wp_domain();
390
  if ( $cnb_cloud_create_domain_check instanceof WP_Error ) {
404
  */
405
  public static function cnb_remote_create_wp_domain( &$cnb_cloud_notifications ) {
406
  global $cnb_options;
407
+ $cnbAppRemote = new CnbAppRemote();
408
  $domain = array(
409
+ 'name' => $cnbAppRemote->cnb_clean_site_url(),
410
  'timezone' => wp_timezone_string(),
411
  'trackGA' => isset($cnb_options['tracking'] ) && $cnb_options['tracking'] != 0,
412
  'trackConversion' => isset($cnb_options['conversions'] ) && $cnb_options['conversions'] != 0,
423
  /**
424
  * Update the CallNowButton Cloud with the current settings
425
  *
426
+ * @return array Array of CnbNotice
427
  */
428
  public static function cnb_wp_migrate_button() {
429
  global $cnb_options;
 
430
  $cnb_cloud_notifications = array();
431
 
432
+ // We can skip all this if the phonenumber is empty and the button is disabled
433
+ if (empty($cnb_options['number'])) {
434
+ $url = admin_url( 'admin.php' );
435
+ $button_overview_link =
436
+ add_query_arg(
437
+ array(
438
+ 'page' => 'call-now-button',
439
+ ),
440
+ $url );
441
+ $button_overview_url = esc_url( $button_overview_link );
442
+
443
+ $notice = new CnbNotice('success', '<p><span class="dashicons dashicons-cloud-saved"></span>
444
+ Congratulations, you have successfully activated the cloud version!
445
+ Click <a href="' . $button_overview_url . '">here</a> to create your first button.</p>');
446
+ array_push( $cnb_cloud_notifications, $notice);
447
+
448
+ return $cnb_cloud_notifications;
449
+ }
450
+
451
+ $cnbAppRemote = new CnbAppRemote();
452
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
453
  if ( $cnb_user instanceof WP_Error ) {
454
+ $notice = new CnbNotice('error', 'Cloud hosting is enabled, but needs to be configured.');
455
+ array_push( $cnb_cloud_notifications,$notice);
456
 
457
  return $cnb_cloud_notifications;
458
  }
460
  // Initialize the cloud
461
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
462
  if ( $domain instanceof WP_Error ) {
463
+ $notice = new CnbNotice('error', 'Cloud hosting is enabled, but there is no domain matching ' . $cnbAppRemote->cnb_clean_site_url());
464
+ array_push( $cnb_cloud_notifications, $notice);
465
  }
466
 
467
+ /**
468
+ * During migration, we don't care about notifications
469
+ */
470
+ $ignore_notifications = array();
471
  // 1: Create action
472
+ $action = self::cnb_wp_create_action( $ignore_notifications, $cnb_options );
473
 
474
  // 2: Create condition
475
+ $condition = self::cnb_wp_create_condition( $ignore_notifications, $cnb_options );
476
 
477
  // 3: Create button
478
+ $button = self::cnb_wp_create_button( $ignore_notifications, $domain, $action, $condition, $cnb_options );
479
 
480
  if ( ! ( $button instanceof WP_Error ) ) {
481
  $url = admin_url( 'admin.php' );
489
  $url );
490
  $button_edit_url = esc_url( $button_edit_link );
491
 
492
+ $notice = new CnbNotice('success', '<p><span class="dashicons dashicons-cloud-saved"></span>
493
+ Congratulations! You are now using the Call Now Button cloud version!
494
+ Click <a href="' . $button_edit_url . '">here</a> to edit your button.</p>');
495
+ array_push( $cnb_cloud_notifications, $notice);
496
  }
497
 
498
  return $cnb_cloud_notifications;
504
  'actionValue' => $options['number'],
505
  'labelText' => $options['text'],
506
  'backgroundColor' => $options['color'],
507
+ 'iconColor' => $options['iconcolor'],
508
  'iconEnabled' => isset( $options['hideIcon'] ) && $options['hideIcon'] == 1 ? false : true,
509
  'schedule' => array(
510
  'showAlways' => true
521
  }
522
 
523
  $condition = array(
524
+ 'conditionType' => 'URL',
525
  'filterType' => 'EXCLUDE',
526
  'matchType' => 'EXACT',
527
  'matchValue' => get_home_url(),
532
 
533
  /**
534
  *
535
+ * @param $cnb_cloud_notifications CnbNotice[]
536
  * @param $domain
537
  * @param $action
538
  * @param $condition
539
  * @param $options
540
  *
541
+ * @return CnbButton|WP_Error
542
  */
543
  public static function cnb_wp_create_button( &$cnb_cloud_notifications, $domain, $action, $condition, $options ) {
544
  $appearance = 'default';
602
  $button = array(
603
  'name' => 'Button created via Wordpress plugin',
604
  'domain' => $domain->id,
605
+ 'active' => false,
606
  'actions' => $actions,
607
  'conditions' => $conditions,
608
  'type' => $type,
619
  /**
620
  * NOTE: Currently only be called via button-overview, for a specific listing use case
621
  *
622
+ * @param $button array The button array as created by the button-overview table class
623
+ * @param $max int (optional) The maximum amount of Actions to retrieve
624
  *
625
  * @return array Array of Action objects, between 0 and $max items
626
  */
640
  }
641
 
642
  return $result;
643
+ }}
src/admin/api/CnbAppRemote.php CHANGED
@@ -42,21 +42,135 @@ class CnbGet {
42
  }
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  class CnbAppRemote {
46
 
 
 
 
 
 
 
 
 
47
  /**
48
  * Return a cleaned up version of the Site URL.
49
  *
50
- * Removes protocol and port
51
  *
52
  * Example:
53
- * https://www.testdomain.com:8080 becomes www.testdomain.com
54
  *
55
  * @return string
56
  */
57
- public static function cnb_clean_site_url() {
58
- return preg_replace( '/:[0-9]+/', '',
59
- preg_replace( '/.*\/\//', '', get_site_url(), 1 ), 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  }
61
 
62
  /**
@@ -147,8 +261,8 @@ class CnbAppRemote {
147
  *
148
  * Includes Trace support
149
  *
150
- * @param $url
151
- * @param $parsed_args
152
  *
153
  * @return array|WP_Error
154
  */
@@ -167,8 +281,8 @@ class CnbAppRemote {
167
  *
168
  * This is inspired by https://developer.wordpress.org/reference/functions/wp_remote_post/
169
  *
170
- * @param $url
171
- * @param array $args
172
  *
173
  * @return array|WP_Error
174
  */
@@ -184,8 +298,8 @@ class CnbAppRemote {
184
  *
185
  * This is inspired by https://developer.wordpress.org/reference/functions/wp_remote_post/
186
  *
187
- * @param $url
188
- * @param array $args
189
  *
190
  * @return array|WP_Error
191
  */
@@ -230,7 +344,7 @@ class CnbAppRemote {
230
  return self::cnb_remote_handle_response( $response );
231
  }
232
 
233
- public static function cnb_remote_post( $rest_endpoint, $body ) {
234
  $args = self::cnb_remote_get_args();
235
  if ( $args instanceof WP_Error ) {
236
  return $args;
@@ -276,7 +390,8 @@ class CnbAppRemote {
276
  * @return mixed|WP_Error
277
  */
278
  public static function cnb_remote_get_wp_domain() {
279
- $rest_endpoint = '/v1/domain/byName/' . self::cnb_clean_site_url();
 
280
 
281
  return self::cnb_remote_get( $rest_endpoint );
282
  }
@@ -330,7 +445,7 @@ class CnbAppRemote {
330
  }
331
 
332
  public static function cnb_remote_get_conditions() {
333
- $rest_endpoint = '/v1/condition/';
334
 
335
  return self::cnb_remote_get( $rest_endpoint );
336
  }
@@ -446,30 +561,8 @@ class CnbAppRemote {
446
  return new WP_Error( 'CNB_ACTION_ID_MISSING', 'actionId expected, but not found' );
447
  }
448
 
449
- $schedule = null;
450
- if (isset($action['schedule'])) {
451
- $schedule = array(
452
- 'showAlways' => $action['schedule']['showAlways'],
453
- 'daysOfWeek' => isset( $action['schedule']['daysOfWeek'] ) ? $action['schedule']['daysOfWeek'] : array(),
454
- 'start' => $action['schedule']['start'],
455
- 'stop' => $action['schedule']['stop'],
456
- 'timezone' => $action['schedule']['timezone'],
457
- 'outsideHours' => isset( $action['schedule']['outsideHours'] ) ? $action['schedule']['outsideHours'] : false,
458
- );
459
- }
460
- $body = array(
461
- 'actionType' => $action['actionType'],
462
- 'actionValue' => $action['actionValue'],
463
- 'schedule' => $schedule,
464
- 'backgroundColor' => isset( $action['color'] ) ? $action['color'] : '#009900',
465
- 'iconColor' => $action['iconColor'],
466
- // phpcs:ignore
467
- 'iconEnabled' => isset( $action['iconEnabled'] ) ? boolval( $action['iconEnabled'] ) : false,
468
- 'labelText' => $action['labelText'],
469
- // 'iconText' => !empty($action['iconText']) ? $action['iconText'] : cnb_actiontype_to_icontext($action['actionType']),
470
- 'iconText' => cnb_actiontype_to_icontext($action['actionType']),
471
- 'properties' => ! empty( $action['properties'] ) ? $action['properties'] : null,
472
- );
473
 
474
  $rest_endpoint = '/v1/action/' . $actionId;
475
 
@@ -492,39 +585,21 @@ class CnbAppRemote {
492
  return new WP_Error( 'CNB_BUTTON_ID_MISSING', 'buttonId expected, but not found' );
493
  }
494
 
495
- $body = array(
496
- 'id' => $button['id'],
497
- // phpcs:ignore
498
- 'active' => boolval( $button['active'] ),
499
- 'name' => ! empty( $button['name'] ) ? $button['name'] : 'Button created via Wordpress plugin',
500
- 'domain' => $button['domain'],
501
- 'actions' => is_array( $actions ) ? cnb_array_column( $actions, 'id' ) : array(),
502
- 'conditions' => is_array( $conditions ) ? cnb_array_column( $conditions, 'id' ) : array(),
503
- 'type' => $button['type'],
504
- 'options' => $button['options']
505
- );
506
 
507
  return self::cnb_remote_update_button( $body );
508
  }
509
 
510
- public static function cnb_remote_cleanup_properties( $array ) {
511
- return empty( $array['properties'] ) || ! is_array( $array['properties'] ) ? null : $array['properties'];
512
- }
513
-
514
  public static function cnb_remote_create_domain( $domain ) {
515
  $domainId = isset( $domain['id'] ) && $domain['id'];
516
 
517
  if ( $domainId ) {
518
  return new WP_Error( 'CNB_DOMAIN_ID_FOUND', 'no domainId expected, but one was given' );
519
  }
520
- $body = array(
521
- 'name' => $domain['name'],
522
- 'timezone' => $domain['timezone'],
523
- 'trackGA' => $domain['trackGA'],
524
- 'trackConversion' => $domain['trackConversion'],
525
- 'renew' => $domain['renew'],
526
- 'properties' => self::cnb_remote_cleanup_properties( $domain )
527
- );
528
 
529
  $rest_endpoint = '/v1/domain';
530
 
@@ -534,7 +609,7 @@ class CnbAppRemote {
534
  /**
535
  * @param $button array Single Button object
536
  *
537
- * @return mixed|WP_Error
538
  */
539
  public static function cnb_remote_create_button( $button ) {
540
  $buttonId = isset($button['id']) && $button['id'];
@@ -543,16 +618,8 @@ class CnbAppRemote {
543
  return new WP_Error( 'CNB_BUTTON_ID_FOUND', 'no buttonId expected, but one was given' );
544
  }
545
 
546
- $body = array(
547
- 'name' => ! empty( $button['name'] ) ? $button['name'] : 'Button created via Wordpress plugin',
548
- 'domain' => $button['domain'],
549
- // phpcs:ignore
550
- 'active' => isset( $button['active'] ) ? boolval( $button['active'] ) : false,
551
- 'actions' => isset( $button['actions'] ) && is_array( $button['actions'] ) ? cnb_array_column( $button['actions'], 'id' ) : array(),
552
- 'conditions' => isset( $button['conditions'] ) && is_array( $button['conditions'] ) ? cnb_array_column( $button['conditions'], 'id' ) : array(),
553
- 'type' => $button['type'],
554
- 'options' => $button['options']
555
- );
556
 
557
  $rest_endpoint = '/v1/button';
558
 
@@ -566,26 +633,8 @@ class CnbAppRemote {
566
  return new WP_Error( 'CNB_ACTION_ID_FOUND', 'no actionId expected, but one was given' );
567
  }
568
 
569
- $body = array(
570
- 'actionType' => ! empty( $action['actionType'] ) ? $action['actionType'] : 'PHONE',
571
- 'actionValue' => $action['actionValue'],
572
- 'schedule' => array(
573
- 'showAlways' => $action['schedule']['showAlways'],
574
- 'daysOfWeek' => isset( $action['schedule']['daysOfWeek'] ) ? $action['schedule']['daysOfWeek'] : null,
575
- 'start' => isset($action['schedule']['start']) ? $action['schedule']['start'] : null,
576
- 'stop' => isset($action['schedule']['stop']) ? $action['schedule']['stop'] : null,
577
- 'timezone' => isset( $action['schedule']['timezone'] ) ? $action['schedule']['timezone'] : null,
578
- 'outsideHours' => isset( $action['schedule']['outsideHours'] ) ? $action['schedule']['outsideHours'] : null,
579
- ),
580
- 'backgroundColor' => ! empty( $action['backgroundColor'] ) ? $action['backgroundColor'] : '#009900',
581
- 'iconColor' => ! empty( $action['iconcolor'] ) ? $action['iconcolor'] : '#ffffff',
582
- // phpcs:ignore
583
- 'iconEnabled' => isset( $action['iconEnabled'] ) ? boolval( $action['iconEnabled'] ) : false,
584
- 'labelText' => isset($action['labelText']) ? $action['labelText'] : null,
585
- // 'iconText' => isset($action['iconText']) ? $action['iconText'] : null,
586
- 'iconText' => cnb_actiontype_to_icontext($action['actionType']),
587
- 'properties' => ! empty( $action['properties'] ) ? $action['properties'] : null,
588
- );
589
 
590
  $rest_endpoint = '/v1/action';
591
 
@@ -593,12 +642,14 @@ class CnbAppRemote {
593
  }
594
 
595
  public static function cnb_remote_create_condition( $condition ) {
596
- $body = array(
597
- 'conditionType' => $condition['conditionType'],
598
- 'filterType' => $condition['filterType'],
599
- 'matchType' => $condition['matchType'],
600
- 'matchValue' => $condition['matchValue'],
601
- );
 
 
602
 
603
  $rest_endpoint = '/v1/condition';
604
 
@@ -610,13 +661,8 @@ class CnbAppRemote {
610
  return new WP_Error( 'CNB_CONDITION_ID_MISSING', 'conditionId expected, but not found' );
611
  }
612
 
613
- $body = array(
614
- 'id' => $condition['id'],
615
- 'conditionType' => $condition['conditionType'],
616
- 'filterType' => $condition['filterType'],
617
- 'matchType' => $condition['matchType'],
618
- 'matchValue' => $condition['matchValue'],
619
- );
620
 
621
  $rest_endpoint = '/v1/condition/' . $condition['id'];
622
 
@@ -624,11 +670,18 @@ class CnbAppRemote {
624
  }
625
 
626
  public static function cnb_remote_create_apikey( $apikey ) {
627
- $body = array(
628
- 'name' => $apikey['name'],
629
- );
630
 
631
  $rest_endpoint = '/v1/apikey';
632
 
633
  return self::cnb_remote_post( $rest_endpoint, $body);
634
- }}
 
 
 
 
 
 
 
 
42
  }
43
  }
44
 
45
+ class CnbAppRemoteHelper {
46
+
47
+ private function cnb_remote_cleanup_properties( $array ) {
48
+ return empty( $array['properties'] ) || ! is_array( $array['properties'] ) ? null : $array['properties'];
49
+ }
50
+
51
+ public function convertAction($action) {
52
+ $schedule = null;
53
+ if (isset($action['schedule'])) {
54
+ $schedule = array(
55
+ 'showAlways' => isset( $action['schedule']['showAlways'] ) ? $action['schedule']['showAlways'] : true,
56
+ 'daysOfWeek' => isset( $action['schedule']['daysOfWeek'] ) ? $action['schedule']['daysOfWeek'] : array(),
57
+ 'start' => isset( $action['schedule']['start'] ) ? $action['schedule']['start'] : null,
58
+ 'stop' => isset( $action['schedule']['stop'] ) ? $action['schedule']['stop'] : null,
59
+ 'timezone' => isset( $action['schedule']['timezone'] ) ? $action['schedule']['timezone'] : null,
60
+ 'outsideHours' => isset( $action['schedule']['outsideHours'] ) ? $action['schedule']['outsideHours'] : false,
61
+ );
62
+ }
63
+
64
+ return array(
65
+ 'actionType' => !empty( $action['actionType'] ) ? $action['actionType'] : 'PHONE',
66
+ 'actionValue' => $action['actionValue'],
67
+ 'schedule' => $schedule,
68
+ 'backgroundColor' => !empty( $action['backgroundColor'] ) ? $action['backgroundColor'] : '#009900',
69
+ 'iconColor' => !empty( $action['iconColor'] ) ? $action['iconColor'] : '#ffffff',
70
+ // phpcs:ignore
71
+ 'iconEnabled' => isset( $action['iconEnabled'] ) ? boolval( $action['iconEnabled'] ) : false,
72
+ 'labelText' => isset($action['labelText']) ? $action['labelText'] : null,
73
+ // 'iconText' => isset($action['iconText']) ? $action['iconText'] : null,
74
+ 'iconText' => cnb_actiontype_to_icontext($action['actionType']),
75
+ 'properties' => self::cnb_remote_cleanup_properties($action)
76
+ );
77
+ }
78
+
79
+ public function convertButton($button, $actions=null, $conditions=null) {
80
+ if ($actions != null) {
81
+ $button['actions'] = is_array( $actions ) ? cnb_array_column( $actions, 'id' ) : array();
82
+ } else if (isset($button['actions']) && $button['actions'] != null) {
83
+ $button['actions'] = is_array( $button['actions'] ) ? cnb_array_column( $button['actions'], 'id' ) : array();
84
+ }
85
+
86
+ if ($conditions != null) {
87
+ $button['conditions'] = is_array( $conditions ) ? cnb_array_column( $conditions, 'id' ) : array();
88
+ } else if (isset($button['conditions']) && $button['conditions'] != null) {
89
+ $button['conditions'] = is_array( $button['conditions'] ) ? cnb_array_column( $button['conditions'], 'id' ) : array();
90
+ }
91
+
92
+ if (!isset($button['id'])) {
93
+ $button['id'] = null;
94
+ }
95
+
96
+ return array(
97
+ 'id' => $button['id'],
98
+ // phpcs:ignore
99
+ 'active' => isset( $button['active'] ) ? boolval( $button['active'] ) : false,
100
+ 'name' => ! empty( $button['name'] ) ? $button['name'] : 'Button created via Wordpress plugin',
101
+ 'domain' => $button['domain'],
102
+ 'actions' => isset( $button['actions'] ) && is_array( $button['actions'] ) ? $button['actions'] : array(),
103
+ 'conditions' => isset( $button['conditions'] ) && is_array( $button['conditions'] ) ? $button['conditions'] : array(),
104
+ 'type' => $button['type'],
105
+ 'options' => $button['options']
106
+ );
107
+ }
108
+
109
+ public function convertDomain($domain) {
110
+ return array(
111
+ 'name' => $domain['name'],
112
+ 'timezone' => $domain['timezone'],
113
+ 'trackGA' => $domain['trackGA'],
114
+ 'trackConversion' => $domain['trackConversion'],
115
+ 'renew' => $domain['renew'],
116
+ 'properties' => self::cnb_remote_cleanup_properties( $domain )
117
+ );
118
+ }
119
+
120
+ public function convertCondition($condition) {
121
+ return array(
122
+ 'id' => isset($condition['id']) ? $condition['id'] : null,
123
+ 'conditionType' => $condition['conditionType'],
124
+ 'filterType' => $condition['filterType'],
125
+ 'matchType' => $condition['matchType'],
126
+ 'matchValue' => $condition['matchValue'],
127
+ );
128
+ }
129
+
130
+ public function convertApiKey($apikey) {
131
+ return array(
132
+ 'name' => $apikey['name'],
133
+ );
134
+ }
135
+ }
136
+
137
  class CnbAppRemote {
138
 
139
+ /**
140
+ * By creating a proxy method, we can easily stub this for testing
141
+ *
142
+ * @return string Site URL link with optional path appended.
143
+ */
144
+ function get_site_url() {
145
+ return \get_site_url();
146
+ }
147
  /**
148
  * Return a cleaned up version of the Site URL.
149
  *
150
+ * Removes protocol, port and path (and lowercases it)
151
  *
152
  * Example:
153
+ * https://www.TestDomain.com:8080/test becomes www.testdomain.com
154
  *
155
  * @return string
156
  */
157
+ public function cnb_clean_site_url() {
158
+ $siteUrl = $this->get_site_url();
159
+
160
+ $url = parse_url($siteUrl, PHP_URL_HOST);
161
+ if ($url) {
162
+ return strtolower($url);
163
+ }
164
+
165
+ // Fallback behavior
166
+ // Order:
167
+ // 1: Strip everything after // (so to remove a potential protocol like http(s)://
168
+ // 2: Strip the port if found, via :1234
169
+ // 3: Strip everything after /, so that "example.org/test" becomes "example.org"
170
+
171
+ return strtolower(preg_replace( '/\/.*/', '',
172
+ preg_replace( '/:[0-9]+/', '',
173
+ preg_replace( '/.*\/\//', '', $siteUrl, 1 ), 1 ), 1 ));
174
  }
175
 
176
  /**
261
  *
262
  * Includes Trace support
263
  *
264
+ * @param $url string
265
+ * @param $parsed_args array
266
  *
267
  * @return array|WP_Error
268
  */
281
  *
282
  * This is inspired by https://developer.wordpress.org/reference/functions/wp_remote_post/
283
  *
284
+ * @param $url string
285
+ * @param $args array
286
  *
287
  * @return array|WP_Error
288
  */
298
  *
299
  * This is inspired by https://developer.wordpress.org/reference/functions/wp_remote_post/
300
  *
301
+ * @param $url string
302
+ * @param $args array
303
  *
304
  * @return array|WP_Error
305
  */
344
  return self::cnb_remote_handle_response( $response );
345
  }
346
 
347
+ public static function cnb_remote_post( $rest_endpoint, $body = null ) {
348
  $args = self::cnb_remote_get_args();
349
  if ( $args instanceof WP_Error ) {
350
  return $args;
390
  * @return mixed|WP_Error
391
  */
392
  public static function cnb_remote_get_wp_domain() {
393
+ $cnbAppRemote = new CnbAppRemote();
394
+ $rest_endpoint = '/v1/domain/byName/' . $cnbAppRemote->cnb_clean_site_url();
395
 
396
  return self::cnb_remote_get( $rest_endpoint );
397
  }
445
  }
446
 
447
  public static function cnb_remote_get_conditions() {
448
+ $rest_endpoint = '/v1/condition';
449
 
450
  return self::cnb_remote_get( $rest_endpoint );
451
  }
561
  return new WP_Error( 'CNB_ACTION_ID_MISSING', 'actionId expected, but not found' );
562
  }
563
 
564
+ $helper = new CnbAppRemoteHelper();
565
+ $body = $helper->convertAction($action);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
 
567
  $rest_endpoint = '/v1/action/' . $actionId;
568
 
585
  return new WP_Error( 'CNB_BUTTON_ID_MISSING', 'buttonId expected, but not found' );
586
  }
587
 
588
+ $helper = new CnbAppRemoteHelper();
589
+ $body = $helper->convertButton($button, $actions, $conditions);
 
 
 
 
 
 
 
 
 
590
 
591
  return self::cnb_remote_update_button( $body );
592
  }
593
 
 
 
 
 
594
  public static function cnb_remote_create_domain( $domain ) {
595
  $domainId = isset( $domain['id'] ) && $domain['id'];
596
 
597
  if ( $domainId ) {
598
  return new WP_Error( 'CNB_DOMAIN_ID_FOUND', 'no domainId expected, but one was given' );
599
  }
600
+
601
+ $helper = new CnbAppRemoteHelper();
602
+ $body = $helper->convertDomain($domain);
 
 
 
 
 
603
 
604
  $rest_endpoint = '/v1/domain';
605
 
609
  /**
610
  * @param $button array Single Button object
611
  *
612
+ * @return CnbButton|WP_Error
613
  */
614
  public static function cnb_remote_create_button( $button ) {
615
  $buttonId = isset($button['id']) && $button['id'];
618
  return new WP_Error( 'CNB_BUTTON_ID_FOUND', 'no buttonId expected, but one was given' );
619
  }
620
 
621
+ $helper = new CnbAppRemoteHelper();
622
+ $body = $helper->convertButton($button);
 
 
 
 
 
 
 
 
623
 
624
  $rest_endpoint = '/v1/button';
625
 
633
  return new WP_Error( 'CNB_ACTION_ID_FOUND', 'no actionId expected, but one was given' );
634
  }
635
 
636
+ $helper = new CnbAppRemoteHelper();
637
+ $body = $helper->convertAction($action);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
 
639
  $rest_endpoint = '/v1/action';
640
 
642
  }
643
 
644
  public static function cnb_remote_create_condition( $condition ) {
645
+ $conditionId = isset($condition['id']) && $condition['id'];
646
+
647
+ if ( $conditionId ) {
648
+ return new WP_Error( 'CNB_CONDITION_ID_FOUND', 'no conditionId expected, but one was given' );
649
+ }
650
+
651
+ $helper = new CnbAppRemoteHelper();
652
+ $body = $helper->convertCondition($condition);
653
 
654
  $rest_endpoint = '/v1/condition';
655
 
661
  return new WP_Error( 'CNB_CONDITION_ID_MISSING', 'conditionId expected, but not found' );
662
  }
663
 
664
+ $helper = new CnbAppRemoteHelper();
665
+ $body = $helper->convertCondition($condition);
 
 
 
 
 
666
 
667
  $rest_endpoint = '/v1/condition/' . $condition['id'];
668
 
670
  }
671
 
672
  public static function cnb_remote_create_apikey( $apikey ) {
673
+ $helper = new CnbAppRemoteHelper();
674
+ $body = $helper->convertApiKey($apikey);
 
675
 
676
  $rest_endpoint = '/v1/apikey';
677
 
678
  return self::cnb_remote_post( $rest_endpoint, $body);
679
+ }
680
+
681
+ public static function cnb_remote_create_billing_portal() {
682
+ $rest_endpoint = '/v1/stripe/createBillingPortal';
683
+
684
+ return self::cnb_remote_post( $rest_endpoint);
685
+
686
+ }
687
+ }
src/admin/api/RemoteTrace.php CHANGED
@@ -44,7 +44,7 @@ class RemoteTrace {
44
  }
45
 
46
  /**
47
- * @param bool $cacheHit
48
  */
49
  public function setCacheHit( $cacheHit ) {
50
  // phpcs:ignore
44
  }
45
 
46
  /**
47
+ * @param $cacheHit boolean
48
  */
49
  public function setCacheHit( $cacheHit ) {
50
  // phpcs:ignore
src/admin/api/RemoteTracer.php CHANGED
@@ -34,7 +34,7 @@ class RemoteTracer {
34
  protected $traces = array();
35
 
36
  /**
37
- * @param RemoteTrace $trace
38
  */
39
  public function addTrace($trace) {
40
  self::$instance->traces[] = $trace;
34
  protected $traces = array();
35
 
36
  /**
37
+ * @param $trace RemoteTrace
38
  */
39
  public function addTrace($trace) {
40
  self::$instance->traces[] = $trace;
src/admin/apikey-overview.php CHANGED
@@ -6,11 +6,15 @@ require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
 
 
 
 
 
9
  function cnb_add_header_apikey_overview() {
10
  echo 'API keys ';
11
  }
12
 
13
- function cnb_add_new_modal_action() {
14
  $url = admin_url('admin.php');
15
  $new_link =
16
  add_query_arg(
@@ -78,10 +82,6 @@ function cnb_admin_page_apikey_create_process() {
78
  }
79
  }
80
 
81
- if(!class_exists('WP_List_Table')) {
82
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
83
- }
84
-
85
  class Cnb_Apikey_List_Table extends WP_List_Table {
86
 
87
  /**
@@ -183,7 +183,7 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
183
  case 'id':
184
  return '<code>' . esc_html($item[ $column_name ]) . '</code>';
185
  case 'name':
186
- return esc_html($item[ $column_name ]);
187
  case 'created':
188
  case 'lastUsed':
189
  case 'updateTime':
@@ -265,92 +265,77 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
265
  $apikey = array('id' => $apikeyId);
266
  CnbAppRemote::cnb_remote_delete_apikey( $apikey );
267
  }
268
- echo '<div class="notice-success notice"><p>' . count($apikeyIds) . ' Api key(s) deleted</p></div>';
269
  break;
270
  }
271
  }
272
  }
273
  }
274
- }
275
 
276
- function cnb_after_header() {
277
- // Only add the "Add new" action in the overview part
278
- $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
279
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
280
- if ($id === null || ($action != 'new' && $action != 'edit')) {
281
- // Create link
282
- $url = admin_url('admin.php');
283
- $new_link =
284
- add_query_arg(
285
- array(
286
- 'page' => 'call-now-button-apikeys',
287
- 'action' => 'new',
288
- 'id' => 'new'),
289
- $url);
290
- $new_url = esc_url($new_link);
291
-
292
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
293
  }
294
  }
295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  /**
297
  * Main entrypoint, used by `call-now-button.php`.
298
  */
299
  function cnb_admin_page_apikey_overview_render() {
300
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
301
  $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
 
302
  if ($id === null || $action === null) {
303
  cnb_admin_page_apikey_overview_render_list();
304
- } else {
305
- switch ($action) {
306
- case 'delete':
307
- if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
308
- $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
309
- $action = 'cnb_delete_apikey';
310
-
311
- if (wp_verify_nonce($nonce, $action)) {
312
- $cnb_cloud_notifications = array();
313
- CnbAdminCloud::cnb_delete_apikey( $cnb_cloud_notifications, $id );
314
- foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
315
- echo $cnb_cloud_notification;
316
- }
317
- cnb_admin_page_apikey_overview_render_list();
318
- }
319
- }
320
- break;
321
- }
322
  }
323
  }
324
 
325
  function cnb_admin_page_apikey_overview_render_list() {
326
- global $cnb_options, $cnb_settings;
327
-
328
- add_action('cnb_header', 'cnb_add_header_apikey_overview');
329
-
330
- $cnb_notices = cnb_get_notices();
331
- $cnb_changelog = cnb_get_changelog();
332
-
333
  $wp_list_table = new Cnb_Apikey_List_Table();
334
  $data = $wp_list_table->prepare_items();
335
 
 
 
336
  if ($data instanceof WP_Error) {
337
- $cnb_notices[] = cnb_admin_header_get_cloud_error($data);
338
  } else {
339
- add_action('cnb_after_header', 'cnb_add_new_modal_action');
340
  }
341
 
342
- echo '<div class="wrap">';
343
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
344
 
345
  echo '<form id="wp_list_event" method="post">';
346
- //Prepare Table of elements
347
 
348
  //Table of elements
349
  $wp_list_table->display();
350
  echo '</form>';
351
- cnb_admin_footer();
352
- echo '</div>';
353
  cnb_admin_page_render_thickbox();
 
 
354
  }
355
 
356
  function cnb_admin_page_render_thickbox() {
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
 
9
+ if(!class_exists('WP_List_Table')) {
10
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
11
+ }
12
+
13
  function cnb_add_header_apikey_overview() {
14
  echo 'API keys ';
15
  }
16
 
17
+ function cnb_add_new_apikey_modal_action() {
18
  $url = admin_url('admin.php');
19
  $new_link =
20
  add_query_arg(
82
  }
83
  }
84
 
 
 
 
 
85
  class Cnb_Apikey_List_Table extends WP_List_Table {
86
 
87
  /**
183
  case 'id':
184
  return '<code>' . esc_html($item[ $column_name ]) . '</code>';
185
  case 'name':
186
+ return '<strong>' . esc_html($item[ $column_name ]) . '</strong>';
187
  case 'created':
188
  case 'lastUsed':
189
  case 'updateTime':
265
  $apikey = array('id' => $apikeyId);
266
  CnbAppRemote::cnb_remote_delete_apikey( $apikey );
267
  }
268
+ CnbAdminNotices::get_instance()->renderSuccess('<p>' . count($apikeyIds) . ' Api key(s) deleted.</p>');
269
  break;
270
  }
271
  }
272
  }
273
  }
 
274
 
275
+ function no_items() {
276
+ _e( 'No API keys found.' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  }
278
  }
279
 
280
+ function cnb_delete_apikey() {
281
+ if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
282
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
283
+ $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
284
+ $action = 'cnb_delete_apikey';
285
+
286
+ if (wp_verify_nonce($nonce, $action)) {
287
+ $adminNotices = CnbAdminNotices::get_instance();
288
+ $cnb_cloud_notifications = array();
289
+ CnbAdminCloud::cnb_delete_apikey( $cnb_cloud_notifications, $id );
290
+ foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
291
+ $adminNotices->renderNotice($cnb_cloud_notification);
292
+ }
293
+ }
294
+ }
295
+ }
296
  /**
297
  * Main entrypoint, used by `call-now-button.php`.
298
  */
299
  function cnb_admin_page_apikey_overview_render() {
300
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
301
  $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
302
+
303
  if ($id === null || $action === null) {
304
  cnb_admin_page_apikey_overview_render_list();
305
+ return;
306
+ }
307
+
308
+ switch ($action) {
309
+ case 'delete':
310
+ cnb_delete_apikey();
311
+ cnb_admin_page_apikey_overview_render_list();
312
+ break;
 
 
 
 
 
 
 
 
 
 
313
  }
314
  }
315
 
316
  function cnb_admin_page_apikey_overview_render_list() {
317
+ //Prepare Table of elements
 
 
 
 
 
 
318
  $wp_list_table = new Cnb_Apikey_List_Table();
319
  $data = $wp_list_table->prepare_items();
320
 
321
+ add_action('cnb_header_name', 'cnb_add_header_apikey_overview');
322
+
323
  if ($data instanceof WP_Error) {
324
+ cnb_api_key_invalid_notice($data);
325
  } else {
326
+ add_action('cnb_after_header', 'cnb_add_new_apikey_modal_action');
327
  }
328
 
329
+ do_action('cnb_header');
 
330
 
331
  echo '<form id="wp_list_event" method="post">';
 
332
 
333
  //Table of elements
334
  $wp_list_table->display();
335
  echo '</form>';
 
 
336
  cnb_admin_page_render_thickbox();
337
+
338
+ do_action('cnb_footer');
339
  }
340
 
341
  function cnb_admin_page_render_thickbox() {
src/admin/button-edit.php CHANGED
@@ -5,6 +5,8 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
 
8
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
9
  require_once dirname( __FILE__ ) . '/action-overview.php';
10
  require_once dirname( __FILE__ ) . '/action-edit.php';
@@ -12,7 +14,7 @@ require_once dirname( __FILE__ ) . '/action-edit.php';
12
  /**
13
  * Renders the "Edit <type>" header
14
  *
15
- * @param object $button (optional) Used to determine type if available
16
  */
17
  function cnb_add_header_button_edit($button = null) {
18
  $type = strtoupper(filter_input(INPUT_GET, 'type', FILTER_SANITIZE_STRING));
@@ -26,7 +28,7 @@ function cnb_add_header_button_edit($button = null) {
26
  echo 'Edit ' . esc_html($typeName) . ': "' . esc_html($name) . '"';
27
  }
28
 
29
- function cnb_create_tab_url($button, $tab) {
30
  $url = admin_url('admin.php');
31
  $tab_link =
32
  add_query_arg(
@@ -56,11 +58,14 @@ function cnb_admin_create_button() {
56
  FILTER_SANITIZE_STRING,
57
  FILTER_REQUIRE_ARRAY | FILTER_FLAG_NO_ENCODE_QUOTES);
58
 
59
-
60
  // ensure the position is valid for FULL
61
  if (strtoupper($button['type']) === 'FULL') {
62
- $placement = $button['options']['placement'];
63
- if ($placement !== 'BOTTOM_CENTER' || $placement !== 'TOP_CENTER') {
 
 
 
 
64
  $button['options']['placement'] = 'BOTTOM_CENTER';
65
  }
66
  }
@@ -70,24 +75,33 @@ function cnb_admin_create_button() {
70
  $new_button = CnbAdminCloud::cnb_create_button( $cnb_cloud_notifications, $button );
71
 
72
  // redirect the user to the appropriate page
73
- $tab = filter_input( INPUT_POST, 'tab', FILTER_SANITIZE_STRING );
74
  $transient_id = 'cnb-' . wp_generate_uuid4();
75
- set_transient($transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS);
 
 
 
 
 
 
 
 
76
 
77
  // Create link
78
- $url = admin_url('admin.php');
79
  $redirect_link =
80
  add_query_arg(
81
  array(
82
- 'page' => 'call-now-button',
83
  'action' => 'edit',
84
- 'type' => strtolower($new_button->type),
85
- 'id' => $new_button->id,
86
- 'tid' => $transient_id,
87
- 'tab' => $tab),
 
88
  $url );
89
- $redirect_url = esc_url_raw( $redirect_link );
90
- wp_safe_redirect($redirect_url);
91
  exit;
92
  }
93
  else {
@@ -130,16 +144,22 @@ function cnb_admin_update_button() {
130
 
131
  // ensure the position is valid for FULL
132
  if (strtoupper($button['type']) === 'FULL') {
133
- $placement = $button['options']['placement'];
134
- if ($placement !== 'BOTTOM_CENTER' || $placement !== 'TOP_CENTER') {
 
 
 
 
135
  $button['options']['placement'] = 'BOTTOM_CENTER';
136
  }
137
  }
138
 
139
  // do the processing
140
  $processed_actions = array();
141
- foreach($actions as $action) {
142
- $processed_actions[] = cnb_admin_process_action( $action );
 
 
143
  }
144
  $result = CnbAdminCloud::cnb_update_button_and_conditions( $button, $processed_actions, $conditions );
145
 
@@ -227,13 +247,13 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
227
  <?php } ?>
228
 
229
  <div class="cnb-button-name-field <?php if(!$hide_on_modal) { echo cnb_is_active_tab('basic_options'); } else { echo 'nav-tab-only'; } ?>">
230
- <label for="cnb[name]"><input type="text" name="cnb[name]" id="cnb[name]" class="large-text" placeholder="Name your button" required="required" value="<?php esc_attr_e($button->name); ?>" /></label>
231
  </div>
232
 
233
- <table class="form-table <?php if(!$hide_on_modal) { echo cnb_is_active_tab('basic_options'); } else { echo 'nav-tab-only'; } ?>">
234
  <tr class="cnb_hide_on_modal">
235
- <th scope="row">Button status:</th>
236
-
237
  <td class="activated">
238
  <div class="cnb-radio-item">
239
  <input id="cnb-disable" type="radio" name="cnb[active]" value="0" <?php checked(false, $button->active); ?> />
@@ -242,11 +262,11 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
242
  <div class="cnb-radio-item">
243
  <input id="cnb-enable" type="radio" name="cnb[active]" value="1" <?php checked(true, $button->active); ?> />
244
  <label for="cnb-enable">Enabled</label>
245
- </div>
246
  </td>
247
  </tr>
248
  <tr class="cnb_hide_on_modal cnb_advanced_view">
249
- <th scope="row"><label for="cnb[domain]">Domain:</label></th>
250
  <td>
251
  <select name="cnb[domain]" id="cnb[domain]">
252
  <?php
@@ -274,12 +294,12 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
274
  if ($button->type === 'SINGLE') {
275
  if (!empty($is_active_tab_basic_options)) {
276
  // Create a dummy Action
277
- $action = new stdClass();
278
  $action->id = 'new';
279
  $action->actionType = '';
280
  $action->actionValue = '';
281
  $action->labelText = '';
282
- $action->properties = new stdClass();
283
 
284
  if (sizeof($button->actions) > 0) {
285
  $action = $button->actions[0];
@@ -298,39 +318,26 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
298
  } ?>
299
  <?php if ($button_id === 'new') { ?>
300
  <tr>
301
- <th scope="row">Type</th>
302
- <td></td>
303
  </tr>
304
  <tr>
305
- <th scope="row" colspan="2" class="cnb_type_selector">
306
- <div style="width:33.3%;float:left;text-align: center;<?php if ($button->type !== 'SINGLE') { ?>opacity: 0.25;<?php } ?>" class="cnb_type_selector_single"
307
- onclick="
308
- jQuery('#cnb_type').val('single');
309
- jQuery('.cnb_type_selector_multi').animate({opacity: 0.25});
310
- jQuery('.cnb_type_selector_full').animate({opacity: 0.25});
311
- jQuery(this).animate({opacity: 1});"
312
- >
313
  <img style="max-width:100%;" alt="Choose a Single button type" src="<?php echo $cnb_single_image ?>">
 
314
  </div>
315
- <div style="width:33.3%;float:left;text-align: center;<?php if ($button->type !== 'MULTI') { ?>opacity: 0.25;<?php } ?>" class="cnb_type_selector_multi"
316
- onclick="
317
- jQuery('#cnb_type').val('multi');
318
- jQuery('.cnb_type_selector_single').animate({opacity: 0.25});
319
- jQuery('.cnb_type_selector_full').animate({opacity: 0.25});
320
- jQuery(this).animate({opacity: 1});"
321
- >
322
- <img style="max-width:100%;" alt="Choose a Multi button type" src="<?php echo $cnb_multi_image ?>">
323
  </div>
324
- <div style="width:33.3%;float:left;text-align: center;<?php if ($button->type !== 'FULL') { ?>opacity: 0.25;<?php } ?>" class="cnb_type_selector_full"
325
- onclick="
326
- jQuery('#cnb_type').val('full');
327
- jQuery('.cnb_type_selector_single').animate({opacity: 0.25});
328
- jQuery('.cnb_type_selector_multi').animate({opacity: 0.25});
329
- jQuery(this).animate({opacity: 1});"
330
- >
331
  <img style="max-width:100%;" alt="Choose a Full button type" src="<?php echo $cnb_full_image ?>">
 
332
  </div>
333
- </th>
 
334
  </tr>
335
  <?php } ?>
336
  </table>
@@ -338,7 +345,7 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
338
  <?php if ($button->type === 'FULL') { ?>
339
  <tr>
340
  <th colspan="2">
341
- <h2>Colors for the Button bar are defined via the Actions.</h2>
342
  <input name="cnb[options][iconBackgroundColor]" type="hidden" value="<?php esc_attr_e($button->options->iconBackgroundColor); ?>" />
343
  <input name="cnb[options][iconColor]" type="hidden" value="<?php esc_attr_e($button->options->iconColor); ?>" />
344
  </th>
@@ -349,7 +356,7 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
349
  <td></td>
350
  </tr>
351
  <tr>
352
- <th scope="row"><label for="cnb[options][iconBackgroundColor]">Background color:</label></th>
353
  <td>
354
  <input name="cnb[options][iconBackgroundColor]" id="cnb[options][iconBackgroundColor]" type="text" value="<?php esc_attr_e($button->options->iconBackgroundColor); ?>"
355
  class="cnb-iconcolor-field" data-default-color="#009900"/>
@@ -359,7 +366,7 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
359
  </td>
360
  </tr>
361
  <tr>
362
- <th scope="row"><label for="cnb[options][iconColor]">Icon color:</label></th>
363
  <td>
364
  <input name="cnb[options][iconColor]" id="cnb[options][iconColor]" type="text" value="<?php esc_attr_e($button->options->iconColor); ?>"
365
  class="cnb-iconcolor-field" data-default-color="#FFFFFF"/>
@@ -370,7 +377,7 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
370
  </tr>
371
  <?php } ?>
372
  <tr>
373
- <th scope="row">Position: <a
374
  href="<?php echo CNB_SUPPORT; ?>button-position/<?php cnb_utm_params("question-mark", "button-position"); ?>"
375
  target="_blank" class="cnb-nounderscore">
376
  <span class="dashicons dashicons-editor-help"></span>
@@ -456,7 +463,8 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
456
  <?php } else { ?>
457
  <?php foreach ($button->conditions as $condition) { ?>
458
  <tr class="appearance" id="cnb_condition_<?php esc_attr_e($condition->id) ?>">
459
- <th scope="row"><label for="condition[<?php esc_attr_e($condition->id) ?>][filterType]">Condition:<div class="cnb_font_normal cnb_font_90">ID: <code class="cnb_font_90"><?php esc_html_e($condition->id) ?></code></div></label></th>
 
460
  <td>
461
  <input type="hidden" name="condition[<?php esc_attr_e($condition->id) ?>][id]" value="<?php esc_attr_e($condition->id) ?>" />
462
  <input type="hidden" name="condition[<?php esc_attr_e($condition->id) ?>][conditionType]" value="<?php esc_attr_e($condition->conditionType) ?>" />
@@ -494,7 +502,7 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
494
  <tr id="cnb_form_table_add_condition">
495
  <th></th>
496
  <td>
497
-
498
  </td>
499
  </tr>
500
  </tbody>
@@ -506,14 +514,14 @@ function cnb_button_edit_form($button_id, $button, $default_domain, $options=arr
506
  <?php
507
  }
508
 
 
 
 
509
  function cnb_admin_page_edit_render() {
510
- global $cnb_options, $cnb_settings;
511
-
512
- $cnb_notices = cnb_get_notices();
513
- $cnb_changelog = cnb_get_changelog();
514
 
515
  $button_id = cnb_get_button_id();
516
- $button = new stdClass();
517
 
518
  // Get the various supported domains
519
  $default_domain = CnbAppRemote::cnb_remote_get_wp_domain();
@@ -529,41 +537,32 @@ function cnb_admin_page_edit_render() {
529
  }
530
 
531
  // Set some sane defaults
532
- if (!isset($button->options)) $button->options = new stdClass();
533
- $button->options->iconBackgroundColor = !empty($button->options->iconBackgroundColor)
534
- ? $button->options->iconBackgroundColor
535
- : '#009900';
536
- $button->options->iconColor = !empty($button->options->iconColor)
537
- ? $button->options->iconColor
538
- : '#FFFFFF';
539
- $button->options->placement = !empty($button->options->placement)
540
- ? $button->options->placement
541
- : ($button->type === 'FULL' ? 'BOTTOM_CENTER' : 'BOTTOM_RIGHT');
542
 
543
  // Create options
544
  $options = array();
545
  $options['advanced_view'] = $cnb_options['advanced_view'];
546
 
547
- add_action('cnb_header', function() use($button) {
548
  cnb_add_header_button_edit($button);
549
  });
 
 
550
  ?>
551
 
552
- <div class="wrap">
553
- <?php cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog) ?>
554
- <h2 class="nav-tab-wrapper">
555
- <a href="<?php echo cnb_create_tab_url($button, 'basic_options') ?>"
556
- class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
557
- <?php if ($button_id !== 'new') { ?>
558
- <a href="<?php echo cnb_create_tab_url($button, 'extra_options') ?>"
559
- class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
560
- <a href="<?php echo cnb_create_tab_url($button, 'visibility') ?>"
561
- class="nav-tab <?php echo cnb_is_active_tab('visibility') ?>">Visibility</a>
562
- <?php } else { ?>
563
- <a class="nav-tab"><i>Additional options available after saving</i></a>
564
- <?php } ?>
565
- </h2>
566
- <?php cnb_button_edit_form($button_id, $button, $default_domain, $options) ?>
567
- <?php cnb_admin_footer() ?>
568
- </div>
569
- <?php }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/models/CnbButton.class.php';
9
+ require_once dirname( __FILE__ ) . '/models/CnbAction.class.php';
10
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
11
  require_once dirname( __FILE__ ) . '/action-overview.php';
12
  require_once dirname( __FILE__ ) . '/action-edit.php';
14
  /**
15
  * Renders the "Edit <type>" header
16
  *
17
+ * @param $button CnbButton (optional) Used to determine type if available
18
  */
19
  function cnb_add_header_button_edit($button = null) {
20
  $type = strtoupper(filter_input(INPUT_GET, 'type', FILTER_SANITIZE_STRING));
28
  echo 'Edit ' . esc_html($typeName) . ': "' . esc_html($name) . '"';
29
  }
30
 
31
+ function cnb_create_tab_url_button($button, $tab) {
32
  $url = admin_url('admin.php');
33
  $tab_link =
34
  add_query_arg(
58
  FILTER_SANITIZE_STRING,
59
  FILTER_REQUIRE_ARRAY | FILTER_FLAG_NO_ENCODE_QUOTES);
60
 
 
61
  // ensure the position is valid for FULL
62
  if (strtoupper($button['type']) === 'FULL') {
63
+ if (!empty($button['options']) && !empty($button['options']['placement'])) {
64
+ $placement = $button['options']['placement'];
65
+ if ($placement !== 'BOTTOM_CENTER' && $placement !== 'TOP_CENTER') {
66
+ $button['options']['placement'] = 'BOTTOM_CENTER';
67
+ }
68
+ } else {
69
  $button['options']['placement'] = 'BOTTOM_CENTER';
70
  }
71
  }
75
  $new_button = CnbAdminCloud::cnb_create_button( $cnb_cloud_notifications, $button );
76
 
77
  // redirect the user to the appropriate page
78
+ $tab = filter_input( INPUT_POST, 'tab', FILTER_SANITIZE_STRING );
79
  $transient_id = 'cnb-' . wp_generate_uuid4();
80
+ set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
81
+
82
+ if ($new_button instanceof WP_Error) {
83
+ $new_button_type = null;
84
+ $new_button_id = null;
85
+ } else {
86
+ $new_button_type = strtolower( $new_button->type );
87
+ $new_button_id = $new_button->id;
88
+ }
89
 
90
  // Create link
91
+ $url = admin_url( 'admin.php' );
92
  $redirect_link =
93
  add_query_arg(
94
  array(
95
+ 'page' => 'call-now-button',
96
  'action' => 'edit',
97
+ 'type' => $new_button_type,
98
+ 'id' => $new_button_id,
99
+ 'tid' => $transient_id,
100
+ 'tab' => $tab
101
+ ),
102
  $url );
103
+ $redirect_url = esc_url_raw( $redirect_link );
104
+ wp_safe_redirect( $redirect_url );
105
  exit;
106
  }
107
  else {
144
 
145
  // ensure the position is valid for FULL
146
  if (strtoupper($button['type']) === 'FULL') {
147
+ if (!empty($button['options']) && !empty($button['options']['placement'])) {
148
+ $placement = $button['options']['placement'];
149
+ if ( $placement !== 'BOTTOM_CENTER' && $placement !== 'TOP_CENTER' ) {
150
+ $button['options']['placement'] = 'BOTTOM_CENTER';
151
+ }
152
+ } else {
153
  $button['options']['placement'] = 'BOTTOM_CENTER';
154
  }
155
  }
156
 
157
  // do the processing
158
  $processed_actions = array();
159
+ if (is_array($actions)) {
160
+ foreach ( $actions as $action ) {
161
+ $processed_actions[] = cnb_admin_process_action( $action );
162
+ }
163
  }
164
  $result = CnbAdminCloud::cnb_update_button_and_conditions( $button, $processed_actions, $conditions );
165
 
247
  <?php } ?>
248
 
249
  <div class="cnb-button-name-field <?php if(!$hide_on_modal) { echo cnb_is_active_tab('basic_options'); } else { echo 'nav-tab-only'; } ?>">
250
+ <label for="cnb[name]"><input type="text" name="cnb[name]" id="cnb[name]" class="large-text" placeholder="Button name" required="required" value="<?php esc_attr_e($button->name); ?>" /></label>
251
  </div>
252
 
253
+ <table class="form-table <?php if(!$hide_on_modal) { echo cnb_is_active_tab('basic_options'); } else { echo 'nav-tab-only'; } ?>">
254
  <tr class="cnb_hide_on_modal">
255
+ <th scope="row">Button status</th>
256
+
257
  <td class="activated">
258
  <div class="cnb-radio-item">
259
  <input id="cnb-disable" type="radio" name="cnb[active]" value="0" <?php checked(false, $button->active); ?> />
262
  <div class="cnb-radio-item">
263
  <input id="cnb-enable" type="radio" name="cnb[active]" value="1" <?php checked(true, $button->active); ?> />
264
  <label for="cnb-enable">Enabled</label>
265
+ </div>
266
  </td>
267
  </tr>
268
  <tr class="cnb_hide_on_modal cnb_advanced_view">
269
+ <th scope="row"><label for="cnb[domain]">Domain</label></th>
270
  <td>
271
  <select name="cnb[domain]" id="cnb[domain]">
272
  <?php
294
  if ($button->type === 'SINGLE') {
295
  if (!empty($is_active_tab_basic_options)) {
296
  // Create a dummy Action
297
+ $action = new CnbAction();
298
  $action->id = 'new';
299
  $action->actionType = '';
300
  $action->actionValue = '';
301
  $action->labelText = '';
302
+ $action->properties = new CnbActionProperties();
303
 
304
  if (sizeof($button->actions) > 0) {
305
  $action = $button->actions[0];
318
  } ?>
319
  <?php if ($button_id === 'new') { ?>
320
  <tr>
321
+ <th scope="row">Select button type</th>
322
+
323
  </tr>
324
  <tr>
325
+ <td scope="row" colspan="2" class="cnb_type_selector">
326
+ <div class="cnb-flexbox">
327
+ <div class="cnb_type_selector_item cnb_type_selector_single cnb_type_selector_active" data-cnb-selection="single">
 
 
 
 
 
328
  <img style="max-width:100%;" alt="Choose a Single button type" src="<?php echo $cnb_single_image ?>">
329
+ <div style="text-align:center">Single button</div>
330
  </div>
331
+ <div class="cnb_type_selector_item cnb_type_selector_multi" data-cnb-selection="multi">
332
+ <img style="max-width:100%;" alt="Choose a Multibutton type" src="<?php echo $cnb_multi_image ?>">
333
+ <div style="text-align:center">Multibutton</div>
 
 
 
 
 
334
  </div>
335
+ <div class="cnb_type_selector_item cnb_type_selector_full" data-cnb-selection="full">
 
 
 
 
 
 
336
  <img style="max-width:100%;" alt="Choose a Full button type" src="<?php echo $cnb_full_image ?>">
337
+ <div style="text-align:center">Buttonbar</div>
338
  </div>
339
+ </div>
340
+ </td>
341
  </tr>
342
  <?php } ?>
343
  </table>
345
  <?php if ($button->type === 'FULL') { ?>
346
  <tr>
347
  <th colspan="2">
348
+ <h2>Colors for the Buttonbar are defined via the Actions.</h2>
349
  <input name="cnb[options][iconBackgroundColor]" type="hidden" value="<?php esc_attr_e($button->options->iconBackgroundColor); ?>" />
350
  <input name="cnb[options][iconColor]" type="hidden" value="<?php esc_attr_e($button->options->iconColor); ?>" />
351
  </th>
356
  <td></td>
357
  </tr>
358
  <tr>
359
+ <th scope="row"><label for="cnb[options][iconBackgroundColor]">Background color</label></th>
360
  <td>
361
  <input name="cnb[options][iconBackgroundColor]" id="cnb[options][iconBackgroundColor]" type="text" value="<?php esc_attr_e($button->options->iconBackgroundColor); ?>"
362
  class="cnb-iconcolor-field" data-default-color="#009900"/>
366
  </td>
367
  </tr>
368
  <tr>
369
+ <th scope="row"><label for="cnb[options][iconColor]">Icon color</label></th>
370
  <td>
371
  <input name="cnb[options][iconColor]" id="cnb[options][iconColor]" type="text" value="<?php esc_attr_e($button->options->iconColor); ?>"
372
  class="cnb-iconcolor-field" data-default-color="#FFFFFF"/>
377
  </tr>
378
  <?php } ?>
379
  <tr>
380
+ <th scope="row">Position <a
381
  href="<?php echo CNB_SUPPORT; ?>button-position/<?php cnb_utm_params("question-mark", "button-position"); ?>"
382
  target="_blank" class="cnb-nounderscore">
383
  <span class="dashicons dashicons-editor-help"></span>
463
  <?php } else { ?>
464
  <?php foreach ($button->conditions as $condition) { ?>
465
  <tr class="appearance" id="cnb_condition_<?php esc_attr_e($condition->id) ?>">
466
+ <th scope="row"><label for="condition[<?php esc_attr_e($condition->id) ?>][filterType]">Condition
467
+ <div class="cnb_font_normal cnb_font_90 cnb_advanced_view">ID: <code class="cnb_font_90"><?php esc_html_e($condition->id) ?></code></div></label></th>
468
  <td>
469
  <input type="hidden" name="condition[<?php esc_attr_e($condition->id) ?>][id]" value="<?php esc_attr_e($condition->id) ?>" />
470
  <input type="hidden" name="condition[<?php esc_attr_e($condition->id) ?>][conditionType]" value="<?php esc_attr_e($condition->conditionType) ?>" />
502
  <tr id="cnb_form_table_add_condition">
503
  <th></th>
504
  <td>
505
+
506
  </td>
507
  </tr>
508
  </tbody>
514
  <?php
515
  }
516
 
517
+ /**
518
+ * Main entrypoint, used by `call-now-button.php`.
519
+ */
520
  function cnb_admin_page_edit_render() {
521
+ global $cnb_options;
 
 
 
522
 
523
  $button_id = cnb_get_button_id();
524
+ $button = new CnbButton();
525
 
526
  // Get the various supported domains
527
  $default_domain = CnbAppRemote::cnb_remote_get_wp_domain();
537
  }
538
 
539
  // Set some sane defaults
540
+ CnbButton::setSaneDefault($button);
 
 
 
 
 
 
 
 
 
541
 
542
  // Create options
543
  $options = array();
544
  $options['advanced_view'] = $cnb_options['advanced_view'];
545
 
546
+ add_action('cnb_header_name', function() use($button) {
547
  cnb_add_header_button_edit($button);
548
  });
549
+
550
+ do_action('cnb_header');
551
  ?>
552
 
553
+ <h2 class="nav-tab-wrapper">
554
+ <a href="<?php echo cnb_create_tab_url_button($button, 'basic_options') ?>"
555
+ class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
556
+ <?php if ($button_id !== 'new') { ?>
557
+ <a href="<?php echo cnb_create_tab_url_button($button, 'extra_options') ?>"
558
+ class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
559
+ <a href="<?php echo cnb_create_tab_url_button($button, 'visibility') ?>"
560
+ class="nav-tab <?php echo cnb_is_active_tab('visibility') ?>">Visibility</a>
561
+ <?php } else { ?>
562
+ <a class="nav-tab"><i>Additional options available after saving</i></a>
563
+ <?php } ?>
564
+ </h2>
565
+ <?php
566
+ cnb_button_edit_form($button_id, $button, $default_domain, $options);
567
+ do_action('cnb_footer');
568
+ }
 
 
src/admin/button-overview.php CHANGED
@@ -5,9 +5,14 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
8
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
9
  require_once dirname( __FILE__ ) . '/button-edit.php';
10
 
 
 
 
 
11
  function cnb_add_header_button_overview() {
12
  echo 'Buttons ';
13
  }
@@ -26,7 +31,7 @@ function cnb_add_new_modal_action() {
26
  'id' => 'new' ),
27
  $url );
28
  printf(
29
- '<a href="%s" title="%s" class="thickbox open-plugin-details-modal page-title-action" data-title="%s">%s</a>',
30
  $new_link,
31
  __('Create new button', CNB_NAME),
32
  __('Choose a Button type', CNB_NAME),
@@ -34,13 +39,20 @@ function cnb_add_new_modal_action() {
34
  );
35
  }
36
 
37
- if(!class_exists('WP_List_Table')) {
38
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
39
- }
40
 
41
  class Cnb_Button_List_Table extends WP_List_Table {
42
 
 
 
 
 
 
43
  private $data;
 
 
 
 
 
44
  /**
45
  * Constructor, we override the parent to pass our own arguments
46
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
@@ -53,6 +65,10 @@ class Cnb_Button_List_Table extends WP_List_Table {
53
  ));
54
  }
55
 
 
 
 
 
56
  /**
57
  * Define the columns that are going to be used in the table
58
  * @return array $columns, the array of columns to use with the table
@@ -64,7 +80,6 @@ class Cnb_Button_List_Table extends WP_List_Table {
64
  'name' => __('Name'),
65
  'type' => __('Type'),
66
  'actions' => __('Actions'),
67
- 'status' => __('Status')
68
  );
69
  }
70
 
@@ -73,7 +88,6 @@ class Cnb_Button_List_Table extends WP_List_Table {
73
  'name' => array('name', false),
74
  'type' => array('type', false),
75
  'title' => array('title', false),
76
- 'status' => array('status', false),
77
  );
78
  }
79
 
@@ -191,8 +205,7 @@ class Cnb_Button_List_Table extends WP_List_Table {
191
  }
192
  case 'actions':
193
  // Moved to column_actions
194
- case 'status':
195
- return $item[ $column_name ] ? 'Active' : 'Inactive';
196
 
197
  default:
198
  return '<em>Unknown column ' .esc_html($column_name) . '</em>';
@@ -238,12 +251,16 @@ class Cnb_Button_List_Table extends WP_List_Table {
238
  }
239
 
240
  private function get_data() {
241
- if ($this->data != null) return $this->data;
242
  $buttons = CnbAppRemote::cnb_remote_get_buttons_full();
243
 
244
  if ($buttons instanceof WP_Error) {
 
245
  return $buttons;
246
  }
 
 
 
247
 
248
  $data = array();
249
  foreach ($buttons as $button) {
@@ -256,10 +273,16 @@ class Cnb_Button_List_Table extends WP_List_Table {
256
  'domain' => $button->domain
257
  );
258
  }
 
 
 
 
 
 
 
259
  $this->data = $data;
260
  return $data;
261
  }
262
-
263
 
264
  /**
265
  * Allows you to sort the data by the variables set in the $_GET
@@ -274,11 +297,6 @@ class Cnb_Button_List_Table extends WP_List_Table {
274
 
275
  $result = strcmp( $a[$orderby], $b[$orderby] );
276
 
277
- // Flip Enabled/Disabled, since we actually consider "Enabled" to be before "Disabled"
278
- if ($orderby === 'status') {
279
- $result = -$result;
280
- }
281
-
282
  if($order === 'asc') {
283
  return $result;
284
  }
@@ -336,9 +354,13 @@ class Cnb_Button_List_Table extends WP_List_Table {
336
  $delete_url = esc_url( $delete_link );
337
  $actions['delete'] = '<a href="'.$delete_url.'">Delete</a>';
338
 
 
 
 
 
339
  return sprintf(
340
  '%1$s %2$s',
341
- '<a href="'.$edit_url.'">'.esc_html($item['name']) . '</a>',
342
  $this->row_actions($actions)
343
  );
344
  }
@@ -365,19 +387,61 @@ class Cnb_Button_List_Table extends WP_List_Table {
365
  $button = array('id' => $buttonId, 'active' => $this->current_action() === 'enable');
366
  CnbAppRemote::cnb_remote_update_button( $button );
367
  }
368
- echo '<div class="notice-success notice"><p>' . count($buttonIds) . ' Buttons updated</p></div>';
369
  break;
370
  case 'delete':
371
  foreach ($buttonIds as $buttonId) {
372
  $button = array('id' => $buttonId);
373
  CnbAppRemote::cnb_remote_delete_button( $button );
374
  }
375
- echo '<div class="notice-success notice"><p>' . count($buttonIds) . ' Button(s) deleted</p></div>';
376
  break;
377
  }
378
  }
379
  }
380
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  }
382
 
383
  /**
@@ -385,70 +449,49 @@ class Cnb_Button_List_Table extends WP_List_Table {
385
  */
386
  function cnb_admin_button_overview_render() {
387
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
388
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
389
 
390
  if ($id === null) {
391
  cnb_admin_page_overview_render_list();
392
- } else {
393
- switch ($action) {
394
- case 'new':
395
- case 'edit':
396
- require_once dirname( __FILE__ ) . "/button-edit.php";
397
- cnb_admin_page_edit_render();
398
- break;
399
- case 'cnb_enable_button':
400
- case 'cnb_disable_button':
401
- if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
402
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
403
-
404
- if ( wp_verify_nonce( $nonce, 'cnb_enable_disable_button' ) ) {
405
- $buttonId = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
406
- $button = array( 'id' => $buttonId, 'active' => $action === 'cnb_enable_button' );
407
- CnbAppRemote::cnb_remote_update_button( $button );
408
- echo '<div class="notice-success notice is-dismissible"><p>Button <code>' . esc_html($buttonId) . '</code> updated</p></div>';
409
- } else {
410
- echo '<div class="notice-error notice"><p>Something went wrong</p></div>';
411
- }
412
- }
413
  cnb_admin_page_overview_render_list();
414
  break;
415
- case 'cnb_delete_button':
416
- if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
417
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
418
-
419
- if ( wp_verify_nonce( $nonce, $action ) ) {
420
- $cnb_cloud_notifications = array();
421
- CnbAdminCloud::cnb_delete_button( $cnb_cloud_notifications, $id );
422
- foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
423
- echo $cnb_cloud_notification;
424
- }
425
- }
426
- }
427
- cnb_admin_page_overview_render_list();
428
- break;
429
- }
430
  }
431
  }
432
 
433
  function cnb_admin_page_overview_render_list() {
434
- global $cnb_options, $cnb_settings;
435
 
436
- $cnb_notices = cnb_get_notices();
437
- $cnb_changelog = cnb_get_changelog();
438
 
439
  //Prepare Table of elements
440
  $wp_list_table = new Cnb_Button_List_Table();
441
- $data = $wp_list_table->prepare_items();
442
 
443
- if ($data instanceof WP_Error) {
444
- $cnb_notices[] = cnb_admin_header_get_cloud_error($data);
445
- } else {
446
- add_action('cnb_header', 'cnb_add_header_button_overview');
447
- add_action('cnb_after_header', 'cnb_add_new_modal_action');
 
448
  }
449
 
450
- $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
451
- if (!($cnb_cloud_domain instanceof WP_Error)) {
 
452
  $url = admin_url('admin.php');
453
  $upgrade_link =
454
  add_query_arg(array(
@@ -459,52 +502,55 @@ function cnb_admin_page_overview_render_list() {
459
  $url);
460
  $upgrade_url = esc_url($upgrade_link);
461
  }
462
- echo '<div class="wrap">';
463
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
464
 
465
- echo '<div id="poststuff">
 
466
 
467
- <div id="post-body" class="metabox-holder columns-2">
468
- <div id="post-body-content" style="position: relative;">';
 
 
469
 
470
- // Check if we should warn about inactive buttons
471
- $views = $wp_list_table->get_views();
472
- $active_views = isset($views['active']) ? $views['active'] : '';
473
- if (false !== strpos($active_views, '(0)')) {
474
- echo '<div class="notice-warning notice"><p><strong>You have no active buttons.</strong> Create or enable one (or more) buttons to use the Call Now Button.</p></div>';
 
 
 
475
  }
 
 
 
 
 
 
 
476
  $wp_list_table->views();
477
 
478
  echo '<form id="wp_list_event" method="post">';
479
-
480
- //Table of elements
481
- $wp_list_table->display();
482
- echo '</form></div>' ?>
483
 
484
  <?php if (isset($upgrade_url)) { ?>
485
  <div id="postbox-container-1" class="postbox-container"> <!-- Sidebar promo boxes -->
486
- <?php if (!($cnb_cloud_domain instanceof WP_Error) && $cnb_cloud_domain->type === 'FREE') { ?>
487
  <!-- Sidebar messages -->
488
  <div id="cnb_upgrade_box" class="postbox "> <!-- Upgrade promobox -->
489
  <div class="postbox-header">
490
- <h2 class="hndle">Need more power?</h2>
491
  </div>
492
  <div class="inside">
493
  <div class="submitbox" id="submitpost">
494
  <div id="minor-publishing">
495
  <div id="misc-publishing-actions">
496
- <div class="cnb_promobox_item">Upgrade to add the following functionality:</div>
497
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Unlimited buttons</div>
498
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Email, Maps, URL, WhatsApp</div>
499
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Button bar with multiple actions</div>
500
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Expandable multi button</div>
501
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Advanced page selection per button</div>
502
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">Button scheduling</div>
503
- <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox">And much more!</div>
504
  </div>
505
  <div class="clear"></div>
506
  </div>
507
  <div id="major-publishing-actions">
 
508
  <div id="publishing-action">
509
  <a class="button button-primary button-large" href="<?php echo $upgrade_url ?>">Upgrade</a>
510
  </div>
@@ -530,22 +576,22 @@ function cnb_admin_page_overview_render_list() {
530
  <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox"><a href="https://help.callnowbutton.com/" target="_blank">FAQ</a></div>
531
  </div>
532
  <div class="clear"></div>
533
- </div>
534
  </div>
535
  </div>
536
  </div>
537
  </div><!-- end #postbox-container-1 -->
538
  <?php } ?>
539
-
540
-
541
-
542
-
543
  <br class="clear">
544
  <?php
545
- echo '</div><!--End #poststuff -->';
546
- cnb_admin_footer();
547
- echo '</div>';
548
- cnb_admin_page_render_thickbox($cnb_cloud_domain);
 
 
 
549
  }
550
 
551
  function cnb_admin_page_render_thickbox($default_domain = null) {
@@ -560,30 +606,19 @@ function cnb_admin_page_render_thickbox($default_domain = null) {
560
  $button_id = 'new';
561
 
562
  // Create a dummy button
563
- $button = new stdClass();
564
- $button->id = '';
565
- $button->active = false;
566
- $button->name = '';
567
- $button->type = 'SINGLE';
568
- $button->domain = $default_domain;
569
- $button->actions = array();
570
-
571
- // Set some sane defaults
572
- if (!isset($button->options)) $button->options = new stdClass();
573
- $button->options->iconBackgroundColor = !empty($button->options->iconBackgroundColor)
574
- ? $button->options->iconBackgroundColor
575
- : '#009900';
576
- $button->options->iconColor = !empty($button->options->iconColor)
577
- ? $button->options->iconColor
578
- : '#FFFFFF';
579
- $button->options->placement = !empty($button->options->placement)
580
- ? $button->options->placement
581
- : ($button->type === 'FULL' ? 'BOTTOM_CENTER' : 'BOTTOM_RIGHT');
582
- $button->options->scale = !empty($button->options->scale)
583
- ? $button->options->scale
584
- : '1';
585
 
586
  $options = array('modal_view' => true, 'submit_button_text' => 'Next');
587
  cnb_button_edit_form($button_id, $button, $default_domain, $options);
588
  echo '</div></div>';
 
 
 
 
 
 
 
 
 
589
  }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/models/CnbButton.class.php';
9
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
10
  require_once dirname( __FILE__ ) . '/button-edit.php';
11
 
12
+ if(!class_exists('WP_List_Table')) {
13
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
14
+ }
15
+
16
  function cnb_add_header_button_overview() {
17
  echo 'Buttons ';
18
  }
31
  'id' => 'new' ),
32
  $url );
33
  printf(
34
+ '<a href="%s" title="%s" class="thickbox open-plugin-details-modal page-title-action" id="cnb-button-overview-modal-add-new" data-title="%s">%s</a>',
35
  $new_link,
36
  __('Create new button', CNB_NAME),
37
  __('Choose a Button type', CNB_NAME),
39
  );
40
  }
41
 
 
 
 
42
 
43
  class Cnb_Button_List_Table extends WP_List_Table {
44
 
45
+ /**
46
+ * Used as a local caching variable to avoid multiple calls to the external datasource (i.e. API calls)
47
+ *
48
+ * @var array of Buttons
49
+ */
50
  private $data;
51
+
52
+ private $options = array(
53
+ 'filter_buttons_for_domain' => null,
54
+ );
55
+
56
  /**
57
  * Constructor, we override the parent to pass our own arguments
58
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
65
  ));
66
  }
67
 
68
+ function setOption($optionName, $optionValue) {
69
+ $this->options[$optionName] = $optionValue;
70
+ }
71
+
72
  /**
73
  * Define the columns that are going to be used in the table
74
  * @return array $columns, the array of columns to use with the table
80
  'name' => __('Name'),
81
  'type' => __('Type'),
82
  'actions' => __('Actions'),
 
83
  );
84
  }
85
 
88
  'name' => array('name', false),
89
  'type' => array('type', false),
90
  'title' => array('title', false),
 
91
  );
92
  }
93
 
205
  }
206
  case 'actions':
207
  // Moved to column_actions
208
+ break;
 
209
 
210
  default:
211
  return '<em>Unknown column ' .esc_html($column_name) . '</em>';
251
  }
252
 
253
  private function get_data() {
254
+ if (is_array($this->data)) return $this->data;
255
  $buttons = CnbAppRemote::cnb_remote_get_buttons_full();
256
 
257
  if ($buttons instanceof WP_Error) {
258
+ $this->data = array();
259
  return $buttons;
260
  }
261
+ if ($buttons === null) {
262
+ $buttons = array();
263
+ }
264
 
265
  $data = array();
266
  foreach ($buttons as $button) {
273
  'domain' => $button->domain
274
  );
275
  }
276
+
277
+ // Filter for current or all domains
278
+ $filterOnDomainId = $this->options['filter_buttons_for_domain'];
279
+ if ($filterOnDomainId) {
280
+ $data = array_filter($data, function($el) use ( $filterOnDomainId ) { return $el['domain']->id === $filterOnDomainId; });
281
+ }
282
+
283
  $this->data = $data;
284
  return $data;
285
  }
 
286
 
287
  /**
288
  * Allows you to sort the data by the variables set in the $_GET
297
 
298
  $result = strcmp( $a[$orderby], $b[$orderby] );
299
 
 
 
 
 
 
300
  if($order === 'asc') {
301
  return $result;
302
  }
354
  $delete_url = esc_url( $delete_link );
355
  $actions['delete'] = '<a href="'.$delete_url.'">Delete</a>';
356
 
357
+ $inactive_str = '';
358
+ if (!$item['status']) {
359
+ $inactive_str = ' — <span class="post-state">Inactive</span>';
360
+ }
361
  return sprintf(
362
  '%1$s %2$s',
363
+ '<strong><a class="row-title" href="'.$edit_url.'">'.esc_html($item['name']) . '</a>' . $inactive_str . '</strong>',
364
  $this->row_actions($actions)
365
  );
366
  }
387
  $button = array('id' => $buttonId, 'active' => $this->current_action() === 'enable');
388
  CnbAppRemote::cnb_remote_update_button( $button );
389
  }
390
+ CnbAdminNotices::get_instance()->renderSuccess('<p>' . count($buttonIds) . ' Buttons updated.</p>');
391
  break;
392
  case 'delete':
393
  foreach ($buttonIds as $buttonId) {
394
  $button = array('id' => $buttonId);
395
  CnbAppRemote::cnb_remote_delete_button( $button );
396
  }
397
+ CnbAdminNotices::get_instance()->renderSuccess('<p>' . count($buttonIds) . ' Button(s) deleted.</p>');
398
  break;
399
  }
400
  }
401
  }
402
  }
403
+
404
+ function no_items() {
405
+ _e( 'No buttons found.' );
406
+ }
407
+ }
408
+
409
+ function cnb_enable_disable_button($action) {
410
+ if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
411
+ $id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
412
+ $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
413
+
414
+ if ( wp_verify_nonce( $nonce, 'cnb_enable_disable_button' ) ) {
415
+ $active = $action === 'cnb_enable_button';
416
+ $action_verb = $active ? 'enable' : 'disable';
417
+ $action_name = $action_verb . 'd';
418
+ $button = array( 'id' => $id, 'active' => $active );
419
+ $updated_button = CnbAppRemote::cnb_remote_update_button( $button );
420
+
421
+ if (!is_wp_error($updated_button)) {
422
+ $notice = new CnbNotice( 'success', '<p>Button <strong>' . esc_html( $updated_button->name ) . '</strong> '.$action_name.'.</p>', true );
423
+ } else {
424
+ $notice = CnbAdminCloud::cnb_admin_get_error_message($action_verb, 'button', $updated_button);
425
+ }
426
+ CnbAdminNotices::get_instance()->renderNotice($notice);
427
+ }
428
+ }
429
+ }
430
+
431
+ function cnb_delete_button($action) {
432
+ if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
433
+ $id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
434
+ $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
435
+
436
+ if ( wp_verify_nonce( $nonce, $action ) ) {
437
+ $cnb_cloud_notifications = array();
438
+ CnbAdminCloud::cnb_delete_button( $cnb_cloud_notifications, $id );
439
+ // TODO Should we be rendering ALL notices?!
440
+ foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
441
+ CnbAdminNotices::get_instance()->renderNotice($cnb_cloud_notification);
442
+ }
443
+ }
444
+ }
445
  }
446
 
447
  /**
449
  */
450
  function cnb_admin_button_overview_render() {
451
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
 
452
 
453
  if ($id === null) {
454
  cnb_admin_page_overview_render_list();
455
+ return;
456
+ }
457
+
458
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
459
+ switch ($action) {
460
+ case 'new':
461
+ case 'edit':
462
+ cnb_admin_page_edit_render();
463
+ break;
464
+ case 'cnb_enable_button':
465
+ case 'cnb_disable_button':
466
+ cnb_enable_disable_button($action);
467
+ cnb_admin_page_overview_render_list();
468
+ break;
469
+ case 'cnb_delete_button':
470
+ cnb_delete_button($action);
 
 
 
 
 
471
  cnb_admin_page_overview_render_list();
472
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  }
474
  }
475
 
476
  function cnb_admin_page_overview_render_list() {
477
+ global $cnb_options;
478
 
479
+ $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
 
480
 
481
  //Prepare Table of elements
482
  $wp_list_table = new Cnb_Button_List_Table();
 
483
 
484
+ // Set filter
485
+ if (isset($cnb_options['show_all_buttons_for_domain'])
486
+ && $cnb_options['show_all_buttons_for_domain'] != 1
487
+ && $cnb_cloud_domain != null
488
+ && !($cnb_cloud_domain instanceof WP_Error)) {
489
+ $wp_list_table->setOption( 'filter_buttons_for_domain', $cnb_cloud_domain->id);
490
  }
491
 
492
+ add_action('cnb_header_name', 'cnb_add_header_button_overview');
493
+
494
+ if ($cnb_cloud_domain !== null && !($cnb_cloud_domain instanceof WP_Error)) {
495
  $url = admin_url('admin.php');
496
  $upgrade_link =
497
  add_query_arg(array(
502
  $url);
503
  $upgrade_url = esc_url($upgrade_link);
504
  }
 
 
505
 
506
+ // CNB: Start content
507
+ $data = $wp_list_table->prepare_items();
508
 
509
+ if ($data instanceof WP_Error) {
510
+ cnb_api_key_invalid_notice( $data );
511
+ } else {
512
+ add_action('cnb_after_header', 'cnb_add_new_modal_action');
513
 
514
+ // Check if we should warn about inactive buttons
515
+ $views = $wp_list_table->get_views();
516
+ $active_views = isset($views['active']) ? $views['active'] : '';
517
+ if (false !== strpos($active_views, '(0)')) {
518
+ $message = '<p>You have no active buttons. The Call Now Button is not visible to your visitors.</p>';
519
+ $adminNotices = CnbAdminNotices::get_instance();
520
+ $adminNotices->renderWarning($message);
521
+ }
522
  }
523
+
524
+ do_action('cnb_header');
525
+
526
+ echo '<div id="poststuff">
527
+ <div id="post-body" class="metabox-holder columns-2">
528
+ <div id="post-body-content" style="position: relative;">';
529
+
530
  $wp_list_table->views();
531
 
532
  echo '<form id="wp_list_event" method="post">';
533
+ $wp_list_table->display(); //Table of elements
534
+ echo '</form></div><!--End #post-body-content-->' ?>
 
 
535
 
536
  <?php if (isset($upgrade_url)) { ?>
537
  <div id="postbox-container-1" class="postbox-container"> <!-- Sidebar promo boxes -->
538
+ <?php if ($cnb_cloud_domain !== null && !($cnb_cloud_domain instanceof WP_Error) && $cnb_cloud_domain->type === 'FREE') { ?>
539
  <!-- Sidebar messages -->
540
  <div id="cnb_upgrade_box" class="postbox "> <!-- Upgrade promobox -->
541
  <div class="postbox-header">
542
+ <h2 class="hndle">"Powered by Call Now Button"</h2>
543
  </div>
544
  <div class="inside">
545
  <div class="submitbox" id="submitpost">
546
  <div id="minor-publishing">
547
  <div id="misc-publishing-actions">
548
+ <div class="cnb_promobox_item">Remove the "Powered by" mesage from your buttons for just &euro;1.67/$1.99 per month.</div>
 
 
 
 
 
 
 
549
  </div>
550
  <div class="clear"></div>
551
  </div>
552
  <div id="major-publishing-actions">
553
+
554
  <div id="publishing-action">
555
  <a class="button button-primary button-large" href="<?php echo $upgrade_url ?>">Upgrade</a>
556
  </div>
576
  <div class="cnb_promobox_item cnb-side-icon cnb-side-checkbox"><a href="https://help.callnowbutton.com/" target="_blank">FAQ</a></div>
577
  </div>
578
  <div class="clear"></div>
579
+ </div>
580
  </div>
581
  </div>
582
  </div>
583
  </div><!-- end #postbox-container-1 -->
584
  <?php } ?>
585
+
 
 
 
586
  <br class="clear">
587
  <?php
588
+ echo '</div><!--End #post-body-->';
589
+ echo '</div><!--End #poststuff-->';
590
+ // Do not do this when there are errors!
591
+ if (!is_wp_error($data)) {
592
+ cnb_admin_page_render_thickbox( $cnb_cloud_domain );
593
+ }
594
+ do_action('cnb_footer');
595
  }
596
 
597
  function cnb_admin_page_render_thickbox($default_domain = null) {
606
  $button_id = 'new';
607
 
608
  // Create a dummy button
609
+ $button = CnbButton::createDummyButton($default_domain);
610
+ CnbButton::setSaneDefault($button);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
 
612
  $options = array('modal_view' => true, 'submit_button_text' => 'Next');
613
  cnb_button_edit_form($button_id, $button, $default_domain, $options);
614
  echo '</div></div>';
615
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
616
+ if ($action === 'new') {
617
+ echo '
618
+ <script>jQuery( document ).ready(function() {
619
+ setTimeout(function() {
620
+ jQuery("#cnb-button-overview-modal-add-new").click();
621
+ });
622
+ });</script>';
623
+ }
624
  }
src/admin/condition-edit.php CHANGED
@@ -5,6 +5,7 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
8
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
9
 
10
  function cnb_add_header_condition_edit($condition) {
@@ -23,6 +24,73 @@ function cnb_add_header_condition_edit($condition) {
23
  }
24
  }
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  /**
27
  * This is called to update the condition
28
  * via `call-now-button.php#cnb_update_condition`
@@ -30,7 +98,7 @@ function cnb_add_header_condition_edit($condition) {
30
  function cnb_admin_page_condition_edit_process() {
31
  global $cnb_slug_base;
32
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
33
- if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb-condition-edit') ) {
34
 
35
  // sanitize the input
36
  $conditions = filter_input(
@@ -89,7 +157,7 @@ function cnb_admin_page_condition_edit_process() {
89
  }
90
  }
91
 
92
- function cnb_create_tab_url($button, $tab) {
93
  $url = admin_url('admin.php');
94
  $tab_link =
95
  add_query_arg(
@@ -104,10 +172,10 @@ function cnb_create_tab_url($button, $tab) {
104
  }
105
 
106
  /**
107
- * @param $condition
108
- * @param object? $button
109
  */
110
- function cnb_render_form($condition, $button=null) { ?>
 
111
  <table class="form-table nav-tab-active">
112
  <tr>
113
  <th colspan="2"><h2>Basic Settings</h2>
@@ -152,13 +220,8 @@ function cnb_render_form($condition, $button=null) { ?>
152
  }
153
 
154
  function cnb_admin_page_condition_edit_render() {
155
- global $cnb_options, $cnb_settings;
156
-
157
- $cnb_notices = cnb_get_notices();
158
- $cnb_changelog = cnb_get_changelog();
159
-
160
  $condition_id = cnb_get_button_id();
161
- $condition = new stdClass();
162
  $button = null;
163
  if (strlen($condition_id) > 0 && $condition_id !== 'new') {
164
  $condition = CnbAppRemote::cnb_remote_get_condition( $condition_id );
@@ -166,13 +229,10 @@ function cnb_admin_page_condition_edit_render() {
166
  $condition->id = 'new';
167
  }
168
 
169
- add_action('cnb_header', function() use($condition) {
170
  cnb_add_header_condition_edit($condition);
171
  });
172
 
173
- echo '<div class="wrap">';
174
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
175
-
176
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
177
  if ($bid !== null) {
178
  $button = CnbAppRemote::cnb_remote_get_button( $bid );
@@ -188,13 +248,12 @@ function cnb_admin_page_condition_edit_render() {
188
  $url ));
189
 
190
  $action_verb = $condition->id === 'new' ? 'adding' : 'editing';
191
- echo '<div class="notice notice-info">
192
- <p>You are '.$action_verb.' a Condition for Button ID <code>'.esc_html($button->id).'</code> (<strong>'.esc_html($button->name).'</strong>),
193
- click <a href="'.$redirect_link.'">here</a> to go back to continue configuring the Button.</p></div>';
194
  }
195
 
196
  $url = admin_url('admin-post.php');
197
-
198
  $form_action = esc_url( $url );
199
  $redirect_link = add_query_arg(
200
  array(
@@ -203,31 +262,32 @@ function cnb_admin_page_condition_edit_render() {
203
  $form_action
204
  );
205
 
 
 
206
  if ($bid !== null) { ?>
207
  <h2 class="nav-tab-wrapper">
208
- <a href="<?php echo cnb_create_tab_url($button, 'basic_options') ?>"
209
  class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
210
- <a href="<?php echo cnb_create_tab_url($button, 'actions') ?>"
211
  class="nav-tab <?php echo cnb_is_active_tab('actions') ?>">Actions</a>
212
- <a href="<?php echo cnb_create_tab_url($button, 'extra_options') ?>"
213
  class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
214
- <a href="<?php echo cnb_create_tab_url($button, 'visibility') ?>"
215
  class="nav-tab <?php echo cnb_is_active_tab('visibility') ?>">Visibility</a>
216
- <a href="<?php echo cnb_create_tab_url($button, 'advanced_options') ?>"
217
  class="nav-tab <?php echo cnb_is_active_tab('advanced_options') ?>">Advanced</a>
218
  </h2>
219
- <?php } ?>
220
- <form action="<?php echo $redirect_link; ?>" method="post">
221
- <input type="hidden" name="page" value="call-now-button-conditions" />
222
- <input type="hidden" name="bid" value="<?php esc_attr_e($bid) ?>" />
223
- <input type="hidden" name="condition_id" value="<?php esc_attr_e($condition->id) ?>" />
224
- <input type="hidden" name="action" value="<?php echo $condition_id === 'new' ? 'cnb_create_condition' :'cnb_update_condition' ?>" />
225
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('cnb-condition-edit')?>" />
226
- <?php
227
- cnb_render_form($condition, $button);
228
- submit_button();
229
- ?>
230
- </form>
231
- <?php cnb_admin_footer();
232
- echo '</div>';
233
  }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/models/CnbCondition.class.php';
9
  require_once dirname( __FILE__ ) . '/../utils/utils.php';
10
 
11
  function cnb_add_header_condition_edit($condition) {
24
  }
25
  }
26
 
27
+ /**
28
+ * This is called to create the condition
29
+ * via `call-now-button.php#cnb_admin_create_condition`
30
+ */
31
+ function cnb_admin_page_condition_create_process() {
32
+ global $cnb_slug_base;
33
+ $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
34
+ if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_create_condition') ) {
35
+
36
+ // sanitize the input
37
+ $conditions = filter_input(
38
+ INPUT_POST,
39
+ 'conditions',
40
+ FILTER_SANITIZE_STRING,
41
+ FILTER_REQUIRE_ARRAY | FILTER_FLAG_NO_ENCODE_QUOTES);
42
+
43
+ $result = '';
44
+ $cnb_cloud_notifications = array();
45
+ foreach($conditions as $condition) {
46
+ // do the processing
47
+ $result = CnbAdminCloud::cnb_create_condition( $cnb_cloud_notifications, $condition );
48
+ }
49
+
50
+ // redirect the user to the appropriate page
51
+ $transient_id = 'cnb-' . wp_generate_uuid4();
52
+ set_transient($transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS);
53
+
54
+ // Create link
55
+ $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
56
+ $url = admin_url('admin.php');
57
+ if (!empty($bid)) {
58
+ $redirect_link =
59
+ add_query_arg(
60
+ array(
61
+ 'page' => 'call-now-button',
62
+ 'action' => 'edit',
63
+ 'id' => $bid,
64
+ 'tid' => $transient_id,
65
+ 'tab' => 'visibility',
66
+ ),
67
+ $url);
68
+ $redirect_url = esc_url_raw($redirect_link);
69
+ wp_safe_redirect($redirect_url);
70
+ exit;
71
+ } else {
72
+ $redirect_link =
73
+ add_query_arg(
74
+ array(
75
+ 'page' => 'call-now-button-conditions',
76
+ 'action' => 'edit',
77
+ 'id' => $result->id,
78
+ 'tid' => $transient_id,
79
+ 'bid' => $bid),
80
+ $url);
81
+ $redirect_url = esc_url_raw($redirect_link);
82
+ wp_safe_redirect($redirect_url);
83
+ exit;
84
+ }
85
+ }
86
+ else {
87
+ wp_die( __( 'Invalid nonce specified', CNB_NAME), __( 'Error', CNB_NAME), array(
88
+ 'response' => 403,
89
+ 'back_link' => 'admin.php?page=' . $cnb_slug_base,
90
+ ) );
91
+ }
92
+ }
93
+
94
  /**
95
  * This is called to update the condition
96
  * via `call-now-button.php#cnb_update_condition`
98
  function cnb_admin_page_condition_edit_process() {
99
  global $cnb_slug_base;
100
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
101
+ if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_update_condition') ) {
102
 
103
  // sanitize the input
104
  $conditions = filter_input(
157
  }
158
  }
159
 
160
+ function cnb_create_tab_url_conditions($button, $tab) {
161
  $url = admin_url('admin.php');
162
  $tab_link =
163
  add_query_arg(
172
  }
173
 
174
  /**
175
+ * @param $condition CnbCondition
 
176
  */
177
+ function cnb_render_form_condition($condition) {
178
+ ?>
179
  <table class="form-table nav-tab-active">
180
  <tr>
181
  <th colspan="2"><h2>Basic Settings</h2>
220
  }
221
 
222
  function cnb_admin_page_condition_edit_render() {
 
 
 
 
 
223
  $condition_id = cnb_get_button_id();
224
+ $condition = new CnbCondition();
225
  $button = null;
226
  if (strlen($condition_id) > 0 && $condition_id !== 'new') {
227
  $condition = CnbAppRemote::cnb_remote_get_condition( $condition_id );
229
  $condition->id = 'new';
230
  }
231
 
232
+ add_action('cnb_header_name', function() use($condition) {
233
  cnb_add_header_condition_edit($condition);
234
  });
235
 
 
 
 
236
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
237
  if ($bid !== null) {
238
  $button = CnbAppRemote::cnb_remote_get_button( $bid );
248
  $url ));
249
 
250
  $action_verb = $condition->id === 'new' ? 'adding' : 'editing';
251
+ $mesage = '<strong>You are '.$action_verb.' a Condition.</strong>.
252
+ Click <a href="'.$redirect_link.'">here</a> to go back to continue configuring the Button.';
253
+ CnbAdminNotices::get_instance()->renderInfo($mesage);
254
  }
255
 
256
  $url = admin_url('admin-post.php');
 
257
  $form_action = esc_url( $url );
258
  $redirect_link = add_query_arg(
259
  array(
262
  $form_action
263
  );
264
 
265
+ do_action('cnb_header');
266
+
267
  if ($bid !== null) { ?>
268
  <h2 class="nav-tab-wrapper">
269
+ <a href="<?php echo cnb_create_tab_url_conditions($button, 'basic_options') ?>"
270
  class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
271
+ <a href="<?php echo cnb_create_tab_url_conditions($button, 'actions') ?>"
272
  class="nav-tab <?php echo cnb_is_active_tab('actions') ?>">Actions</a>
273
+ <a href="<?php echo cnb_create_tab_url_conditions($button, 'extra_options') ?>"
274
  class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
275
+ <a href="<?php echo cnb_create_tab_url_conditions($button, 'visibility') ?>"
276
  class="nav-tab <?php echo cnb_is_active_tab('visibility') ?>">Visibility</a>
277
+ <a href="<?php echo cnb_create_tab_url_conditions($button, 'advanced_options') ?>"
278
  class="nav-tab <?php echo cnb_is_active_tab('advanced_options') ?>">Advanced</a>
279
  </h2>
280
+ <?php } ?>
281
+ <form action="<?php echo $redirect_link; ?>" method="post">
282
+ <input type="hidden" name="page" value="call-now-button-conditions" />
283
+ <input type="hidden" name="bid" value="<?php esc_attr_e($bid) ?>" />
284
+ <input type="hidden" name="condition_id" value="<?php esc_attr_e($condition->id) ?>" />
285
+ <input type="hidden" name="action" value="<?php echo $condition_id === 'new' ? 'cnb_create_condition' :'cnb_update_condition' ?>" />
286
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce($condition->id === 'new' ? 'cnb_create_condition' : 'cnb_update_condition') ?>" />
287
+ <?php
288
+ cnb_render_form_condition($condition);
289
+ submit_button();
290
+ ?>
291
+ </form>
292
+ <?php do_action('cnb_footer');
 
293
  }
src/admin/condition-overview.php CHANGED
@@ -5,6 +5,7 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
8
 
9
  if(!class_exists('WP_List_Table')) {
10
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
@@ -14,6 +15,28 @@ function cnb_add_header_condition_overview() {
14
  echo 'Conditions ';
15
  }
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  class Cnb_Condition_List_Table extends WP_List_Table {
18
 
19
  /**
@@ -239,7 +262,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
239
  $value = !empty($item['conditionType']) ? $item['conditionType'] : '<em>No value</em>';
240
  return sprintf(
241
  '%1$s %2$s',
242
- '<a href="'.$edit_url.'">'.esc_html($value) . '</a>',
243
  $this->row_actions($actions)
244
  );
245
  }
@@ -265,7 +288,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
265
  $entity = array('id' => $entityId);
266
  CnbAppRemote::cnb_remote_delete_condition( $entity );
267
  }
268
- echo '<div class="notice-success notice"><p>' . count($entityIds) . ' Condition(s) deleted</p></div>';
269
  break;
270
  }
271
  }
@@ -273,25 +296,40 @@ class Cnb_Condition_List_Table extends WP_List_Table {
273
  }
274
  }
275
 
276
- function cnb_action_after_header() {
277
- // Only add the "Add new" action in the overview part
278
- $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
279
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
280
- $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
281
- if ($id === null || ($action != 'new' && $action != 'edit')) {
282
- // Create link
283
- $url = admin_url('admin.php');
284
- $new_link =
285
- add_query_arg(
286
- array(
287
- 'page' => 'call-now-button-conditions',
288
- 'action' => 'new',
289
- 'id' => 'new',
290
- 'bid' => $bid),
291
- $url);
292
- $new_url = esc_url($new_link);
 
 
 
 
 
293
 
294
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
 
 
 
 
 
 
 
 
 
 
295
  }
296
  }
297
 
@@ -300,70 +338,29 @@ function cnb_action_after_header() {
300
  */
301
  function cnb_admin_page_condition_overview_render() {
302
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
303
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
304
  if ($id === null) {
305
  cnb_admin_page_condition_overview_render_list();
306
- } else {
307
- switch ($action) {
308
- case 'new':
309
- case 'edit':
310
- require_once dirname( __FILE__ ) . '/condition-edit.php';
311
- cnb_admin_page_condition_edit_render();
312
- break;
313
- case 'delete':
314
- if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
315
- $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
316
- $action = 'cnb_delete_condition';
317
-
318
- if (wp_verify_nonce($nonce, $action)) {
319
- $cnb_cloud_notifications = array();
320
- // If a button is set, remove this ID from the conditions array
321
- $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
322
- if ($bid !== null) {
323
- // Get the button
324
- $button = CnbAppRemote::cnb_remote_get_button( $bid );
325
-
326
- // Remove the current Condition
327
- $pos = array_search($id, $button->conditions);
328
- unset($button->conditions[$pos]);
329
-
330
- // Convert to array and update
331
- $button_array = json_decode(json_encode($button), true);
332
- CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button_array );
333
- }
334
-
335
- CnbAdminCloud::cnb_delete_condition( $cnb_cloud_notifications, $id );
336
 
337
- foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
338
- echo $cnb_cloud_notification;
339
- }
340
- if ($bid !== null) {
341
- // Create link
342
- // Create link
343
- $url = admin_url('admin.php');
344
- $new_link =
345
- add_query_arg(
346
- array(
347
- 'page' => 'call-now-button',
348
- 'action' => 'edit',
349
- 'id' => $bid,
350
- 'tab' => 'visibility'),
351
- $url);
352
- $new_url = esc_url_raw($new_link);
353
- echo '<div class="notice-success notice"><p>';
354
- echo '<p>You will be redirected back to the Button overview in 5 seconds...</p><p>Or click here to go immediately: <a href="'.$new_url.'">'.$new_url.'</a></p>';
355
- echo '<script type="text/javascript">setTimeout(function(){location.href="' . $new_url .'"} , 5000); </script>';
356
- echo '</p></div>';
357
- } else {
358
- cnb_admin_page_condition_overview_render_list();
359
- }
360
- }
361
- }
362
- break;
363
- }
364
  }
365
  }
366
 
 
 
 
 
 
367
  function cnb_admin_page_condition_overview_bid(&$cnb_notices) {
368
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
369
  $args = array();
@@ -374,35 +371,33 @@ function cnb_admin_page_condition_overview_bid(&$cnb_notices) {
374
 
375
  if ($button && !($button instanceof WP_Error)) {
376
  $args['button'] = $button;
377
- $cnb_notices[] = '<div class="notice notice-info"><p>Only conditions for Button ID <code>'.esc_html($button->id).'</code> (<strong>'.esc_html($button->name).'</strong>) are shown</p></div>';
 
378
  }
379
  return $args;
380
  }
381
- function cnb_admin_page_condition_overview_render_list() {
382
- global $cnb_options, $cnb_settings;
383
-
384
- add_action('cnb_header', 'cnb_add_header_condition_overview');
385
 
 
386
  $cnb_notices = cnb_get_notices();
387
- $cnb_changelog = cnb_get_changelog();
388
 
389
  $args = cnb_admin_page_condition_overview_bid($cnb_notices);
390
  //Prepare Table of elements
391
  $wp_list_table = new Cnb_Condition_List_Table($args);
392
  $data = $wp_list_table->prepare_items();
393
 
 
 
394
  if ($data instanceof WP_Error) {
395
- $cnb_notices[] = cnb_admin_header_get_cloud_error($data);
 
 
396
  }
397
-
398
- echo '<div class="wrap">';
399
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
400
 
401
  echo '<form id="wp_list_event" method="post">';
402
 
403
  //Table of elements
404
  $wp_list_table->display();
405
  echo '</form>';
406
- cnb_admin_footer();
407
- echo '</div>';
408
  }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/condition-edit.php';
9
 
10
  if(!class_exists('WP_List_Table')) {
11
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
15
  echo 'Conditions ';
16
  }
17
 
18
+ function cnb_conditions_after_header() {
19
+ // Only add the "Add new" action in the overview part
20
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
21
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
22
+ $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
23
+ if ($id === null || ($action != 'new' && $action != 'edit')) {
24
+ // Create link
25
+ $url = admin_url('admin.php');
26
+ $new_link =
27
+ add_query_arg(
28
+ array(
29
+ 'page' => 'call-now-button-conditions',
30
+ 'action' => 'new',
31
+ 'id' => 'new',
32
+ 'bid' => $bid),
33
+ $url);
34
+ $new_url = esc_url($new_link);
35
+
36
+ echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
37
+ }
38
+ }
39
+
40
  class Cnb_Condition_List_Table extends WP_List_Table {
41
 
42
  /**
262
  $value = !empty($item['conditionType']) ? $item['conditionType'] : '<em>No value</em>';
263
  return sprintf(
264
  '%1$s %2$s',
265
+ '<strong><a class="row-title" href="'.$edit_url.'">'.esc_html($value) . '</a></strong>',
266
  $this->row_actions($actions)
267
  );
268
  }
288
  $entity = array('id' => $entityId);
289
  CnbAppRemote::cnb_remote_delete_condition( $entity );
290
  }
291
+ CnbAdminNotices::get_instance()->renderSuccess(count($entityIds) . ' Condition(s) deleted.');
292
  break;
293
  }
294
  }
296
  }
297
  }
298
 
299
+ function cnb_delete_condition() {
300
+ if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
301
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
302
+ $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
303
+ $action = 'cnb_delete_condition';
304
+
305
+ if (wp_verify_nonce($nonce, $action)) {
306
+ $cnb_cloud_notifications = array();
307
+ // If a button is set, remove this ID from the conditions array
308
+ $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
309
+ if ($bid !== null) {
310
+ // Get the button
311
+ $button = CnbAppRemote::cnb_remote_get_button( $bid );
312
+
313
+ // Remove the current Condition
314
+ $pos = array_search($id, $button->conditions);
315
+ unset($button->conditions[$pos]);
316
+
317
+ // Convert to array and update
318
+ $button_array = json_decode(json_encode($button), true);
319
+ CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button_array );
320
+ }
321
 
322
+ CnbAdminCloud::cnb_delete_condition( $cnb_cloud_notifications, $id );
323
+ $adminNotices = CnbAdminNotices::get_instance();
324
+
325
+ foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
326
+ $adminNotices->renderNotice($cnb_cloud_notification);
327
+ }
328
+ }
329
+ }
330
+
331
+ function no_items() {
332
+ _e( 'No conditions found.' );
333
  }
334
  }
335
 
338
  */
339
  function cnb_admin_page_condition_overview_render() {
340
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
 
341
  if ($id === null) {
342
  cnb_admin_page_condition_overview_render_list();
343
+ return;
344
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
347
+ switch ($action) {
348
+ case 'new':
349
+ case 'edit':
350
+ cnb_admin_page_condition_edit_render();
351
+ break;
352
+ case 'delete':
353
+ cnb_delete_condition();
354
+ cnb_admin_page_condition_overview_render_list();
355
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  }
357
  }
358
 
359
+ /**
360
+ * @param $cnb_notices CnbNotice[]
361
+ *
362
+ * @return array
363
+ */
364
  function cnb_admin_page_condition_overview_bid(&$cnb_notices) {
365
  $bid = !empty($_GET['bid']) ? sanitize_text_field($_GET['bid']) : null;
366
  $args = array();
371
 
372
  if ($button && !($button instanceof WP_Error)) {
373
  $args['button'] = $button;
374
+ $notice = new CnbNotice('info', 'Only conditions for Button ID <code>'.esc_html($button->id).'</code> (<strong>'.esc_html($button->name).'</strong>) are shown.');
375
+ $cnb_notices[] = $notice;
376
  }
377
  return $args;
378
  }
 
 
 
 
379
 
380
+ function cnb_admin_page_condition_overview_render_list() {
381
  $cnb_notices = cnb_get_notices();
 
382
 
383
  $args = cnb_admin_page_condition_overview_bid($cnb_notices);
384
  //Prepare Table of elements
385
  $wp_list_table = new Cnb_Condition_List_Table($args);
386
  $data = $wp_list_table->prepare_items();
387
 
388
+ add_action('cnb_header_name', 'cnb_add_header_condition_overview');
389
+
390
  if ($data instanceof WP_Error) {
391
+ cnb_api_key_invalid_notice($data);
392
+ } else {
393
+ add_action('cnb_after_header', 'cnb_conditions_after_header');
394
  }
395
+ do_action('cnb_header');
 
 
396
 
397
  echo '<form id="wp_list_event" method="post">';
398
 
399
  //Table of elements
400
  $wp_list_table->display();
401
  echo '</form>';
402
+ do_action('cnb_footer');
 
403
  }
src/admin/domain-edit.php CHANGED
@@ -5,27 +5,8 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
-
9
- /***
10
- * To ensure arrays are properly sanitized to WordPress Codex standards,
11
- * they encourage usage of sanitize_text_field(). That only works with a single
12
- * variable (string). This function allows for a full blown array to get sanitized
13
- * properly, while sanitizing each individual value in a key -> value pair.
14
- *
15
- * Source: https://wordpress.stackexchange.com/questions/24736/wordpress-sanitize-array
16
- * Author: Broshi, answered Feb 5 '17 at 9:14
17
- * Via: https://developer.wordpress.org/reference/functions/sanitize_text_field/
18
- */
19
- function cnb_wporg_recursive_sanitize_text_field( $array ) {
20
- foreach ( $array as $key => &$value ) {
21
- if ( is_array( $value ) ) {
22
- $value = cnb_wporg_recursive_sanitize_text_field( $value );
23
- } else {
24
- $value = sanitize_text_field( $value );
25
- }
26
- }
27
- return $array;
28
- }
29
 
30
  function cnb_add_header_domain_edit($domain=null) {
31
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
@@ -173,72 +154,44 @@ function cnb_admin_page_domain_edit_process() {
173
  }
174
  }
175
 
 
 
 
176
  function cnb_admin_page_domain_edit_render() {
177
- global $cnb_options, $cnb_settings;
178
-
179
- $cnb_notices = cnb_get_notices();
180
- $cnb_changelog = cnb_get_changelog();
181
-
182
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
183
- $domain = new stdClass();
184
- if (strlen($domain_id) > 0 && $domain_id != 'new') {
 
185
  $domain = CnbAppRemote::cnb_remote_get_domain( $domain_id );
186
  }
187
- // Domain specific conversions
188
 
189
  // Set default values in case they are missing
190
- if (strlen($domain_id) > 0 && $domain_id == 'new' && empty($domain->id)) {
191
- $domain->id = null;
192
- }
193
- if (empty($domain->timezone)) {
194
- $domain->timezone = wp_timezone_string();
195
- }
196
- if (empty($domain->type)) {
197
- $domain->type = 'FREE';
198
- }
199
- if (empty($domain->properties)) {
200
- $domain->properties = new stdClass();
201
- $domain->properties->scale = '1';
202
- $domain->properties->debug = false;
203
- }
204
- if (empty($domain->name)) {
205
- $domain->name = null;
206
- }
207
- if (!isset($domain->trackGA)) {
208
- $domain->trackGA = true;
209
- }
210
- if (!isset($domain->trackConversion)) {
211
- $domain->trackConversion = true;
212
- }
213
 
214
- add_action('cnb_header', function() use($domain) {
215
  cnb_add_header_domain_edit($domain);
216
  });
217
 
 
218
  ?>
219
 
220
- <div class="wrap">
221
- <?php cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog) ?>
222
- <form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">
223
- <input type="hidden" name="page" value="call-now-button" />
224
- <input type="hidden" name="action" value="<?php echo $domain_id === 'new' ? 'cnb_create_domain' :'cnb_update_domain' ?>" />
225
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce($domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain')?>" />
226
-
227
- <table class="form-table nav-tab-active" role="presentation">
228
- <?php cnb_admin_page_domain_edit_render_form($domain) ?>
229
- </table>
230
 
231
- <?php submit_button(); ?>
232
- </form>
 
233
 
234
- <?php cnb_admin_footer() ?>
235
- </div>
236
- <?php }
237
 
238
- function cnb_admin_page_domain_edit_render_form($domain) {
239
- $domain_properties_zindex = !empty($domain->properties->zindex) ? $domain->properties->zindex : 2147483647;
240
- $domain_properties_zindex_order = zindexToOrder($domain_properties_zindex);
241
 
 
242
  $url = admin_url( 'admin.php' );
243
  $upgrade_link =
244
  add_query_arg( array(
@@ -248,98 +201,126 @@ function cnb_admin_page_domain_edit_render_form($domain) {
248
  ),
249
  $url );
250
  $upgrade_url = esc_url( $upgrade_link );
251
- ?>
252
- <tr>
253
- <th>Plan</th>
254
- <td>
255
- <code><?php esc_html_e($domain->type) ?></code>
256
- <?php
257
- if ($domain->type !== 'PROPLUS') {
258
- echo '<a href="' . $upgrade_url . '">Upgrade!</a>';
259
- }
260
- ?>
261
- </td>
262
- </tr> <?php if ($domain->type != 'FREE') { ?>
263
- <tr>
264
- <th scope="row">Renew</th>
265
- <td><fieldset><legend class="screen-reader-text"><span>Renew</span></legend><label for="renew">
266
- <input name="domain[renew]" type="checkbox" id="renew" value="true" <?php checked('1', $domain->renew); ?> />
267
- Renew domain automatically</label>
268
- </fieldset>
269
- <?php if (!empty($domain->expires)) { ?>
270
- <p class="description" id="domain_expires-description">
271
- Domain expires <code><?php esc_html_e($domain->expires) ?></code>.
272
- </p>
273
- <?php } ?>
274
- </td>
275
- </tr>
276
- <?php } ?>
277
- <tr>
278
- <th colspan="2"><h2>Tracking</h2></th>
279
- </tr>
280
  <tr>
281
- <th scope="row">Google Analytics</th>
282
  <td>
283
- <input type="hidden" name="domain[trackGA]" value="0" />
284
- <input name="domain[trackGA]" type="checkbox" id="google_analytics" value="true" <?php checked('1', $domain->trackGA); ?> />
285
- <label for="google_analytics">Enable </label>
286
- <p class="description">
287
- Supports Classic, Universal Analytics and Global site tag (v3 and v4).<br>
288
- Using Google Tag Manager? Set up click tracking in GTM. <a href="https://callnowbutton.com/support/click-tracking/google-tag-manager-event-tracking/?utm_source=wp-plugin&amp;utm_medium=referral&amp;utm_campaign=description_link&amp;utm_term=google-tag-manager-event-tracking" target="_blank">Learn how to do this...</a>
 
 
289
  </p>
290
- </td>
291
- </tr>
292
- <tr>
293
- <th scope="row">Google Ads conversions</th>
294
- <td>
295
- <input type="hidden" name="domain[trackConversion]" value="0" />
296
- <input name="domain[trackConversion]" type="checkbox" id="conversion_tracking" value="true" <?php checked('1', $domain->trackConversion); ?> />
297
- <label for="conversion_tracking">Enable</label>
298
- <p class="description">Select this option if you want to count clicks on the button as Google Ads conversions. This option requires the Event snippet to be present on the page. <a href="https://support.google.com/google-ads/answer/6331304" target="_blank">Learn more...</a></p>
299
- </td>
300
- </tr>
301
- <tr>
302
- <th colspan="2"><h2>Button display</h2></th>
303
- </tr>
304
- <tr class="zoom">
305
- <th scope="row">Button size <span id="cnb_slider_value"></span></th>
306
- <td><fieldset>
307
- <label class="cnb_slider_value" for="cnb_slider" onclick="jQuery('#cnb_slider:enabled')[0].stepDown();cnb_update_sliders()">Smaller&nbsp;&laquo;&nbsp;</label>
308
- <input type="range" min="0.7" max="1.3" step="0.1" name="domain[properties][scale]"
309
- value="<?php esc_attr_e($domain->properties->scale) ?>" class="slider" id="cnb_slider">
310
- <label class="cnb_slider_value" for="cnb_slider" onclick="jQuery('#cnb_slider:enabled')[0].stepUp();cnb_update_sliders()">&nbsp;&raquo;&nbsp;Bigger</label>
311
- </fieldset></td>
312
- </tr>
313
- <tr class="z-index">
314
- <th scope="row">Order (<span id="cnb_order_value"></span>) <a
315
- href="https://callnowbutton.com/set-order/" target="_blank" class="cnb-nounderscore">
316
- <span class="dashicons dashicons-editor-help"></span>
317
- </a></th>
318
- <td>
319
- <label class="cnb_slider_value" for="cnb_order_slider" onclick="jQuery('#cnb_order_slider:enabled')[0].stepDown();cnb_update_sliders()">Backwards&nbsp;&laquo;&nbsp;</label>
320
- <input type="range" min="1" max="10" name="domain[properties][zindex]"
321
- value="<?php esc_attr_e($domain_properties_zindex_order) ?>" class="slider2" id="cnb_order_slider"
322
- step="1">
323
- <label class="cnb_slider_value" for="cnb_order_slider" onclick="jQuery('#cnb_order_slider:enabled')[0].stepUp();cnb_update_sliders()">&nbsp;&raquo;&nbsp;Front</label>
324
- <p class="description">The default (and recommended) value is all the way to the front so the
325
- button sits on top of everything else. In case you have a specific usecase where you want
326
- something else to sit in front of the Call Now Button (e.g. a chat window or a cookie
327
- notice) you can move this backwards one step at a time to adapt it to your situation.</p>
328
  </td>
329
  </tr>
330
- <tr>
331
- <th colspan="2"><h2>Advanced</h2></th>
332
- </tr>
 
333
  <tr>
334
- <th scope="row"><label for="domain_name">Domain name</label></th>
 
 
 
335
  <td>
336
- <input type="hidden" name="domain[id]" value="<?php esc_attr_e($domain->id) ?>" />
337
- <input type="text" id="domain_name" name="domain[name]" value="<?php esc_attr_e($domain->name) ?>" class="regular-text" disabled="disabled"/>
 
338
  <p class="description">
339
- <strong>Warning</strong>: Changing your domain name means remapping all existing Buttons for that domain. Please use with caution. <a class="cnb_cursor_pointer" onclick="return jQuery('#domain_name').prop('disabled', false);">Click here to change your domain.</a>
 
340
  </p>
341
  </td>
342
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  <tr>
344
  <th scope="row"><label for="domain_timezone">Timezone</label></th>
345
  <td>
@@ -356,15 +337,22 @@ function cnb_admin_page_domain_edit_render_form($domain) {
356
  </td>
357
  </tr>
358
  <tr>
359
- <th scope="row">Debug mode</th>
360
- <td>
361
- <input type="hidden" name="domain[properties][debug]" value="false" />
362
- <input name="domain[properties][debug]" type="checkbox" id="domain_properties_debug" value="true" <?php checked('true', $domain->properties->debug); ?> />
363
- <label for="domain_properties_debug">Enabled</label>
364
- <p class="description">
365
- This enables some additional information in your browser's console, which can help during troubleshooting.
366
- </p>
367
- </fieldset></td>
368
- </tr>
369
- <?php
 
 
 
 
 
 
 
370
  }
5
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
8
+ require_once dirname( __FILE__ ) . '/models/CnbDomain.class.php';
9
+ require_once dirname( __FILE__ ) . '/../utils/utils.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  function cnb_add_header_domain_edit($domain=null) {
12
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
154
  }
155
  }
156
 
157
+ /**
158
+ * Main entrypoint, used by `domain-overview.php`.
159
+ */
160
  function cnb_admin_page_domain_edit_render() {
 
 
 
 
 
161
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
162
+
163
+ $domain = new CnbDomain();
164
+ if (strlen($domain_id) > 0 && $domain_id !== 'new') {
165
  $domain = CnbAppRemote::cnb_remote_get_domain( $domain_id );
166
  }
 
167
 
168
  // Set default values in case they are missing
169
+ CnbDomain::setSaneDefault($domain, $domain_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ add_action('cnb_header_name', function() use($domain) {
172
  cnb_add_header_domain_edit($domain);
173
  });
174
 
175
+ do_action('cnb_header');
176
  ?>
177
 
178
+ <form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">
179
+ <input type="hidden" name="page" value="call-now-button" />
180
+ <input type="hidden" name="action" value="<?php echo $domain_id === 'new' ? 'cnb_create_domain' :'cnb_update_domain' ?>" />
181
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce($domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain')?>" />
 
 
 
 
 
 
182
 
183
+ <table class="form-table nav-tab-active" role="presentation">
184
+ <?php cnb_admin_page_domain_edit_render_form($domain) ?>
185
+ </table>
186
 
187
+ <?php submit_button(); ?>
188
+ </form>
 
189
 
190
+ <?php
191
+ do_action('cnb_footer');
192
+ }
193
 
194
+ function cnb_admin_page_domain_edit_render_form_plan_details($domain) {
195
  $url = admin_url( 'admin.php' );
196
  $upgrade_link =
197
  add_query_arg( array(
201
  ),
202
  $url );
203
  $upgrade_url = esc_url( $upgrade_link );
204
+ ?>
205
+ <tr>
206
+ <th>Plan</th>
207
+ <td>
208
+ <code><?php esc_html_e($domain->type) ?></code>
209
+ <?php
210
+ if ($domain->type !== 'PRO' && !empty($domain->id)) {
211
+ echo '<a href="' . $upgrade_url . '">Upgrade!</a>
212
+ <p class="description">The FREE plan offers all features but adds delicate branding to your buttons.</p>';
213
+ }
214
+ ?>
215
+ </td>
216
+ </tr>
217
+ <?php if ($domain->type != 'FREE') { ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  <tr>
219
+ <th scope="row">Subscription</th>
220
  <td>
221
+ <input name="domain[renew]" type="checkbox" id="cnb-renew" value="true" <?php checked('1', $domain->renew); ?> />
222
+ <label for="cnb-renew">Renew automatically</label>
223
+
224
+ <?php if (!empty($domain->expires)) { ?>
225
+ <p class="description" id="domain_expires-description">
226
+ Your subscription will
227
+ <?php echo $domain->renew == 1 ? ' renew automatically ' : ' expire '; ?>
228
+ on <?php echo date('F d, Y', strtotime(esc_html($domain->expires))); ?>.
229
  </p>
230
+ <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  </td>
232
  </tr>
233
+ <?php }
234
+ }
235
+
236
+ function cnb_admin_page_domain_edit_render_form_tracking($domain) { ?>
237
  <tr>
238
+ <th colspan="2"><h2>Tracking</h2></th>
239
+ </tr>
240
+ <tr>
241
+ <th scope="row">Google Analytics</th>
242
  <td>
243
+ <input type="hidden" name="domain[trackGA]" value="0" />
244
+ <input name="domain[trackGA]" type="checkbox" id="google_analytics" value="true" <?php checked('1', $domain->trackGA); ?> />
245
+ <label for="google_analytics">Enable </label>
246
  <p class="description">
247
+ Supports Classic, Universal Analytics and Global site tag (v3 and v4).<br>
248
+ Using Google Tag Manager? Set up click tracking in GTM. <a href="https://callnowbutton.com/support/click-tracking/google-tag-manager-event-tracking/?utm_source=wp-plugin&amp;utm_medium=referral&amp;utm_campaign=description_link&amp;utm_term=google-tag-manager-event-tracking" target="_blank">Learn how to do this...</a>
249
  </p>
250
  </td>
251
  </tr>
252
+ <tr>
253
+ <th scope="row">Google Ads conversions</th>
254
+ <td>
255
+ <input type="hidden" name="domain[trackConversion]" value="0" />
256
+ <input name="domain[trackConversion]" type="checkbox" id="conversion_tracking" value="true" <?php checked('1', $domain->trackConversion); ?> />
257
+ <label for="conversion_tracking">Enable</label>
258
+ <p class="description">Select this option if you want to count clicks on the button as Google Ads conversions. This option requires the Event snippet to be present on the page. <a href="https://support.google.com/google-ads/answer/6331304" target="_blank">Learn more...</a></p>
259
+ </td>
260
+ </tr>
261
+ <?php
262
+ }
263
+
264
+ function cnb_admin_page_domain_edit_render_form_button_display($domain) {
265
+ $domain_properties_zindex = !empty($domain->properties->zindex) ? $domain->properties->zindex : 2147483647;
266
+ $domain_properties_zindex_order = zindexToOrder($domain_properties_zindex);
267
+ ?>
268
+ <tr>
269
+ <th colspan="2"><h2>Button display</h2></th>
270
+ </tr>
271
+ <tr class="zoom">
272
+ <th scope="row">Button size <span id="cnb_slider_value"></span></th>
273
+ <td><fieldset>
274
+ <label class="cnb_slider_value" for="cnb_slider" onclick="jQuery('#cnb_slider:enabled')[0].stepDown();cnb_update_sliders()">Smaller&nbsp;&laquo;&nbsp;</label>
275
+ <input type="range" min="0.7" max="1.3" step="0.1" name="domain[properties][scale]"
276
+ value="<?php esc_attr_e($domain->properties->scale) ?>" class="slider" id="cnb_slider">
277
+ <label class="cnb_slider_value" for="cnb_slider" onclick="jQuery('#cnb_slider:enabled')[0].stepUp();cnb_update_sliders()">&nbsp;&raquo;&nbsp;Bigger</label>
278
+ </fieldset></td>
279
+ </tr>
280
+ <tr class="z-index">
281
+ <th scope="row">Order (<span id="cnb_order_value"></span>) <a
282
+ href="https://callnowbutton.com/set-order/" target="_blank" class="cnb-nounderscore">
283
+ <span class="dashicons dashicons-editor-help"></span>
284
+ </a></th>
285
+ <td>
286
+ <label class="cnb_slider_value" for="cnb_order_slider" onclick="jQuery('#cnb_order_slider:enabled')[0].stepDown();cnb_update_sliders()">Backwards&nbsp;&laquo;&nbsp;</label>
287
+ <input type="range" min="1" max="10" name="domain[properties][zindex]"
288
+ value="<?php esc_attr_e($domain_properties_zindex_order) ?>" class="slider2" id="cnb_order_slider"
289
+ step="1">
290
+ <label class="cnb_slider_value" for="cnb_order_slider" onclick="jQuery('#cnb_order_slider:enabled')[0].stepUp();cnb_update_sliders()">&nbsp;&raquo;&nbsp;Front</label>
291
+ <p class="description">The default (and recommended) value is all the way to the front so the
292
+ button sits on top of everything else. In case you have a specific usecase where you want
293
+ something else to sit in front of the Call Now Button (e.g. a chat window or a cookie
294
+ notice) you can move this backwards one step at a time to adapt it to your situation.</p>
295
+ </td>
296
+ </tr>
297
+ <?php
298
+ }
299
+
300
+ function cnb_admin_page_domain_edit_render_form_advanced($domain, $header=true) {
301
+ global $cnb_options;
302
+ $show_advanced_view_only = array_key_exists('advanced_view', $cnb_options) && $cnb_options['advanced_view'] === 1;
303
+ if($header) { ?>
304
+ <tr>
305
+ <th colspan="2"><h2>Advanced</h2></th>
306
+ </tr>
307
+ <?php } ?>
308
+ <tr>
309
+ <th scope="row"><label for="domain_name">Domain name</label></th>
310
+ <td>
311
+ <input type="hidden" name="domain[id]" value="<?php esc_attr_e($domain->id) ?>" />
312
+ <?php if($show_advanced_view_only) { ?>
313
+ <input type="text" id="domain_name" name="domain[name]" value="<?php esc_attr_e($domain->name) ?>" class="regular-text" <?php if(!empty($domain->id)) { echo 'disabled="disabled"'; } ?> required="required"/>
314
+ <?php if(!empty($domain->id)) { ?>
315
+ <p class="description">
316
+ <strong>Warning</strong>: Changing your domain name means remapping all existing Buttons for that domain. Please use with caution. <a class="cnb_cursor_pointer" onclick="return jQuery('#domain_name').prop('disabled', false);">Click here to change your domain.</a>
317
+ </p>
318
+ <?php } ?>
319
+ <?php } else {
320
+ esc_html_e($domain->name);
321
+ } ?>
322
+ </td>
323
+ </tr>
324
  <tr>
325
  <th scope="row"><label for="domain_timezone">Timezone</label></th>
326
  <td>
337
  </td>
338
  </tr>
339
  <tr>
340
+ <th scope="row">Debug mode</th>
341
+ <td>
342
+ <input type="hidden" name="domain[properties][debug]" value="false" />
343
+ <input name="domain[properties][debug]" type="checkbox" id="domain_properties_debug" value="true" <?php checked('true', $domain->properties->debug); ?> />
344
+ <label for="domain_properties_debug">Enabled</label>
345
+ <p class="description">
346
+ This enables some additional information in your browser's console, which can help during troubleshooting.
347
+ </p>
348
+ </fieldset></td>
349
+ </tr>
350
+ <?php
351
+ }
352
+
353
+ function cnb_admin_page_domain_edit_render_form($domain) {
354
+ cnb_admin_page_domain_edit_render_form_plan_details($domain);
355
+ cnb_admin_page_domain_edit_render_form_tracking($domain);
356
+ cnb_admin_page_domain_edit_render_form_button_display($domain);
357
+ cnb_admin_page_domain_edit_render_form_advanced($domain);
358
  }
src/admin/domain-overview.php CHANGED
@@ -6,6 +6,8 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
 
9
 
10
  if(!class_exists('WP_List_Table')) {
11
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
@@ -15,6 +17,26 @@ function cnb_add_header_domain_overview() {
15
  echo 'Domains ';
16
  }
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  class Cnb_Domain_List_Table extends WP_List_Table {
19
 
20
  /**
@@ -122,8 +144,6 @@ class Cnb_Domain_List_Table extends WP_List_Table {
122
  return 'Free';
123
  case 'PRO':
124
  return 'Pro';
125
- case 'PROPLUS':
126
- return 'Pro+';
127
  default:
128
  return esc_html($item[$column_name]);
129
  }
@@ -186,7 +206,8 @@ class Cnb_Domain_List_Table extends WP_List_Table {
186
  * Custom action for `cb` columns (checkboxes)
187
  *
188
  * @param array|object $item
189
- * @return string|void
 
190
  */
191
  function column_cb($item) {
192
  return sprintf(
@@ -217,8 +238,8 @@ class Cnb_Domain_List_Table extends WP_List_Table {
217
  $delete_url = esc_url( $delete_link );
218
  $actions['delete'] = '<a href="'.$delete_url.'">Delete</a>';
219
 
220
- // If the type is not PRO+, offer an upgrade
221
- if ($item['type'] !== 'PROPLUS') {
222
  $upgrade_link =
223
  add_query_arg( array(
224
  'page' => 'call-now-button-domains',
@@ -232,7 +253,7 @@ class Cnb_Domain_List_Table extends WP_List_Table {
232
 
233
  return sprintf(
234
  '%1$s %2$s',
235
- '<a href="'.$edit_url.'">'.esc_html($item['name']) . '</a>',
236
  $this->row_actions($actions)
237
  );
238
  }
@@ -256,31 +277,34 @@ class Cnb_Domain_List_Table extends WP_List_Table {
256
  $domain = array('id' => $domainId);
257
  CnbAppRemote::cnb_remote_delete_domain( $domain );
258
  }
259
- echo '<div class="notice-success notice"><p>' . count($domainIds) . ' Domain(s) deleted</p></div>';
 
260
  break;
261
  }
262
  }
263
  }
264
  }
 
 
 
 
265
  }
266
 
267
- function cnb_after_header() {
268
- // Only add the "Add new" action in the overview part
269
- $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
270
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
271
- if ($id === null || ($action != 'new' && $action != 'edit')) {
272
- // Create link
273
- $url = admin_url('admin.php');
274
- $new_link =
275
- add_query_arg(
276
- array(
277
- 'page' => 'call-now-button-domains',
278
- 'action' => 'new',
279
- 'id' => 'new'),
280
- $url);
281
- $new_url = esc_url($new_link);
282
 
283
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
 
 
 
 
 
 
 
 
284
  }
285
  }
286
 
@@ -289,64 +313,45 @@ function cnb_after_header() {
289
  */
290
  function cnb_admin_page_domain_overview_render() {
291
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
292
- $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
293
  if ($id === null) {
294
  cnb_admin_page_domain_overview_render_list();
295
- } else {
296
- switch ($action) {
297
- case 'new':
298
- case 'edit':
299
- require_once dirname( __FILE__ ) . "/domain-edit.php";
300
- cnb_admin_page_domain_edit_render();
301
- break;
302
- case 'upgrade':
303
- require_once dirname( __FILE__ ) . "/domain-upgrade.php";
304
- cnb_admin_page_domain_upgrade_render();
305
- break;
306
- case 'delete':
307
- if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
308
- $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
309
- $action = 'cnb_delete_domain';
310
-
311
- if (wp_verify_nonce($nonce, $action)) {
312
- $cnb_cloud_notifications = array();
313
- CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $id );
314
- foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
315
- echo $cnb_cloud_notification;
316
- }
317
- cnb_admin_page_domain_overview_render_list();
318
- }
319
- }
320
- break;
321
- }
322
  }
323
  }
324
 
325
  function cnb_admin_page_domain_overview_render_list() {
326
- global $cnb_options, $cnb_settings;
327
-
328
- $cnb_notices = cnb_get_notices();
329
- $cnb_changelog = cnb_get_changelog();
330
-
331
  $wp_list_table = new Cnb_Domain_List_Table();
332
  $data = $wp_list_table->prepare_items();
333
 
 
 
334
  if ($data instanceof WP_Error) {
335
- $cnb_notices[] = cnb_admin_header_get_cloud_error($data);
336
  } else {
337
- add_action('cnb_header', 'cnb_add_header_domain_overview');
338
- add_action('cnb_after_header', 'cnb_after_header');
339
  }
340
-
341
- echo '<div class="wrap">';
342
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
343
 
344
  echo '<form id="wp_list_event" method="post">';
345
- //Prepare Table of elements
346
 
347
  //Table of elements
348
  $wp_list_table->display();
349
  echo '</form>';
350
- cnb_admin_footer();
351
- echo '</div>';
352
  }
6
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
9
+ require_once dirname( __FILE__ ) . '/domain-edit.php';
10
+ require_once dirname( __FILE__ ) . '/domain-upgrade.php';
11
 
12
  if(!class_exists('WP_List_Table')) {
13
  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
17
  echo 'Domains ';
18
  }
19
 
20
+ function cnb_add_new_domain_action() {
21
+ // Only add the "Add new" action in the overview part
22
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
23
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
24
+ if ($id === null || ($action != 'new' && $action != 'edit')) {
25
+ // Create link
26
+ $url = admin_url('admin.php');
27
+ $new_link =
28
+ add_query_arg(
29
+ array(
30
+ 'page' => 'call-now-button-domains',
31
+ 'action' => 'new',
32
+ 'id' => 'new'),
33
+ $url);
34
+ $new_url = esc_url($new_link);
35
+
36
+ echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
37
+ }
38
+ }
39
+
40
  class Cnb_Domain_List_Table extends WP_List_Table {
41
 
42
  /**
144
  return 'Free';
145
  case 'PRO':
146
  return 'Pro';
 
 
147
  default:
148
  return esc_html($item[$column_name]);
149
  }
206
  * Custom action for `cb` columns (checkboxes)
207
  *
208
  * @param array|object $item
209
+ *
210
+ * @return string
211
  */
212
  function column_cb($item) {
213
  return sprintf(
238
  $delete_url = esc_url( $delete_link );
239
  $actions['delete'] = '<a href="'.$delete_url.'">Delete</a>';
240
 
241
+ // If the type is not PRO, offer an upgrade
242
+ if ($item['type'] !== 'PRO') {
243
  $upgrade_link =
244
  add_query_arg( array(
245
  'page' => 'call-now-button-domains',
253
 
254
  return sprintf(
255
  '%1$s %2$s',
256
+ '<strong><a class="row-title" href="'.$edit_url.'">'.esc_html($item['name']) . '</a></strong>',
257
  $this->row_actions($actions)
258
  );
259
  }
277
  $domain = array('id' => $domainId);
278
  CnbAppRemote::cnb_remote_delete_domain( $domain );
279
  }
280
+ $notice = new CnbNotice('success', count($domainIds) . ' Domain(s) deleted');
281
+ CnbAdminNotices::get_instance()->renderNotice($notice);
282
  break;
283
  }
284
  }
285
  }
286
  }
287
+
288
+ function no_items() {
289
+ _e( 'No domains found.' );
290
+ }
291
  }
292
 
293
+ function cnb_delete_domain() {
294
+ if (isset($_REQUEST['_wpnonce']) && !empty($_REQUEST['_wpnonce'])) {
295
+ $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
296
+ $nonce = filter_input(INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING);
297
+ $action = 'cnb_delete_domain';
 
 
 
 
 
 
 
 
 
 
298
 
299
+ if (wp_verify_nonce($nonce, $action)) {
300
+ $adminNotices = CnbAdminNotices::get_instance();
301
+
302
+ $cnb_cloud_notifications = array();
303
+ CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $id );
304
+ foreach ($cnb_cloud_notifications as $cnb_cloud_notification) {
305
+ $adminNotices->renderNotice($cnb_cloud_notification);
306
+ }
307
+ }
308
  }
309
  }
310
 
313
  */
314
  function cnb_admin_page_domain_overview_render() {
315
  $id = !empty($_GET['id']) ? sanitize_text_field($_GET['id']) : null;
 
316
  if ($id === null) {
317
  cnb_admin_page_domain_overview_render_list();
318
+ return;
319
+ }
320
+
321
+ $action = !empty($_GET['action']) ? sanitize_text_field($_GET['action']) : null;
322
+ switch ($action) {
323
+ case 'new':
324
+ case 'edit':
325
+ cnb_admin_page_domain_edit_render();
326
+ break;
327
+ case 'upgrade':
328
+ cnb_admin_page_domain_upgrade_render();
329
+ break;
330
+ case 'delete':
331
+ cnb_delete_domain();
332
+ cnb_admin_page_domain_overview_render_list();
333
+ break;
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
  }
336
 
337
  function cnb_admin_page_domain_overview_render_list() {
338
+ //Prepare Table of elements
 
 
 
 
339
  $wp_list_table = new Cnb_Domain_List_Table();
340
  $data = $wp_list_table->prepare_items();
341
 
342
+ add_action('cnb_header_name', 'cnb_add_header_domain_overview');
343
+
344
  if ($data instanceof WP_Error) {
345
+ cnb_api_key_invalid_notice($data);
346
  } else {
347
+ add_action('cnb_after_header', 'cnb_add_new_domain_action');
 
348
  }
349
+ do_action('cnb_header');
 
 
350
 
351
  echo '<form id="wp_list_event" method="post">';
 
352
 
353
  //Table of elements
354
  $wp_list_table->display();
355
  echo '</form>';
356
+ do_action('cnb_footer');
 
357
  }
src/admin/domain-upgrade.php CHANGED
@@ -6,45 +6,34 @@ require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
6
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
9
 
10
  function cnb_add_header_domain_upgrade() {
11
- echo 'Upgrade domain';
12
  }
13
 
14
- /**
15
- * Sort currency first, then type (so EUR->Pro, EUR->Pro+, USD->Pro, USD->Pro+)
16
- */
17
- function cnb_plan_sort($a, $b) {
18
- $currency = strcmp($a->currency, $b->currency);
19
- if ($currency === 0) {
20
- return strcmp($a->domainType, $b->domainType);
21
- }
22
- return $currency;
23
  }
24
 
 
 
 
25
  function cnb_get_domain() {
26
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
27
- $domain = new stdClass();
28
  if (strlen($domain_id) > 0 && $domain_id != 'new') {
29
  $domain = CnbAppRemote::cnb_remote_get_domain( $domain_id );
30
  }
31
  return $domain;
32
  }
33
 
34
- function cnb_domain_type_is_current_or_better($plan, $domain) {
35
- if ($domain->type === 'FREE') {
36
- return false;
37
- }
38
- switch ($domain->type) {
39
- case 'PRO':
40
- return $plan->domainType === 'PRO';
41
- case 'PROPLUS':
42
- return $plan->domainType === 'PRO' || $plan->domainType === 'PROPLUS';
43
- default: // Same as 'FREE'
44
- return false;
45
- }
46
- }
47
-
48
  function cnb_print_domain_upgrade_notice_cache_flush() {
49
  $upgradeStatus = filter_input( INPUT_GET, 'upgrade', FILTER_SANITIZE_STRING );
50
  $checkoutSesionId = filter_input( INPUT_GET, 'checkout_session_id', FILTER_SANITIZE_STRING );
@@ -55,7 +44,12 @@ function cnb_print_domain_upgrade_notice_cache_flush() {
55
  }
56
 
57
 
58
- function cnb_print_domain_upgrade_notice($domain, &$cnb_notices) {
 
 
 
 
 
59
  $upgradeStatus = filter_input( INPUT_GET, 'upgrade', FILTER_SANITIZE_STRING );
60
  $checkoutSesionId = filter_input( INPUT_GET, 'checkout_session_id', FILTER_SANITIZE_STRING );
61
  if ($upgradeStatus === 'success?payment=success') {
@@ -63,38 +57,30 @@ function cnb_print_domain_upgrade_notice($domain, &$cnb_notices) {
63
  $session = CnbAppRemotePayment::cnb_remote_get_subscription_session( $checkoutSesionId );
64
  // This results in a subscription (via ->subscriptionId), get that for ->type
65
  $subscription = CnbAppRemotePayment::cnb_remote_get_subscription( $session->subscriptionId );
66
- //
67
- $message = '<div class="notice-success notice"><p>Your domain <strong>'.esc_html($domain->name).'</strong> has been upgraded to <strong>'.esc_html($subscription->type).'</strong>!</p></div>';
68
- $cnb_notices[] = $message;
69
- return true;
70
  }
71
- return false;
72
  }
73
 
74
- function cnb_admin_page_domain_upgrade_render() {
75
- global $cnb_options, $cnb_settings;
76
-
77
- add_action('cnb_header', 'cnb_add_header_domain_upgrade');
 
 
 
 
78
 
79
- $cnb_notices = cnb_get_notices();
80
- $cnb_changelog = cnb_get_changelog();
81
 
82
  $domain = cnb_get_domain();
83
- $updated = cnb_print_domain_upgrade_notice($domain, $cnb_notices);
84
-
85
- if ($updated) {
86
- cnb_print_domain_upgrade_notice_cache_flush();
87
- $domain = cnb_get_domain();
88
- }
89
 
 
90
 
91
- echo '<div class="wrap">';
92
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
93
 
94
- $plans = CnbAppRemotePayment::cnb_remote_get_plans();
95
- usort($plans, 'cnb_plan_sort');
96
-
97
- $planCount = count($plans);
98
 
99
  // If the type is missing, we assume FREE
100
  if (empty($domain->type)) {
@@ -105,94 +91,106 @@ function cnb_admin_page_domain_upgrade_render() {
105
  ?>
106
  <script src="https://js.stripe.com/v3/"></script>
107
  <script>
108
- function cnb_get_checkout(planId) {
109
- jQuery('.spinner');
110
- const data = {
111
- 'action': 'cnb_get_checkout',
112
- 'planId': planId,
113
- 'domainId': jQuery('#cnb_domain_id').val()
114
- };
115
-
116
- jQuery.post(ajaxurl, data, function(response) {
117
- cnb_goto_checkout(response)
118
- });
119
- }
120
-
121
- function cnb_goto_checkout(checkoutSessionId) {
122
- stripe.redirectToCheckout({ sessionId: checkoutSessionId });
123
- }
124
-
125
  const stripe = Stripe("<?php echo esc_js( CnbAppRemotePayment::cnb_remote_get_stripe_key()->key) ?>");
126
  </script>
127
 
128
- <h2><?php esc_html_e($domain->name) ?></h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  <form id="wp_domain_upgrade" method="post">
130
  <input type="hidden" name="cnb_domain_id" id="cnb_domain_id" value="<?php esc_attr_e($domain->id) ?>">
131
- <p>Your current plan: <code><?php esc_html_e($domain->type) ?></code></p>
132
- <h2>Select Plan</h2>
133
- <table class="cnb-pricing">
134
- <tr>
135
- <?php foreach ($plans as $plan) { ?>
136
- <td>
137
- <h1><?php echo $plan->domainType === 'PROPLUS' ? 'PRO+' : 'PRO'; ?></h1>
138
- <div class="cnb_font_120 cnb_font_bold"><?php echo $plan->currency === 'EUR' ? '€' : '$' ?><?php echo round($plan->price / 12.0, 2) ?>/month</div>
139
- billed annually<br />
140
- <?php if ($plan->domainType === $domain->type) { ?>
141
- <strong>CURRENT PLAN</strong>
142
- <?php } ?>
143
- </td>
144
- <?php } ?>
145
- </tr>
146
- <tr><?php echo str_repeat('<td>Unlimited buttons</td>', $planCount); ?></tr>
147
- <tr><?php echo str_repeat('<td>Scheduling</td>', $planCount); ?></tr>
148
- <tr><?php echo str_repeat('<td>Multi button</td>', $planCount); ?></tr>
149
- <tr><?php echo str_repeat('<td>Button bar</td>', $planCount); ?></tr>
150
- <tr>
151
- <?php foreach ($plans as $plan) {
152
- if ($plan->domainType === 'PRO') { ?>
153
- <td>
154
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
155
- <path d="M6.54 5c.06.89.21 1.76.45 2.59l-1.2 1.2c-.41-1.2-.67-2.47-.76-3.79h1.51m9.86 12.02c.85.24 1.72.39 2.6.45v1.49c-1.32-.09-2.59-.35-3.8-.75l1.2-1.19M7.5 3H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.49c0-.55-.45-1-1-1-1.24 0-2.45-.2-3.57-.57-.1-.04-.21-.05-.31-.05-.26 0-.51.1-.71.29l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.2c.28-.28.36-.67.25-1.02C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1z"></path>
156
- </svg>
157
- </td>
158
- <?php } else { ?>
159
- <td>
160
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
161
- <path d="M6.54 5c.06.89.21 1.76.45 2.59l-1.2 1.2c-.41-1.2-.67-2.47-.76-3.79h1.51m9.86 12.02c.85.24 1.72.39 2.6.45v1.49c-1.32-.09-2.59-.35-3.8-.75l1.2-1.19M7.5 3H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.49c0-.55-.45-1-1-1-1.24 0-2.45-.2-3.57-.57-.1-.04-.21-.05-.31-.05-.26 0-.51.1-.71.29l-2.2 2.2c-2.83-1.45-5.15-3.76-6.59-6.59l2.2-2.2c.28-.28.36-.67.25-1.02C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1z"></path>
162
- </svg>
163
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
164
- <path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0l-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z"></path>
165
- </svg>
166
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
167
- <path d="M16.75,13.96C17,14.09 17.16,14.16 17.21,14.26C17.27,14.37 17.25,14.87 17,15.44C16.8,16 15.76,16.54 15.3,16.56C14.84,16.58 14.83,16.92 12.34,15.83C9.85,14.74 8.35,12.08 8.23,11.91C8.11,11.74 7.27,10.53 7.31,9.3C7.36,8.08 8,7.5 8.26,7.26C8.5,7 8.77,6.97 8.94,7H9.41C9.56,7 9.77,6.94 9.96,7.45L10.65,9.32C10.71,9.45 10.75,9.6 10.66,9.76L10.39,10.17L10,10.59C9.88,10.71 9.74,10.84 9.88,11.09C10,11.35 10.5,12.18 11.2,12.87C12.11,13.75 12.91,14.04 13.15,14.17C13.39,14.31 13.54,14.29 13.69,14.13L14.5,13.19C14.69,12.94 14.85,13 15.08,13.08L16.75,13.96M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22C10.03,22 8.2,21.43 6.65,20.45L2,22L3.55,17.35C2.57,15.8 2,13.97 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12C4,13.72 4.54,15.31 5.46,16.61L4.5,19.5L7.39,18.54C8.69,19.46 10.28,20 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z"></path>
168
- </svg>
169
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
170
- <path d="M12 12c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm6-1.8C18 6.57 15.35 4 12 4s-6 2.57-6 6.2c0 2.34 1.95 5.44 6 9.14 4.05-3.7 6-6.8 6-9.14zM12 2c4.2 0 8 3.22 8 8.2 0 3.32-2.67 7.25-8 11.8-5.33-4.55-8-8.48-8-11.8C4 5.22 7.8 2 12 2z"></path>
171
- </svg>
172
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
173
- <path d="M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z"></path>
174
- </svg>
175
- <svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
176
- <path d="M12,2A3,3 0 0,0 9,5C9,6.27 9.8,7.4 11,7.83V10H8V12H11V18.92C9.16,18.63 7.53,17.57 6.53,16H8V14H3V19H5V17.3C6.58,19.61 9.2,21 12,21C14.8,21 17.42,19.61 19,17.31V19H21V14H16V16H17.46C16.46,17.56 14.83,18.63 13,18.92V12H16V10H13V7.82C14.2,7.4 15,6.27 15,5A3,3 0 0,0 12,2M12,4A1,1 0 0,1 13,5A1,1 0 0,1 12,6A1,1 0 0,1 11,5A1,1 0 0,1 12,4Z"></path>
177
- </svg>
178
- </td>
179
- <?php } } ?>
180
- </tr>
181
- <tr><?php
182
- // Get link based on Stripe checkoutSessionId
183
- foreach ( $plans as $plan ) {
184
- echo '<td><button class="button button-secondary" type="button" ';
185
- if ( cnb_domain_type_is_current_or_better($plan, $domain) ) {
186
- echo 'disabled="disabled"';
187
- } else {
188
- echo 'onclick="cnb_get_checkout(\'' . esc_js($plan->id) . '\')"';
189
- }
190
- echo '>Upgrade</button></td>';
191
- }
192
- ?></tr>
193
- </table>
194
  </form>
 
 
 
 
 
 
 
 
 
 
 
195
  <?php
196
- cnb_admin_footer();
197
- echo '</div>';
198
  }
6
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
9
+ require_once dirname( __FILE__ ) . '/models/CnbDomain.class.php';
10
 
11
  function cnb_add_header_domain_upgrade() {
12
+ echo 'Upgrade the Call Now Button';
13
  }
14
 
15
+ function cnb_upgrade_create_settings_url() {
16
+ $url = admin_url('admin.php');
17
+ $tab_link =
18
+ add_query_arg(
19
+ array(
20
+ 'page' => 'call-now-button-settings'),
21
+ $url );
22
+ return esc_url( $tab_link );
 
23
  }
24
 
25
+ /**
26
+ * @return CnbDomain
27
+ */
28
  function cnb_get_domain() {
29
  $domain_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
30
+ $domain = new CnbDomain();
31
  if (strlen($domain_id) > 0 && $domain_id != 'new') {
32
  $domain = CnbAppRemote::cnb_remote_get_domain( $domain_id );
33
  }
34
  return $domain;
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  function cnb_print_domain_upgrade_notice_cache_flush() {
38
  $upgradeStatus = filter_input( INPUT_GET, 'upgrade', FILTER_SANITIZE_STRING );
39
  $checkoutSesionId = filter_input( INPUT_GET, 'checkout_session_id', FILTER_SANITIZE_STRING );
44
  }
45
 
46
 
47
+ /**
48
+ * @param $domain CnbDomain
49
+ *
50
+ * @return CnbNotice
51
+ */
52
+ function cnb_print_domain_upgrade_notice($domain) {
53
  $upgradeStatus = filter_input( INPUT_GET, 'upgrade', FILTER_SANITIZE_STRING );
54
  $checkoutSesionId = filter_input( INPUT_GET, 'checkout_session_id', FILTER_SANITIZE_STRING );
55
  if ($upgradeStatus === 'success?payment=success') {
57
  $session = CnbAppRemotePayment::cnb_remote_get_subscription_session( $checkoutSesionId );
58
  // This results in a subscription (via ->subscriptionId), get that for ->type
59
  $subscription = CnbAppRemotePayment::cnb_remote_get_subscription( $session->subscriptionId );
60
+
61
+ return new CnbNotice('success', '<p>Your domain <strong>'.esc_html($domain->name).'</strong> has been successfully upgraded to <strong>'.esc_html($subscription->type).'</strong>!</p>');
 
 
62
  }
63
+ return null;
64
  }
65
 
66
+ function cnb_get_plan($plans, $name) {
67
+ foreach ($plans as $plan) {
68
+ if ($plan->nickname === $name) {
69
+ return $plan;
70
+ }
71
+ }
72
+ return null;
73
+ }
74
 
75
+ function cnb_admin_page_domain_upgrade_render() {
 
76
 
77
  $domain = cnb_get_domain();
78
+ $notice = cnb_print_domain_upgrade_notice($domain);
 
 
 
 
 
79
 
80
+ add_action('cnb_header_name', 'cnb_add_header_domain_upgrade');
81
 
82
+ do_action('cnb_header');
 
83
 
 
 
 
 
84
 
85
  // If the type is missing, we assume FREE
86
  if (empty($domain->type)) {
91
  ?>
92
  <script src="https://js.stripe.com/v3/"></script>
93
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  const stripe = Stripe("<?php echo esc_js( CnbAppRemotePayment::cnb_remote_get_stripe_key()->key) ?>");
95
  </script>
96
 
97
+ <p>Your domain <?php esc_html_e($domain->name) ?> is currently on the <code><?php esc_html_e($domain->type) ?></code> cloud plan.</p>
98
+
99
+
100
+ <?php if ($domain->type == 'PRO') {
101
+ // Render notice if JUST upgraded and show general information about domain (instead of upgrade form)
102
+ if ($notice) {
103
+ CnbAdminNotices::get_instance()->renderNotice( $notice );
104
+ }
105
+ $portal_url = CnbAppRemote::cnb_remote_create_billing_portal();
106
+ if (!empty($domain->expires)) { ?>
107
+ <p class="description" id="domain_expires-description">
108
+ Your subscription will
109
+ <?php echo $domain->renew == 1 ? ' renew automatically ' : ' expire '; ?>
110
+ on <?php echo date('F d, Y', strtotime(esc_html($domain->expires))); ?>.
111
+ </p>
112
+ <?php } ?>
113
+ <p>You can change this on the <a href="<?php esc_html_e(cnb_upgrade_create_settings_url()) ?>">settings page</a>.</p>
114
+ <p>If you have any questions about your subscriptions, you can see <a href="<?php esc_html_e($portal_url->url); ?>">your invoice dashboard</a> here or contact us via the <a href="https://help.callnowbutton.com/">support forums</a>.</p>
115
+
116
+ <?php
117
+ } else {
118
+ // Render upgrade form
119
+ $plans = CnbAppRemotePayment::cnb_remote_get_plans();
120
+ ?>
121
+
122
  <form id="wp_domain_upgrade" method="post">
123
  <input type="hidden" name="cnb_domain_id" id="cnb_domain_id" value="<?php esc_attr_e($domain->id) ?>">
124
+
125
+ <h2>Select a plan to remove the "Powered by Call Now Button" message from your buttons</h2>
126
+
127
+
128
+ <h2 class="nav-tab-wrapper">
129
+ <a href="#" data-cnb-currency="eur" class="cnb-currency-select cnb-currency-eur nav-tab nav-tab-active">Euro (&euro;)</a>
130
+ <a href="#" data-cnb-currency="usd" class="cnb-currency-select cnb-currency-usd nav-tab ">US Dollar ($)</a>
131
+ </h2>
132
+ <div class="cnb-message"><p class="cnb-error-message"></p></div>
133
+ <div class="cnb-price-plans">
134
+ <div class="currency-box currency-box-eur currency-box-active cnb-flexbox">
135
+ <?php $plan = cnb_get_plan($plans, 'powered-by-eur-yearly'); ?>
136
+ <div class="pricebox">
137
+ <h3 class="yearly">Yearly Plan</h3>
138
+ <div class="benefit">All branding removed</div>
139
+ <div class="plan-amount"><span class="currency">€</span><span class="euros">1</span><span class="cents">.67</span><span class="timeframe">/month</span></div>
140
+ <div class="billingprice">
141
+ Billed at €19.99 annually
142
+ </div>
143
+ <a class="button button-primary" href="#" onclick="cnb_get_checkout('<?php _e($plan->id) ?>')">Upgrade</a>
144
+ </div>
145
+
146
+ <?php $plan = cnb_get_plan($plans, 'powered-by-eur-monthly'); ?>
147
+ <div class="pricebox">
148
+ <h3 class="">Monthly Plan</h3>
149
+ <div class="benefit">All branding removed</div>
150
+ <div class="plan-amount"><span class="currency">€</span><span class="euros">4</span><span class="cents">.99</span><span class="timeframe">/month</span></div>
151
+ <div class="billingprice">
152
+ Billed at €4.99 monthly
153
+ </div>
154
+ <a class="button button-secondary" href="#" onclick="cnb_get_checkout('<?php _e($plan->id) ?>')">Upgrade</a>
155
+ </div>
156
+ </div>
157
+ <div class="currency-box currency-box-usd cnb-flexbox">
158
+ <?php $plan = cnb_get_plan($plans, 'powered-by-usd-yearly'); ?>
159
+ <div class="pricebox">
160
+ <h3 class="yearly">Yearly Plan</h3>
161
+ <div class="benefit">All branding removed</div>
162
+ <div class="plan-amount"><span class="currency">$</span><span class="euros">1</span><span class="cents">.99</span><span class="timeframe">/month</span></div>
163
+ <div class="billingprice">
164
+ Billed at $23.88 annually
165
+ </div>
166
+ <a class="button button-primary" href="#" onclick="cnb_get_checkout('<?php _e($plan->id) ?>')">Upgrade</a>
167
+ </div>
168
+ <?php $plan = cnb_get_plan($plans, 'powered-by-usd-monthly'); ?>
169
+ <div class="pricebox">
170
+ <h3 class="">Monthly Plan</h3>
171
+ <div class="benefit">All branding removed</div>
172
+ <div class="plan-amount"><span class="currency">$</span><span class="euros">5</span><span class="cents">.99</span><span class="timeframe">/month</span></div>
173
+ <div class="billingprice">
174
+ Billed at $5.99 monthly
175
+ </div>
176
+ <a class="button button-secondary" href="#" onclick="cnb_get_checkout('<?php _e($plan->id) ?>')">Upgrade</a>
177
+ </div>
178
+ </div>
179
+
180
+ </div>
 
 
 
 
 
 
181
  </form>
182
+ <?php } ?>
183
+
184
+ <p class="cnb-center">All <u>cloud</u> plans (free and paid) contain the following features:</p>
185
+ <div class="cnb-center" style="margin-bottom:50px;">
186
+ <div><b>&check;</b> Phone, Email, Location, WhatsApp, Links</div>
187
+ <div><b>&check;</b> Unlimited buttons</div>
188
+ <div><b>&check;</b> Multibutton</div>
189
+ <div><b>&check;</b> Buttonbar (full width with multiple actions)</div>
190
+ <div><b>&check;</b> Advanced page targeting options</div>
191
+ <div><b>&check;</b> Scheduling</div>
192
+ </div>
193
  <?php
194
+
195
+ do_action('cnb_footer');
196
  }
src/admin/legacy-edit.php CHANGED
@@ -7,7 +7,7 @@ function cnb_add_header_legacy_edit() {
7
  echo CNB_NAME . ' <span class="cnb-version">v' . CNB_VERSION . '</span>';
8
  }
9
 
10
- function cnb_create_tab_url($tab) {
11
  $url = admin_url('admin.php');
12
  $tab_link =
13
  add_query_arg(
@@ -19,38 +19,127 @@ function cnb_create_tab_url($tab) {
19
  return esc_url( $tab_link );
20
  }
21
 
22
- function cnb_admin_page_legacy_edit_render() {
23
- global $cnb_options, $cnb_settings;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- add_action('cnb_header', 'cnb_add_header_legacy_edit');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- $cnb_notices = cnb_get_notices();
28
- $cnb_changelog = cnb_get_changelog();
29
 
30
- echo '<div class="wrap">';
31
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
32
  ?>
33
 
34
  <h2 class="nav-tab-wrapper">
35
- <a href="<?php echo cnb_create_tab_url('basic_options') ?>"
36
  class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
37
- <a href="<?php echo cnb_create_tab_url('extra_options') ?>"
38
  class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
39
  </h2>
40
  <form method="post" action="<?php echo esc_url( admin_url('options.php') ); ?>" class="cnb-container">
41
  <?php settings_fields('cnb_options'); ?>
42
  <table class="form-table <?php echo cnb_is_active_tab('basic_options') ?>">
43
  <tr>
44
- <th colspan="2"><h2>Basic Settings</h2></th>
45
  </tr>
46
  <tr>
47
- <th scope="row">Phone number:<a href="<?php echo CNB_SUPPORT; ?>phone-number/<?php cnb_utm_params("question-mark", "phone-number"); ?>" target="_blank" class="cnb-nounderscore">
 
 
 
 
 
 
 
 
48
  <span class="dashicons dashicons-editor-help"></span>
49
  </a></th>
50
  <td><input type="text" name="cnb[number]" value="<?php esc_attr_e($cnb_options['number']) ?>" /></td>
51
  </tr>
52
  <tr class="button-text">
53
- <th scope="row">Button text <small style="font-weight: 400">(optional)</small>:<a href="<?php echo CNB_SUPPORT; ?>using-text-buttons/<?php cnb_utm_params("question-mark", "using-text-buttons"); ?>" target="_blank" class="cnb-nounderscore">
54
  <span class="dashicons dashicons-editor-help"></span>
55
  </a></th>
56
  <td>
@@ -61,20 +150,20 @@ function cnb_admin_page_legacy_edit_render() {
61
  </table>
62
 
63
  <table class="form-table <?php echo cnb_is_active_tab('extra_options') ?>">
64
- <tr>
65
- <th colspan="2"><h2>Presentation Settings</h2></th>
66
- </tr>
67
 
68
  <tr>
69
- <th scope="row">Button color:</th>
70
  <td><input name="cnb[color]" type="text" value="<?php esc_attr_e($cnb_options['color']) ?>" class="cnb-color-field" data-default-color="#009900" /></td>
71
  </tr>
72
  <tr>
73
- <th scope="row">Icon color:</th>
74
  <td><input name="cnb[iconcolor]" type="text" value="<?php esc_attr_e($cnb_options['iconcolor']) ?>" class="cnb-iconcolor-field" data-default-color="#ffffff" /></td>
75
  </tr>
76
  <tr>
77
- <th scope="row">Position: <a href="<?php echo CNB_SUPPORT; ?>button-position/<?php cnb_utm_params("question-mark", "button-position"); ?>" target="_blank" class="cnb-nounderscore">
78
  <span class="dashicons dashicons-editor-help"></span>
79
  </a></th>
80
  <td class="appearance">
@@ -136,7 +225,7 @@ function cnb_admin_page_legacy_edit_render() {
136
  </td>
137
  </tr>
138
  <tr class="appearance">
139
- <th scope="row">Limit appearance: <a href="<?php echo CNB_SUPPORT; ?>limit-appearance/<?php cnb_utm_params("question-mark", "limit-appearance"); ?>" target="_blank" class="cnb-nounderscore">
140
  <span class="dashicons dashicons-editor-help"></span>
141
  </a></th>
142
  <td>
@@ -163,69 +252,15 @@ function cnb_admin_page_legacy_edit_render() {
163
  <tr>
164
  <th colspan="2"><h2>Advanced Settings</h2></th>
165
  </tr>
166
- <tr>
167
- <th scope="row">Click tracking: <a href="<?php echo CNB_SUPPORT; ?>click-tracking/<?php cnb_utm_params("question-mark", "click-tracking"); ?>" target="_blank" class="cnb-nounderscore">
168
- <span class="dashicons dashicons-editor-help"></span>
169
- </a></th>
170
- <td>
171
- <div class="cnb-radio-item">
172
- <input id="tracking3" type="radio" name="cnb[tracking]" value="0" <?php checked('0', $cnb_options['tracking']); ?> />
173
- <label for="tracking3">Disabled</label>
174
- </div>
175
- <div class="cnb-radio-item">
176
- <input id="tracking4" type="radio" name="cnb[tracking]" value="3" <?php checked('3', $cnb_options['tracking']); ?> />
177
- <label for="tracking4">Latest Google Analytics (gtag.js)</label>
178
- </div>
179
- <div class="cnb-radio-item">
180
- <input id="tracking1" type="radio" name="cnb[tracking]" value="2" <?php checked('2', $cnb_options['tracking']); ?> />
181
- <label for="tracking1">Google Universal Analytics (analytics.js)</label>
182
- </div>
183
- <div class="cnb-radio-item">
184
- <input id="tracking2" type="radio" name="cnb[tracking]" value="1" <?php checked('1', $cnb_options['tracking']); ?> />
185
- <label for="tracking2">Classic Google Analytics (ga.js)</label>
186
- </div>
187
- <p class="description">Using Google Tag Manager? Set up click tracking in GTM. <a href="<?php echo CNB_SUPPORT; ?>click-tracking/google-tag-manager-event-tracking/<?php cnb_utm_params("description_link", "google-tag-manager-event-tracking"); ?>" target="_blank">Learn how to do this...</a></p>
188
- </td>
189
- </tr>
190
- <tr>
191
- <th scope="row">Google Ads: <a href="<?php echo CNB_SUPPORT; ?>google-ads/<?php cnb_utm_params("question-mark", "google-ads"); ?>" target="_blank" class="cnb-nounderscore">
192
- <span class="dashicons dashicons-editor-help"></span>
193
- </a></th>
194
- <td class="conversions">
195
- <div class="cnb-radio-item">
196
- <input name="cnb[conversions]" type="radio" value="0" <?php checked('0', $cnb_options['conversions']); ?> /> <label for="conversions">Off </label>
197
- </div>
198
- <div class="cnb-radio-item">
199
- <input name="cnb[conversions]" type="radio" value="1" <?php checked('1', $cnb_options['conversions']); ?> /> <label for="conversions">Conversion Tracking using Google's global site tag </label>
200
- </div>
201
- <div class="cnb-radio-item">
202
- <input name="cnb[conversions]" type="radio" value="2" <?php checked('2', $cnb_options['conversions']); ?> /> <label for="conversions">Conversion Tracking using JavaScript</label>
203
- </div>
204
- <p class="description">Select this option if you want to track clicks on the button as Google Ads conversions. This option requires the Event snippet to be present on the page. <a href="https">Learn more...</a></p>
205
- </td>
206
- </tr>
207
- <tr class="zoom">
208
- <th scope="row">Button size <span id="cnb_slider_value"></span>:</th>
209
- <td>
210
- <label class="cnb_slider_value">Smaller&nbsp;&laquo;&nbsp;</label>
211
- <input type="range" min="0.7" max="1.3" name="cnb[zoom]" value="<?php esc_attr_e($cnb_options['zoom']) ?>" class="slider" id="cnb_slider" step="0.1">
212
- <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Bigger</label>
213
- </td>
214
- </tr>
215
- <tr class="z-index">
216
- <th scope="row">Order (<span id="cnb_order_value"></span>): <a href="https://callnowbutton.com/set-order/" target="_blank" class="cnb-nounderscore">
217
- <span class="dashicons dashicons-editor-help"></span>
218
- </a></th>
219
- <td>
220
- <label class="cnb_slider_value">Backwards&nbsp;&laquo;&nbsp;</label>
221
- <input type="range" min="1" max="10" name="cnb[z-index]" value="<?php esc_attr_e($cnb_options['z-index']) ?>" class="slider2" id="cnb_order_slider" step="1">
222
- <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Front</label>
223
- <p class="description">The default (and recommended) value is all the way to the front so the button sits on top of everything else. In case you have a specific usecase where you want something else to sit in front of the Call Now Button (e.g. a chat window or a cookie notice) you can move this backwards one step at a time to adapt it to your situation.</p>
224
- </td>
225
- </tr>
226
- <?php if($cnb_options['classic'] == 1) { ?>
227
  <tr class="classic">
228
- <th scope="row">Classic button: <a href="https://callnowbutton.com/new-button-design/<?php cnb_utm_params("question-mark", "new-button-design"); ?>" target="_blank" class="cnb-nounderscore">
229
  <span class="dashicons dashicons-editor-help"></span>
230
  </a></th>
231
  <td>
@@ -241,6 +276,5 @@ function cnb_admin_page_legacy_edit_render() {
241
  </form>
242
 
243
  <?php
244
- cnb_admin_footer();
245
- echo '</div>';
246
  }
7
  echo CNB_NAME . ' <span class="cnb-version">v' . CNB_VERSION . '</span>';
8
  }
9
 
10
+ function cnb_create_tab_url_legacy($tab) {
11
  $url = admin_url('admin.php');
12
  $tab_link =
13
  add_query_arg(
19
  return esc_url( $tab_link );
20
  }
21
 
22
+ function cnb_admin_page_leagcy_edit_render_tracking() {
23
+ global $cnb_options;
24
+ ?>
25
+ <tr>
26
+ <th scope="row">Click tracking <a href="<?php echo CNB_SUPPORT; ?>click-tracking/<?php cnb_utm_params("question-mark", "click-tracking"); ?>" target="_blank" class="cnb-nounderscore">
27
+ <span class="dashicons dashicons-editor-help"></span>
28
+ </a></th>
29
+ <td>
30
+ <div class="cnb-radio-item">
31
+ <input id="tracking3" type="radio" name="cnb[tracking]" value="0" <?php checked('0', $cnb_options['tracking']); ?> />
32
+ <label for="tracking3">Disabled</label>
33
+ </div>
34
+ <div class="cnb-radio-item">
35
+ <input id="tracking4" type="radio" name="cnb[tracking]" value="3" <?php checked('3', $cnb_options['tracking']); ?> />
36
+ <label for="tracking4">Latest Google Analytics (gtag.js)</label>
37
+ </div>
38
+ <div class="cnb-radio-item">
39
+ <input id="tracking1" type="radio" name="cnb[tracking]" value="2" <?php checked('2', $cnb_options['tracking']); ?> />
40
+ <label for="tracking1">Google Universal Analytics (analytics.js)</label>
41
+ </div>
42
+ <div class="cnb-radio-item">
43
+ <input id="tracking2" type="radio" name="cnb[tracking]" value="1" <?php checked('1', $cnb_options['tracking']); ?> />
44
+ <label for="tracking2">Classic Google Analytics (ga.js)</label>
45
+ </div>
46
+ <p class="description">Using Google Tag Manager? Set up click tracking in GTM. <a href="<?php echo CNB_SUPPORT; ?>click-tracking/google-tag-manager-event-tracking/<?php cnb_utm_params("description_link", "google-tag-manager-event-tracking"); ?>" target="_blank">Learn how to do this...</a></p>
47
+ </td>
48
+ </tr>
49
+ <?php
50
+ }
51
+
52
+ function cnb_admin_page_leagcy_edit_render_conversions() {
53
+ global $cnb_options;
54
+ ?>
55
+ <tr>
56
+ <th scope="row">Google Ads <a href="<?php echo CNB_SUPPORT; ?>google-ads/<?php cnb_utm_params("question-mark", "google-ads"); ?>" target="_blank" class="cnb-nounderscore">
57
+ <span class="dashicons dashicons-editor-help"></span>
58
+ </a></th>
59
+ <td class="conversions">
60
+ <div class="cnb-radio-item">
61
+ <input id="cnb_conversions_0" name="cnb[conversions]" type="radio" value="0" <?php checked('0', $cnb_options['conversions']); ?> /> <label for="cnb_conversions_0">Off </label>
62
+ </div>
63
+ <div class="cnb-radio-item">
64
+ <input id="cnb_conversions_1" name="cnb[conversions]" type="radio" value="1" <?php checked('1', $cnb_options['conversions']); ?> /> <label for="cnb_conversions_1">Conversion Tracking using Google's global site tag </label>
65
+ </div>
66
+ <div class="cnb-radio-item">
67
+ <input id="cnb_conversions_2" name="cnb[conversions]" type="radio" value="2" <?php checked('2', $cnb_options['conversions']); ?> /> <label for="cnb_conversions_2">Conversion Tracking using JavaScript</label>
68
+ </div>
69
+ <p class="description">Select this option if you want to track clicks on the button as Google Ads conversions. This option requires the Event snippet to be present on the page. <a href="<?php echo CNB_SUPPORT; ?>google-ads/<?php cnb_utm_params("question-mark", "google-ads"); ?>" target="_blank">Learn more...</a></p>
70
+ </td>
71
+ </tr>
72
+ <?php
73
+ }
74
+
75
+ function cnb_admin_page_leagcy_edit_render_zoom() {
76
+ global $cnb_options;
77
+ ?>
78
+ <tr class="zoom">
79
+ <th scope="row">Button size <span id="cnb_slider_value"></span></th>
80
+ <td>
81
+ <label class="cnb_slider_value">Smaller&nbsp;&laquo;&nbsp;</label>
82
+ <input type="range" min="0.7" max="1.3" name="cnb[zoom]" value="<?php esc_attr_e($cnb_options['zoom']) ?>" class="slider" id="cnb_slider" step="0.1">
83
+ <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Bigger</label>
84
+ </td>
85
+ </tr>
86
+ <?php
87
+ }
88
 
89
+ function cnb_admin_page_leagcy_edit_render_zindex() {
90
+ global $cnb_options;
91
+ ?>
92
+ <tr class="z-index">
93
+ <th scope="row">Order (<span id="cnb_order_value"></span>) <a href="https://callnowbutton.com/set-order/" target="_blank" class="cnb-nounderscore">
94
+ <span class="dashicons dashicons-editor-help"></span>
95
+ </a></th>
96
+ <td>
97
+ <label class="cnb_slider_value">Backwards&nbsp;&laquo;&nbsp;</label>
98
+ <input type="range" min="1" max="10" name="cnb[z-index]" value="<?php esc_attr_e($cnb_options['z-index']) ?>" class="slider2" id="cnb_order_slider" step="1">
99
+ <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Front</label>
100
+ <p class="description">The default (and recommended) value is all the way to the front so the button sits on top of everything else. In case you have a specific usecase where you want something else to sit in front of the Call Now Button (e.g. a chat window or a cookie notice) you can move this backwards one step at a time to adapt it to your situation.</p>
101
+ </td>
102
+ </tr>
103
+
104
+ <?php
105
+ }
106
+
107
+ function cnb_admin_page_legacy_edit_render() {
108
+ global $cnb_options;
109
 
110
+ add_action('cnb_header_name', 'cnb_add_header_legacy_edit');
 
111
 
112
+ do_action('cnb_header');
 
113
  ?>
114
 
115
  <h2 class="nav-tab-wrapper">
116
+ <a href="<?php echo cnb_create_tab_url_legacy('basic_options') ?>"
117
  class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">Basics</a>
118
+ <a href="<?php echo cnb_create_tab_url_legacy('extra_options') ?>"
119
  class="nav-tab <?php echo cnb_is_active_tab('extra_options') ?>">Presentation</a>
120
  </h2>
121
  <form method="post" action="<?php echo esc_url( admin_url('options.php') ); ?>" class="cnb-container">
122
  <?php settings_fields('cnb_options'); ?>
123
  <table class="form-table <?php echo cnb_is_active_tab('basic_options') ?>">
124
  <tr>
125
+ <th colspan="2"></th>
126
  </tr>
127
  <tr>
128
+ <th scope="row">Button status</th>
129
+ <td>
130
+ <input type="hidden" name="cnb[active]" value="0" />
131
+ <input id="cnb-active" type="checkbox" name="cnb[active]" value="1" <?php checked('1', $cnb_options['active']); ?>>
132
+ <label for="cnb-active">Enable</label>
133
+ </td>
134
+ </tr>
135
+ <tr>
136
+ <th scope="row">Phone number <a href="<?php echo CNB_SUPPORT; ?>phone-number/<?php cnb_utm_params("question-mark", "phone-number"); ?>" target="_blank" class="cnb-nounderscore">
137
  <span class="dashicons dashicons-editor-help"></span>
138
  </a></th>
139
  <td><input type="text" name="cnb[number]" value="<?php esc_attr_e($cnb_options['number']) ?>" /></td>
140
  </tr>
141
  <tr class="button-text">
142
+ <th scope="row">Button text <small style="font-weight: 400">(optional)</small> <a href="<?php echo CNB_SUPPORT; ?>using-text-buttons/<?php cnb_utm_params("question-mark", "using-text-buttons"); ?>" target="_blank" class="cnb-nounderscore">
143
  <span class="dashicons dashicons-editor-help"></span>
144
  </a></th>
145
  <td>
150
  </table>
151
 
152
  <table class="form-table <?php echo cnb_is_active_tab('extra_options') ?>">
153
+ <tr>
154
+ <th colspan="2"></th>
155
+ </tr>
156
 
157
  <tr>
158
+ <th scope="row">Button color</th>
159
  <td><input name="cnb[color]" type="text" value="<?php esc_attr_e($cnb_options['color']) ?>" class="cnb-color-field" data-default-color="#009900" /></td>
160
  </tr>
161
  <tr>
162
+ <th scope="row">Icon color</th>
163
  <td><input name="cnb[iconcolor]" type="text" value="<?php esc_attr_e($cnb_options['iconcolor']) ?>" class="cnb-iconcolor-field" data-default-color="#ffffff" /></td>
164
  </tr>
165
  <tr>
166
+ <th scope="row">Position <a href="<?php echo CNB_SUPPORT; ?>button-position/<?php cnb_utm_params("question-mark", "button-position"); ?>" target="_blank" class="cnb-nounderscore">
167
  <span class="dashicons dashicons-editor-help"></span>
168
  </a></th>
169
  <td class="appearance">
225
  </td>
226
  </tr>
227
  <tr class="appearance">
228
+ <th scope="row">Limit appearance <a href="<?php echo CNB_SUPPORT; ?>limit-appearance/<?php cnb_utm_params("question-mark", "limit-appearance"); ?>" target="_blank" class="cnb-nounderscore">
229
  <span class="dashicons dashicons-editor-help"></span>
230
  </a></th>
231
  <td>
252
  <tr>
253
  <th colspan="2"><h2>Advanced Settings</h2></th>
254
  </tr>
255
+ <?php
256
+ cnb_admin_page_leagcy_edit_render_tracking();
257
+ cnb_admin_page_leagcy_edit_render_conversions();
258
+ cnb_admin_page_leagcy_edit_render_zoom();
259
+ cnb_admin_page_leagcy_edit_render_zindex();
260
+
261
+ if($cnb_options['classic'] == 1) { ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  <tr class="classic">
263
+ <th scope="row">Classic button <a href="https://callnowbutton.com/new-button-design/<?php cnb_utm_params("question-mark", "new-button-design"); ?>" target="_blank" class="cnb-nounderscore">
264
  <span class="dashicons dashicons-editor-help"></span>
265
  </a></th>
266
  <td>
276
  </form>
277
 
278
  <?php
279
+ do_action('cnb_footer');
 
280
  }
src/admin/models/CnbAction.class.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // don't load directly
3
+ defined( 'ABSPATH' ) || die( '-1' );
4
+
5
+ class CnbAction {
6
+ public $id;
7
+ public $actionType;
8
+ public $actionValue;
9
+ public $labelText;
10
+ public $schedule;
11
+
12
+ /**
13
+ * @var boolean
14
+ */
15
+ public $iconEnabled;
16
+
17
+ public $backgroundColor;
18
+ public $iconColor;
19
+
20
+ /**
21
+ * @var CnbActionProperties
22
+ */
23
+ public $properties;
24
+ }
25
+
26
+ class CnbActionProperties {
27
+
28
+ }
src/admin/models/CnbButton.class.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // don't load directly
3
+ defined( 'ABSPATH' ) || die( '-1' );
4
+
5
+ class CnbButton {
6
+
7
+ /**
8
+ * @var string
9
+ */
10
+ public $id;
11
+
12
+ /**
13
+ * @var boolean
14
+ */
15
+ public $active;
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ public $name;
21
+
22
+ /**
23
+ * @var string
24
+ */
25
+ public $type;
26
+
27
+ public $domain;
28
+
29
+ public $actions;
30
+
31
+ public $conditions;
32
+
33
+ public static function setSaneDefault($button) {
34
+ // Set some sane defaults
35
+ if (!isset($button->options)) $button->options = new CnbButtonOptions();
36
+ $button->options->iconBackgroundColor = !empty($button->options->iconBackgroundColor)
37
+ ? $button->options->iconBackgroundColor
38
+ : '#009900';
39
+ $button->options->iconColor = !empty($button->options->iconColor)
40
+ ? $button->options->iconColor
41
+ : '#FFFFFF';
42
+ $button->options->placement = !empty($button->options->placement)
43
+ ? $button->options->placement
44
+ : ($button->type === 'FULL' ? 'BOTTOM_CENTER' : 'BOTTOM_RIGHT');
45
+ $button->options->scale = !empty($button->options->scale)
46
+ ? $button->options->scale
47
+ : '1';
48
+ }
49
+
50
+ public static function createDummyButton($domain = null) {
51
+ $button = new CnbButton();
52
+ $button->id = '';
53
+ $button->active = false;
54
+ $button->name = '';
55
+ $button->type = 'SINGLE';
56
+ $button->domain = $domain;
57
+ $button->actions = array();
58
+
59
+ return $button;
60
+ }
61
+ }
62
+
63
+ class CnbButtonOptions {
64
+ public $iconBackgroundColor;
65
+ public $iconColor;
66
+ public $placement;
67
+ public $scale;
68
+ }
src/admin/models/CnbCondition.class.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // don't load directly
3
+ defined( 'ABSPATH' ) || die( '-1' );
4
+
5
+ class CnbCondition {
6
+ public $id;
7
+ public $conditionType = 'URL';
8
+ public $filterType;
9
+ public $matchType;
10
+ public $matchValue;
11
+ }
src/admin/models/CnbDomain.class.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // don't load directly
3
+ defined( 'ABSPATH' ) || die( '-1' );
4
+
5
+ class CnbDomain {
6
+
7
+ public $id;
8
+ public $name;
9
+ public $timezone;
10
+ public $type;
11
+ /**
12
+ * @var CnbDomainProperties
13
+ */
14
+ public $properties;
15
+ /**
16
+ * @var boolean
17
+ */
18
+ public $trackGA;
19
+ /**
20
+ * @var boolean
21
+ */
22
+ public $trackConversion;
23
+ /**
24
+ * @var boolean
25
+ */
26
+ public $renew;
27
+
28
+ /**
29
+ *
30
+ * This changes the object itself, settings some sane defaults in case those are missing
31
+ *
32
+ * @param $domain CnbDomain|null
33
+ * @param $domain_id number|null
34
+ */
35
+ public static function setSaneDefault( $domain = null, $domain_id = null ) {
36
+ if (is_wp_error($domain)) {
37
+ return;
38
+ }
39
+
40
+ if ( $domain === null ) {
41
+ $domain = new CnbDomain();
42
+ }
43
+
44
+ if ( strlen( $domain_id ) > 0 && $domain_id == 'new' && empty( $domain->id ) ) {
45
+ $domain->id = null;
46
+ }
47
+ if ( empty( $domain->timezone ) ) {
48
+ $domain->timezone = wp_timezone_string();
49
+ }
50
+ if ( empty( $domain->type ) ) {
51
+ $domain->type = 'FREE';
52
+ }
53
+ if ( empty( $domain->properties ) ) {
54
+ $domain->properties = new CnbDomainProperties();
55
+ $domain->properties->scale = '1';
56
+ $domain->properties->debug = false;
57
+ }
58
+ if ( empty( $domain->name ) ) {
59
+ $domain->name = null;
60
+ }
61
+ if ( ! isset( $domain->trackGA ) ) {
62
+ $domain->trackGA = true;
63
+ }
64
+ if ( ! isset( $domain->trackConversion ) ) {
65
+ $domain->trackConversion = true;
66
+ }
67
+
68
+ }
69
+ }
70
+
71
+ class CnbDomainProperties {
72
+ /**
73
+ * @var number
74
+ */
75
+ public $scale;
76
+
77
+ /**
78
+ * @var boolean
79
+ */
80
+ public $debug;
81
+ }
src/admin/partials/admin-footer.php CHANGED
@@ -1,8 +1,13 @@
1
  <?php
2
 
3
  function cnb_admin_footer() {
4
- global $cnb_options;
 
 
 
5
 
 
 
6
  $beta = '';
7
  if (isset($cnb_options['cloud_beta_enabled']) && $cnb_options['cloud_beta_enabled']) {
8
  $beta = '<span class="cnb_footer_beta">beta mode</span>';
@@ -19,7 +24,11 @@ function cnb_admin_footer() {
19
  target="_blank" title="Feature Requests">Suggestions</a> &middot;
20
  <strong><a href="https://www.paypal.com/paypalme/jgrietveld/" target="_blank" title="Thanks or your support">Donate</a></strong>
21
  </p>
22
- <?php
 
 
 
 
23
  global $cnb_options;
24
  if (isset($cnb_options['footer_show_traces']) && $cnb_options['footer_show_traces'] == 1 &&
25
  isset($cnb_options['advanced_view']) && $cnb_options['advanced_view'] == 1) {
@@ -48,6 +57,4 @@ function cnb_admin_footer() {
48
  echo '</p>';
49
  }
50
  }
51
- ?>
52
- </div>
53
- <?php }
1
  <?php
2
 
3
  function cnb_admin_footer() {
4
+ cnb_show_feedback_collection();
5
+ cnb_show_api_traces();
6
+ echo '</div> <!-- /wrap -->'; // This is started in cnb_admin_header
7
+ }
8
 
9
+ function cnb_show_feedback_collection() {
10
+ global $cnb_options;
11
  $beta = '';
12
  if (isset($cnb_options['cloud_beta_enabled']) && $cnb_options['cloud_beta_enabled']) {
13
  $beta = '<span class="cnb_footer_beta">beta mode</span>';
24
  target="_blank" title="Feature Requests">Suggestions</a> &middot;
25
  <strong><a href="https://www.paypal.com/paypalme/jgrietveld/" target="_blank" title="Thanks or your support">Donate</a></strong>
26
  </p>
27
+ </div>
28
+ <?php
29
+ }
30
+
31
+ function cnb_show_api_traces() {
32
  global $cnb_options;
33
  if (isset($cnb_options['footer_show_traces']) && $cnb_options['footer_show_traces'] == 1 &&
34
  isset($cnb_options['advanced_view']) && $cnb_options['advanced_view'] == 1) {
57
  echo '</p>';
58
  }
59
  }
60
+ }
 
 
src/admin/partials/admin-functions.php CHANGED
@@ -1,7 +1,8 @@
1
  <?php
2
 
3
  function cnb_get_active_tab_name() {
4
- return isset($_GET['tab']) ? filter_input( INPUT_GET, 'tab', FILTER_SANITIZE_STRING ) : 'basic_options';
 
5
  }
6
  function cnb_is_active_tab($tab_name) {
7
  $active_tab = cnb_get_active_tab_name();
@@ -10,7 +11,8 @@ function cnb_is_active_tab($tab_name) {
10
 
11
  function cnb_get_changelog() {
12
  return array(
13
- '0.4.7' => 'Small UI improvements',
 
14
  '0.4.2' => 'Button styling adjustments, security improvements',
15
  '0.4.0' => array(
16
  'Text bubbles for standard buttons',
@@ -41,8 +43,8 @@ function cnb_get_changelog() {
41
  function cnb_get_button_types() {
42
  return array(
43
  'SINGLE' => 'Single button',
44
- 'FULL' => 'Button bar',
45
- 'MULTI' => 'Multi button',
46
  );
47
  }
48
 
1
  <?php
2
 
3
  function cnb_get_active_tab_name() {
4
+ // using filter_var instead of filter_input so we can do some "just in time" rewriting of the tab variable if needed
5
+ return isset($_GET['tab']) ? filter_var( $_GET['tab'], FILTER_SANITIZE_STRING ) : 'basic_options';
6
  }
7
  function cnb_is_active_tab($tab_name) {
8
  $active_tab = cnb_get_active_tab_name();
11
 
12
  function cnb_get_changelog() {
13
  return array(
14
+ '0.5.0' => 'Better button creation flow, UI improvements, small fixes',
15
+ '0.4.7' => 'Small UI improvements',
16
  '0.4.2' => 'Button styling adjustments, security improvements',
17
  '0.4.0' => array(
18
  'Text bubbles for standard buttons',
43
  function cnb_get_button_types() {
44
  return array(
45
  'SINGLE' => 'Single button',
46
+ 'FULL' => 'Buttonbar',
47
+ 'MULTI' => 'Multibutton',
48
  );
49
  }
50
 
src/admin/partials/admin-header.php CHANGED
@@ -1,60 +1,62 @@
1
  <?php
2
  require_once dirname( __FILE__ ) . '/../../utils/notices.php';
 
3
 
4
- function cnb_admin_header_get_cloud_error($error) {
5
- return cnb_api_key_invalid_notice($error);
 
 
 
 
 
 
6
  }
7
 
8
- function cnb_admin_header( $cnb_options, $cnb_settings, $cnb_cloud_notifications = array(), $cnb_changelog = array() ) {
9
- echo '<h1 class="wp-heading-inline">';
10
- do_action( 'cnb_header' );
11
- do_action( 'cnb_after_header' );
12
- echo '</h1>';
13
 
14
  echo '<!--## NOTIFICATION BARS ## -->';
 
15
 
16
  // Display notification that the button is active or inactive
17
- if ( $cnb_options['active'] != 1 ) {
18
- echo cnb_button_disabled_notice();
19
  }
20
 
21
  if ( $cnb_options['active'] == 1 && $cnb_options['status'] == 'enabled' && empty($cnb_options['number'])) {
22
- echo cnb_button_classic_enabled_but_no_number_notice();
23
  }
24
 
25
  // Display notification that there's a caching plugin active
26
  if ( isset( $_GET['settings-updated'] ) ) {
27
  $cnb_caching_check = cnb_check_for_caching();
28
  if ( $cnb_caching_check[0] == true ) {
29
- echo cnb_caching_plugin_warning_notice($cnb_caching_check[1]);
30
  }
31
  }
32
 
33
  // Show the notifications after updating the cloud
34
  if ( is_array( $cnb_cloud_notifications ) ) {
 
35
  foreach ( $cnb_cloud_notifications as $cnb_cloud_notification ) {
36
- echo $cnb_cloud_notification;
 
 
 
 
37
  }
38
  }
39
 
40
  // inform existing users about updates to the button
41
  if ( $cnb_settings['updated'][0] ) {
42
- echo '<div class="notice-warning notice is-dismissible">';
43
- $cnb_old_version = $cnb_settings['updated'][1];
44
- echo '<h3>' . CNB_NAME . ' has been updated!</h3><h4>What\'s new?</h4>';
45
- // Only on first run after update show list of changes since last update
46
- foreach ( $cnb_changelog as $key => $value ) {
47
- if ( $key > $cnb_old_version ) {
48
- echo '<h3>' . esc_html($key) . '</h3>';
49
- if ( is_array( $value ) ) {
50
- foreach ( $value as $item ) {
51
- echo '<p><span class="dashicons dashicons-yes"></span> ' . esc_html($item) . '</p>';
52
- }
53
- } else {
54
- echo '<p><span class="dashicons dashicons-yes"></span> ' . esc_html($value) . '</p>';
55
- }
56
- }
57
- }
58
- echo '</div>';
59
  }
60
  }
 
 
 
 
 
 
 
 
1
  <?php
2
  require_once dirname( __FILE__ ) . '/../../utils/notices.php';
3
+ require_once dirname( __FILE__ ) . '/admin-functions.php';
4
 
5
+ function cnb_admin_header_no_args() {
6
+ global $cnb_options, $cnb_settings;
7
+
8
+ $cnb_notices = cnb_get_notices();
9
+ $cnb_changelog = cnb_get_changelog();
10
+
11
+ cnb_admin_header_args($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog);
12
+ do_action('cnb_admin_notices');
13
  }
14
 
15
+ function cnb_admin_header_args( $cnb_options, $cnb_settings, $cnb_cloud_notifications = array(), $cnb_changelog = array() ) {
16
+ echo '<div class="wrap">'; // This is closed in cnb_admin_footer
 
 
 
17
 
18
  echo '<!--## NOTIFICATION BARS ## -->';
19
+ $cnb_cloud_notifications = array_merge($cnb_cloud_notifications, cnb_get_cloud_notices());
20
 
21
  // Display notification that the button is active or inactive
22
+ if ( $cnb_options['active'] != 1 && !empty($cnb_options['number']) && $cnb_options['status'] != 'cloud' ) {
23
+ cnb_button_disabled_notice();
24
  }
25
 
26
  if ( $cnb_options['active'] == 1 && $cnb_options['status'] == 'enabled' && empty($cnb_options['number'])) {
27
+ cnb_button_classic_enabled_but_no_number_notice();
28
  }
29
 
30
  // Display notification that there's a caching plugin active
31
  if ( isset( $_GET['settings-updated'] ) ) {
32
  $cnb_caching_check = cnb_check_for_caching();
33
  if ( $cnb_caching_check[0] == true ) {
34
+ cnb_caching_plugin_warning_notice($cnb_caching_check[1]);
35
  }
36
  }
37
 
38
  // Show the notifications after updating the cloud
39
  if ( is_array( $cnb_cloud_notifications ) ) {
40
+ $adminNotices = CnbAdminNotices::get_instance();
41
  foreach ( $cnb_cloud_notifications as $cnb_cloud_notification ) {
42
+ if (is_string($cnb_cloud_notification)) {
43
+ $adminNotices->info($cnb_cloud_notification);
44
+ } else {
45
+ $adminNotices->notice( $cnb_cloud_notification);
46
+ }
47
  }
48
  }
49
 
50
  // inform existing users about updates to the button
51
  if ( $cnb_settings['updated'][0] ) {
52
+ cnb_upgrade_notice($cnb_settings['updated'][1], $cnb_changelog);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
  }
55
+
56
+ function cnb_admin_header() {
57
+ do_action('cnb_in_admin_header');
58
+ echo '<h1>';
59
+ do_action( 'cnb_header_name' );
60
+ do_action( 'cnb_after_header' );
61
+ echo '</h1>';
62
+ }
src/admin/settings.php CHANGED
@@ -3,9 +3,11 @@
3
  require_once dirname( __FILE__ ) . '/api/CnbAppRemote.php';
4
  require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/domain-edit.php';
 
6
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
 
9
 
10
  function cnb_add_header_settings() {
11
  echo 'Settings';
@@ -22,14 +24,33 @@ function cnb_settings_create_tab_url($tab) {
22
  return esc_url( $tab_link );
23
  }
24
 
25
- function cnb_settings_options_validate($input) {
26
- $messages = array();
27
- $messages[] = '<div class="notice-success notice is-dismissible"><p>Your settings have been updated!</p></div>';
 
 
 
 
 
 
 
 
 
 
 
28
 
 
 
 
 
 
 
 
29
  // When beta mode is disabled, disable the cloud as well
30
  if (array_key_exists('cloud_beta_enabled', $input) && $input['cloud_beta_enabled'] == 0) {
31
  $input['cloud_enabled'] = 0;
32
  $input['status'] = 'enabled';
 
33
  }
34
 
35
  // Since "active" and "cloud_enabled" have been merged into "status", we have to deal with that
@@ -50,26 +71,61 @@ function cnb_settings_options_validate($input) {
50
  }
51
  }
52
 
 
 
53
  // Cloud Domain settings can be set here as well
54
  if(array_key_exists('domain', $_POST) &&
55
- array_key_exists('cloud_enabled', $input) && $input['cloud_enabled'] === 1) {
 
56
  $domain = $_POST['domain'];
57
  $transient_id = null;
58
  cnb_admin_page_domain_edit_process_domain($domain, $transient_id);
59
- $messages = array_merge($messages, get_transient($transient_id));
 
 
 
 
 
 
60
 
61
  // Remove from settings
62
  unset($input['domain']);
63
  }
64
 
65
- $updated_options = array_merge(get_option('cnb'), $input);
66
- if (isset($updated_options['cloud_enabled']) && $updated_options['cloud_enabled'] === '1') {
 
 
 
 
 
 
 
 
67
  $cloud_id = CnbAdminCloud::cnb_set_default_option_for_cloud( $updated_options );
 
68
  if ($cloud_id != null) {
69
  $updated_options['cloud_use_id'] = $cloud_id;
70
  }
71
  }
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  $transient_id = 'cnb-options';
74
  $_GET['tid'] = $transient_id;
75
  set_transient($transient_id, $messages, HOUR_IN_SECONDS);
@@ -121,6 +177,7 @@ function cnb_admin_settings_create_cloud_domain($cnb_user) {
121
  if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_create_cloud_domain') ) {
122
  return CnbAdminCloud::cnb_wp_create_domain( $cnb_user );
123
  }
 
124
  }
125
 
126
  function cnb_admin_settings_migrate_legacy_to_cloud() {
@@ -128,6 +185,7 @@ function cnb_admin_settings_migrate_legacy_to_cloud() {
128
  if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_migrate_legacy_button') ) {
129
  return CnbAdminCloud::cnb_wp_migrate_button();
130
  }
 
131
  }
132
 
133
  function cnb_admin_setting_migrate() {
@@ -164,187 +222,159 @@ function cnb_admin_setting_migrate() {
164
  }
165
 
166
  function cnb_admin_settings_page() {
167
- global $cnb_options, $cnb_settings;
168
 
169
- add_action('cnb_header', 'cnb_add_header_settings');
170
 
171
- $cnb_notices = cnb_get_notices();
172
- $cnb_changelog = cnb_get_changelog();
173
 
174
  $beta = cnb_is_beta_user($cnb_options);
175
  $beta_tmp = cnb_is_beta_user_via_url_only($cnb_options);
176
  if ($beta_tmp) {
177
- $notice = '<form method="post" action="' . esc_url( admin_url('options.php') ) . '" class="cnb-container">';
178
- ob_start();
179
- settings_fields('cnb_options');
180
- $notice .= ob_get_clean();
181
- $notice .= '<input type="hidden" name="page" value="call-now-button-settings" />
182
- <table>
183
- <tr>
184
- <th scope="row"</th>
185
- <td>
186
- <input type="hidden" name="cnb[cloud_beta_enabled]" value="1" />
187
- <input type="submit" class="button-primary" value="' . __('Activate beta mode') . '"/> For testing new unreleased functionality.
188
- </td>
189
- </table>
190
- </form>';
191
- $cnb_notices[] = '<div class="notice-warning notice"><p>'.$notice.'</p></div>';
192
  }
193
- $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
194
 
195
- if (!($cnb_user instanceof WP_Error)) {
196
- // Let's check if the domain already exists
197
- $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
198
- $cnb_cloud_domains = CnbAppRemote::cnb_remote_get_domains();
199
- $cnb_clean_site_url = CnbAppRemote::cnb_clean_site_url();
200
 
201
- if (empty($cnb_cloud_domain->properties)) {
202
- $cnb_cloud_domain->properties = array();
 
 
 
 
203
  }
204
- }
205
- ?>
206
 
207
- <div class="wrap">
208
- <?php
209
- $show_advanced_view_only = array_key_exists('advanced_view', $cnb_options) && $cnb_options['advanced_view'] === 1;
210
- if ($show_advanced_view_only) {
211
- echo '<script type="text/javascript">show_advanced_view_only_set=1</script>';
 
212
  }
 
213
 
214
- cnb_admin_header($cnb_options, $cnb_settings, $cnb_notices, $cnb_changelog) ?>
 
 
 
 
215
 
216
- <h2 class="nav-tab-wrapper">
217
- <a href="<?php echo cnb_settings_create_tab_url('basic_options') ?>"
218
- class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">General</a>
219
- <?php if ($cnb_options['status'] === 'cloud') { ?>
220
- <a href="<?php echo cnb_settings_create_tab_url('account_options') ?>"
221
- class="nav-tab <?php echo cnb_is_active_tab('account_options') ?>">Account</a>
222
- <?php if ($show_advanced_view_only) { ?>
223
- <a href="<?php echo cnb_settings_create_tab_url('advanced_options') ?>"
224
- class="nav-tab <?php echo cnb_is_active_tab('advanced_options') ?>">Advanced</a>
225
- <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  <?php } ?>
227
- </h2>
228
- <form method="post" action="<?php echo esc_url( admin_url('options.php') ); ?>" class="cnb-container">
229
- <?php settings_fields('cnb_options'); ?>
230
- <table class="form-table <?php echo cnb_is_active_tab('basic_options'); ?>">
231
- <tr>
232
- <th colspan="2"></th>
233
- </tr>
234
- <tr>
235
- <th scope="row">Button status:</th>
236
- <td>
237
- <div class="cnb-radio-item">
238
- <input type="radio" name="cnb[status]" id="cnb_status_disabled" value="disabled" <?php checked('disabled', $cnb_options['status']); ?> />
239
- <label for="cnb_status_disabled">Disabled</label>
240
- </div>
241
- <div class="cnb-radio-item">
242
- <input type="radio" name="cnb[status]" id="cnb_status_enabled" value="enabled" <?php checked('enabled', $cnb_options['status']); ?> />
243
- <label for="cnb_status_enabled">Enabled <?php if (isset($cnb_options['cloud_beta_enabled']) && $cnb_options['cloud_beta_enabled']) { ?>(local)<?php } ?></label>
244
- </div>
245
- <?php if ($beta) { ?>
246
- <div class="cnb-radio-item">
247
- <input type="radio" id="cloud_enabled" name="cnb[status]" value="cloud" <?php checked('cloud', $cnb_options['status']) ?> />
248
- <label for="cloud_enabled">Enabled (cloud)
249
- <a href="<?php echo CNB_SUPPORT; ?>click-tracking/<?php cnb_utm_params("question-mark", "click-tracking"); ?>" target="_blank" class="cnb-nounderscore">
250
- <span class="dashicons dashicons-editor-help"></span>
251
- </a>
252
- </label>
253
- </div>
254
- <?php } ?>
255
- </td>
256
- </tr>
257
- <?php if ($cnb_options['status'] === 'enabled') { ?>
258
- <tr>
259
- <th colspan="2"><h2>Tracking</h2></th>
260
- </tr>
261
- <tr>
262
- <th scope="row">Click tracking: <a href="<?php echo CNB_SUPPORT; ?>click-tracking/<?php cnb_utm_params("question-mark", "click-tracking"); ?>" target="_blank" class="cnb-nounderscore">
263
- <span class="dashicons dashicons-editor-help"></span>
264
- </a></th>
265
- <td>
266
- <div class="cnb-radio-item">
267
- <input id="tracking3" type="radio" name="cnb[tracking]" value="0" <?php checked('0', $cnb_options['tracking']); ?> />
268
- <label for="tracking3">Disabled</label>
269
- </div>
270
- <div class="cnb-radio-item">
271
- <input id="tracking4" type="radio" name="cnb[tracking]" value="3" <?php checked('3', $cnb_options['tracking']); ?> />
272
- <label for="tracking4">Latest Google Analytics (gtag.js)</label>
273
- </div>
274
- <div class="cnb-radio-item">
275
- <input id="tracking1" type="radio" name="cnb[tracking]" value="2" <?php checked('2', $cnb_options['tracking']); ?> />
276
- <label for="tracking1">Google Universal Analytics (analytics.js)</label>
277
- </div>
278
- <div class="cnb-radio-item">
279
- <input id="tracking2" type="radio" name="cnb[tracking]" value="1" <?php checked('1', $cnb_options['tracking']); ?> />
280
- <label for="tracking2">Classic Google Analytics (ga.js)</label>
281
- </div>
282
- <p class="description">Using Google Tag Manager? Set up click tracking in GTM. <a href="<?php echo CNB_SUPPORT; ?>click-tracking/google-tag-manager-event-tracking/<?php cnb_utm_params("description_link", "google-tag-manager-event-tracking"); ?>" target="_blank">Learn how to do this...</a></p>
283
- </td>
284
- </tr>
285
- <tr>
286
- <th scope="row">Google Ads: <a href="<?php echo CNB_SUPPORT; ?>google-ads/<?php cnb_utm_params("question-mark", "google-ads"); ?>" target="_blank" class="cnb-nounderscore">
287
- <span class="dashicons dashicons-editor-help"></span>
288
- </a></th>
289
- <td class="conversions">
290
- <div class="cnb-radio-item">
291
- <input name="cnb[conversions]" id="conversions_0" type="radio" value="0" <?php checked('0', $cnb_options['conversions']); ?> /> <label for="conversions_0">Off </label>
292
- </div>
293
- <div class="cnb-radio-item">
294
- <input name="cnb[conversions]" id="conversions_1" type="radio" value="1" <?php checked('1', $cnb_options['conversions']); ?> /> <label for="conversions_1">Conversion Tracking using Google's global site tag </label>
295
- </div>
296
- <div class="cnb-radio-item">
297
- <input name="cnb[conversions]" id="conversions_2" type="radio" value="2" <?php checked('2', $cnb_options['conversions']); ?> /> <label for="conversions_2">Conversion Tracking using JavaScript</label>
298
- </div>
299
- <p class="description">Select this option if you want to track clicks on the button as Google Ads conversions. This option requires the Event snippet to be present on the page. <a href="https">Learn more...</a></p>
300
- </td>
301
- </tr>
302
- <tr>
303
- <th colspan="2"><h2>Button display</h2></th>
304
- </tr>
305
- <tr class="zoom">
306
- <th scope="row">Button size <span id="cnb_slider_value"></span>:</th>
307
  <td>
308
- <label class="cnb_slider_value">Smaller&nbsp;&laquo;&nbsp;</label>
309
- <input type="range" min="0.7" max="1.3" name="cnb[zoom]" value="<?php esc_attr_e($cnb_options['zoom']) ?>" class="slider" id="cnb_slider" step="0.1">
310
- <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Bigger</label>
 
311
  </td>
312
  </tr>
313
- <tr class="z-index">
314
- <th scope="row">Order (<span id="cnb_order_value"></span>): <a href="https://callnowbutton.com/set-order/" target="_blank" class="cnb-nounderscore">
315
- <span class="dashicons dashicons-editor-help"></span>
316
- </a></th>
317
- <td>
318
- <label class="cnb_slider_value">Backwards&nbsp;&laquo;&nbsp;</label>
319
- <input type="range" min="1" max="10" name="cnb[z-index]" value="<?php esc_attr_e($cnb_options['z-index']) ?>" class="slider2" id="cnb_order_slider" step="1">
320
- <label class="cnb_slider_value">&nbsp;&raquo;&nbsp;Front</label>
321
- <p class="description">The default (and recommended) value is all the way to the front so the button sits on top of everything else. In case you have a specific usecase where you want something else to sit in front of the Call Now Button (e.g. a chat window or a cookie notice) you can move this backwards one step at a time to adapt it to your situation.</p>
322
- </td>
323
  </tr>
324
- <?php if($cnb_options['classic'] == 1) { ?>
325
- <tr class="classic">
326
- <th scope="row">Classic button: <a href="https://callnowbutton.com/new-button-design/<?php cnb_utm_params("question-mark", "new-button-design"); ?>" target="_blank" class="cnb-nounderscore">
327
- <span class="dashicons dashicons-editor-help"></span>
328
- </a></th>
329
- <td>
330
- <input type="hidden" name="cnb[classic]" value="0" />
331
- <input id="classic" name="cnb[classic]" type="checkbox" value="1" <?php checked('1', $cnb_options['classic']); ?> /> <label title="Enable" for="classic">Active</label>
332
- </td>
333
- </tr>
334
- <?php
335
- }
336
- }
337
- if($cnb_options['status'] === 'cloud' && isset($cnb_cloud_domain) && !($cnb_cloud_domain instanceof WP_Error)) {
338
- cnb_admin_page_domain_edit_render_form($cnb_cloud_domain);
339
- } ?>
340
- <?php if ($beta) { ?>
341
- <?php if ($cnb_options['status'] !== 'cloud') { ?>
342
- <tr>
343
- <th colspan="2"><h2>Advanced</h2></th>
344
- </tr>
345
- <?php } ?>
346
  <tr>
347
- <th>Beta mode:</th>
348
  <td><label>
349
  <input type="hidden" name="cnb[cloud_beta_enabled]" value="0" />
350
  <input id="beta" type="checkbox" name="cnb[cloud_beta_enabled]" value="1" <?php checked('1', $beta); ?> />
@@ -353,119 +383,109 @@ function cnb_admin_settings_page() {
353
  <p class="description">You can stop being a beta user and return to the original button at any time</p>
354
  </td>
355
  </tr>
356
- <?php } ?>
357
- </table>
358
- <?php if ($cnb_options['status'] === 'cloud') { ?>
359
- <table class="form-table <?php echo cnb_is_active_tab('account_options'); ?>">
360
- <tr>
361
- <th scope="row">API key</th>
362
- <td>
363
- <input type="text" class="regular-text" name="cnb[api_key]"
364
- value="<?php if (isset($cnb_options['api_key'])) { esc_attr_e($cnb_options['api_key']); } ?>"
365
- placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/>
366
- <?php if ($cnb_user instanceof WP_Error) { ?>
367
- <p class="description">Get you key at <a href="<?php echo CNB_WEBSITE?>"><?php echo CNB_WEBSITE?></a></p>
368
- <?php } ?>
369
- </td>
370
- </tr>
371
- <?php if (!$cnb_user instanceof WP_Error) { ?>
372
- <tr>
373
- <th scope="row">Account owner</th>
374
- <td>
375
- <?php esc_html_e($cnb_user->name) ?>
376
- <?php
377
- if ($cnb_user->email !== $cnb_user->name) { esc_html_e(' (' . $cnb_user->email . ')');
378
- } ?>
379
- </td>
380
- </tr>
381
- <tr>
382
- <th scope="row">Account ID</th>
383
- <td><code><?php esc_html_e($cnb_user->id) ?></code></td>
384
- </tr>
385
- <?php } ?>
386
- </table>
387
- <table class="form-table <?php echo cnb_is_active_tab('advanced_options'); ?>">
388
  <tr>
389
- <th>Advanced view</th>
390
- <td><label>
391
- <input type="hidden" name="cnb[advanced_view]" value="0" />
392
- <input type="checkbox" name="cnb[advanced_view]" value="1" <?php checked('1', $cnb_options['advanced_view']); ?> />
393
- <p class="description">Show all the bells and whistles (for power users)</p>
394
- </label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  </td>
396
  </tr>
397
- <?php if ($beta) { ?>
398
- <tr class="cnb_advanced_view">
399
- <th>Show traces</th>
400
- <td><label>
401
- <input type="hidden" name="cnb[footer_show_traces]" value="0" />
402
- <input type="checkbox" name="cnb[footer_show_traces]" value="1" <?php checked('1', $cnb_options['footer_show_traces']); ?> />
403
- <p class="description">Show the API calls and their timing in the footer.</p>
404
- </label>
405
- </td>
406
- </tr>
407
- <?php if (!($cnb_user instanceof WP_Error) && isset($cnb_cloud_domain)) { ?>
408
- <tr class="when-cloud-enabled cnb_advanced_view">
409
- <th scope="row">Domain</th>
410
- <td>
411
- <div>
412
- <p>Your domain: <strong><?php esc_html_e($cnb_clean_site_url) ?></strong></p>
413
- <?php if ($cnb_cloud_domain instanceof WP_Error) { ?>
414
- <p class="description notice notice-warning">Almost there! Create your domain using the button at the top of this page.</p>
415
- <?php } else { ?>
416
- <p class="description">Your domain <strong><?php esc_html_e($cnb_cloud_domain->name) ?></strong> is connected with ID <strong><?php esc_html_e($cnb_cloud_domain->id) ?></strong></p>
417
- <?php }?>
418
- <select name="cnb[cloud_use_id]">
419
-
420
- <optgroup label="Account-wide">
421
  <option
422
- value="<?php esc_attr_e($cnb_user->id) ?>"
423
- <?php selected($cnb_user->id, $cnb_options['cloud_use_id']) ?>
424
  >
425
- Let the button decide
426
  </option>
427
- </optgroup>
428
- <optgroup label="Specific domain">
429
- <?php foreach ($cnb_cloud_domains as $domain) { ?>
430
- <option
431
- value="<?php esc_attr_e($domain->id) ?>"
432
- <?php selected($domain->id, $cnb_options['cloud_use_id']) ?>
433
- >
434
- <?php esc_html_e($domain->name) ?>
435
- </option>
436
- <?php } ?>
437
- </optgroup>
438
- </select>
439
- </div>
440
- </td>
441
- </tr>
442
- <?php } ?>
443
- <?php } // end of beta check ?>
444
- <tr class="when-cloud-enabled cnb_advanced_view">
445
- <th>API endpoint</th>
446
- <td><label>
447
- <input type="text" name="cnb[api_base]" class="regular-text"
448
- value="<?php echo CnbAppRemote::cnb_get_api_base() ?>" />
449
- <p class="description">The API endpoint to use to communicate with the CallNowButton Cloud service. <br />
450
- <strong>Do not change this unless you know what you're doing!</strong>
451
- </p>
452
- </label>
453
- </td>
454
- </tr>
455
- <tr class="cnb_advanced_view">
456
- <th>API caching</th>
457
- <td><label>
458
- <input type="hidden" name="cnb[api_caching]" value="0" />
459
- <input type="checkbox" name="cnb[api_caching]" value="1" <?php checked('1', $cnb_options['api_caching']); ?> />
460
- <p class="description">Cache API requests (using Wordpress transients)</p>
461
- </label></td>
462
- </tr>
463
- </table>
464
- <?php } ?>
465
- <input type="hidden" name="cnb[version]" value="<?php echo CNB_VERSION; ?>"/>
466
- <p class="submit"><input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>"/></p>
467
- </form>
 
 
468
 
469
- <?php cnb_admin_footer() ?>
470
- </div>
471
  <?php }
3
  require_once dirname( __FILE__ ) . '/api/CnbAppRemote.php';
4
  require_once dirname( __FILE__ ) . '/api/CnbAdminCloud.php';
5
  require_once dirname( __FILE__ ) . '/domain-edit.php';
6
+ require_once dirname( __FILE__ ) . '/legacy-edit.php';
7
  require_once dirname( __FILE__ ) . '/partials/admin-functions.php';
8
  require_once dirname( __FILE__ ) . '/partials/admin-header.php';
9
  require_once dirname( __FILE__ ) . '/partials/admin-footer.php';
10
+ require_once dirname( __FILE__ ) . '/../utils/notices.php';
11
 
12
  function cnb_add_header_settings() {
13
  echo 'Settings';
24
  return esc_url( $tab_link );
25
  }
26
 
27
+ /**
28
+ * For the Legacy button, disallow setting it to active with a missing phone number
29
+ *
30
+ * @param array $input
31
+ *
32
+ * @return void|WP_Error
33
+ */
34
+ function cnb_settings_disallow_active_without_phone_number($input) {
35
+ $number = trim($input['number']);
36
+ $cloud_enabled = array_key_exists('cloud_enabled', $input) ? $input['cloud_enabled'] : 0;
37
+ if ($input['active'] == 1 && $cloud_enabled == 0 && empty($number)) {
38
+ return new WP_Error('CNB_PHONE_NUMBER_MISSING', 'Please enter a phone number before enabling your button.');
39
+ }
40
+ }
41
 
42
+ /**
43
+ * @param array $input
44
+ *
45
+ * @return array The new (fully adjusted) settings for <code>cnb</code>
46
+ */
47
+ function cnb_settings_options_validate($input) {
48
+ $original_settings = get_option('cnb');
49
  // When beta mode is disabled, disable the cloud as well
50
  if (array_key_exists('cloud_beta_enabled', $input) && $input['cloud_beta_enabled'] == 0) {
51
  $input['cloud_enabled'] = 0;
52
  $input['status'] = 'enabled';
53
+ delete_option('cnb_cloud_migration_done');
54
  }
55
 
56
  // Since "active" and "cloud_enabled" have been merged into "status", we have to deal with that
71
  }
72
  }
73
 
74
+ $messages = array();
75
+
76
  // Cloud Domain settings can be set here as well
77
  if(array_key_exists('domain', $_POST) &&
78
+ array_key_exists('cloud_enabled', $input) &&
79
+ $input['cloud_enabled'] == 1) {
80
  $domain = $_POST['domain'];
81
  $transient_id = null;
82
  cnb_admin_page_domain_edit_process_domain($domain, $transient_id);
83
+ $message = get_transient($transient_id);
84
+
85
+ // Only add the message to the results if something went wrong
86
+ if (is_array($message) && sizeof($message) === 1 &&
87
+ $message[0] instanceof CnbNotice && $message[0]->type != 'success') {
88
+ $messages = array_merge( $messages, $message);
89
+ }
90
 
91
  // Remove from settings
92
  unset($input['domain']);
93
  }
94
 
95
+ // If api_key is empty, assume unchanged and unset it (so it uses the old value)
96
+ if (isset($input['api_key']) && empty($input['api_key'])) {
97
+ unset($input['api_key']);
98
+ }
99
+
100
+ $updated_options = array_merge($original_settings, $input);
101
+
102
+ // If the cloud is enabled, this is a fail-safe to ensure the user ID is set, even if it isn't
103
+ // explicitly set by the user YET. (since the whole "cnb[cloud_use_id] input field doesn't exist yet...
104
+ if (isset($updated_options['cloud_enabled']) && $updated_options['cloud_enabled'] == 1) {
105
  $cloud_id = CnbAdminCloud::cnb_set_default_option_for_cloud( $updated_options );
106
+ // Normally, this returns null, since there is a cnb[cloud_use_id].
107
  if ($cloud_id != null) {
108
  $updated_options['cloud_use_id'] = $cloud_id;
109
  }
110
  }
111
 
112
+ // Check for legacy button
113
+ $check = cnb_settings_disallow_active_without_phone_number($updated_options);
114
+ if (is_wp_error($check)) {
115
+ if ($check->get_error_code() === 'CNB_PHONE_NUMBER_MISSING') {
116
+ $messages[] = new CnbNotice( 'warning', '<p>Your settings have been updated, but your button could <strong>not</strong> be enabled. Please enter a <i>Phone number</i>.</p>' );
117
+ // Reset enabled/active to false
118
+ $updated_options['active'] = 0;
119
+ } else {
120
+ // This part is VERY generic and should not be reached, since
121
+ // cnb_settings_disallow_active_without_phone_number() returns a single WP_Error.
122
+ // But just in case, this is here for other unseen errors..
123
+ $messages[] = CnbAdminCloud::cnb_admin_get_error_message( 'save', 'settings', $check );
124
+ }
125
+ } else {
126
+ $messages[] = new CnbNotice( 'success', '<p>Your settings have been updated!</p>' );
127
+ }
128
+
129
  $transient_id = 'cnb-options';
130
  $_GET['tid'] = $transient_id;
131
  set_transient($transient_id, $messages, HOUR_IN_SECONDS);
177
  if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_create_cloud_domain') ) {
178
  return CnbAdminCloud::cnb_wp_create_domain( $cnb_user );
179
  }
180
+ return null;
181
  }
182
 
183
  function cnb_admin_settings_migrate_legacy_to_cloud() {
185
  if( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'cnb_migrate_legacy_button') ) {
186
  return CnbAdminCloud::cnb_wp_migrate_button();
187
  }
188
+ return null;
189
  }
190
 
191
  function cnb_admin_setting_migrate() {
222
  }
223
 
224
  function cnb_admin_settings_page() {
225
+ global $cnb_options;
226
 
227
+ add_action('cnb_header_name', 'cnb_add_header_settings');
228
 
229
+ // Fix for https://github.com/callnowbutton/wp-plugin/issues/263
230
+ $cnb_options['cloud_enabled'] = isset($cnb_options['cloud_enabled']) ? $cnb_options['cloud_enabled'] : 0;
231
 
232
  $beta = cnb_is_beta_user($cnb_options);
233
  $beta_tmp = cnb_is_beta_user_via_url_only($cnb_options);
234
  if ($beta_tmp) {
235
+ cnb_activate_beta_render_notice();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
 
237
 
238
+ if ($beta && $cnb_options['cloud_enabled']) {
239
+ $cnbAppRemote = new CnbAppRemote();
240
+ $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
 
 
241
 
242
+ if ( ! ( $cnb_user instanceof WP_Error ) ) {
243
+ // Let's check if the domain already exists
244
+ $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
245
+ $cnb_cloud_domains = CnbAppRemote::cnb_remote_get_domains();
246
+ $cnb_clean_site_url = $cnbAppRemote->cnb_clean_site_url();
247
+ CnbDomain::setSaneDefault($cnb_cloud_domain);
248
  }
 
 
249
 
250
+ // Set "cloud_use_id" to the user if "cloud_use_id" has not been set yet
251
+ if ( ! array_key_exists( 'cloud_use_id', $cnb_options ) ) {
252
+ $cnb_options['cloud_use_id'] = 0;
253
+ if ( ! ( $cnb_user instanceof WP_Error ) ) {
254
+ $cnb_options['cloud_use_id'] = $cnb_user->id;
255
+ }
256
  }
257
+ }
258
 
259
+ // If beta is not enabled, there are actually no "advanced" tab, so we reset to "basic_options"
260
+ $active_advanced_tab = cnb_is_active_tab('advanced_options');
261
+ if (!$beta && !empty($active_advanced_tab)) {
262
+ $_GET['tab'] = 'basic_options';
263
+ }
264
 
265
+ do_action('cnb_header');
266
+ ?>
267
+
268
+ <?php
269
+ $show_advanced_view_only = array_key_exists('advanced_view', $cnb_options) && $cnb_options['advanced_view'] === 1;
270
+ if ($show_advanced_view_only) {
271
+ echo '<script type="text/javascript">show_advanced_view_only_set=1</script>';
272
+ }
273
+ ?>
274
+
275
+ <h2 class="nav-tab-wrapper">
276
+ <a href="<?php echo cnb_settings_create_tab_url('basic_options') ?>"
277
+ class="nav-tab <?php echo cnb_is_active_tab('basic_options') ?>">General</a>
278
+ <?php if ($cnb_options['status'] === 'cloud') { ?>
279
+ <a href="<?php echo cnb_settings_create_tab_url('account_options') ?>"
280
+ class="nav-tab <?php echo cnb_is_active_tab('account_options') ?>">Account</a>
281
+ <?php } ?>
282
+ <?php if ($beta) { ?>
283
+ <a href="<?php echo cnb_settings_create_tab_url('advanced_options') ?>"
284
+ class="nav-tab <?php echo cnb_is_active_tab('advanced_options') ?>">Advanced</a>
285
+ <?php } ?>
286
+ </h2>
287
+ <form method="post" action="<?php echo esc_url( admin_url('options.php') ); ?>" class="cnb-container">
288
+ <?php settings_fields('cnb_options'); ?>
289
+ <table class="form-table <?php echo cnb_is_active_tab('basic_options'); ?>">
290
+ <?php if ($beta) { ?>
291
+ <tr><th colspan="2"></th></tr>
292
+ <tr>
293
+ <th scope="row">Account type</th>
294
+ <td>
295
+ <div class="cnb-radio-item">
296
+ <input type="radio" name="cnb[cloud_enabled]" id="cnb_cloud_disabled" value="0" <?php checked('0', $cnb_options['cloud_enabled']); ?>>
297
+ <label for="cnb_cloud_disabled">Normal</label>
298
+ <p class="description">One call button for your website.</p>
299
+ </div>
300
+ <div class="cnb-radio-item">
301
+ <input type="radio" name="cnb[cloud_enabled]" id="cnb_cloud_enabled" value="1" <?php checked('1', $cnb_options['cloud_enabled']); ?>>
302
+ <label for="cnb_cloud_enabled">Cloud</label>
303
+ <p class="description">Unlimited buttons for your website for calls, emails, WhatsApp, URLs and locations. Also provides a button scheduler and better page targeting.</p>
304
+ </div>
305
+ </td>
306
+ </tr>
307
  <?php } ?>
308
+ <?php if ($cnb_options['status'] !== 'cloud') { ?>
309
+ <tr>
310
+ <th colspan="2"><h2>Tracking</h2></th>
311
+ </tr>
312
+ <?php
313
+ cnb_admin_page_leagcy_edit_render_tracking();
314
+ cnb_admin_page_leagcy_edit_render_conversions();
315
+ ?>
316
+ <tr>
317
+ <th colspan="2"><h2>Button display</h2></th>
318
+ </tr>
319
+ <?php
320
+ cnb_admin_page_leagcy_edit_render_zoom();
321
+ cnb_admin_page_leagcy_edit_render_zindex();
322
+
323
+ if($cnb_options['classic'] == 1) { ?>
324
+ <tr class="classic">
325
+ <th scope="row">Classic button: <a href="https://callnowbutton.com/new-button-design/<?php cnb_utm_params("question-mark", "new-button-design"); ?>" target="_blank" class="cnb-nounderscore">
326
+ <span class="dashicons dashicons-editor-help"></span>
327
+ </a></th>
328
+ <td>
329
+ <input type="hidden" name="cnb[classic]" value="0" />
330
+ <input id="classic" name="cnb[classic]" type="checkbox" value="1" <?php checked('1', $cnb_options['classic']); ?> /> <label title="Enable" for="classic">Active</label>
331
+ </td>
332
+ </tr>
333
+ <?php
334
+ }
335
+ }
336
+ if($cnb_options['status'] === 'cloud' && isset($cnb_cloud_domain) && !($cnb_cloud_domain instanceof WP_Error)) {
337
+ cnb_admin_page_domain_edit_render_form_plan_details($cnb_cloud_domain);
338
+ cnb_admin_page_domain_edit_render_form_tracking($cnb_cloud_domain);
339
+ cnb_admin_page_domain_edit_render_form_button_display($cnb_cloud_domain);
340
+ } ?>
341
+ </table>
342
+ <?php if ($beta && $cnb_options['status'] === 'cloud') { ?>
343
+ <table class="form-table <?php echo cnb_is_active_tab('account_options'); ?>">
344
+ <tr><th colspan="2"></th></tr>
345
+ <tr>
346
+ <th scope="row">API key</th>
347
+ <td>
348
+ <?php if ($cnb_user instanceof WP_Error || $show_advanced_view_only) { ?>
349
+ <label><input type="text" class="regular-text" name="cnb[api_key]" id="cnb_api_key"
350
+ placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/></label>
351
+ <?php if ($cnb_user instanceof WP_Error) { ?><p class="description">Get you key at <a href="<?php echo CNB_WEBSITE?>"><?php echo CNB_WEBSITE?></a></p><?php } ?>
352
+ <?php } ?>
353
+ <?php if (isset($cnb_options['api_key']) && !is_wp_error($cnb_user)) { ?><p class="description"><span class="dashicons dashicons-saved"></span>Your key is set correctly.</p><?php }?>
354
+ </td>
355
+ </tr>
356
+ <?php if ($cnb_user !== null && !$cnb_user instanceof WP_Error) { ?>
357
+ <tr>
358
+ <th scope="row">Account owner</th>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  <td>
360
+ <?php esc_html_e($cnb_user->name) ?>
361
+ <?php
362
+ if ($cnb_user->email !== $cnb_user->name) { esc_html_e(' (' . $cnb_user->email . ')');
363
+ } ?>
364
  </td>
365
  </tr>
366
+ <tr>
367
+ <th scope="row">Account ID</th>
368
+ <td><code><?php esc_html_e($cnb_user->id) ?></code></td>
 
 
 
 
 
 
 
369
  </tr>
370
+ <?php } ?>
371
+ </table>
372
+ <?php } ?>
373
+ <?php if ($beta) { ?>
374
+ <table class="form-table <?php echo cnb_is_active_tab('advanced_options'); ?>">
375
+ <tr><th colspan="2"></th></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  <tr>
377
+ <th>Beta mode</th>
378
  <td><label>
379
  <input type="hidden" name="cnb[cloud_beta_enabled]" value="0" />
380
  <input id="beta" type="checkbox" name="cnb[cloud_beta_enabled]" value="1" <?php checked('1', $beta); ?> />
383
  <p class="description">You can stop being a beta user and return to the original button at any time</p>
384
  </td>
385
  </tr>
386
+ <?php if(isset($cnb_cloud_domain) && !($cnb_cloud_domain instanceof WP_Error) && $cnb_options['status'] === 'cloud') {
387
+ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  <tr>
389
+ <th colspan="2"><h2>Domain settings</h2></th>
390
+ </tr>
391
+ <?php
392
+ cnb_admin_page_domain_edit_render_form_advanced($cnb_cloud_domain, false);
393
+ } ?>
394
+ <tr class="when-cloud-enabled cnb_advanced_view">
395
+ <th colspan="2"><h2>For power users</h2></th>
396
+ </tr>
397
+ <tr class="when-cloud-enabled cnb_advanced_view">
398
+ <th>Advanced view</th>
399
+ <td>
400
+ <input type="hidden" name="cnb[advanced_view]" value="0" />
401
+ <input id="cnb-advanced-view" type="checkbox" name="cnb[advanced_view]" value="1" <?php checked('1', $cnb_options['advanced_view']); ?> />
402
+ <label for="cnb-advanced-view">Enable</label>
403
+ <p class="description">For power users only.</p>
404
+ </td>
405
+ </tr>
406
+ <?php if ($cnb_options['status'] === 'cloud') { ?>
407
+ <tr class="cnb_advanced_view">
408
+ <th>Show traces</th>
409
+ <td>
410
+ <input type="hidden" name="cnb[footer_show_traces]" value="0" />
411
+ <input id="cnb-show-traces" type="checkbox" name="cnb[footer_show_traces]" value="1" <?php checked('1', $cnb_options['footer_show_traces']); ?> />
412
+ <label for="cnb-show-traces">Enable</label>
413
+ <p class="description">Display API calls and timings in the footer.</p>
414
  </td>
415
  </tr>
416
+ <?php if (!($cnb_user instanceof WP_Error) && isset($cnb_cloud_domain) && $cnb_options['status'] === 'cloud') { ?>
417
+ <tr class="when-cloud-enabled cnb_advanced_view">
418
+ <th scope="row">Domain</th>
419
+ <td>
420
+ <div>
421
+ <p>Your domain: <strong><?php esc_html_e($cnb_clean_site_url) ?></strong></p>
422
+ <?php if ($cnb_cloud_domain instanceof WP_Error) {
423
+ CnbAdminNotices::get_instance()->warning('Almost there! Create your domain using the button at the top of this page.')
424
+ ?>
425
+ <?php } else { ?>
426
+ <p class="description">Your domain <strong><?php esc_html_e($cnb_cloud_domain->name) ?></strong> is connected with ID <code><?php esc_html_e($cnb_cloud_domain->id) ?></code></p>
427
+ <?php }?>
428
+ <label><select name="cnb[cloud_use_id]">
429
+
430
+ <optgroup label="Account-wide">
431
+ <option
432
+ value="<?php esc_attr_e($cnb_user->id) ?>"
433
+ <?php selected($cnb_user->id, $cnb_options['cloud_use_id']) ?>
434
+ >
435
+ Let the button decide
436
+ </option>
437
+ </optgroup>
438
+ <optgroup label="Specific domain">
439
+ <?php foreach ($cnb_cloud_domains as $domain) { ?>
440
  <option
441
+ value="<?php esc_attr_e($domain->id) ?>"
442
+ <?php selected($domain->id, $cnb_options['cloud_use_id']) ?>
443
  >
444
+ <?php esc_html_e($domain->name) ?>
445
  </option>
446
+ <?php } ?>
447
+ </optgroup>
448
+ </select></label>
449
+ <p class="description">The current value is <code><?php esc_html_e($cnb_options['cloud_use_id']) ?></code></p>
450
+ </div>
451
+ </td>
452
+ </tr>
453
+ <?php } ?>
454
+ <tr class="when-cloud-enabled cnb_advanced_view">
455
+ <th>Show all buttons</th>
456
+ <td>
457
+ <input type="hidden" name="cnb[show_all_buttons_for_domain]" value="0" />
458
+ <input id="cnb-all-domains" type="checkbox" name="cnb[show_all_buttons_for_domain]" value="1" <?php checked('1', $cnb_options['show_all_buttons_for_domain']); ?> />
459
+ <label for="cnb-all-domains">Enable</label>
460
+ <p class="description">When checked, the "All Buttons" overview shows all buttons for this account, not just for the current domain.</p>
461
+ </td>
462
+ </tr>
463
+ <tr class="when-cloud-enabled cnb_advanced_view">
464
+ <th>API endpoint</th>
465
+ <td><label>
466
+ <input type="text" name="cnb[api_base]" class="regular-text"
467
+ value="<?php echo CnbAppRemote::cnb_get_api_base() ?>" />
468
+ </label>
469
+ <p class="description">The API endpoint to use to communicate with the CallNowButton Cloud service.<br />
470
+ <strong>Do not change this unless you know what you're doing!</strong>
471
+ </p>
472
+ </td>
473
+ </tr>
474
+ <tr class="cnb_advanced_view">
475
+ <th>API caching</th>
476
+ <td>
477
+ <input type="hidden" name="cnb[api_caching]" value="0" />
478
+ <input id="cnb-api-caching" type="checkbox" name="cnb[api_caching]" value="1" <?php checked('1', $cnb_options['api_caching']); ?> />
479
+ <label for="cnb-api-caching">Enable</label>
480
+ <p class="description">Cache API requests (using Wordpress transients)</p>
481
+ </td>
482
+ </tr>
483
+ <?php } // end of beta check ?>
484
+ </table>
485
+ <?php } ?>
486
+ <input type="hidden" name="cnb[version]" value="<?php echo CNB_VERSION; ?>"/>
487
+ <p class="submit"><input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>"/></p>
488
+ </form>
489
 
490
+ <?php do_action('cnb_footer'); ?>
 
491
  <?php }
src/call-now-button.php CHANGED
@@ -2,18 +2,21 @@
2
 
3
  require_once dirname( __FILE__ ) . '/utils/utils.php';
4
  require_once dirname( __FILE__ ) . '/admin/admin-ajax.php';
 
 
5
 
6
  // Grabbing the settings and checking for latest version
7
  // OR creating the options file for first time installations
8
  $cnb_settings = cnb_get_options();
9
  $cnb_options = $cnb_settings['options'];
10
- $cnb_slug_base = 'call-now-button';
11
 
12
  $cnb_options['active'] = isset($cnb_options['active']) && $cnb_options['active'] == 1 ? 1 : 0;
13
  $cnb_options['classic'] = isset($cnb_options['classic']) && $cnb_options['classic'] == 1 ? 1 : 0;
14
  $cnb_options['hideIcon'] = isset($cnb_options['hideIcon']) && $cnb_options['hideIcon'] == 1 ? 1 : 0;
15
  $cnb_options['frontpage'] = isset($cnb_options['frontpage']) && $cnb_options['frontpage'] == 1 ? 1 : 0;
16
  $cnb_options['advanced_view'] = isset($cnb_options['advanced_view']) && $cnb_options['advanced_view'] == 1 ? 1 : 0;
 
17
  $cnb_options['footer_show_traces'] = isset($cnb_options['footer_show_traces']) && $cnb_options['footer_show_traces'] == 1 ? 1 : 0;
18
  $cnb_options['api_caching'] = isset($cnb_options['api_caching']) && $cnb_options['api_caching'] == 1 ? 1 : 0;
19
 
@@ -23,7 +26,7 @@ $cnb_cloud_hosting = isset($cnb_options['cloud_enabled']) && $cnb_options['cloud
23
  // Used by settings
24
  $cnb_options['status'] = $cnb_cloud_hosting ? 'cloud' : ($cnb_options['active'] ? 'enabled' : 'disabled');
25
 
26
- /**
27
  * Used by cnb_register_admin_page
28
  */
29
  function cnb_admin_styling() {
@@ -73,22 +76,28 @@ function cnb_register_admin_pages() {
73
 
74
  $menu_page_function = $cnb_cloud_hosting ? 'cnb_admin_button_overview' : 'cnb_admin_page_legacy_edit';
75
 
76
- // Oldest wordpress only has "smartphone", no "phone" (this is added in a later version)
 
 
 
77
  $icon_url = version_compare($wp_version, '5.5.0', '<') ? 'dashicons-smartphone' : 'dashicons-phone';
78
  $menu_page = add_menu_page(
79
  __( 'Call Now Button - Overview', CNB_NAME ),
80
- 'Call Now Button',
81
  'manage_options',
82
  $cnb_slug_base,
83
  $menu_page_function,
84
  $icon_url,
85
- 61
86
  );
87
  add_action('admin_print_styles-' . $menu_page, 'cnb_admin_styling');
88
 
89
  if ($cnb_cloud_hosting) {
90
  // Button overview
91
- $button_overview = add_submenu_page( $cnb_slug_base, $plugin_title, 'Buttons', 'manage_options', $cnb_slug_base, 'cnb_admin_button_overview' );
 
 
 
92
  add_action( 'admin_print_styles-' . $button_overview, 'cnb_admin_styling' );
93
 
94
  if ($cnb_options['advanced_view'] === 1) {
@@ -121,7 +130,7 @@ function cnb_register_admin_pages() {
121
  }
122
  } else {
123
  // Legacy edit
124
- $legacy_edit = add_submenu_page( $cnb_slug_base, $plugin_title, 'Button', 'manage_options', $cnb_slug_base, 'cnb_admin_page_legacy_edit' );
125
  add_action( 'admin_print_styles-' . $legacy_edit, 'cnb_admin_styling' );
126
  }
127
 
@@ -151,8 +160,19 @@ function cnb_enqueue_script_dialog() {
151
  add_action('admin_enqueue_scripts', 'cnb_enqueue_script_dialog');
152
 
153
  function cnb_plugin_meta($links, $file) {
 
154
  if ($file == CNB_BASENAME) {
 
 
155
  $url = admin_url('admin.php');
 
 
 
 
 
 
 
 
156
  $settings_link =
157
  add_query_arg(
158
  array(
@@ -161,12 +181,18 @@ function cnb_plugin_meta($links, $file) {
161
  $settings_url = esc_url($settings_link);
162
 
163
  $cnb_new_links = array(
164
- sprintf('<a href="%s">%s</a>', $settings_url, __('Settings')),
165
- '<a href="' . CNB_SUPPORT . '">Support</a>');
 
 
 
 
 
166
  array_push(
167
  $links,
168
  $cnb_new_links[0],
169
- $cnb_new_links[1]
 
170
  );
171
  }
172
  return $links;
@@ -174,12 +200,27 @@ function cnb_plugin_meta($links, $file) {
174
 
175
  add_filter('plugin_row_meta', 'cnb_plugin_meta', 10, 2);
176
 
177
- function cnb_plugin_add_settings_link($links) {
178
- array_unshift($links, sprintf('<a href="admin.php?page=%s-settings">%s</a>', CNB_BASEFOLDER, __('Settings')));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  return $links;
180
  }
181
 
182
- add_filter('plugin_action_links_' . CNB_BASENAME, 'cnb_plugin_add_settings_link');
183
 
184
 
185
  function cnb_options_validate($input) {
@@ -256,6 +297,16 @@ function cnb_admin_update_action() {
256
 
257
  add_action( 'admin_post_cnb_update_action', 'cnb_admin_update_action' );
258
 
 
 
 
 
 
 
 
 
 
 
259
  /**
260
  * Called when a condition is saved via POST
261
  */
@@ -287,6 +338,15 @@ function cnb_admin_migrate_to_cloud() {
287
  add_action( 'admin_post_cnb_create_cloud_domain', 'cnb_admin_migrate_to_cloud' );
288
  add_action( 'admin_post_cnb_migrate_legacy_button', 'cnb_admin_migrate_to_cloud' );
289
 
 
 
 
 
 
 
 
 
 
290
  // Render the Frontend
291
  if (!is_admin() && isButtonActive($cnb_options)) {
292
  $cnb_has_text = ($cnb_options['text'] == '') ? false : true;
2
 
3
  require_once dirname( __FILE__ ) . '/utils/utils.php';
4
  require_once dirname( __FILE__ ) . '/admin/admin-ajax.php';
5
+ require_once dirname( __FILE__ ) . '/utils/CnbAdminNotices.class.php';
6
+ require_once dirname( __FILE__ ) . '/admin/partials/admin-header.php';
7
 
8
  // Grabbing the settings and checking for latest version
9
  // OR creating the options file for first time installations
10
  $cnb_settings = cnb_get_options();
11
  $cnb_options = $cnb_settings['options'];
12
+ $cnb_slug_base = CNB_SLUG;
13
 
14
  $cnb_options['active'] = isset($cnb_options['active']) && $cnb_options['active'] == 1 ? 1 : 0;
15
  $cnb_options['classic'] = isset($cnb_options['classic']) && $cnb_options['classic'] == 1 ? 1 : 0;
16
  $cnb_options['hideIcon'] = isset($cnb_options['hideIcon']) && $cnb_options['hideIcon'] == 1 ? 1 : 0;
17
  $cnb_options['frontpage'] = isset($cnb_options['frontpage']) && $cnb_options['frontpage'] == 1 ? 1 : 0;
18
  $cnb_options['advanced_view'] = isset($cnb_options['advanced_view']) && $cnb_options['advanced_view'] == 1 ? 1 : 0;
19
+ $cnb_options['show_all_buttons_for_domain'] = isset($cnb_options['show_all_buttons_for_domain']) && $cnb_options['show_all_buttons_for_domain'] == 1 ? 1 : 0;
20
  $cnb_options['footer_show_traces'] = isset($cnb_options['footer_show_traces']) && $cnb_options['footer_show_traces'] == 1 ? 1 : 0;
21
  $cnb_options['api_caching'] = isset($cnb_options['api_caching']) && $cnb_options['api_caching'] == 1 ? 1 : 0;
22
 
26
  // Used by settings
27
  $cnb_options['status'] = $cnb_cloud_hosting ? 'cloud' : ($cnb_options['active'] ? 'enabled' : 'disabled');
28
 
29
+ /**
30
  * Used by cnb_register_admin_page
31
  */
32
  function cnb_admin_styling() {
76
 
77
  $menu_page_function = $cnb_cloud_hosting ? 'cnb_admin_button_overview' : 'cnb_admin_page_legacy_edit';
78
 
79
+ $menu_page_title = $cnb_cloud_hosting ? 'Buttons' : 'Call Now Button';
80
+ $menu_page_position = $cnb_cloud_hosting ? 30 : 66;
81
+
82
+ // Oldest WordPress only has "smartphone", no "phone" (this is added in a later version)
83
  $icon_url = version_compare($wp_version, '5.5.0', '<') ? 'dashicons-smartphone' : 'dashicons-phone';
84
  $menu_page = add_menu_page(
85
  __( 'Call Now Button - Overview', CNB_NAME ),
86
+ $menu_page_title,
87
  'manage_options',
88
  $cnb_slug_base,
89
  $menu_page_function,
90
  $icon_url,
91
+ $menu_page_position
92
  );
93
  add_action('admin_print_styles-' . $menu_page, 'cnb_admin_styling');
94
 
95
  if ($cnb_cloud_hosting) {
96
  // Button overview
97
+ $button_overview = add_submenu_page( $cnb_slug_base, $plugin_title, 'All buttons', 'manage_options', $cnb_slug_base, 'cnb_admin_button_overview' );
98
+ add_action( 'admin_print_styles-' . $button_overview, 'cnb_admin_styling' );
99
+
100
+ $button_overview = add_submenu_page( $cnb_slug_base, $plugin_title, 'Add New', 'manage_options', $cnb_slug_base . '&action=new', 'cnb_admin_button_overview' );
101
  add_action( 'admin_print_styles-' . $button_overview, 'cnb_admin_styling' );
102
 
103
  if ($cnb_options['advanced_view'] === 1) {
130
  }
131
  } else {
132
  // Legacy edit
133
+ $legacy_edit = add_submenu_page( $cnb_slug_base, $plugin_title, 'My button', 'manage_options', $cnb_slug_base, 'cnb_admin_page_legacy_edit' );
134
  add_action( 'admin_print_styles-' . $legacy_edit, 'cnb_admin_styling' );
135
  }
136
 
160
  add_action('admin_enqueue_scripts', 'cnb_enqueue_script_dialog');
161
 
162
  function cnb_plugin_meta($links, $file) {
163
+ global $cnb_cloud_hosting;
164
  if ($file == CNB_BASENAME) {
165
+ $link_name = $cnb_cloud_hosting ? 'All buttons' : 'My button';
166
+
167
  $url = admin_url('admin.php');
168
+
169
+ $button_link =
170
+ add_query_arg(
171
+ array(
172
+ 'page' => 'call-now-button'),
173
+ $url);
174
+ $button_url = esc_url($button_link);
175
+
176
  $settings_link =
177
  add_query_arg(
178
  array(
181
  $settings_url = esc_url($settings_link);
182
 
183
  $cnb_new_links = array(
184
+ sprintf(
185
+ '<a href="%s">%s</a>', $button_url, __($link_name)),
186
+ sprintf(
187
+ '<a href="%s">%s</a>', $settings_url, __('Settings')),
188
+ sprintf(
189
+ '<a href="%s">%s</a>', CNB_SUPPORT, __('Support'))
190
+ );
191
  array_push(
192
  $links,
193
  $cnb_new_links[0],
194
+ $cnb_new_links[1],
195
+ $cnb_new_links[2]
196
  );
197
  }
198
  return $links;
200
 
201
  add_filter('plugin_row_meta', 'cnb_plugin_meta', 10, 2);
202
 
203
+ function cnb_plugin_add_action_link($links) {
204
+ global $cnb_cloud_hosting;
205
+ $link_name = $cnb_cloud_hosting ? 'All buttons' : 'My button';
206
+
207
+ $url = admin_url( 'admin.php' );
208
+ $button_link =
209
+ add_query_arg(
210
+ array(
211
+ 'page' => 'call-now-button'
212
+ ),
213
+ $url );
214
+ $button_url = esc_url( $button_link );
215
+
216
+
217
+ $button = sprintf(
218
+ '<a href="%s">%s</a>', $button_url, __( $link_name ) );
219
+ array_unshift($links, $button);
220
  return $links;
221
  }
222
 
223
+ add_filter('plugin_action_links_' . CNB_BASENAME, 'cnb_plugin_add_action_link');
224
 
225
 
226
  function cnb_options_validate($input) {
297
 
298
  add_action( 'admin_post_cnb_update_action', 'cnb_admin_update_action' );
299
 
300
+ /**
301
+ * Called when a condition is saved via POST
302
+ */
303
+ function cnb_admin_create_condition() {
304
+ require_once dirname( __FILE__ ) . '/admin/condition-edit.php';
305
+ cnb_admin_page_condition_create_process();
306
+ }
307
+
308
+ add_action( 'admin_post_cnb_create_condition', 'cnb_admin_create_condition' );
309
+
310
  /**
311
  * Called when a condition is saved via POST
312
  */
338
  add_action( 'admin_post_cnb_create_cloud_domain', 'cnb_admin_migrate_to_cloud' );
339
  add_action( 'admin_post_cnb_migrate_legacy_button', 'cnb_admin_migrate_to_cloud' );
340
 
341
+ add_action( 'cnb_in_admin_header', 'cnb_admin_header_no_args' );
342
+ add_action('cnb_header', 'cnb_admin_header');
343
+ add_action( 'cnb_footer', 'cnb_admin_footer');
344
+
345
+ /**
346
+ * Initialize the permanent is-dismissible notices code
347
+ */
348
+ $adminNotices = CnbAdminNotices::get_instance();
349
+
350
  // Render the Frontend
351
  if (!is_admin() && isButtonActive($cnb_options)) {
352
  $cnb_has_text = ($cnb_options['text'] == '') ? false : true;
src/renderers/classic/wp_head.php CHANGED
@@ -15,7 +15,7 @@ function cnb_head() {
15
  $cnb_button_appearance = "width:100px;right:0;border-bottom-left-radius:40px; border-top-left-radius:40px;";
16
  }
17
 
18
- $cnb_button_css .= "<style>#callnowbutton, #callnowbutton span {display:none;} @media screen and (max-width:650px){#callnowbutton .NoButtonText{display:none;}#callnowbutton {display:block; " .
19
  $cnb_button_appearance .
20
  " height:80px; position:fixed; bottom:-20px; border-top:2px solid " .
21
  changeColor(esc_html($cnb_options['color']), 'lighter') .
15
  $cnb_button_appearance = "width:100px;right:0;border-bottom-left-radius:40px; border-top-left-radius:40px;";
16
  }
17
 
18
+ $cnb_button_css .= "<style data-cnb-version=\"" . CNB_VERSION . "\">#callnowbutton, #callnowbutton span {display:none;} @media screen and (max-width:650px){#callnowbutton .NoButtonText{display:none;}#callnowbutton {display:block; " .
19
  $cnb_button_appearance .
20
  " height:80px; position:fixed; bottom:-20px; border-top:2px solid " .
21
  changeColor(esc_html($cnb_options['color']), 'lighter') .
src/renderers/cloud/wp_head.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
  function cnb_head() {
3
  global $cnb_options;
4
- $id = $cnb_options['cloud_use_id'];
5
  $cnb_button_js = "\n<!-- Call Now Button " . CNB_VERSION . " by Jerry Rietveld (callnowbutton.com) [renderer:cloud, id:".esc_attr($id)."]-->\n";
6
  if ($id) {
7
- $cnb_button_js .= '<script type="text/javascript" src="'.CnbAppRemote::cnb_get_user_base().'/' . esc_attr($id) . '.js"></script>';
8
  }
9
  echo $cnb_button_js;
10
  }
1
  <?php
2
  function cnb_head() {
3
  global $cnb_options;
4
+ $id = isset($cnb_options['cloud_use_id']) ? $cnb_options['cloud_use_id'] : 0;
5
  $cnb_button_js = "\n<!-- Call Now Button " . CNB_VERSION . " by Jerry Rietveld (callnowbutton.com) [renderer:cloud, id:".esc_attr($id)."]-->\n";
6
  if ($id) {
7
+ $cnb_button_js .= '<script data-cnb-version="' . CNB_VERSION . '" type="text/javascript" src="'.CnbAppRemote::cnb_get_user_base().'/' . esc_attr($id) . '.js"></script>';
8
  }
9
  echo $cnb_button_js;
10
  }
src/renderers/modern/wp_head.php CHANGED
@@ -27,9 +27,6 @@ function cnb_head() {
27
  $ButtonExtra = "body {padding-" . $cnb_top_or_bottom . ":60px;}#callnowbutton img {transform: scale(" . esc_html($cnb_options['zoom']) . ");}";
28
  if ($cnb_has_text) {
29
  $cnb_button_appearance .= "text-align:center;color:#fff; font-weight:600; font-size:120%; overflow: hidden;";
30
- if (isset($cnb_options['hideIcon']) && $cnb_options['hideIcon'] == 1) {
31
- $cnb_button_appearance .= 'padding-right:20px;';
32
- }
33
  }
34
  } else {
35
  $cnb_button_appearance = $cnb_button_shape . $cnb_button_positions[$cnb_options['appearance']];
@@ -47,7 +44,7 @@ function cnb_head() {
47
  $circularButtonTextCSS = "";
48
  }
49
 
50
- $cnb_button_css = $cnb_button_css . "<style>";
51
  $cnb_button_css .= "#callnowbutton {display:none;} @media screen and (max-width:650px){#callnowbutton {display:block; position:fixed; text-decoration:none; z-index:" . zindex($cnb_options['z-index']) . ";";
52
  $cnb_button_css .= $cnb_button_appearance;
53
  if ($cnb_is_full_width) {
27
  $ButtonExtra = "body {padding-" . $cnb_top_or_bottom . ":60px;}#callnowbutton img {transform: scale(" . esc_html($cnb_options['zoom']) . ");}";
28
  if ($cnb_has_text) {
29
  $cnb_button_appearance .= "text-align:center;color:#fff; font-weight:600; font-size:120%; overflow: hidden;";
 
 
 
30
  }
31
  } else {
32
  $cnb_button_appearance = $cnb_button_shape . $cnb_button_positions[$cnb_options['appearance']];
44
  $circularButtonTextCSS = "";
45
  }
46
 
47
+ $cnb_button_css = $cnb_button_css . '<style data-cnb-version="' . CNB_VERSION . '">';
48
  $cnb_button_css .= "#callnowbutton {display:none;} @media screen and (max-width:650px){#callnowbutton {display:block; position:fixed; text-decoration:none; z-index:" . zindex($cnb_options['z-index']) . ";";
49
  $cnb_button_css .= $cnb_button_appearance;
50
  if ($cnb_is_full_width) {
src/utils/CnbAdminNotices.class.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // don't load directly
3
+ defined( 'ABSPATH' ) || die( '-1' );
4
+
5
+ /**
6
+ * @var $type string one of info, success, warning, error
7
+ * @var $dismissable boolean false by default
8
+ */
9
+ class CnbNotice {
10
+ public function __construct($type = null, $message = null, $dismissable = false, $dismiss_option = null) {
11
+ $this->type = $type;
12
+ $this->message = $message;
13
+ $this->dismissable = $dismissable;
14
+ $this->dismiss_option = $dismiss_option;
15
+ }
16
+
17
+ public $type;
18
+ public $message;
19
+ public $dismissable;
20
+ public $dismiss_option;
21
+ }
22
+
23
+ class CnbNotices {
24
+ }
25
+
26
+ class CnbAdminNotices {
27
+
28
+ private static $_instance;
29
+ /**
30
+ * @var CnbNotices
31
+ */
32
+ private $admin_notices;
33
+ const TYPES = 'error,warning,info,success';
34
+
35
+ private function __construct() {
36
+ $this->admin_notices = new CnbNotices();
37
+ foreach ( explode( ',', self::TYPES ) as $type ) {
38
+ $this->admin_notices->{$type} = array();
39
+ }
40
+ add_action( 'admin_init', array( &$this, 'action_admin_init' ) );
41
+ add_action( 'cnb_admin_notices', array( &$this, 'action_admin_notices' ) );
42
+ add_action( 'admin_enqueue_scripts', array( &$this, 'action_admin_enqueue_scripts' ) );
43
+ }
44
+
45
+ public static function get_instance() {
46
+ if ( ! ( self::$_instance instanceof self ) ) {
47
+ self::$_instance = new self();
48
+ }
49
+ return self::$_instance;
50
+ }
51
+
52
+ public function action_admin_init() {
53
+ $dismiss_option = filter_input( INPUT_GET, CNB_SLUG . '_dismiss', FILTER_SANITIZE_STRING );
54
+ if ( is_string( $dismiss_option ) ) {
55
+ update_option( CNB_SLUG . '_dismissed_' . $dismiss_option, true );
56
+ wp_die(
57
+ __( 'Dismissed notice: ' . $dismiss_option, CNB_NAME), __( 'Dismissed notice', CNB_NAME),
58
+ array(
59
+ 'response' => 200,
60
+ )
61
+ );
62
+ }
63
+ }
64
+
65
+ public function action_admin_enqueue_scripts() {
66
+ wp_enqueue_script( 'jquery' );
67
+ wp_enqueue_script(
68
+ CNB_SLUG . '-notify',
69
+ plugins_url( '../../resources/js/dismiss.js', __FILE__ ),
70
+ array( 'jquery' )
71
+ );
72
+ }
73
+
74
+ /**
75
+ * @param $notice CnbNotice
76
+ */
77
+ public function renderNotice($notice) {
78
+ if ($notice == null) {
79
+ return;
80
+ }
81
+
82
+ $dismiss_classes = '';
83
+ $dismiss_data_url = '';
84
+ if ( $notice->dismiss_option ) {
85
+ $notice->dismissable = true;
86
+ $url = admin_url('admin.php');
87
+ $dismiss_url = add_query_arg( array(
88
+ CNB_SLUG . '_dismiss' => $notice->dismiss_option
89
+ ), $url );
90
+
91
+ $dismiss_data_url .= ' data-dismiss-url="' . esc_url( $dismiss_url ) . '"';
92
+ }
93
+
94
+ if ($notice->dismissable) {
95
+ $dismiss_classes .= ' is-dismissible';
96
+ }
97
+
98
+ echo '<div class="notice notice-' . CNB_SLUG . ' notice-' . $notice->type . $dismiss_classes . '"'.$dismiss_data_url.'>';
99
+ echo $notice->message;
100
+ echo '</div>';
101
+ }
102
+
103
+ public function action_admin_notices() {
104
+ foreach ( explode( ',', self::TYPES ) as $type ) {
105
+ foreach ( $this->admin_notices->{$type} as $admin_notice ) {
106
+ $option = CNB_SLUG . '_dismissed_' . $admin_notice->dismiss_option;
107
+ if ( !$admin_notice->dismiss_option || !get_option( $option ) ) {
108
+ $this->renderNotice($admin_notice);
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * @param $notices CnbNotice[]
116
+ */
117
+ public function notices( $notices ) {
118
+ foreach ($notices as $notice) {
119
+ $this->notice($notice);
120
+ }
121
+ }
122
+
123
+ /**
124
+ * @param $notice CnbNotice
125
+ */
126
+ public function notice( $notice ) {
127
+ $notice = $this->createNotice( $notice->type, $notice->message, $notice->dismissable, $notice->dismiss_option );
128
+ $this->addNotice($notice);
129
+ }
130
+
131
+ public function error( $message, $dismiss_option = false ) {
132
+ $notice = $this->createNotice( 'error', $message, false, $dismiss_option );
133
+ $this->addNotice($notice);
134
+ }
135
+
136
+ public function renderError( $message, $dismiss_option = false ) {
137
+ $notice = $this->createNotice( 'error', $message, false, $dismiss_option );
138
+ $this->renderNotice($notice);
139
+ }
140
+
141
+ public function warning( $message, $dismiss_option = false ) {
142
+ $notice = $this->createNotice( 'warning', $message, false, $dismiss_option );
143
+ $this->addNotice($notice);
144
+ }
145
+
146
+ public function renderWarning( $message, $dismiss_option = false ) {
147
+ $notice = $this->createNotice( 'warning', $message, false, $dismiss_option );
148
+ $this->renderNotice($notice);
149
+ }
150
+
151
+ public function success( $message, $dismiss_option = false ) {
152
+ $notice = $this->createNotice( 'success', $message, false, $dismiss_option );
153
+ $this->addNotice($notice);
154
+ }
155
+
156
+ public function renderSuccess( $message, $dismiss_option = false ) {
157
+ $notice = $this->createNotice( 'success', $message, false, $dismiss_option );
158
+ $this->renderNotice($notice);
159
+ }
160
+
161
+ public function info( $message, $dismiss_option = false ) {
162
+ $notice = $this->createNotice( 'info', $message, false, $dismiss_option );
163
+ $this->addNotice($notice);
164
+ }
165
+ public function renderInfo( $message, $dismiss_option = false ) {
166
+ $notice = $this->createNotice( 'info', $message, false, $dismiss_option );
167
+ $this->renderNotice($notice);
168
+ }
169
+
170
+ /**
171
+ * @var $type string one of info, success, warning, error
172
+ * @param $message string
173
+ * @param $dismissable boolean
174
+ * @param $dismiss_option boolean
175
+ *
176
+ * @return CnbNotice
177
+ */
178
+ private function createNotice( $type, $message, $dismissable = false, $dismiss_option = false ) {
179
+ $notice = new CnbNotice();
180
+ $notice->message = $message;
181
+ $notice->dismissable = $dismissable;
182
+ $notice->dismiss_option = $dismiss_option;
183
+ $notice->type = $type;
184
+ return $notice;
185
+ }
186
+
187
+ /**
188
+ * @param $notice CnbNotice
189
+ */
190
+ private function addNotice( $notice ) {
191
+ $this->admin_notices->{$notice->type}[] = $notice;
192
+ }
193
+ }
src/utils/notices.php CHANGED
@@ -1,41 +1,101 @@
1
  <?php
2
- function cnb_settings_get_account_missing_notice($user) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  global $cnb_options;
4
 
5
- $notice = '<div class="notice notice-warning">
6
- <h2 class="title">You\'re almost there!</h2>
7
- <p>You have enabled Cloud Hosting, but you need an account and API key from
8
- <a href="https://app.callnowbutton.com?utm_source=wp-plugin&utm_medium=referral&utm_campaign=beta_tester&utm_term=sign-up-for-api">https://app.callnowbutton.com</a>.</p>
9
- <p><ul>
10
- <li>Create an account on <a href="https://app.callnowbutton.com?utm_source=wp-plugin&utm_medium=referral&utm_campaign=beta_tester&utm_term=sign-up-for-api">https://app.callnowbutton.com</a></li>
11
- <li>Go to your profile page and click <strong>Create new API key</strong>.</li>
12
- <li>Copy the API key into the "API key" field below</li>
13
- <li>Click "Save API key"</li>
14
- </ul></p>
15
- <form method="post" action="' . esc_url( admin_url('options.php') ) . '" class="cnb-container">';
16
  ob_start();
17
  settings_fields('cnb_options');
18
- $notice .= ob_get_clean();
19
- $notice .= '<input type="hidden" name="page" value="call-now-button-settings" />
20
  <table class="form-table">
21
  <tr class="when-cloud-enabled">
22
- <th scope="row">Enter API key:</th>
23
  <td>
24
  <input type="text" class="regular-text" name="cnb[api_key]"
25
- value="' . ((isset($cnb_options['api_key'])) ? esc_attr($cnb_options['api_key']) : '') . '"
26
  placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/>
27
  <input type="submit" class="button-primary" value="' . __('Save API key') . '"/>
28
  </td>
29
  </table>
30
  </form>';
31
- $notice .= CnbAdminCloud::cnb_admin_get_error_message_details($user);
32
- $notice .= '</div>';
33
- return $notice;
34
  }
35
 
36
  function cnb_settings_get_domain_missing_notice($domain) {
37
- $notice = '<div class="notice notice-warning">
38
- <h2 class="title">Domain not found yet</h2>
39
  <p>You have enabled Cloud Hosting and are logged in,
40
  but we need to create the domain remotely.</p>
41
  <p>
@@ -46,35 +106,37 @@ function cnb_settings_get_domain_missing_notice($domain) {
46
  <input type="submit" value="Create domain" class="button button-secondary" />
47
  </form>
48
  </p>';
49
- $notice .= CnbAdminCloud::cnb_admin_get_error_message_details( $domain );
50
- $notice .= '</div>';
51
- return $notice;
 
52
  }
53
 
54
  function cnb_settings_get_button_missing_notice() {
55
- return '<div class="notice notice-warning">
56
- <h2 class="title">Creating your first button</h2>
57
  <p>You have enabled Cloud Hosting and have your domain setup,
58
  so now it\'s time to create your first button.</p>
59
  <p>To make it easy, we can migrate your existing button to the Cloud.</p>
60
- <p>
61
- <form action="'. esc_url( admin_url('admin-post.php') ) .'" method="post">
62
  <input type="hidden" name="page" value="call-now-button-settings" />
63
  <input type="hidden" name="action" value="cnb_migrate_legacy_button" />
64
  <input type="hidden" name="_wpnonce" value="'. wp_create_nonce('cnb_migrate_legacy_button') .'" />
65
  <input type="submit" value="Migrate button" class="button button-secondary" />
66
- </form>
67
- </p>
68
- </div>';
 
 
 
69
  }
70
 
71
  function cnb_settings_get_buttons_missing_notice($error) {
72
- $notice = '<div class="notice notice-warning">
73
- <h2 class="title">Could not retrieve Buttons</h2>
74
  <p>Something unexpected went wrong retrieving the Buttons for this API key</p>';
75
- $notice .= CnbAdminCloud::cnb_admin_get_error_message_details( $error );
76
- $notice .= '</div>';
77
- return $notice;
 
78
  }
79
 
80
  function cnb_api_key_invalid_notice($error) {
@@ -87,13 +149,13 @@ function cnb_api_key_invalid_notice($error) {
87
  $url );
88
  $redirect_url = esc_url( $redirect_link );
89
 
90
- $errorNotice = '<div class="notice notice-error">
91
- <h2 class="title">API Key invalid</h2>
92
  <p>You have enabled Cloud Hosting, but you need a valid API key from CallNowButtom</p>
93
  <p>Go to <a href="'.$redirect_url.'">Settings</a> for instructions.</p>';
94
- $errorNotice .= CnbAdminCloud::cnb_admin_get_error_message_details( $error );
95
- $errorNotice .= '</div>';
96
- return $errorNotice;
 
97
 
98
  }
99
 
@@ -102,14 +164,15 @@ function cnb_button_disabled_notice() {
102
  $redirect_link =
103
  add_query_arg(
104
  array(
105
- 'page' => 'call-now-button-settings',
106
  ),
107
  $url );
108
  $redirect_url = esc_url( $redirect_link );
109
 
110
- return '<div class="notice-error notice">
111
- <p>The Call Now Button is currently <b>disabled</b>.
112
- Change the <i>Button status</i> under <a href="'.$redirect_url.'">Settings</a> to enable.</p></div>';
 
113
  }
114
 
115
  function cnb_button_classic_enabled_but_no_number_notice() {
@@ -117,19 +180,43 @@ function cnb_button_classic_enabled_but_no_number_notice() {
117
  $redirect_link =
118
  add_query_arg(
119
  array(
120
- 'page' => 'call-now-button-settings',
121
  ),
122
  $url );
123
  $redirect_url = esc_url( $redirect_link );
124
 
125
- return '<div class="notice-warning notice">
126
- <p>The Call Now Button is currently <strong>active without a phone number</strong>.
127
- Change the <i>Button status</i> under <a href="'.$redirect_url.'">Settings</a> to disable or enter a phone number.</p></div>';
 
 
128
  }
129
 
130
  function cnb_caching_plugin_warning_notice($caching_plugin_name) {
131
- return '<div class="notice-error notice">
132
- <p><span class="dashicons dashicons-warning"></span>
133
  Your website is using a <strong><i>Caching Plugin</i></strong> (' . $caching_plugin_name . ').
134
- If you\'re not seeing your button or your changes, make sure you empty your cache first.</p></div>';
135
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
+
3
+ require_once dirname( __FILE__ ) . '/CnbAdminNotices.class.php';
4
+ require_once dirname( __FILE__ ) . '/../admin/api/CnbAdminCloud.php';
5
+
6
+ function cnb_upgrade_notice($cnb_old_version, $cnb_changelog) {
7
+
8
+ $message = '<h3>' . CNB_NAME . ' has been updated!</h3><h4>What\'s new?</h4>';
9
+ // Only on first run after update show list of changes since last update
10
+ foreach ( $cnb_changelog as $key => $value ) {
11
+ if ( $key > $cnb_old_version ) {
12
+ $message .= '<h3>' . esc_html($key) . '</h3>';
13
+ if ( is_array( $value ) ) {
14
+ foreach ( $value as $item ) {
15
+ $message .= '<p><span class="dashicons dashicons-yes"></span> ' . esc_html($item) . '</p>';
16
+ }
17
+ } else {
18
+ $message .= '<p><span class="dashicons dashicons-yes"></span> ' . esc_html($value) . '</p>';
19
+ }
20
+ }
21
+ }
22
+
23
+ $adminNotices = CnbAdminNotices::get_instance();
24
+ $adminNotices->warning($message, 'cnb_update_'.$cnb_old_version);
25
+
26
+ }
27
+
28
+ function cnb_settings_get_account_missing_notice() {
29
+ $message = '<h3 class="title">Activate cloud version</h3>
30
+ <p>To activate the cloud version of the Call Now Button, you\'ll need an account at
31
+ <a href="https://app.callnowbutton.com?utm_source=wp-plugin&utm_medium=referral&utm_campaign=beta_tester&utm_term=sign-up-for-api">https://app.callnowbutton.com</a>, get a unique API key and add it to the field below.</p>
32
+ <p>Let\'s go:</p>
33
+ <ol>
34
+ <li>Create your account on <a href="https://app.callnowbutton.com?utm_source=wp-plugin&utm_medium=referral&utm_campaign=beta_tester&utm_term=sign-up-for-api">https://app.callnowbutton.com</a></li>
35
+ <li>Go to your profile info by clicking on the user icon in the top right corner and then click <strong>Create new API key</strong>.</li>
36
+ <li>Copy the API key, paste it into the field below and click <strong>Save API key</strong>.</li>
37
+ </ol>';
38
+ $message .= cnb_settings_api_key_input();
39
+
40
+ $adminNotices = CnbAdminNotices::get_instance();
41
+ $adminNotices->warning($message);
42
+ }
43
+
44
+ function cnb_settings_api_key_invalid_notice() {
45
+ $message = '<h3 class="title">API key is incorrect</h3>
46
+ <p>Your API key seems to be invalid. This might have a few reasons:
47
+ <ol>
48
+ <li>You didn\'t copy the entire API key (it is case-sensative and should be in the form of a UUID).</li>
49
+ <li>
50
+ You have deleted your API key (check <a href="https://app.callnowbutton.com/app/profile">your profile</a>).
51
+ <ol>
52
+ <li>Go to your profile page and click <strong>Create new API key</strong>.</li>
53
+ <li>Copy the API key into the "API key" field below</li>
54
+ <li>Click "Save API key"</li>
55
+ </ol>
56
+ </li>
57
+ <li>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com">our status page</a>).</li>
58
+ </ol>';
59
+ $message .= cnb_settings_api_key_input();
60
+
61
+ $adminNotices = CnbAdminNotices::get_instance();
62
+ $adminNotices->warning($message);
63
+ }
64
+
65
+ function cnb_generic_error_notice($user) {
66
+ $message = '<h3 class="title">Something went wrong!</h3>
67
+ <p>Something has gone wrong and we do not know why...</p>
68
+ <p>As unlikely as it is, our service might be experiencing issues (check <a href="https://status.callnowbutton.com">our status page</a>).</p>
69
+ <p>If you think you found a bug, please report it at our <a href="https://wordpress.org/support/plugin/call-now-button/">support forum</a>.';
70
+ $message .= CnbAdminCloud::cnb_admin_get_error_message_details($user);
71
+
72
+ $adminNotices = CnbAdminNotices::get_instance();
73
+ $adminNotices->warning($message);
74
+ }
75
+
76
+ function cnb_settings_api_key_input() {
77
  global $cnb_options;
78
 
79
+ $message = '<form method="post" action="' . esc_url( admin_url('options.php') ) . '" class="cnb-container">';
 
 
 
 
 
 
 
 
 
 
80
  ob_start();
81
  settings_fields('cnb_options');
82
+ $message .= ob_get_clean();
83
+ $message .= '<input type="hidden" name="page" value="call-now-button-settings" />
84
  <table class="form-table">
85
  <tr class="when-cloud-enabled">
86
+ <th scope="row">API key</th>
87
  <td>
88
  <input type="text" class="regular-text" name="cnb[api_key]"
 
89
  placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/>
90
  <input type="submit" class="button-primary" value="' . __('Save API key') . '"/>
91
  </td>
92
  </table>
93
  </form>';
94
+ return $message;
 
 
95
  }
96
 
97
  function cnb_settings_get_domain_missing_notice($domain) {
98
+ $message = '<h3 class="title">Domain not found yet</h3>
 
99
  <p>You have enabled Cloud Hosting and are logged in,
100
  but we need to create the domain remotely.</p>
101
  <p>
106
  <input type="submit" value="Create domain" class="button button-secondary" />
107
  </form>
108
  </p>';
109
+ $message .= CnbAdminCloud::cnb_admin_get_error_message_details( $domain );
110
+
111
+ $adminNotices = CnbAdminNotices::get_instance();
112
+ $adminNotices->warning($message);
113
  }
114
 
115
  function cnb_settings_get_button_missing_notice() {
116
+ $message = '<h3 class="title">Creating your first button</h3>
 
117
  <p>You have enabled Cloud Hosting and have your domain setup,
118
  so now it\'s time to create your first button.</p>
119
  <p>To make it easy, we can migrate your existing button to the Cloud.</p>
120
+ <p><form action="'. esc_url( admin_url('admin-post.php') ) .'" method="post">
 
121
  <input type="hidden" name="page" value="call-now-button-settings" />
122
  <input type="hidden" name="action" value="cnb_migrate_legacy_button" />
123
  <input type="hidden" name="_wpnonce" value="'. wp_create_nonce('cnb_migrate_legacy_button') .'" />
124
  <input type="submit" value="Migrate button" class="button button-secondary" />
125
+ </form></p>';
126
+
127
+ $notice = new CnbNotice('warning', $message);
128
+ $notice->dismiss_option = 'cnb_settings_get_button_missing_notice';
129
+ $adminNotices = CnbAdminNotices::get_instance();
130
+ $adminNotices->notice($notice);
131
  }
132
 
133
  function cnb_settings_get_buttons_missing_notice($error) {
134
+ $message = '<h3 class="title">Could not retrieve Buttons</h3>
 
135
  <p>Something unexpected went wrong retrieving the Buttons for this API key</p>';
136
+ $message .= CnbAdminCloud::cnb_admin_get_error_message_details( $error );
137
+
138
+ $adminNotices = CnbAdminNotices::get_instance();
139
+ $adminNotices->warning($message);
140
  }
141
 
142
  function cnb_api_key_invalid_notice($error) {
149
  $url );
150
  $redirect_url = esc_url( $redirect_link );
151
 
152
+ $message = '<h3 class="title">API Key invalid</h3>
 
153
  <p>You have enabled Cloud Hosting, but you need a valid API key from CallNowButtom</p>
154
  <p>Go to <a href="'.$redirect_url.'">Settings</a> for instructions.</p>';
155
+ $message .= CnbAdminCloud::cnb_admin_get_error_message_details( $error );
156
+
157
+ $adminNotices = CnbAdminNotices::get_instance();
158
+ $adminNotices->renderError($message);
159
 
160
  }
161
 
164
  $redirect_link =
165
  add_query_arg(
166
  array(
167
+ 'page' => 'call-now-button',
168
  ),
169
  $url );
170
  $redirect_url = esc_url( $redirect_link );
171
 
172
+ $message = '<p>Your button is currently <strong>not enabled</strong>. Click <a href="'.$redirect_url.'">here</a> to enable your button.</p>';
173
+
174
+ $adminNotices = CnbAdminNotices::get_instance();
175
+ $adminNotices->warning($message);
176
  }
177
 
178
  function cnb_button_classic_enabled_but_no_number_notice() {
180
  $redirect_link =
181
  add_query_arg(
182
  array(
183
+ 'page' => 'call-now-button',
184
  ),
185
  $url );
186
  $redirect_url = esc_url( $redirect_link );
187
 
188
+ $message = '<p>The Call Now Button is currently <strong>active without a phone number</strong>.
189
+ Change the <i>Button status</i> under <a href="'.$redirect_url.'">My button</a> to disable or enter a phone number.</p>';
190
+
191
+ $adminNotices = CnbAdminNotices::get_instance();
192
+ $adminNotices->warning($message);
193
  }
194
 
195
  function cnb_caching_plugin_warning_notice($caching_plugin_name) {
196
+ $message = '<p><span class="dashicons dashicons-warning"></span>
 
197
  Your website is using a <strong><i>Caching Plugin</i></strong> (' . $caching_plugin_name . ').
198
+ If you\'re not seeing your button or your changes, make sure you empty your cache first.</p>';
199
+
200
+ $adminNotices = CnbAdminNotices::get_instance();
201
+ $adminNotices->error($message);
202
+ }
203
+
204
+ function cnb_activate_beta_render_notice() {
205
+ $message = '<form method="post" action="' . esc_url( admin_url('options.php') ) . '" class="cnb-container">';
206
+ ob_start();
207
+ settings_fields('cnb_options');
208
+ $message .= ob_get_clean();
209
+ $message .= '<input type="hidden" name="page" value="call-now-button-settings" />
210
+ <table>
211
+ <tr>
212
+ <th scope="row"</th>
213
+ <td>
214
+ <input type="hidden" name="cnb[cloud_beta_enabled]" value="1" />
215
+ <input type="submit" class="button-primary" value="' . __('Activate beta mode') . '"/> For testing new unreleased functionality.
216
+ </td>
217
+ </table>
218
+ </form>';
219
+ $adminNotices = CnbAdminNotices::get_instance();
220
+ $adminNotices->renderWarning($message);
221
+
222
+ }
src/utils/utils.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
  require_once dirname( __FILE__ ) . '/notices.php';
 
3
 
4
  /**
5
  * Returns the default values for a (legacy) Button
@@ -162,7 +163,9 @@ function svg($color, $icon) {
162
  * @return bool
163
  */
164
  function isButtonActive($cnb_options) {
165
- return isset($cnb_options['active']) && $cnb_options['active'] == 1;
 
 
166
  }
167
 
168
  function getZindexMap() {
@@ -252,38 +255,81 @@ function cnb_get_button_id() {
252
  return filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
253
  }
254
 
 
 
 
255
  function cnb_get_cloud_notices() {
256
  global $cnb_options;
257
 
 
258
  if (isset($cnb_options['cloud_enabled']) && $cnb_options['cloud_enabled'] == 1) {
259
- // TODO - These 3 REMOTE calls are VERY expensive
260
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
 
 
261
  if ($cnb_user instanceof WP_Error) {
262
- return array(cnb_settings_get_account_missing_notice($cnb_user));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  }
264
 
265
  $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
266
- if ($cnb_cloud_domain instanceof WP_Error) {
267
- return array(cnb_settings_get_domain_missing_notice($cnb_cloud_domain));
268
- }
269
-
270
- // Check if any buttons are for the current WP domain
271
- $cnb_cloud_buttons = CnbAppRemote::cnb_remote_get_buttons();
272
- if ($cnb_cloud_buttons instanceof WP_Error) {
273
- return array(cnb_settings_get_buttons_missing_notice($cnb_cloud_buttons));
274
- }
275
-
276
- $cnb_cloud_buttons_this_domain = array_filter($cnb_cloud_buttons, function ($button) use ($cnb_cloud_domain) {
277
- return $button->domain === $cnb_cloud_domain->id;
278
- });
279
-
280
- if ( ! ( $cnb_cloud_domain instanceof WP_Error ) && count( $cnb_cloud_buttons_this_domain ) === 0 ) {
281
- return array(cnb_settings_get_button_missing_notice());
282
  }
283
  }
284
- return array();
285
  }
286
 
 
 
 
287
  function cnb_get_notices() {
288
  $transient_id = filter_input( INPUT_GET, 'tid', FILTER_SANITIZE_STRING );
289
 
@@ -302,7 +348,7 @@ function cnb_get_notices() {
302
  delete_transient('cnb-options');
303
  }
304
 
305
- return array_merge($notices, cnb_get_cloud_notices());
306
  }
307
 
308
  /**
@@ -352,6 +398,7 @@ if (!function_exists('wp_generate_uuid4')) {
352
  );
353
  }
354
  }
 
355
  function cnb_array_column($array, $column_key, $index_key = null) {
356
  if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
357
  // phpcs:ignore
@@ -375,4 +422,36 @@ function cnb_timestamp_to_string($timestamp){
375
  return date("r", $timestamp->seconds);
376
  }
377
  return $timestamp;
378
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  require_once dirname( __FILE__ ) . '/notices.php';
3
+ require_once dirname( __FILE__ ) . '/../admin/settings.php';
4
 
5
  /**
6
  * Returns the default values for a (legacy) Button
163
  * @return bool
164
  */
165
  function isButtonActive($cnb_options) {
166
+ $active = isset($cnb_options['active']) && $cnb_options['active'] == 1;
167
+ $cloud = isset($cnb_options['cloud_enabled']) && $cnb_options['cloud_enabled'] == 1;
168
+ return $active || $cloud;
169
  }
170
 
171
  function getZindexMap() {
255
  return filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
256
  }
257
 
258
+ /**
259
+ * @return CnbNotice[]
260
+ */
261
  function cnb_get_cloud_notices() {
262
  global $cnb_options;
263
 
264
+ $notices = array();
265
  if (isset($cnb_options['cloud_enabled']) && $cnb_options['cloud_enabled'] == 1) {
266
+
267
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
268
+ $cnb_cloud_buttons_this_domain = array();
269
+
270
  if ($cnb_user instanceof WP_Error) {
271
+ if ($cnb_user->get_error_code() === 'CNB_API_NOT_SETUP_YET') {
272
+ // Notice: You're almost there! (enter API key)
273
+ cnb_settings_get_account_missing_notice();
274
+ } else if ($cnb_user->get_error_code() === 'CNB_API_KEY_INVALID') {
275
+ // Notice: API key is incorrect
276
+ cnb_settings_api_key_invalid_notice();
277
+ } else {
278
+ // Notice: something went wrong
279
+ cnb_generic_error_notice( $cnb_user );
280
+ }
281
+ } else {
282
+ $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
283
+ if ( $cnb_cloud_domain instanceof WP_Error ) {
284
+ // Notice: Domain not found yet
285
+ //cnb_settings_get_domain_missing_notice( $cnb_cloud_domain );
286
+
287
+ // Instead, create the domain
288
+ $_notices = CnbAdminCloud::cnb_wp_create_domain( $cnb_user );
289
+ $notices = array_merge($notices, $_notices);
290
+
291
+ // Fix for https://github.com/callnowbutton/wp-plugin/issues/295
292
+ // We also need to refetch the domain since it is a WP_Error at the moment,
293
+ // Since it as just created, we can just refetch it.
294
+ $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
295
+ }
296
+
297
+ // Check if any buttons are for the current WP domain
298
+ $cnb_cloud_buttons = CnbAppRemote::cnb_remote_get_buttons();
299
+ if ( $cnb_cloud_buttons instanceof WP_Error ) {
300
+ // Could not retrieve Buttons
301
+ cnb_settings_get_buttons_missing_notice( $cnb_cloud_buttons );
302
+ } else if ( $cnb_cloud_buttons !== null ) {
303
+ $cnb_cloud_buttons_this_domain = array_filter( $cnb_cloud_buttons, function ( $button ) use ( $cnb_cloud_domain ) {
304
+ // Fix for https://github.com/callnowbutton/wp-plugin/issues/295
305
+ if (is_wp_error($cnb_cloud_domain)) return false;
306
+ return $button->domain === $cnb_cloud_domain->id;
307
+ } );
308
+ }
309
  }
310
 
311
  $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
312
+ $migration_done = get_option('cnb_cloud_migration_done');
313
+ if ( !is_wp_error($cnb_cloud_domain)
314
+ && count($cnb_cloud_buttons_this_domain) === 0
315
+ && !$migration_done) {
316
+ // Notice: Creating your first button
317
+ //cnb_settings_get_button_missing_notice();
318
+
319
+ // Instead, migrate the button
320
+ $_notices = CnbAdminCloud::cnb_wp_migrate_button();
321
+ $notices = array_merge($notices, $_notices);
322
+
323
+ // We should really only do this once, so we need to save something in the settings to stop continious migration.
324
+ add_option('cnb_cloud_migration_done', true);
 
 
 
325
  }
326
  }
327
+ return $notices;
328
  }
329
 
330
+ /**
331
+ * @return CnbNotice[]
332
+ */
333
  function cnb_get_notices() {
334
  $transient_id = filter_input( INPUT_GET, 'tid', FILTER_SANITIZE_STRING );
335
 
348
  delete_transient('cnb-options');
349
  }
350
 
351
+ return $notices;
352
  }
353
 
354
  /**
398
  );
399
  }
400
  }
401
+
402
  function cnb_array_column($array, $column_key, $index_key = null) {
403
  if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
404
  // phpcs:ignore
422
  return date("r", $timestamp->seconds);
423
  }
424
  return $timestamp;
425
+ }
426
+
427
+ /***
428
+ * To ensure arrays are properly sanitized to WordPress Codex standards,
429
+ * they encourage usage of sanitize_text_field(). That only works with a single
430
+ * variable (string). This function allows for a full blown array to get sanitized
431
+ * properly, while sanitizing each individual value in a key -> value pair.
432
+ *
433
+ * Source: https://wordpress.stackexchange.com/questions/24736/wordpress-sanitize-array
434
+ * Author: Broshi, answered Feb 5 '17 at 9:14
435
+ * Via: https://developer.wordpress.org/reference/functions/sanitize_text_field/
436
+ */
437
+ function cnb_wporg_recursive_sanitize_text_field( $array ) {
438
+ foreach ( $array as $key => &$value ) {
439
+ if ( is_array( $value ) ) {
440
+ $value = cnb_wporg_recursive_sanitize_text_field( $value );
441
+ } else {
442
+ $value = sanitize_text_field( $value );
443
+ }
444
+ }
445
+ return $array;
446
+ }
447
+
448
+ /**
449
+ * Same as check_ajax_referer, but does not die() by default
450
+ * @param string $action
451
+ * @param bool $query_arg
452
+ * @param bool $die
453
+ * @return false|int|mixed|void
454
+ */
455
+ function cnb_check_ajax_referer($action, $query_arg=false, $die=false) {
456
+ return check_ajax_referer($action, $query_arg, $die);
457
+ }
uninstall.php CHANGED
@@ -4,13 +4,28 @@
4
 
5
  // if uninstall.php is not called by WordPress, die
6
  if (!defined('WP_UNINSTALL_PLUGIN')) {
7
- die;
8
  }
9
 
10
- $option_name = 'cnb';
 
11
 
12
- // Delete the standard options
13
- delete_option($option_name);
 
14
 
15
- // Delete site options in Multisite
16
- delete_site_option($option_name);
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  // if uninstall.php is not called by WordPress, die
6
  if (!defined('WP_UNINSTALL_PLUGIN')) {
7
+ die;
8
  }
9
 
10
+ // Delete known options
11
+ $option_names = array('cnb', 'cnb_cloud_migration_done');
12
 
13
+ foreach ($option_names as $option_name) {
14
+ // Delete the standard options
15
+ delete_option($option_name);
16
 
17
+ // Delete site options in Multisite
18
+ delete_site_option($option_name);
19
+ }
20
+
21
+ // Delete notice dismissals
22
+ $options_slug = 'call-now-button';
23
+
24
+ global $wpdb;
25
+ $wpdb->query(
26
+ $wpdb->prepare(
27
+ "DELETE FROM $wpdb->options
28
+ WHERE option_name
29
+ LIKE %s",
30
+ $options_slug.'_dismissed_%' )
31
+ );