Call Now Button - Version 1.1.4

Version Description

  • New phone icon on call button
  • Sunsetted the original (classic) corner button
  • Added Facebook Messenger, Telegram and Signal buttons (Premium)
  • New icons for link (calendar) and anchor (up arrow) buttons (Premium)
  • Anchor button now has smooth scroll (Premium)
  • Location button now has directions (Premium)
  • WhatsApp modal improvement (multiple speech bubbles, animated conversation and notification count) (Premium)
Download this release

Release Info

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

Code changes from version 1.1.3 to 1.1.4

Files changed (81) hide show
  1. call-now-button.php +2 -2
  2. readme.txt +21 -13
  3. resources/js/action-edit.js +1 -1
  4. resources/js/action-type-to-icon-text.js +3 -0
  5. resources/js/call-now-button.js +24 -5
  6. resources/js/preview.js +4 -2
  7. resources/style/call-now-button.css +40 -2
  8. resources/style/modern.css +135 -0
  9. src/CallNowButton.php +29 -29
  10. src/admin/CnbAdminAjax.php +21 -14
  11. src/admin/action/CnbAction.php +4 -4
  12. src/admin/action/CnbActionController.php +60 -23
  13. src/admin/action/CnbActionRouter.php +4 -2
  14. src/admin/action/CnbActionView.php +12 -6
  15. src/admin/action/CnbActionViewEdit.php +130 -75
  16. src/admin/action/Cnb_Action_List_Table.php +28 -17
  17. src/admin/api/CnbAdminCloud.php +8 -8
  18. src/admin/api/CnbAppRemote.php +12 -8
  19. src/admin/api/CnbAppRemotePayment.php +1 -1
  20. src/admin/api/CnbDeleteResult.php +9 -8
  21. src/admin/api/CnbGet.php +2 -2
  22. src/admin/api/CnbMigration.php +22 -17
  23. src/admin/api/RemoteTrace.php +1 -1
  24. src/admin/apikey/CnbApiKeyController.php +61 -25
  25. src/admin/apikey/CnbApiKeyView.php +6 -5
  26. src/admin/apikey/Cnb_Apikey_List_Table.php +13 -6
  27. src/admin/button/CnbButton.php +7 -6
  28. src/admin/button/CnbButtonController.php +57 -35
  29. src/admin/button/CnbButtonRouter.php +3 -1
  30. src/admin/button/CnbButtonView.php +18 -17
  31. src/admin/button/CnbButtonViewEdit.php +65 -71
  32. src/admin/button/Cnb_Button_List_Table.php +22 -15
  33. src/admin/condition/CnbCondition.php +1 -0
  34. src/admin/condition/CnbConditionController.php +67 -27
  35. src/admin/condition/CnbConditionRouter.php +3 -1
  36. src/admin/condition/CnbConditionView.php +14 -7
  37. src/admin/condition/CnbConditionViewEdit.php +11 -37
  38. src/admin/condition/Cnb_Condition_List_Table.php +44 -32
  39. src/admin/domain/CnbDomainController.php +78 -33
  40. src/admin/domain/CnbDomainRouter.php +5 -3
  41. src/admin/domain/CnbDomainView.php +12 -4
  42. src/admin/domain/CnbDomainViewEdit.php +23 -21
  43. src/admin/domain/CnbDomainViewUpgrade.php +2 -2
  44. src/admin/domain/Cnb_Domain_List_Table.php +13 -5
  45. src/admin/domain/partials/CnbDomainViewUpgradeFinished.php +6 -6
  46. src/admin/domain/partials/CnbDomainViewUpgradeOverview.php +66 -42
  47. src/admin/legacy/CnbLegacyController.php +1 -1
  48. src/admin/legacy/CnbLegacyEdit.php +75 -93
  49. src/admin/legacy/CnbLegacyUpgrade.php +9 -8
  50. src/admin/models/CnbActivation.php +3 -3
  51. src/admin/models/CnbPlan.php +6 -6
  52. src/admin/models/CnbUser.php +18 -17
  53. src/admin/partials/CnbFooter.php +18 -15
  54. src/admin/partials/CnbHeader.php +2 -2
  55. src/admin/partials/CnbHeaderNotices.php +80 -43
  56. src/admin/profile/CnbProfileController.php +241 -243
  57. src/admin/profile/CnbProfileEdit.php +9 -4
  58. src/admin/settings/CnbApiKeyActivatedView.php +41 -36
  59. src/admin/settings/CnbSettingsController.php +45 -44
  60. src/admin/settings/CnbSettingsRouter.php +3 -2
  61. src/admin/settings/CnbSettingsViewEdit.php +83 -92
  62. src/autoload.php +6 -0
  63. src/call-now-button.php +3 -1
  64. src/cli/mocks/WP_CLI_Utils.class.php +1 -1
  65. src/notices/CnbAdminNotices.php +14 -6
  66. src/renderers/class-renderer.php +21 -0
  67. src/renderers/class-rendererfactory.php +63 -0
  68. src/renderers/classic/wp_foot.php +0 -90
  69. src/renderers/classic/wp_head.php +0 -41
  70. src/renderers/cloud/class-cloudrenderer.php +89 -0
  71. src/renderers/cloud/wp_foot.php +0 -4
  72. src/renderers/cloud/wp_head.php +0 -18
  73. src/renderers/modern/class-modernrenderer.php +318 -0
  74. src/renderers/modern/wp_foot.php +0 -2
  75. src/renderers/modern/wp_head.php +0 -64
  76. src/renderers/noop/class-nooprenderer.php +28 -0
  77. src/renderers/{classic → noop}/index.php +0 -0
  78. src/renderers/render.php +0 -34
  79. src/utils/CnbAdminFunctions.php +54 -117
  80. src/utils/CnbUtils.php +82 -78
  81. src/utils/cnb-backwards-compatible.php +9 -9
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: 1.1.3
7
  Author: Jerry Rietveld
8
  Author URI: https://www.callnowbutton.com
9
  GitHub Plugin URI: https://github.com/callnowbutton/wp-plugin
@@ -26,7 +26,7 @@ License: GPL2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
- define('CNB_VERSION', '1.1.3');
30
  define('CNB_NAME', 'Call Now Button');
31
  define('CNB_BASENAME', plugin_basename(__FILE__));
32
  define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
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: 1.1.4
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', '1.1.4');
30
  define('CNB_NAME', 'Call Now Button');
31
  define('CNB_BASENAME', plugin_basename(__FILE__));
32
  define('CNB_BASEFOLDER', plugin_basename(dirname(__FILE__)));
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: https://callnowbutton.com/donate/
4
  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.9
8
- Stable tag: 1.1.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -107,27 +107,35 @@ Yes, you can upgrade to Premium to enable tons of extra features. Checkout [call
107
  1. 3 variations of the Call Now Button
108
  2. The basic settings
109
  3. The presentation settings
110
- 4. The advanced settings
111
 
112
 
113
  == Changelog ==
 
 
 
 
 
 
 
 
 
114
  = 1.1.3 =
115
- Bugfixes
116
 
117
  = 1.1.2 =
118
- Bugfixes
119
 
120
  = 1.1.1 =
121
- Fix for storing profile info
122
 
123
  = 1.1.0 =
124
-
125
- Full code refactor
126
- Conditions now in WordPress table (Premium)
127
- Warning notification when debug mode is active (Premium)
128
- Added upgrade success page
129
- Minor bug fixes
130
- Performance improvements
131
 
132
  = 1.0.8 =
133
  * WhatsApp chat modal (Premium)
4
  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: 6.0
8
+ Stable tag: 1.1.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
107
  1. 3 variations of the Call Now Button
108
  2. The basic settings
109
  3. The presentation settings
110
+ 4. The settings
111
 
112
 
113
  == Changelog ==
114
+ = 1.1.4 =
115
+ * New phone icon on call button
116
+ * Sunsetted the original (classic) corner button
117
+ * Added Facebook Messenger, Telegram and Signal buttons (Premium)
118
+ * New icons for link (calendar) and anchor (up arrow) buttons (Premium)
119
+ * Anchor button now has smooth scroll (Premium)
120
+ * Location button now has directions (Premium)
121
+ * WhatsApp modal improvement (multiple speech bubbles, animated conversation and notification count) (Premium)
122
+
123
  = 1.1.3 =
124
+ * Bugfixes
125
 
126
  = 1.1.2 =
127
+ * Bugfixes
128
 
129
  = 1.1.1 =
130
+ * Fix for storing profile info
131
 
132
  = 1.1.0 =
133
+ * Full code refactor
134
+ * Conditions now in WordPress table (Premium)
135
+ * Warning notification when debug mode is active (Premium)
136
+ * Added upgrade success page
137
+ * Minor bug fixes
138
+ * Performance improvements
 
139
 
140
  = 1.0.8 =
141
  * WhatsApp chat modal (Premium)
resources/js/action-edit.js CHANGED
@@ -1,7 +1,7 @@
1
  // If the modal is enabled, we need to clear and disable the "Default message"
2
 
3
  /**
4
- * This sets the various Whatsapp Modal fields to appear only when needed.
5
  *
6
  * When the
7
  */
1
  // If the modal is enabled, we need to clear and disable the "Default message"
2
 
3
  /**
4
+ * This sets the various WhatsApp Modal fields to appear only when needed.
5
  *
6
  * When the
7
  */
resources/js/action-type-to-icon-text.js CHANGED
@@ -17,6 +17,9 @@ function cnbActiontypeToIcontext(actionType) {
17
  case 'PHONE': return 'call'
18
  case 'SMS': return 'chat'
19
  case 'WHATSAPP': return 'whatsapp'
 
 
 
20
  default:
21
  return 'call'
22
  }
17
  case 'PHONE': return 'call'
18
  case 'SMS': return 'chat'
19
  case 'WHATSAPP': return 'whatsapp'
20
+ case 'FACEBOOK': return 'facebook_messenger'
21
+ case 'SIGNAL': return 'signal'
22
+ case 'TELEGRAM': return 'telegram'
23
  default:
24
  return 'call'
25
  }
resources/js/call-now-button.js CHANGED
@@ -197,6 +197,7 @@ function cnb_action_update_appearance(value) {
197
  const linkEle = jQuery('.cnb-action-properties-link');
198
  const emailExtraEle = jQuery('.cnb-action-properties-email-extra');
199
  const whatsappEle = jQuery('.cnb-action-properties-whatsapp');
 
200
  const whatsappExtraEle = jQuery('.cnb-action-properties-whatsapp-extra');
201
  const smsEle = jQuery('.cnb-action-properties-sms');
202
  const smsExtraEle = jQuery('.cnb-action-properties-sms-extra');
@@ -206,9 +207,12 @@ function cnb_action_update_appearance(value) {
206
  const valueTextEle = jQuery('#cnb_action_value_input');
207
  const valuelabelEle = jQuery('#cnb_action_value');
208
  const whatsappValueEle = jQuery('#cnb_action_value_input_whatsapp')
 
 
209
  emailEle.hide();
210
  emailExtraEle.hide();
211
  whatsappEle.hide();
 
212
  whatsappExtraEle.hide();
213
  smsEle.hide();
214
  smsExtraEle.hide();
@@ -232,9 +236,6 @@ function cnb_action_update_appearance(value) {
232
  valueTextEle.attr("required", "required");
233
  emailEle.show()
234
  break
235
- case 'HOURS':
236
- // Not implemented yet
237
- break;
238
  case 'LINK':
239
  valuelabelEle.text('Full URL');
240
  valueTextEle.attr("required", "required");
@@ -255,13 +256,28 @@ function cnb_action_update_appearance(value) {
255
  smsEle.show();
256
  break
257
  case 'WHATSAPP':
258
- valuelabelEle.text('Whatsapp number');
 
259
  valueEle.hide();
260
  valueTextEle.prop( 'disabled', true );
261
  whatsappValueEle.prop( 'disabled', false );
262
- whatsappEle.show();
263
  whatsappValueEle.attr("required", "required");
 
 
 
 
 
 
264
  break
 
 
 
 
 
 
 
 
 
265
  default:
266
  valuelabelEle.text('Action value');
267
  valueTextEle.attr("required", "required");
@@ -437,6 +453,9 @@ function cnb_switch_tab(tabName, addToHistory = true) {
437
  tab.addClass('nav-tab-active')
438
  tabContent.show();
439
 
 
 
 
440
  // Push this to URL
441
  if (addToHistory) {
442
  const url = new URL(window.location);
197
  const linkEle = jQuery('.cnb-action-properties-link');
198
  const emailExtraEle = jQuery('.cnb-action-properties-email-extra');
199
  const whatsappEle = jQuery('.cnb-action-properties-whatsapp');
200
+ const signalEle = jQuery('.cnb-action-properties-signal');
201
  const whatsappExtraEle = jQuery('.cnb-action-properties-whatsapp-extra');
202
  const smsEle = jQuery('.cnb-action-properties-sms');
203
  const smsExtraEle = jQuery('.cnb-action-properties-sms-extra');
207
  const valueTextEle = jQuery('#cnb_action_value_input');
208
  const valuelabelEle = jQuery('#cnb_action_value');
209
  const whatsappValueEle = jQuery('#cnb_action_value_input_whatsapp')
210
+ const intlInputLabel = jQuery('#cnb_action_value_input_intl_input')
211
+
212
  emailEle.hide();
213
  emailExtraEle.hide();
214
  whatsappEle.hide();
215
+ signalEle.hide();
216
  whatsappExtraEle.hide();
217
  smsEle.hide();
218
  smsExtraEle.hide();
236
  valueTextEle.attr("required", "required");
237
  emailEle.show()
238
  break
 
 
 
239
  case 'LINK':
240
  valuelabelEle.text('Full URL');
241
  valueTextEle.attr("required", "required");
256
  smsEle.show();
257
  break
258
  case 'WHATSAPP':
259
+ valuelabelEle.text('WhatsApp number');
260
+ intlInputLabel.text('WhatsApp number')
261
  valueEle.hide();
262
  valueTextEle.prop( 'disabled', true );
263
  whatsappValueEle.prop( 'disabled', false );
 
264
  whatsappValueEle.attr("required", "required");
265
+ whatsappEle.show();
266
+ break
267
+ case 'FACEBOOK':
268
+ case 'TELEGRAM':
269
+ valuelabelEle.text('Username');
270
+ valueTextEle.attr("required", "required");
271
  break
272
+ case 'SIGNAL':
273
+ valuelabelEle.text('Signal number');
274
+ intlInputLabel.text('Signal number')
275
+ valueEle.hide();
276
+ valueTextEle.prop( 'disabled', true );
277
+ whatsappValueEle.prop( 'disabled', false );
278
+ whatsappValueEle.attr("required", "required");
279
+ signalEle.show();
280
+ break;
281
  default:
282
  valuelabelEle.text('Action value');
283
  valueTextEle.attr("required", "required");
453
  tab.addClass('nav-tab-active')
454
  tabContent.show();
455
 
456
+ // If there is an element keeping track of the tab, update it
457
+ jQuery('input[name="tab"]').val(tabName)
458
+
459
  // Push this to URL
460
  if (addToHistory) {
461
  const url = new URL(window.location);
resources/js/preview.js CHANGED
@@ -168,9 +168,11 @@ function livePreview() {
168
  parsedData.domain = cnb_domain;
169
  }
170
 
171
- // Ensure WhatsApp works
172
  if (parsedData.action_id && parsedData.actions &&
173
- parsedData.actions[parsedData.action_id] && parsedData.actions[parsedData.action_id].actionType === 'WHATSAPP') {
 
 
174
  const input = document.querySelector('#cnb_action_value_input_whatsapp');
175
  const iti = window.intlTelInputGlobals.getInstance(input);
176
  parsedData.actions[parsedData.action_id].actionValue = iti.getNumber()
168
  parsedData.domain = cnb_domain;
169
  }
170
 
171
+ // Ensure WhatsApp/Signal works
172
  if (parsedData.action_id && parsedData.actions &&
173
+ parsedData.actions[parsedData.action_id] &&
174
+ (parsedData.actions[parsedData.action_id].actionType === 'WHATSAPP' ||
175
+ parsedData.actions[parsedData.action_id].actionType === 'SIGNAL')) {
176
  const input = document.querySelector('#cnb_action_value_input_whatsapp');
177
  const iti = window.intlTelInputGlobals.getInstance(input);
178
  parsedData.actions[parsedData.action_id].actionValue = iti.getNumber()
resources/style/call-now-button.css CHANGED
@@ -351,7 +351,10 @@ input[type='range'] {
351
  padding-bottom: 1em;
352
  }
353
  .cnb-price-plans .pricebox h3.yearly {
354
- border-bottom:2px solid #2271b1;
 
 
 
355
  }
356
  .cnb-price-plans .plan-amount {
357
  margin:20px 0;
@@ -617,6 +620,19 @@ input[type=checkbox].cnb_day_selector:checked + label.cnb_day_selector {
617
  padding: 0;
618
  line-height: 1;
619
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  .cnb-promobox .cnb-promobox-header {
621
  display: flex;
622
  align-items: center;
@@ -628,6 +644,22 @@ input[type=checkbox].cnb_day_selector:checked + label.cnb_day_selector {
628
  border: 1px solid #2371b1;
629
  color: #fff;
630
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
  .cnb-promobox .cnb-promobox-header .dashicons {
632
  margin-left: 12px;
633
  }
@@ -647,7 +679,13 @@ input[type=checkbox].cnb_day_selector:checked + label.cnb_day_selector {
647
  line-height: 1.4;
648
  }
649
  .cnb-promobox .cnb-promobox-header-blue h2,
650
- .cnb-promobox .cnb-promobox-header-blue h3 {
 
 
 
 
 
 
651
  color:#fff;
652
  }
653
  .cnb-one-column-section .cnb-promobox .inside,
351
  padding-bottom: 1em;
352
  }
353
  .cnb-price-plans .pricebox h3.yearly {
354
+ border-bottom:2px solid #71B123;
355
+ }
356
+ .cnb-price-plans .pricebox h3.monthly {
357
+ border-bottom:2px solid #B12371;
358
  }
359
  .cnb-price-plans .plan-amount {
360
  margin:20px 0;
620
  padding: 0;
621
  line-height: 1;
622
  }
623
+
624
+ .cnb-blue {
625
+ color:#2371b1;
626
+ }
627
+ .cnb-brown {
628
+ color:#B16323;
629
+ }
630
+ .cnb-purple {
631
+ color:#B12371;
632
+ }
633
+ .cnb-green {
634
+ color:#71B123;
635
+ }
636
  .cnb-promobox .cnb-promobox-header {
637
  display: flex;
638
  align-items: center;
644
  border: 1px solid #2371b1;
645
  color: #fff;
646
  }
647
+ .cnb-promobox .cnb-promobox-header-brown {
648
+ background-color: #B16323;
649
+ border: 1px solid #B16323;
650
+ color: #fff;
651
+ }
652
+ .cnb-promobox .cnb-promobox-header-purple {
653
+ background-color: #B12371;
654
+ border: 1px solid #B12371;
655
+ color: #fff;
656
+ }
657
+ .cnb-promobox .cnb-promobox-header-green {
658
+ background-color: #71B123;
659
+ border: 1px solid #71B123;
660
+ color: #fff;
661
+ }
662
+
663
  .cnb-promobox .cnb-promobox-header .dashicons {
664
  margin-left: 12px;
665
  }
679
  line-height: 1.4;
680
  }
681
  .cnb-promobox .cnb-promobox-header-blue h2,
682
+ .cnb-promobox .cnb-promobox-header-blue h3,
683
+ .cnb-promobox .cnb-promobox-header-purple h2,
684
+ .cnb-promobox .cnb-promobox-header-purple h3,
685
+ .cnb-promobox .cnb-promobox-header-brown h2,
686
+ .cnb-promobox .cnb-promobox-header-brown h3,
687
+ .cnb-promobox .cnb-promobox-header-green h2,
688
+ .cnb-promobox .cnb-promobox-header-green h3 {
689
  color:#fff;
690
  }
691
  .cnb-one-column-section .cnb-promobox .inside,
resources/style/modern.css ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #callnowbutton {
2
+ display: none;
3
+ }
4
+
5
+ @media screen and (max-width:650px) {
6
+
7
+ #callnowbutton {
8
+ display: block;
9
+ position: fixed;
10
+ text-decoration: none;
11
+ }
12
+
13
+ #callnowbutton.cnb-full {
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: center;
17
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
18
+ width: 100%;
19
+ left: 0;
20
+ height: 60px;
21
+ }
22
+
23
+ .cnb-full.cnb-full-bottom {
24
+ bottom: 0;
25
+ }
26
+
27
+ .cnb-full.cnb-full-top {
28
+ top: 0;
29
+ }
30
+
31
+ #callnowbutton.cnb-single {
32
+ width: 55px;
33
+ height: 55px;
34
+ border-radius: 50%;
35
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
36
+ }
37
+
38
+ .cnb-single.cnb-middle {
39
+ bottom: 15px;
40
+ left: 50%;
41
+ margin-left: -28px;
42
+ }
43
+
44
+ .cnb-single.cnb-left {
45
+ bottom: 15px;
46
+ left: 20px;
47
+ }
48
+
49
+ .cnb-single.cnb-right {
50
+ bottom: 15px;
51
+ right: 20px;
52
+ }
53
+
54
+ .cnb-single.cnb-mleft {
55
+ top: 50%;
56
+ margin-top: -28px;
57
+ left: 20px;
58
+ }
59
+
60
+ .cnb-single.cnb-mright {
61
+ top: 50%;
62
+ margin-top: -28px;
63
+ right: 20px;
64
+ }
65
+
66
+ .cnb-single.cnb-tleft {
67
+ top: 15px;
68
+ left: 20px;
69
+ }
70
+
71
+ .cnb-single.cnb-tmiddle {
72
+ top: 15px;
73
+ left: 50%;
74
+ margin-left: -28px;
75
+ }
76
+
77
+ .cnb-single.cnb-tright {
78
+ top: 15px;
79
+ right: 20px;
80
+ }
81
+
82
+ /* Don't show a label with top and bottom middle positions */
83
+ #callnowbutton.cnb-single.cnb-middle span,
84
+ #callnowbutton.cnb-single.cnb-tmiddle span {
85
+ display: none;
86
+ }
87
+
88
+ .cnb-single.cnb-left span,
89
+ .cnb-single.cnb-mleft span,
90
+ .cnb-single.cnb-tleft span {
91
+ left: 68px;
92
+ }
93
+
94
+ .cnb-single.cnb-right span,
95
+ .cnb-single.cnb-mright span,
96
+ .cnb-single.cnb-tright span {
97
+ right: 68px;
98
+ }
99
+
100
+ .cnb-single.cnb-text span {
101
+ -moz-osx-font-smoothing: grayscale;
102
+ -webkit-user-select: none;
103
+ -ms-user-select: none;
104
+ user-select: none;
105
+ display: block;
106
+ width: auto;
107
+ background-color: rgba(70,70,70,.9);
108
+ position: absolute;
109
+ border-radius: 2px;
110
+ font-family: helvetica,arial,sans-serif;
111
+ padding: 6px 8px;
112
+ font-size: 13px;
113
+ font-weight: 700;
114
+ color: #ECECEC;
115
+ top: 15px;
116
+ box-shadow: 0 1px 2px rgba(0,0,0,.15);
117
+ word-break: keep-all;
118
+ line-height: 1em;
119
+ text-overflow: ellipsis;
120
+ vertical-align: middle;
121
+ white-space: nowrap;
122
+ }
123
+ .cnb-single:not(.cnb-text) span {
124
+ display: none;
125
+ }
126
+
127
+ .cnb-full.cnb-text {
128
+ text-align: center;
129
+ color: #FFF;
130
+ font-weight: 600;
131
+ font-size: 120%;
132
+ overflow: hidden;
133
+ white-space: nowrap;
134
+ }
135
+ }
src/CallNowButton.php CHANGED
@@ -19,10 +19,10 @@ class CallNowButton {
19
  public static function register_admin_pages() {
20
  global $wp_version;
21
 
22
- $cnb_options = get_option('cnb');
23
- $utils = new CnbUtils();
24
- $cnb_cloud_hosting = $utils->isCloudActive($cnb_options);
25
- $plugin_title = apply_filters( 'cnb_plugin_title', CNB_NAME );
26
 
27
  $menu_page_function = $cnb_cloud_hosting ?
28
  array( 'cnb\admin\button\CnbButtonRouter', 'render' ) :
@@ -32,12 +32,6 @@ class CallNowButton {
32
  $menu_page_title = 'Call Now Button<span class="awaiting-mod" id="cnb-nav-counter" style="display: none">' . $counter . '</span>';
33
  $menu_page_position = $cnb_cloud_hosting ? 30 : 66;
34
 
35
- $adminFunctions = new CnbAdminFunctions();
36
- $has_changelog = $adminFunctions->has_changelog();
37
- if ( $has_changelog ) {
38
- $counter ++;
39
- }
40
-
41
  $legacyController = new CnbLegacyController();
42
  $has_welcome_banner = $legacyController->show_welcome_banner() && ! $cnb_cloud_hosting;
43
  if ( $has_welcome_banner ) {
@@ -57,7 +51,7 @@ class CallNowButton {
57
  $icon_url = version_compare( $wp_version, '5.5.0', '<' ) ? 'dashicons-smartphone' : 'dashicons-phone';
58
 
59
  add_menu_page(
60
- __( 'Call Now Button - Overview', CNB_NAME ),
61
  $menu_page_title,
62
  'manage_options',
63
  CNB_SLUG,
@@ -110,21 +104,21 @@ class CallNowButton {
110
  ) );
111
  } else {
112
  // Fake out Action overview
113
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'call-now-button-actions' && $_GET['action'] ) {
114
  add_submenu_page( CNB_SLUG, $plugin_title, 'Edit action', 'manage_options', CNB_SLUG . '-actions', array(
115
  'cnb\admin\action\CnbActionRouter',
116
  'render'
117
  ) );
118
  }
119
  // Fake out Conditions overview
120
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'call-now-button-conditions' && $_GET['action'] ) {
121
  add_submenu_page( CNB_SLUG, $plugin_title, 'Edit condition', 'manage_options', CNB_SLUG . '-conditions', array(
122
  'cnb\admin\condition\CnbConditionRouter',
123
  'render'
124
  ) );
125
  }
126
  // Fake out Domain upgrade page
127
- if ( isset( $_GET['page'] ) && $_GET['page'] === 'call-now-button-domains' && $_GET['action'] === 'upgrade' ) {
128
  add_submenu_page( CNB_SLUG, $plugin_title, 'Upgrade domain', 'manage_options', CNB_SLUG . '-domains', array(
129
  'cnb\admin\domain\CnbDomainRouter',
130
  'render'
@@ -152,8 +146,8 @@ class CallNowButton {
152
  }
153
 
154
  public static function plugin_meta( $links, $file ) {
155
- $cnb_options = get_option('cnb');
156
- $cnb_cloud_hosting = (new CnbUtils())->isCloudActive($cnb_options);
157
 
158
  if ( $file == CNB_BASENAME ) {
159
 
@@ -193,8 +187,8 @@ class CallNowButton {
193
  }
194
 
195
  public static function plugin_add_action_link( $links ) {
196
- $cnb_options = get_option('cnb');
197
- $cnb_cloud_hosting = (new CnbUtils())->isCloudActive($cnb_options);
198
 
199
  $link_name = $cnb_cloud_hosting ? 'All buttons' : 'My button';
200
  $url = admin_url( 'admin.php' );
@@ -205,7 +199,7 @@ class CallNowButton {
205
  ),
206
  $url );
207
  $button_url = esc_url( $button_link );
208
- $button = sprintf( '<a href="%s">%s</a>', $button_url, __( $link_name ) );
209
  array_unshift( $links, $button );
210
 
211
  if ( ! $cnb_cloud_hosting ) {
@@ -217,7 +211,7 @@ class CallNowButton {
217
  ),
218
  $url );
219
  $upgrade_url = esc_url( $upgrade_link );
220
- $upgrade = sprintf( '<a style="font-weight: bold;" href="%s">%s</a>', $upgrade_url, __( $link_name ) );
221
  array_unshift( $links, $upgrade );
222
  }
223
 
@@ -238,7 +232,7 @@ class CallNowButton {
238
  }
239
 
240
  public static function unregister_options() {
241
- unregister_setting('cnb_options', 'cnb');
242
  }
243
 
244
  public static function register_styles_and_scripts() {
@@ -455,13 +449,19 @@ class CallNowButton {
455
  }
456
 
457
  public static function registerAjax() {
458
- add_action( 'wp_ajax_cnb_time_format', array('cnb\admin\CnbAdminAjax', 'time_format') );
459
- add_action( 'wp_ajax_cnb_settings_profile_save', array('cnb\admin\CnbAdminAjax', 'settings_profile_save') );
460
- add_action( 'wp_ajax_cnb_delete_action', array('cnb\admin\action\CnbActionController', 'delete_ajax') );
461
- add_action( 'wp_ajax_cnb_delete_condition', array('cnb\admin\condition\CnbConditionController', 'delete_ajax') );
462
- add_action( 'wp_ajax_cnb_get_checkout', array('cnb\admin\CnbAdminAjax', 'domain_upgrade_get_checkout') );
463
- add_action( 'wp_ajax_cnb_email_activation', array('cnb\admin\CnbAdminAjax', 'cnb_email_activation') );
464
- add_action( 'wp_ajax_cnb_domain_timezone_change', array('cnb\admin\domain\CnbDomainController', 'updateTimezone') );
465
- add_action( 'wp_ajax_cnb_get_plans', array('cnb\admin\CnbAdminAjax', 'get_plans') );
 
 
 
 
 
 
466
  }
467
  }
19
  public static function register_admin_pages() {
20
  global $wp_version;
21
 
22
+ $cnb_options = get_option( 'cnb' );
23
+ $utils = new CnbUtils();
24
+ $cnb_cloud_hosting = $utils->isCloudActive( $cnb_options );
25
+ $plugin_title = apply_filters( 'cnb_plugin_title', CNB_NAME );
26
 
27
  $menu_page_function = $cnb_cloud_hosting ?
28
  array( 'cnb\admin\button\CnbButtonRouter', 'render' ) :
32
  $menu_page_title = 'Call Now Button<span class="awaiting-mod" id="cnb-nav-counter" style="display: none">' . $counter . '</span>';
33
  $menu_page_position = $cnb_cloud_hosting ? 30 : 66;
34
 
 
 
 
 
 
 
35
  $legacyController = new CnbLegacyController();
36
  $has_welcome_banner = $legacyController->show_welcome_banner() && ! $cnb_cloud_hosting;
37
  if ( $has_welcome_banner ) {
51
  $icon_url = version_compare( $wp_version, '5.5.0', '<' ) ? 'dashicons-smartphone' : 'dashicons-phone';
52
 
53
  add_menu_page(
54
+ 'Call Now Button - Overview',
55
  $menu_page_title,
56
  'manage_options',
57
  CNB_SLUG,
104
  ) );
105
  } else {
106
  // Fake out Action overview
107
+ if ( $utils->get_query_val( 'page' ) === 'call-now-button-actions' && $utils->get_query_val( 'action' ) ) {
108
  add_submenu_page( CNB_SLUG, $plugin_title, 'Edit action', 'manage_options', CNB_SLUG . '-actions', array(
109
  'cnb\admin\action\CnbActionRouter',
110
  'render'
111
  ) );
112
  }
113
  // Fake out Conditions overview
114
+ if ( $utils->get_query_val( 'page' ) === 'call-now-button-conditions' && $utils->get_query_val( 'action' ) ) {
115
  add_submenu_page( CNB_SLUG, $plugin_title, 'Edit condition', 'manage_options', CNB_SLUG . '-conditions', array(
116
  'cnb\admin\condition\CnbConditionRouter',
117
  'render'
118
  ) );
119
  }
120
  // Fake out Domain upgrade page
121
+ if ( $utils->get_query_val( 'page' ) === 'call-now-button-domains' && $utils->get_query_val( 'action' ) === 'upgrade' ) {
122
  add_submenu_page( CNB_SLUG, $plugin_title, 'Upgrade domain', 'manage_options', CNB_SLUG . '-domains', array(
123
  'cnb\admin\domain\CnbDomainRouter',
124
  'render'
146
  }
147
 
148
  public static function plugin_meta( $links, $file ) {
149
+ $cnb_options = get_option( 'cnb' );
150
+ $cnb_cloud_hosting = ( new CnbUtils() )->isCloudActive( $cnb_options );
151
 
152
  if ( $file == CNB_BASENAME ) {
153
 
187
  }
188
 
189
  public static function plugin_add_action_link( $links ) {
190
+ $cnb_options = get_option( 'cnb' );
191
+ $cnb_cloud_hosting = ( new CnbUtils() )->isCloudActive( $cnb_options );
192
 
193
  $link_name = $cnb_cloud_hosting ? 'All buttons' : 'My button';
194
  $url = admin_url( 'admin.php' );
199
  ),
200
  $url );
201
  $button_url = esc_url( $button_link );
202
+ $button = sprintf( '<a href="%s">%s</a>', $button_url, $link_name );
203
  array_unshift( $links, $button );
204
 
205
  if ( ! $cnb_cloud_hosting ) {
211
  ),
212
  $url );
213
  $upgrade_url = esc_url( $upgrade_link );
214
+ $upgrade = sprintf( '<a style="font-weight: bold;" href="%s">%s</a>', $upgrade_url, $link_name );
215
  array_unshift( $links, $upgrade );
216
  }
217
 
232
  }
233
 
234
  public static function unregister_options() {
235
+ unregister_setting( 'cnb_options', 'cnb' );
236
  }
237
 
238
  public static function register_styles_and_scripts() {
449
  }
450
 
451
  public static function registerAjax() {
452
+ add_action( 'wp_ajax_cnb_time_format', array( 'cnb\admin\CnbAdminAjax', 'time_format' ) );
453
+ add_action( 'wp_ajax_cnb_settings_profile_save', array( 'cnb\admin\CnbAdminAjax', 'settings_profile_save' ) );
454
+ add_action( 'wp_ajax_cnb_delete_action', array( 'cnb\admin\action\CnbActionController', 'delete_ajax' ) );
455
+ add_action( 'wp_ajax_cnb_delete_condition', array(
456
+ 'cnb\admin\condition\CnbConditionController',
457
+ 'delete_ajax'
458
+ ) );
459
+ add_action( 'wp_ajax_cnb_get_checkout', array( 'cnb\admin\CnbAdminAjax', 'domain_upgrade_get_checkout' ) );
460
+ add_action( 'wp_ajax_cnb_email_activation', array( 'cnb\admin\CnbAdminAjax', 'cnb_email_activation' ) );
461
+ add_action( 'wp_ajax_cnb_domain_timezone_change', array(
462
+ 'cnb\admin\domain\CnbDomainController',
463
+ 'updateTimezone'
464
+ ) );
465
+ add_action( 'wp_ajax_cnb_get_plans', array( 'cnb\admin\CnbAdminAjax', 'get_plans' ) );
466
  }
467
  }
src/admin/CnbAdminAjax.php CHANGED
@@ -65,13 +65,20 @@ class CnbAdminAjax {
65
  wp_die();
66
  }
67
 
 
 
 
 
68
  public static function settings_profile_save() {
69
  $data = array();
70
- wp_parse_str( $_REQUEST['data'], $data );
 
 
 
71
  $controller = new CnbProfileController();
72
- $nonce = filter_var($data['_wpnonce'], FILTER_SANITIZE_STRING);
73
- $profile = filter_var($data['user'], FILTER_SANITIZE_STRING,
74
- FILTER_REQUIRE_ARRAY | FILTER_FLAG_NO_ENCODE_QUOTES);
75
  $user = CnbUser::fromObject( $profile );
76
 
77
  $result = $controller->update_user( $nonce, $user );
@@ -111,22 +118,22 @@ class CnbAdminAjax {
111
  }
112
 
113
  public static function get_plans() {
114
- $plans = CnbAppRemotePayment::cnb_remote_get_plans();
115
- $eur_yearly_plan = array_filter($plans, function($plan) {
116
  return $plan->nickname === 'powered-by-eur-yearly';
117
- });
118
- $eur_yearly_plan = array_pop($eur_yearly_plan);
119
- $eur_yearly_per_month = round($eur_yearly_plan->price / 12.0, 2);
120
 
121
- $usd_yearly_plan = array_filter($plans, function($plan) {
122
  return $plan->nickname === 'powered-by-usd-yearly';
123
- });
124
- $usd_yearly_plan = array_pop($usd_yearly_plan);
125
- $usd_yearly_per_month = round($usd_yearly_plan->price / 12.0, 2);
126
 
127
  wp_send_json( array(
128
  'eur_per_month' => $eur_yearly_per_month,
129
  'usd_per_month' => $usd_yearly_per_month,
130
- ));
131
  }
132
  }
65
  wp_die();
66
  }
67
 
68
+ /**
69
+ * called via jQuery.post
70
+ * @return void
71
+ */
72
  public static function settings_profile_save() {
73
  $data = array();
74
+ // Security note: the nonce will be checked via update_user (below),
75
+ // and we sanitize the data via filter_var below
76
+ // phpcs:ignore WordPress.Security
77
+ wp_parse_str( $_POST['data'], $data );
78
  $controller = new CnbProfileController();
79
+ $nonce = filter_var( $data['_wpnonce'], FILTER_SANITIZE_STRING );
80
+ $profile = filter_var( $data['user'], FILTER_SANITIZE_STRING,
81
+ FILTER_REQUIRE_ARRAY | FILTER_FLAG_NO_ENCODE_QUOTES );
82
  $user = CnbUser::fromObject( $profile );
83
 
84
  $result = $controller->update_user( $nonce, $user );
118
  }
119
 
120
  public static function get_plans() {
121
+ $plans = CnbAppRemotePayment::cnb_remote_get_plans();
122
+ $eur_yearly_plan = array_filter( $plans, function ( $plan ) {
123
  return $plan->nickname === 'powered-by-eur-yearly';
124
+ } );
125
+ $eur_yearly_plan = array_pop( $eur_yearly_plan );
126
+ $eur_yearly_per_month = round( $eur_yearly_plan->price / 12.0, 2 );
127
 
128
+ $usd_yearly_plan = array_filter( $plans, function ( $plan ) {
129
  return $plan->nickname === 'powered-by-usd-yearly';
130
+ } );
131
+ $usd_yearly_plan = array_pop( $usd_yearly_plan );
132
+ $usd_yearly_per_month = round( $usd_yearly_plan->price / 12.0, 2 );
133
 
134
  wp_send_json( array(
135
  'eur_per_month' => $eur_yearly_per_month,
136
  'usd_per_month' => $usd_yearly_per_month,
137
+ ) );
138
  }
139
  }
src/admin/action/CnbAction.php CHANGED
@@ -99,7 +99,7 @@ class CnbAction implements JsonSerializable {
99
  $action->schedule->outsideHours = CnbUtils::getPropertyOrNull( $schedule, 'outsideHours' );
100
  $daysOfWeek = CnbUtils::getPropertyOrNull( $schedule, 'daysOfWeek' );
101
  if ( isset( $daysOfWeek ) && is_array( $daysOfWeek ) ) {
102
- $action->schedule->daysOfWeek = (new CnbAdminFunctions())->cnb_create_days_of_week_array( $daysOfWeek );
103
  }
104
 
105
  $action->id = CnbUtils::getPropertyOrNull( $object, 'id' );
@@ -110,7 +110,7 @@ class CnbAction implements JsonSerializable {
110
  if ( $iconEnabled === null ) {
111
  $iconEnabled = true;
112
  }
113
- // phpcs:ignore
114
  $action->iconEnabled = boolval( $iconEnabled );
115
  $action->iconClass = CnbUtils::getPropertyOrNull( $object, 'iconClass' );
116
  $action->iconColor = CnbUtils::getPropertyOrNull( $object, 'iconColor' );
@@ -124,13 +124,13 @@ class CnbAction implements JsonSerializable {
124
  // Special cases
125
  // "Fix" the WHATSAPP values
126
  $actionValueWhatsappHidden = CnbUtils::getPropertyOrNull( $object, 'actionValueWhatsappHidden' );
127
- if ( $action->actionType === 'WHATSAPP' && ! empty( $actionValueWhatsappHidden ) ) {
128
  $action->actionValue = $actionValueWhatsappHidden;
129
  }
130
 
131
  // Reset the iconText based on type if the iconText is left empty
132
  if ( isset( $action->iconText ) && empty( $action->iconText ) ) {
133
- $action->iconText = (new CnbUtils())->cnb_actiontype_to_icontext( $action->actionType );
134
  }
135
 
136
  return $action;
99
  $action->schedule->outsideHours = CnbUtils::getPropertyOrNull( $schedule, 'outsideHours' );
100
  $daysOfWeek = CnbUtils::getPropertyOrNull( $schedule, 'daysOfWeek' );
101
  if ( isset( $daysOfWeek ) && is_array( $daysOfWeek ) ) {
102
+ $action->schedule->daysOfWeek = ( new CnbAdminFunctions() )->cnb_create_days_of_week_array( $daysOfWeek );
103
  }
104
 
105
  $action->id = CnbUtils::getPropertyOrNull( $object, 'id' );
110
  if ( $iconEnabled === null ) {
111
  $iconEnabled = true;
112
  }
113
+ // phpcs:ignore PHPCompatibility.FunctionUse
114
  $action->iconEnabled = boolval( $iconEnabled );
115
  $action->iconClass = CnbUtils::getPropertyOrNull( $object, 'iconClass' );
116
  $action->iconColor = CnbUtils::getPropertyOrNull( $object, 'iconColor' );
124
  // Special cases
125
  // "Fix" the WHATSAPP values
126
  $actionValueWhatsappHidden = CnbUtils::getPropertyOrNull( $object, 'actionValueWhatsappHidden' );
127
+ if ( ( $action->actionType === 'WHATSAPP' || $action->actionType === 'SIGNAL' ) && ! empty( $actionValueWhatsappHidden ) ) {
128
  $action->actionValue = $actionValueWhatsappHidden;
129
  }
130
 
131
  // Reset the iconText based on type if the iconText is left empty
132
  if ( isset( $action->iconText ) && empty( $action->iconText ) ) {
133
+ $action->iconText = ( new CnbUtils() )->cnb_actiontype_to_icontext( $action->actionType );
134
  }
135
 
136
  return $action;
src/admin/action/CnbActionController.php CHANGED
@@ -23,7 +23,7 @@ class CnbActionController {
23
  * @return CnbAction|WP_Error|null
24
  */
25
  function deleteWithId( $action_id, &$cnb_cloud_notifications = array() ) {
26
- if ( (new CnbUtils())->cnb_check_ajax_referer( 'cnb_delete_action' ) ) {
27
  $action = new CnbAction();
28
  $action->id = $action_id;
29
 
@@ -33,10 +33,16 @@ class CnbActionController {
33
  return null;
34
  }
35
 
 
 
 
 
 
36
  public static function delete_ajax() {
 
37
  // Action ID
38
- $action_id = ! empty( $_REQUEST['id'] ) ? sanitize_text_field( $_REQUEST['id'] ) : null;
39
- $button_id = ! empty( $_REQUEST['bid'] ) ? sanitize_text_field( $_REQUEST['bid'] ) : null;
40
 
41
  $controller = new CnbActionController();
42
  $result = $controller->deleteWithId( $action_id );
@@ -49,21 +55,30 @@ class CnbActionController {
49
  wp_send_json( $return );
50
  }
51
 
 
 
 
 
 
 
 
52
  function delete() {
53
- $id = ! empty( $_REQUEST['id'] ) ? sanitize_text_field( $_REQUEST['id'] ) : null;
54
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
55
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
 
56
  $action = 'cnb_delete_action';
57
  $nonce_verified = wp_verify_nonce( $nonce, $action );
58
 
59
  if ( $nonce_verified ) {
60
  $cnb_cloud_notifications = array();
61
  $action = new CnbAction();
 
62
  $action->id = $id;
63
  CnbAdminCloud::cnb_delete_action( $cnb_cloud_notifications, $action );
64
 
65
  if ( ! $bid ) {
66
- CnbAdminNotices::get_instance()->renderNotices( $cnb_cloud_notifications );
67
  } else {
68
  // Create link
69
  $url = admin_url( 'admin.php' );
@@ -80,7 +95,7 @@ class CnbActionController {
80
  $message = '<p>You will be redirected back to the Button overview in 1 second...</p>';
81
  $message .= '<p>Or click here to go back immediately: <a href="' . $new_url . '">' . $new_url . '</a></p>';
82
  $message .= '<script type="text/javascript">setTimeout(function(){location.href="' . $new_url . '"} , 1000); </script>';
83
- CnbAdminNotices::get_instance()->renderSuccess( $message );
84
  }
85
  }
86
  }
@@ -94,6 +109,7 @@ class CnbActionController {
94
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
95
  $action = 'cnb-action-edit';
96
  $nonce_verified = wp_verify_nonce( $nonce, $action );
 
97
  if ( $nonce_verified ) {
98
  $actions = filter_input(
99
  INPUT_POST,
@@ -116,8 +132,8 @@ class CnbActionController {
116
 
117
  CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button );
118
  } else {
119
- $message = CnbAdminCloud::cnb_admin_get_error_message( 'create', 'action', $button );
120
- array_push( $cnb_cloud_notifications, $message );
121
  }
122
  }
123
 
@@ -126,7 +142,7 @@ class CnbActionController {
126
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
127
 
128
  // Create link
129
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
130
  $url = admin_url( 'admin.php' );
131
 
132
  if ( ! empty( $bid ) ) {
@@ -162,10 +178,9 @@ class CnbActionController {
162
  'page' => CNB_SLUG
163
  ),
164
  $url );
165
- $redirect_url = esc_url_raw( $redirect_link );
166
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
167
  'response' => 403,
168
- 'back_link' => $redirect_url,
169
  ) );
170
  }
171
  }
@@ -174,6 +189,7 @@ class CnbActionController {
174
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
175
  $action = 'cnb-action-edit';
176
  $nonce_verified = wp_verify_nonce( $nonce, $action );
 
177
  if ( $nonce_verified ) {
178
  // sanitize the input
179
  $actions = filter_input(
@@ -195,7 +211,7 @@ class CnbActionController {
195
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
196
 
197
  // Create link
198
- $bid = ! empty( $_GET["bid"] ) ? sanitize_text_field( $_GET["bid"] ) : null;
199
  $url = admin_url( 'admin.php' );
200
  if ( ! empty( $bid ) ) {
201
  $redirect_link =
@@ -231,9 +247,9 @@ class CnbActionController {
231
  ),
232
  $url );
233
 
234
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
235
  'response' => 403,
236
- 'back_link' => $back_link,
237
  ) );
238
  }
239
  }
@@ -241,19 +257,26 @@ class CnbActionController {
241
  /**
242
  * This is very similar to the <code>delete()</code> function above.
243
  *
 
 
 
244
  * Big differences are:
245
  * - This handles multiple IDs, versus 1
246
  * - Instead of rendering the Notice, is it stored and the user redirected
247
  *
 
 
 
248
  * @return void
249
  */
250
  public static function handle_bulk_actions() {
251
- $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
 
252
  $action = 'bulk-cnb_list_actions';
253
  $nonce_verified = wp_verify_nonce( $nonce, $action );
254
  if ( $nonce_verified ) {
255
  $actionIds = filter_input( INPUT_POST, 'cnb_list_action', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
256
- if ( $_REQUEST['bulk-action'] === 'delete' ) {
257
  $cnb_cloud_notifications = array();
258
  foreach ( $actionIds as $actionId ) {
259
  $cnbAction = new CnbAction();
@@ -276,12 +299,26 @@ class CnbActionController {
276
  $url );
277
  $redirect_url = esc_url_raw( $redirect_link );
278
  wp_safe_redirect( $redirect_url );
 
 
 
 
 
 
 
 
 
 
279
  }
280
  } else {
281
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
282
- 'response' => 403,
283
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
284
- ) );
 
 
 
 
285
  }
286
  }
287
  }
23
  * @return CnbAction|WP_Error|null
24
  */
25
  function deleteWithId( $action_id, &$cnb_cloud_notifications = array() ) {
26
+ if ( ( new CnbUtils() )->cnb_check_ajax_referer( 'cnb_delete_action' ) ) {
27
  $action = new CnbAction();
28
  $action->id = $action_id;
29
 
33
  return null;
34
  }
35
 
36
+ /**
37
+ * The caller should call this via `jQuery.post(ajaxurl, data)`
38
+ *
39
+ * @return void
40
+ */
41
  public static function delete_ajax() {
42
+ $cnb_utils = new CnbUtils();
43
  // Action ID
44
+ $action_id = $cnb_utils->get_post_val( 'id', null );
45
+ $button_id = $cnb_utils->get_post_val( 'bid', null );
46
 
47
  $controller = new CnbActionController();
48
  $result = $controller->deleteWithId( $action_id );
55
  wp_send_json( $return );
56
  }
57
 
58
+ /**
59
+ * This is the quick action where they can delete a single Action
60
+ *
61
+ * It is always called via/with $_GET parameters
62
+ *
63
+ * @return void
64
+ */
65
  function delete() {
66
+ $cnb_utils = new CnbUtils();
67
+ $id = $cnb_utils->get_query_val( 'id', null );
68
+ $bid = $cnb_utils->get_query_val( 'bid', null );
69
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
70
  $action = 'cnb_delete_action';
71
  $nonce_verified = wp_verify_nonce( $nonce, $action );
72
 
73
  if ( $nonce_verified ) {
74
  $cnb_cloud_notifications = array();
75
  $action = new CnbAction();
76
+ $adminNotices = CnbAdminNotices::get_instance();
77
  $action->id = $id;
78
  CnbAdminCloud::cnb_delete_action( $cnb_cloud_notifications, $action );
79
 
80
  if ( ! $bid ) {
81
+ $adminNotices->notices( $cnb_cloud_notifications );
82
  } else {
83
  // Create link
84
  $url = admin_url( 'admin.php' );
95
  $message = '<p>You will be redirected back to the Button overview in 1 second...</p>';
96
  $message .= '<p>Or click here to go back immediately: <a href="' . $new_url . '">' . $new_url . '</a></p>';
97
  $message .= '<script type="text/javascript">setTimeout(function(){location.href="' . $new_url . '"} , 1000); </script>';
98
+ $adminNotices->renderSuccess( $message );
99
  }
100
  }
101
  }
109
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
110
  $action = 'cnb-action-edit';
111
  $nonce_verified = wp_verify_nonce( $nonce, $action );
112
+ $cbn_utils = new CnbUtils();
113
  if ( $nonce_verified ) {
114
  $actions = filter_input(
115
  INPUT_POST,
132
 
133
  CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button );
134
  } else {
135
+ $message = CnbAdminCloud::cnb_admin_get_error_message( 'create', 'action', $button );
136
+ $cnb_cloud_notifications[] = $message;
137
  }
138
  }
139
 
142
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
143
 
144
  // Create link
145
+ $bid = $cbn_utils->get_query_val( 'bid', null );
146
  $url = admin_url( 'admin.php' );
147
 
148
  if ( ! empty( $bid ) ) {
178
  'page' => CNB_SLUG
179
  ),
180
  $url );
181
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
 
182
  'response' => 403,
183
+ 'back_link' => true,
184
  ) );
185
  }
186
  }
189
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
190
  $action = 'cnb-action-edit';
191
  $nonce_verified = wp_verify_nonce( $nonce, $action );
192
+ $cnb_utils = new CnbUtils();
193
  if ( $nonce_verified ) {
194
  // sanitize the input
195
  $actions = filter_input(
211
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
212
 
213
  // Create link
214
+ $bid = $cnb_utils->get_query_val( 'bid', null );
215
  $url = admin_url( 'admin.php' );
216
  if ( ! empty( $bid ) ) {
217
  $redirect_link =
247
  ),
248
  $url );
249
 
250
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
251
  'response' => 403,
252
+ 'back_link' => true,
253
  ) );
254
  }
255
  }
257
  /**
258
  * This is very similar to the <code>delete()</code> function above.
259
  *
260
+ * This always has to come via a $_POST request (specifically, via admin-post.php),
261
+ * so this should end in a redirect (or an error via wp_die)
262
+ *
263
  * Big differences are:
264
  * - This handles multiple IDs, versus 1
265
  * - Instead of rendering the Notice, is it stored and the user redirected
266
  *
267
+ * nonce name via WP_List_Table = bulk-{plural}
268
+ * so in this case: bulk-cnb_list_actions
269
+ *
270
  * @return void
271
  */
272
  public static function handle_bulk_actions() {
273
+ $cnb_utils = new CnbUtils();
274
+ $nonce = $cnb_utils->get_post_val( '_wpnonce' );
275
  $action = 'bulk-cnb_list_actions';
276
  $nonce_verified = wp_verify_nonce( $nonce, $action );
277
  if ( $nonce_verified ) {
278
  $actionIds = filter_input( INPUT_POST, 'cnb_list_action', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
279
+ if ( $cnb_utils->get_post_val( 'bulk-action' ) === 'delete' ) {
280
  $cnb_cloud_notifications = array();
281
  foreach ( $actionIds as $actionId ) {
282
  $cnbAction = new CnbAction();
299
  $url );
300
  $redirect_url = esc_url_raw( $redirect_link );
301
  wp_safe_redirect( $redirect_url );
302
+ } else {
303
+ wp_die(
304
+ esc_html__( 'Unknown Bulk action specified' ),
305
+ esc_html__( 'Cannot process Bulk action' ),
306
+ array(
307
+ 'response' => 403,
308
+ 'link_text' => esc_html( 'Go back to the Actions overview' ),
309
+ 'link_url' => esc_url_raw( admin_url( 'admin.php' ) . '?page=' . CNB_SLUG . '-actions' ),
310
+ )
311
+ );
312
  }
313
  } else {
314
+ wp_die(
315
+ esc_html__( 'Invalid nonce specified' ),
316
+ esc_html__( 'Error' ),
317
+ array(
318
+ 'response' => 403,
319
+ 'back_link' => true,
320
+ )
321
+ );
322
  }
323
  }
324
  }
src/admin/action/CnbActionRouter.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace cnb\admin\action;
4
 
5
  // don't load directly
 
 
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  class CnbActionRouter {
@@ -12,13 +14,13 @@ class CnbActionRouter {
12
  * @return void
13
  */
14
  public static function render() {
15
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
16
  switch ( $action ) {
17
  case 'new':
18
  case 'edit':
19
  ( new CnbActionViewEdit() )->render();
20
  break;
21
- // This is the quick action where they can delete a single Condidion
22
  case 'delete':
23
  ( new CnbActionController() )->delete();
24
  ( new CnbActionView() )->render();
3
  namespace cnb\admin\action;
4
 
5
  // don't load directly
6
+ use cnb\utils\CnbUtils;
7
+
8
  defined( 'ABSPATH' ) || die( '-1' );
9
 
10
  class CnbActionRouter {
14
  * @return void
15
  */
16
  public static function render() {
17
+ $action = ( new CnbUtils() )->get_query_val( 'action', null );
18
  switch ( $action ) {
19
  case 'new':
20
  case 'edit':
21
  ( new CnbActionViewEdit() )->render();
22
  break;
23
+ // This is the quick action where they can delete a single Action
24
  case 'delete':
25
  ( new CnbActionController() )->delete();
26
  ( new CnbActionView() )->render();
src/admin/action/CnbActionView.php CHANGED
@@ -8,9 +8,16 @@ defined( 'ABSPATH' ) || die( '-1' );
8
  use cnb\admin\api\CnbAppRemote;
9
  use cnb\admin\button\CnbButton;
10
  use cnb\notices\CnbAdminNotices;
 
11
  use WP_Error;
12
 
13
  class CnbActionView {
 
 
 
 
 
 
14
  function header() {
15
  echo 'Actions ';
16
  }
@@ -21,9 +28,9 @@ class CnbActionView {
21
  * @return void
22
  */
23
  function add_modal() {
24
- $id = ! empty( $_GET['id'] ) ? sanitize_text_field( $_GET['id'] ) : null;
25
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
26
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
27
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
28
  // Create link
29
  $url = admin_url( 'admin.php' );
@@ -36,9 +43,8 @@ class CnbActionView {
36
  'bid' => $bid
37
  ),
38
  $url );
39
- $new_url = esc_url( $new_link );
40
 
41
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
42
  }
43
  }
44
 
@@ -46,7 +52,7 @@ class CnbActionView {
46
  * @return CnbButton|null
47
  */
48
  function get_button() {
49
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
50
  if ( $bid !== null ) {
51
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
52
 
8
  use cnb\admin\api\CnbAppRemote;
9
  use cnb\admin\button\CnbButton;
10
  use cnb\notices\CnbAdminNotices;
11
+ use cnb\utils\CnbUtils;
12
  use WP_Error;
13
 
14
  class CnbActionView {
15
+ private $cnb_utils;
16
+
17
+ public function __construct() {
18
+ $this->cnb_utils = new CnbUtils();
19
+ }
20
+
21
  function header() {
22
  echo 'Actions ';
23
  }
28
  * @return void
29
  */
30
  function add_modal() {
31
+ $id = $this->cnb_utils->get_query_val( 'id', null );
32
+ $action = $this->cnb_utils->get_query_val( 'action', null );
33
+ $bid = $this->cnb_utils->get_query_val( 'bid', null );
34
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
35
  // Create link
36
  $url = admin_url( 'admin.php' );
43
  'bid' => $bid
44
  ),
45
  $url );
 
46
 
47
+ echo '<a href="' . esc_url( $new_link ) . '" class="page-title-action">Add New</a>';
48
  }
49
  }
50
 
52
  * @return CnbButton|null
53
  */
54
  function get_button() {
55
+ $bid = $this->cnb_utils->get_query_val( 'bid', null );
56
  if ( $bid !== null ) {
57
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
58
 
src/admin/action/CnbActionViewEdit.php CHANGED
@@ -22,19 +22,20 @@ class CnbActionViewEdit {
22
  * @return void
23
  */
24
  function add_header( $action ) {
25
- if (is_wp_error($action)) {
26
- echo __('An error occurred');
 
27
  return;
28
  }
29
  if ( $action->id !== 'new' ) {
30
- $actionTypes = (new CnbAdminFunctions())->cnb_get_action_types();
31
  $name = $actionTypes[ $action->actionType ];
32
  if ( $action->actionValue ) {
33
  $name = $action->actionValue;
34
  }
35
- echo __( 'Editing action' ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
36
  } else {
37
- echo __( 'Add action' );
38
  }
39
  }
40
 
@@ -45,19 +46,17 @@ class CnbActionViewEdit {
45
  * @return string
46
  */
47
  private function create_tab_url( $button, $tab ) {
48
- $url = admin_url( 'admin.php' );
49
- $tab_link =
50
- add_query_arg(
51
- array(
52
- 'page' => CNB_SLUG,
53
- 'action' => 'edit',
54
- 'type' => strtolower( $button->type ),
55
- 'id' => $button->id,
56
- 'tab' => $tab
57
- ),
58
- $url );
59
 
60
- return esc_url( $tab_link );
 
 
 
 
 
 
 
 
61
  }
62
 
63
  /**
@@ -129,7 +128,7 @@ class CnbActionViewEdit {
129
  $action->actionType = 'PHONE';
130
  }
131
  if ( empty( $action->iconText ) ) {
132
- $action->iconText = (new CnbUtils())->cnb_actiontype_to_icontext( $action->actionType );
133
  }
134
  if ( empty( $action->iconType ) ) {
135
  $action->iconType = 'DEFAULT';
@@ -158,7 +157,8 @@ class CnbActionViewEdit {
158
  } ?>"/>
159
  <input type="hidden" name="actions[<?php echo esc_attr( $action->id ) ?>][delete]"
160
  id="cnb_action_<?php echo esc_attr( $action->id ) ?>_delete" value=""/>
161
- <table data-tab-name="basic_options" class="form-table <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>">
 
162
  <?php if ( ! $button ) { ?>
163
  <tr>
164
  <th colspan="2"><h2>Action Settings</h2>
@@ -173,7 +173,7 @@ class CnbActionViewEdit {
173
  <th scope="row"><label for="cnb_action_type">Button type</label></th>
174
  <td>
175
  <select id="cnb_action_type" name="actions[<?php echo esc_attr( $action->id ) ?>][actionType]">
176
- <?php foreach ( (new CnbAdminFunctions())->cnb_get_action_types() as $action_type_key => $action_type_value ) { ?>
177
  <option value="<?php echo esc_attr( $action_type_key ) ?>"<?php selected( $action_type_key, $action->actionType ) ?>>
178
  <?php echo esc_html( $action_type_value ) ?>
179
  </option>
@@ -198,8 +198,9 @@ class CnbActionViewEdit {
198
 
199
  </td>
200
  </tr>
201
- <tr class="cnb-action-properties-whatsapp">
202
- <th scope="row"><label for="cnb_action_value_input_whatsapp">Whatsapp Number</label></th>
 
203
  <td>
204
  <input type="tel" id="cnb_action_value_input_whatsapp"
205
  name="actions[<?php echo esc_attr( $action->id ) ?>][actionValueWhatsapp]"
@@ -210,7 +211,7 @@ class CnbActionViewEdit {
210
  </tr>
211
  <tr class="button-text cnb_hide_on_modal">
212
  <th scope="row"><label for="buttonTextField">Button label text <a
213
- href="<?php echo CNB_SUPPORT; ?>wordpress/buttons/button-label/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "button-label" ); ?>"
214
  target="_blank" class="cnb-nounderscore">
215
  <span class="dashicons dashicons-editor-help"></span>
216
  </a></label></th>
@@ -231,6 +232,9 @@ class CnbActionViewEdit {
231
  <div class="cnb-button-icon">
232
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="close_down">close_down</i>
233
  </div>
 
 
 
234
  </div>
235
  <div class="icon-text-options" id="icon-text-EMAIL">
236
  <div class="cnb-button-icon">
@@ -257,10 +261,6 @@ class CnbActionViewEdit {
257
  <div class="cnb-button-icon">
258
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link">link</i>
259
  </div>
260
- <div class="cnb-button-icon">
261
- <i class="cnb-font-icon family-material" data-icon-type="FONT_MATERIAL"
262
- data-icon-text="link">link</i>
263
- </div>
264
  <div class="cnb-button-icon">
265
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link2">link2</i>
266
  </div>
@@ -273,6 +273,9 @@ class CnbActionViewEdit {
273
  <div class="cnb-button-icon">
274
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link5">link5</i>
275
  </div>
 
 
 
276
  </div>
277
  <div class="icon-text-options" id="icon-text-MAP">
278
  <div class="cnb-button-icon">
@@ -321,6 +324,21 @@ class CnbActionViewEdit {
321
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="whatsapp">whatsapp</i>
322
  </div>
323
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
  <a
326
  href="#"
@@ -409,7 +427,7 @@ class CnbActionViewEdit {
409
 
410
  <tr class="cnb-action-properties-whatsapp">
411
  <th scope="row">Show WhatsApp modal <a
412
- href="<?php echo CNB_SUPPORT; ?>wordpress/buttons/whatsapp-modal/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "whatsapp-modal" ); ?>"
413
  target="_blank" class="cnb-nounderscore">
414
  <span class="dashicons dashicons-editor-help"></span>
415
  </a></th>
@@ -430,7 +448,7 @@ class CnbActionViewEdit {
430
  </tr>
431
  <tr id="action-properties-message-row" class="cnb-action-properties-sms">
432
  <th scope="row"><label for="action-properties-message">Message template <a
433
- href="<?php echo CNB_SUPPORT; ?>wordpress/buttons/message-template/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "message-template" ); ?>"
434
  target="_blank" class="cnb-nounderscore">
435
  <span class="dashicons dashicons-editor-help"></span>
436
  </a></label></th>
@@ -445,24 +463,43 @@ class CnbActionViewEdit {
445
  </tr>
446
 
447
  <tr class="cnb-action-properties-whatsapp-modal">
448
- <th scope="row"><label for="actionWhatsappTitle">Modal title</label></th>
449
  <td>
450
  <input id="actionWhatsappTitle" type="text"
451
  name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-title]"
452
  value="<?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-title'} ) ) {
453
  echo esc_attr( $action->properties->{'whatsapp-title'} );
454
- } ?>" maxlength="30" placeholder="optional"/>
455
- <p class="description">If left empty, the "Button label text" entered above will be used.</p>
456
  </td>
457
  </tr>
458
  <tr class="cnb-action-properties-whatsapp-modal">
459
  <th scope="row"><label for="actionWhatsappWelcomeMessage">Welcome message</label></th>
460
  <td>
461
- <input id="actionWhatsappWelcomeMessage" type="text"
462
- name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-welcomeMessage]"
463
- value="<?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-welcomeMessage'} ) ) {
464
- echo esc_attr( $action->properties->{'whatsapp-welcomeMessage'} );
465
- } ?>" placeholder="How can we help?"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  </td>
467
  </tr>
468
  <tr class="cnb-action-properties-whatsapp-modal">
@@ -472,7 +509,7 @@ class CnbActionViewEdit {
472
  name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-placeholderMessage]"
473
  value="<?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-placeholderMessage'} ) ) {
474
  echo esc_attr( $action->properties->{'whatsapp-placeholderMessage'} );
475
- } ?>" placeholder="Type a message"/>
476
  </td>
477
  </tr>
478
  <tr class="cnb-action-properties-email">
@@ -490,7 +527,7 @@ class CnbActionViewEdit {
490
  </tr>
491
  <tr class="cnb-action-properties-email">
492
  <th scope="row"><label for="action-properties-body">Message template <a
493
- href="<?php echo CNB_SUPPORT; ?>wordpress/buttons/message-template/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "message-template" ); ?>"
494
  target="_blank" class="cnb-nounderscore">
495
  <span class="dashicons dashicons-editor-help"></span>
496
  </a></label></th>
@@ -558,8 +595,28 @@ class CnbActionViewEdit {
558
  </p>
559
  </td>
560
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  </table>
562
- <table data-tab-name="scheduler" class="form-table <?php echo $adminFunctions->is_active_tab( 'scheduler' ); ?>">
 
563
  <tr class="cnb_hide_on_modal">
564
  <th></th>
565
  <td></td>
@@ -568,7 +625,7 @@ class CnbActionViewEdit {
568
  <th scope="row">Show at all times</th>
569
  <td>
570
  <?php
571
- $showAlwaysValue = $action->id === 'new' || (isset($action->schedule) && $action->schedule->showAlways); ?>
572
  <?php if ( $timezone_set_correctly ) { ?>
573
  <input name="actions[<?php echo esc_attr( $action->id ) ?>][schedule][showAlways]" type="hidden"
574
  value="false"/>
@@ -618,14 +675,10 @@ class CnbActionViewEdit {
618
  <td>
619
  <?php
620
  foreach ( $cnb_days_of_week_order as $cnb_day_of_week ) {
621
- $selected = '';
622
  $api_server_index = $this->wp_locale_day_to_daysofweek_array_index( $cnb_day_of_week );
623
- if ( isset( $action->schedule ) && isset( $action->schedule->daysOfWeek ) ) {
624
- $selected = ( isset( $action->schedule->daysOfWeek[ $api_server_index ] ) && $action->schedule->daysOfWeek[ $api_server_index ] == true ) ? 'checked="checked"' : '';
625
- }
626
  echo '
627
- <input class="cnb_day_selector" id="cnb_weekday_' . esc_attr( $api_server_index ) . '" type="checkbox" name="actions[' . esc_attr( $action->id ) . '][schedule][daysOfWeek][' . esc_attr( $api_server_index ) . ']" value="true" ' . $selected . '>
628
- <label title="' . $wp_locale->get_weekday( $cnb_day_of_week ) . '" class="cnb_day_selector" for="cnb_weekday_' . esc_attr( $api_server_index ) . '">' . $wp_locale->get_weekday_abbrev( $wp_locale->get_weekday( $cnb_day_of_week ) ) . '</label>
629
  ';
630
  }
631
 
@@ -674,6 +727,7 @@ class CnbActionViewEdit {
674
  id="actions[<?php echo esc_attr( $action->id ) ?>][schedule][timezone]"
675
  class="cnb_timezone_picker">
676
  <?php
 
677
  echo wp_timezone_choice( $timezone );
678
  ?>
679
  </select>
@@ -708,7 +762,7 @@ class CnbActionViewEdit {
708
  public function render_main( $action, $button, $domain = null ) {
709
  wp_enqueue_style( CNB_SLUG . '-intl-tel-input' );
710
  wp_enqueue_script( CNB_SLUG . '-intl-tel-input' );
711
- $bid = ! empty( $_REQUEST["bid"] ) ? sanitize_text_field( $_REQUEST["bid"] ) : null;
712
  // Set some sane defaults
713
  $action->backgroundColor = ! empty( $action->backgroundColor )
714
  ? $action->backgroundColor
@@ -716,14 +770,15 @@ class CnbActionViewEdit {
716
  $action->iconColor = ! empty( $action->iconColor )
717
  ? $action->iconColor
718
  : '#FFFFFF';
719
- $action->iconEnabled = isset( $action->iconEnabled )
720
- // phpcs:ignore
 
721
  ? boolval( $action->iconEnabled )
722
  : true;
723
  ?>
724
- <input type="hidden" name="bid" value="<?php echo esc_attr($bid) ?>"/>
725
- <input type="hidden" name="action_id" value="<?php echo esc_attr($action->id) ?>"/>
726
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'cnb-action-edit' ) ?>"/>
727
  <?php
728
  $this->render_table( $action, $button, $domain );
729
  }
@@ -745,24 +800,23 @@ class CnbActionViewEdit {
745
  } );
746
 
747
  $button = null;
748
- $bid = ! empty( $_GET["bid"] ) ? sanitize_text_field( $_GET["bid"] ) : null;
749
- if ( $bid !== null && !is_wp_error($action) ) {
750
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
751
 
752
  // Create back link
753
  $url = admin_url( 'admin.php' );
754
- $back_to_button_link = esc_url(
755
- add_query_arg(
756
- array(
757
- 'page' => 'call-now-button',
758
- 'action' => 'edit',
759
- 'id' => $bid
760
- ),
761
- $url ) );
762
 
763
  $action_verb = $action->id === 'new' ? 'adding' : 'editing';
764
  $message = '<p><strong>You are ' . $action_verb . ' an Action</strong>.
765
- Click <a href="' . $back_to_button_link . '">here</a> to go back to continue configuring the Button.</p>';
766
  CnbAdminNotices::get_instance()->renderInfo( $message );
767
  }
768
 
@@ -785,7 +839,7 @@ class CnbActionViewEdit {
785
 
786
  do_action( 'cnb_header' );
787
 
788
- if (is_wp_error($action)) {
789
  return;
790
  }
791
  ?>
@@ -795,29 +849,30 @@ class CnbActionViewEdit {
795
 
796
  <?php if ( $bid !== null ) { ?>
797
  <h2 class="nav-tab-wrapper">
798
- <a href="<?php echo $back_to_button_link; ?>" class="cnb-nav-tab"><span
799
  class="dashicons dashicons-arrow-left-alt"></span></a>
800
  <a data-tab-name="basic_options"
801
- href="<?php echo $this->create_tab_url( $button, 'basic_options' ) ?>"
802
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>">Basics</a>
803
  <a data-tab-name="scheduler"
804
- href="<?php echo $this->create_tab_url( $button, 'scheduler' ) ?>"
805
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'scheduler' ) ?>">Scheduling</a>
806
  </h2>
807
  <?php } ?>
808
  <?php if ( $button ) { ?>
809
  <script>
810
- let cnb_button = <?php echo json_encode( $button ); ?>;
811
- let cnb_actions = <?php echo json_encode( $button->actions ); ?>;
812
- let cnb_domain = <?php echo json_encode( $button->domain ) ?>;
813
  let cnb_css_root = '<?php echo esc_js( CnbAppRemote::cnb_get_static_base() ) ?>';
814
- let cnb_options = <?php echo json_encode( new stdClass() ) ?>;
815
  // disable scheduler for the action-edit screen
816
  let cnb_ignore_schedule = true
817
  </script>
818
  <?php } ?>
819
 
820
- <form class="cnb-container cnb-validation" action="<?php echo $redirect_link; ?>" method="post">
 
821
  <input type="hidden" name="page" value="call-now-button-actions"/>
822
  <input type="hidden" name="action"
823
  value="<?php echo $action->id === 'new' ? 'cnb_create_action' : 'cnb_update_action' ?>"/>
22
  * @return void
23
  */
24
  function add_header( $action ) {
25
+ if ( is_wp_error( $action ) ) {
26
+ esc_html_e( 'An error occurred' );
27
+
28
  return;
29
  }
30
  if ( $action->id !== 'new' ) {
31
+ $actionTypes = ( new CnbAdminFunctions() )->cnb_get_action_types();
32
  $name = $actionTypes[ $action->actionType ];
33
  if ( $action->actionValue ) {
34
  $name = $action->actionValue;
35
  }
36
+ echo esc_html__( 'Editing action' ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
37
  } else {
38
+ echo esc_html__( 'Add action' );
39
  }
40
  }
41
 
46
  * @return string
47
  */
48
  private function create_tab_url( $button, $tab ) {
49
+ $url = admin_url( 'admin.php' );
 
 
 
 
 
 
 
 
 
 
50
 
51
+ return add_query_arg(
52
+ array(
53
+ 'page' => CNB_SLUG,
54
+ 'action' => 'edit',
55
+ 'type' => strtolower( $button->type ),
56
+ 'id' => $button->id,
57
+ 'tab' => $tab
58
+ ),
59
+ $url );
60
  }
61
 
62
  /**
128
  $action->actionType = 'PHONE';
129
  }
130
  if ( empty( $action->iconText ) ) {
131
+ $action->iconText = ( new CnbUtils() )->cnb_actiontype_to_icontext( $action->actionType );
132
  }
133
  if ( empty( $action->iconType ) ) {
134
  $action->iconType = 'DEFAULT';
157
  } ?>"/>
158
  <input type="hidden" name="actions[<?php echo esc_attr( $action->id ) ?>][delete]"
159
  id="cnb_action_<?php echo esc_attr( $action->id ) ?>_delete" value=""/>
160
+ <table data-tab-name="basic_options"
161
+ class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>">
162
  <?php if ( ! $button ) { ?>
163
  <tr>
164
  <th colspan="2"><h2>Action Settings</h2>
173
  <th scope="row"><label for="cnb_action_type">Button type</label></th>
174
  <td>
175
  <select id="cnb_action_type" name="actions[<?php echo esc_attr( $action->id ) ?>][actionType]">
176
+ <?php foreach ( ( new CnbAdminFunctions() )->cnb_get_action_types() as $action_type_key => $action_type_value ) { ?>
177
  <option value="<?php echo esc_attr( $action_type_key ) ?>"<?php selected( $action_type_key, $action->actionType ) ?>>
178
  <?php echo esc_html( $action_type_value ) ?>
179
  </option>
198
 
199
  </td>
200
  </tr>
201
+ <tr class="cnb-action-properties-whatsapp cnb-action-properties-signal">
202
+ <th scope="row"><label id="cnb_action_value_input_intl_input" for="cnb_action_value_input_whatsapp">WhatsApp
203
+ Number</label></th>
204
  <td>
205
  <input type="tel" id="cnb_action_value_input_whatsapp"
206
  name="actions[<?php echo esc_attr( $action->id ) ?>][actionValueWhatsapp]"
211
  </tr>
212
  <tr class="button-text cnb_hide_on_modal">
213
  <th scope="row"><label for="buttonTextField">Button label text <a
214
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress/buttons/button-label/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'button-label' ) ); ?>"
215
  target="_blank" class="cnb-nounderscore">
216
  <span class="dashicons dashicons-editor-help"></span>
217
  </a></label></th>
232
  <div class="cnb-button-icon">
233
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="close_down">close_down</i>
234
  </div>
235
+ <div class="cnb-button-icon">
236
+ <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="anchor_up">anchor_up</i>
237
+ </div>
238
  </div>
239
  <div class="icon-text-options" id="icon-text-EMAIL">
240
  <div class="cnb-button-icon">
261
  <div class="cnb-button-icon">
262
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link">link</i>
263
  </div>
 
 
 
 
264
  <div class="cnb-button-icon">
265
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link2">link2</i>
266
  </div>
273
  <div class="cnb-button-icon">
274
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="link5">link5</i>
275
  </div>
276
+ <div class="cnb-button-icon">
277
+ <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="calendar">calendar</i>
278
+ </div>
279
  </div>
280
  <div class="icon-text-options" id="icon-text-MAP">
281
  <div class="cnb-button-icon">
324
  <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="whatsapp">whatsapp</i>
325
  </div>
326
  </div>
327
+ <div class="icon-text-options" id="icon-text-FACEBOOK">
328
+ <div class="cnb-button-icon">
329
+ <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="facebook_messenger">facebook_messenger</i>
330
+ </div>
331
+ </div>
332
+ <div class="icon-text-options" id="icon-text-TELEGRAM">
333
+ <div class="cnb-button-icon">
334
+ <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="telegram">telegram</i>
335
+ </div>
336
+ </div>
337
+ <div class="icon-text-options" id="icon-text-SIGNAL">
338
+ <div class="cnb-button-icon">
339
+ <i class="cnb-font-icon" data-icon-type="FONT" data-icon-text="signal">signal</i>
340
+ </div>
341
+ </div>
342
 
343
  <a
344
  href="#"
427
 
428
  <tr class="cnb-action-properties-whatsapp">
429
  <th scope="row">Show WhatsApp modal <a
430
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress/buttons/whatsapp-modal/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'whatsapp-modal' ) ); ?>"
431
  target="_blank" class="cnb-nounderscore">
432
  <span class="dashicons dashicons-editor-help"></span>
433
  </a></th>
448
  </tr>
449
  <tr id="action-properties-message-row" class="cnb-action-properties-sms">
450
  <th scope="row"><label for="action-properties-message">Message template <a
451
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress/buttons/message-template/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'message-template' ) ); ?>"
452
  target="_blank" class="cnb-nounderscore">
453
  <span class="dashicons dashicons-editor-help"></span>
454
  </a></label></th>
463
  </tr>
464
 
465
  <tr class="cnb-action-properties-whatsapp-modal">
466
+ <th scope="row"><label for="actionWhatsappTitle">Title</label></th>
467
  <td>
468
  <input id="actionWhatsappTitle" type="text"
469
  name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-title]"
470
  value="<?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-title'} ) ) {
471
  echo esc_attr( $action->properties->{'whatsapp-title'} );
472
+ } ?>" maxlength="30" placeholder="Optional"/>
473
+ <p class="description">When left empty, the "Button label text" entered above will be used here.</p>
474
  </td>
475
  </tr>
476
  <tr class="cnb-action-properties-whatsapp-modal">
477
  <th scope="row"><label for="actionWhatsappWelcomeMessage">Welcome message</label></th>
478
  <td>
479
+ <textarea id="actionWhatsappWelcomeMessage" rows="3"
480
+ name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-welcomeMessage]"
481
+ placeholder="How can we help?"><?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-welcomeMessage'} ) ) {
482
+ echo esc_textarea( $action->properties->{'whatsapp-welcomeMessage'} );
483
+ } ?></textarea>
484
+ <p class="description">Press [Enter] to start a new speech bubble in the chat modal. Speech bubbles will appear in a sequence with a short pause between them.</p>
485
+ </td>
486
+ </tr>
487
+ <tr class="cnb-action-properties-whatsapp">
488
+ <th scope="row"><label for="cnb-action-show-notification-count">Show notification count</label></th>
489
+ <td class="appearance">
490
+ <input type="hidden"
491
+ name="actions[<?php echo esc_attr( $action->id ) ?>][properties][show-notification-count]"
492
+ value=""/>
493
+ <input id="cnb-action-show-notification-count" class="cnb_toggle_checkbox" type="checkbox"
494
+ name="actions[<?php echo esc_attr( $action->id ) ?>][properties][show-notification-count]"
495
+ value="true"
496
+ <?php checked( true, isset( $action->properties ) && isset( $action->properties->{'show-notification-count'} ) && $action->properties->{'show-notification-count'} ); ?> />
497
+ <label for="cnb-action-show-notification-count" class="cnb_toggle_label">Toggle</label>
498
+ <span data-cnb_toggle_state_label="cnb-action-show-notification-count"
499
+ class="cnb_toggle_state cnb_toggle_false">(Off)</span>
500
+ <span data-cnb_toggle_state_label="cnb-action-show-notification-count"
501
+ class="cnb_toggle_state cnb_toggle_true">Yes</span>
502
+ <p class="description">Show a small red notification badge on WhatsApp the button to draw the attention.</p>
503
  </td>
504
  </tr>
505
  <tr class="cnb-action-properties-whatsapp-modal">
509
  name="actions[<?php echo esc_attr( $action->id ) ?>][properties][whatsapp-placeholderMessage]"
510
  value="<?php if ( isset( $action->properties ) && isset( $action->properties->{'whatsapp-placeholderMessage'} ) ) {
511
  echo esc_attr( $action->properties->{'whatsapp-placeholderMessage'} );
512
+ } ?>" placeholder="Type your message"/>
513
  </td>
514
  </tr>
515
  <tr class="cnb-action-properties-email">
527
  </tr>
528
  <tr class="cnb-action-properties-email">
529
  <th scope="row"><label for="action-properties-body">Message template <a
530
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress/buttons/message-template/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'message-template' ) ); ?>"
531
  target="_blank" class="cnb-nounderscore">
532
  <span class="dashicons dashicons-editor-help"></span>
533
  </a></label></th>
595
  </p>
596
  </td>
597
  </tr>
598
+ <tr class="cnb-action-properties-map">
599
+ <th colspan="2">
600
+ <hr/>
601
+ </th>
602
+ </tr>
603
+ <tr class="cnb-action-properties-map">
604
+ <th scope="row"><label for="actionMapQueryTypeSelect">Maps display</label></th>
605
+ <td>
606
+ <?php $action_map_query_type = isset( $action->properties ) && isset( $action->properties->{'map-query-type'} ) ? $action->properties->{'map-query-type'} : null; ?>
607
+ <select id="actionMapQueryTypeSelect"
608
+ name="actions[<?php echo esc_attr( $action->id ) ?>][properties][map-query-type]">
609
+ <option value="q" <?php selected( 'q', $action_map_query_type ) ?>>Show location</option>
610
+ <option value="daddr" <?php selected( 'daddr', $action_map_query_type ) ?>>Show travel
611
+ directions
612
+ </option>
613
+ </select>
614
+ </td>
615
+ </tr>
616
+
617
  </table>
618
+ <table data-tab-name="scheduler"
619
+ class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ); ?>">
620
  <tr class="cnb_hide_on_modal">
621
  <th></th>
622
  <td></td>
625
  <th scope="row">Show at all times</th>
626
  <td>
627
  <?php
628
+ $showAlwaysValue = $action->id === 'new' || ( isset( $action->schedule ) && $action->schedule->showAlways ); ?>
629
  <?php if ( $timezone_set_correctly ) { ?>
630
  <input name="actions[<?php echo esc_attr( $action->id ) ?>][schedule][showAlways]" type="hidden"
631
  value="false"/>
675
  <td>
676
  <?php
677
  foreach ( $cnb_days_of_week_order as $cnb_day_of_week ) {
 
678
  $api_server_index = $this->wp_locale_day_to_daysofweek_array_index( $cnb_day_of_week );
 
 
 
679
  echo '
680
+ <input class="cnb_day_selector" id="cnb_weekday_' . esc_attr( $api_server_index ) . '" type="checkbox" name="actions[' . esc_attr( $action->id ) . '][schedule][daysOfWeek][' . esc_attr( $api_server_index ) . ']" value="true" ' . checked( isset( $action->schedule ) && isset( $action->schedule->daysOfWeek ) && isset( $action->schedule->daysOfWeek[ $api_server_index ] ) && $action->schedule->daysOfWeek[ $api_server_index ], true, false ) . '>
681
+ <label title="' . esc_attr( $wp_locale->get_weekday( $cnb_day_of_week ) ) . '" class="cnb_day_selector" for="cnb_weekday_' . esc_attr( $api_server_index ) . '">' . esc_attr( $wp_locale->get_weekday_abbrev( $wp_locale->get_weekday( $cnb_day_of_week ) ) ) . '</label>
682
  ';
683
  }
684
 
727
  id="actions[<?php echo esc_attr( $action->id ) ?>][schedule][timezone]"
728
  class="cnb_timezone_picker">
729
  <?php
730
+ // phpcs:ignore WordPress.Security
731
  echo wp_timezone_choice( $timezone );
732
  ?>
733
  </select>
762
  public function render_main( $action, $button, $domain = null ) {
763
  wp_enqueue_style( CNB_SLUG . '-intl-tel-input' );
764
  wp_enqueue_script( CNB_SLUG . '-intl-tel-input' );
765
+ $bid = ( new CnbUtils() )->get_query_val( 'bid', null );
766
  // Set some sane defaults
767
  $action->backgroundColor = ! empty( $action->backgroundColor )
768
  ? $action->backgroundColor
770
  $action->iconColor = ! empty( $action->iconColor )
771
  ? $action->iconColor
772
  : '#FFFFFF';
773
+ /** @noinspection PhpTernaryExpressionCanBeReplacedWithConditionInspection */
774
+ $action->iconEnabled = isset( $action->iconEnabled )
775
+ // phpcs:ignore PHPCompatibility.FunctionUse
776
  ? boolval( $action->iconEnabled )
777
  : true;
778
  ?>
779
+ <input type="hidden" name="bid" value="<?php echo esc_attr( $bid ) ?>"/>
780
+ <input type="hidden" name="action_id" value="<?php echo esc_attr( $action->id ) ?>"/>
781
+ <input type="hidden" name="_wpnonce" value="<?php echo esc_attr( wp_create_nonce( 'cnb-action-edit' ) ) ?>"/>
782
  <?php
783
  $this->render_table( $action, $button, $domain );
784
  }
800
  } );
801
 
802
  $button = null;
803
+ $bid = ( new CnbUtils() )->get_query_val( 'bid', null );
804
+ if ( $bid !== null && ! is_wp_error( $action ) ) {
805
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
806
 
807
  // Create back link
808
  $url = admin_url( 'admin.php' );
809
+ $back_to_button_link = add_query_arg(
810
+ array(
811
+ 'page' => 'call-now-button',
812
+ 'action' => 'edit',
813
+ 'id' => $bid
814
+ ),
815
+ $url );
 
816
 
817
  $action_verb = $action->id === 'new' ? 'adding' : 'editing';
818
  $message = '<p><strong>You are ' . $action_verb . ' an Action</strong>.
819
+ Click <a href="' . esc_url( $back_to_button_link ) . '">here</a> to go back to continue configuring the Button.</p>';
820
  CnbAdminNotices::get_instance()->renderInfo( $message );
821
  }
822
 
839
 
840
  do_action( 'cnb_header' );
841
 
842
+ if ( is_wp_error( $action ) ) {
843
  return;
844
  }
845
  ?>
849
 
850
  <?php if ( $bid !== null ) { ?>
851
  <h2 class="nav-tab-wrapper">
852
+ <a href="<?php echo esc_url( $back_to_button_link ); ?>" class="cnb-nav-tab"><span
853
  class="dashicons dashicons-arrow-left-alt"></span></a>
854
  <a data-tab-name="basic_options"
855
+ href="<?php echo esc_url( $this->create_tab_url( $button, 'basic_options' ) ) ?>"
856
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>">Basics</a>
857
  <a data-tab-name="scheduler"
858
+ href="<?php echo esc_url( $this->create_tab_url( $button, 'scheduler' ) ) ?>"
859
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ) ?>">Scheduling</a>
860
  </h2>
861
  <?php } ?>
862
  <?php if ( $button ) { ?>
863
  <script>
864
+ let cnb_button = <?php echo wp_json_encode( $button ); ?>;
865
+ let cnb_actions = <?php echo wp_json_encode( $button->actions ); ?>;
866
+ let cnb_domain = <?php echo wp_json_encode( $button->domain ) ?>;
867
  let cnb_css_root = '<?php echo esc_js( CnbAppRemote::cnb_get_static_base() ) ?>';
868
+ let cnb_options = <?php echo wp_json_encode( new stdClass() ) ?>;
869
  // disable scheduler for the action-edit screen
870
  let cnb_ignore_schedule = true
871
  </script>
872
  <?php } ?>
873
 
874
+ <form class="cnb-container cnb-validation" action="<?php echo esc_url( $redirect_link ); ?>"
875
+ method="post">
876
  <input type="hidden" name="page" value="call-now-button-actions"/>
877
  <input type="hidden" name="action"
878
  value="<?php echo $action->id === 'new' ? 'cnb_create_action' : 'cnb_update_action' ?>"/>
src/admin/action/Cnb_Action_List_Table.php CHANGED
@@ -6,12 +6,13 @@ namespace cnb\admin\action;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
13
  use cnb\admin\button\CnbButton;
14
  use cnb\utils\CnbAdminFunctions;
 
15
  use DateTime;
16
  use WP_Error;
17
  use WP_List_Table;
@@ -27,6 +28,11 @@ class Cnb_Action_List_Table extends WP_List_Table {
27
  */
28
  public $button;
29
 
 
 
 
 
 
30
  /**
31
  * Constructor, we override the parent to pass our own arguments
32
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
@@ -34,14 +40,15 @@ class Cnb_Action_List_Table extends WP_List_Table {
34
  * @param $button CnbButton (can contain at least a single key called 'button')
35
  */
36
  function __construct( $button = null ) {
37
- $this->button = $button;
38
-
39
  parent::__construct( array(
40
  'singular' => 'cnb_list_action', //Singular label
41
  'plural' => 'cnb_list_actions', //plural label, also this well be one of the table css class
42
  'ajax' => true, // We support it, see _js_vars(),
43
  'screen' => 'call-now-button-actions' // Screen name for bulk actions, etc
44
  ) );
 
 
 
45
  }
46
 
47
  /**
@@ -49,8 +56,8 @@ class Cnb_Action_List_Table extends WP_List_Table {
49
  * @return array $columns, the array of columns to use with the table
50
  */
51
  function get_columns() {
52
- $cnb_options = get_option('cnb');
53
- $columns = array(
54
  'cb' => '<input type="checkbox">',
55
  'draggable' => '',
56
  'id' => __( 'ID' ),
@@ -101,8 +108,8 @@ class Cnb_Action_List_Table extends WP_List_Table {
101
 
102
  /* -- Ordering parameters -- */
103
  //Parameters that are going to be used to order the result
104
- if (!$this->button) {
105
- if ( key_exists( 'orderby', $_GET ) ) {
106
  usort( $data, array( &$this, 'sort_data' ) );
107
  }
108
  }
@@ -112,7 +119,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
112
  $totalitems = count( $data ); //return the total number of affected rows
113
  $per_page = 20; //How many to display per page?
114
  //Which page is this?
115
- $current_page = ! empty( $_GET['paged'] ) ? (int) sanitize_text_field( $_GET['paged'] ) : 1;
116
 
117
  //Page Number
118
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
@@ -190,8 +197,8 @@ class Cnb_Action_List_Table extends WP_List_Table {
190
  }
191
 
192
  private function get_data() {
193
- $cnb_options = get_option('cnb');
194
- $actions = array();
195
  if ( $this->button === null ) {
196
  $actions = CnbAppRemote::cnb_remote_get_actions();
197
  } else {
@@ -230,9 +237,9 @@ class Cnb_Action_List_Table extends WP_List_Table {
230
  */
231
  private function sort_data( $a, $b ) {
232
  // If orderby is set, use this as the sort column
233
- $orderby = ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'actionValue';
234
  // If order is set use this as the order
235
- $order = ! empty( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'asc';
236
 
237
  $result = strcmp( $a->$orderby, $b->$orderby );
238
 
@@ -262,6 +269,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
262
  * @param $item CnbAction
263
  *
264
  * @return string|void
 
265
  */
266
  function column_schedule( $item ) {
267
  /**
@@ -335,7 +343,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
335
  }
336
 
337
  // print time
338
- if ( $start == "00:00" && $stop === "23:59" ) {
339
  $time = '<em>' . __( 'All day' ) . '</em>';
340
  } else {
341
  $time = esc_html( $wp_start ) . ' - ' . esc_html( $wp_stop );
@@ -356,6 +364,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
356
  * @param $item CnbAction
357
  *
358
  * @return string
 
359
  */
360
  function column_actionType( $item ) {
361
  $bid = $this->button !== null ? $this->button->id : null;
@@ -403,7 +412,7 @@ class Cnb_Action_List_Table extends WP_List_Table {
403
  $actions['delete'] = '<a href="' . $delete_url . '">' . __( 'Delete' ) . '</a>';
404
  }
405
 
406
- $actionTypes = (new CnbAdminFunctions())->cnb_get_action_types();
407
  $value = ! empty( $item->actionType ) ? esc_html( $actionTypes[ $item->actionType ] ) : '<em>No value</em>';
408
 
409
  return sprintf(
@@ -435,20 +444,22 @@ class Cnb_Action_List_Table extends WP_List_Table {
435
  'data' => $this->get_data(),
436
  );
437
 
 
438
  printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
439
  }
440
 
441
  function no_items() {
442
- _e( 'This button has no actions yet. Let\'s add one!' );
443
  }
444
 
445
  function get_column_count() {
446
  $count = parent::get_column_count();
447
- $data = $this->get_data();
448
  // We hide the draggable column if there are less than 2 items, so we need to account for that.
449
- if ($this->button && count($data) < 2) {
450
  return $count - 1;
451
  }
 
452
  return $count;
453
  }
454
  }
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
13
  use cnb\admin\button\CnbButton;
14
  use cnb\utils\CnbAdminFunctions;
15
+ use cnb\utils\CnbUtils;
16
  use DateTime;
17
  use WP_Error;
18
  use WP_List_Table;
28
  */
29
  public $button;
30
 
31
+ /**
32
+ * @var CnbUtils
33
+ */
34
+ private $cnb_utils;
35
+
36
  /**
37
  * Constructor, we override the parent to pass our own arguments
38
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
40
  * @param $button CnbButton (can contain at least a single key called 'button')
41
  */
42
  function __construct( $button = null ) {
 
 
43
  parent::__construct( array(
44
  'singular' => 'cnb_list_action', //Singular label
45
  'plural' => 'cnb_list_actions', //plural label, also this well be one of the table css class
46
  'ajax' => true, // We support it, see _js_vars(),
47
  'screen' => 'call-now-button-actions' // Screen name for bulk actions, etc
48
  ) );
49
+
50
+ $this->cnb_utils = new CnbUtils();
51
+ $this->button = $button;
52
  }
53
 
54
  /**
56
  * @return array $columns, the array of columns to use with the table
57
  */
58
  function get_columns() {
59
+ $cnb_options = get_option( 'cnb' );
60
+ $columns = array(
61
  'cb' => '<input type="checkbox">',
62
  'draggable' => '',
63
  'id' => __( 'ID' ),
108
 
109
  /* -- Ordering parameters -- */
110
  //Parameters that are going to be used to order the result
111
+ if ( ! $this->button ) {
112
+ if ( $this->cnb_utils->get_query_val( 'orderby' ) ) {
113
  usort( $data, array( &$this, 'sort_data' ) );
114
  }
115
  }
119
  $totalitems = count( $data ); //return the total number of affected rows
120
  $per_page = 20; //How many to display per page?
121
  //Which page is this?
122
+ $current_page = (int) $this->cnb_utils->get_query_val( 'paged', '1' );
123
 
124
  //Page Number
125
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
197
  }
198
 
199
  private function get_data() {
200
+ $cnb_options = get_option( 'cnb' );
201
+ $actions = array();
202
  if ( $this->button === null ) {
203
  $actions = CnbAppRemote::cnb_remote_get_actions();
204
  } else {
237
  */
238
  private function sort_data( $a, $b ) {
239
  // If orderby is set, use this as the sort column
240
+ $orderby = $this->cnb_utils->get_query_val( 'orderby', 'actionValue' );
241
  // If order is set use this as the order
242
+ $order = $this->cnb_utils->get_query_val( 'order', 'asc' );
243
 
244
  $result = strcmp( $a->$orderby, $b->$orderby );
245
 
269
  * @param $item CnbAction
270
  *
271
  * @return string|void
272
+ * @noinspection PhpUnused
273
  */
274
  function column_schedule( $item ) {
275
  /**
343
  }
344
 
345
  // print time
346
+ if ( $start == '00:00' && $stop === '23:59' ) {
347
  $time = '<em>' . __( 'All day' ) . '</em>';
348
  } else {
349
  $time = esc_html( $wp_start ) . ' - ' . esc_html( $wp_stop );
364
  * @param $item CnbAction
365
  *
366
  * @return string
367
+ * @noinspection PhpUnused
368
  */
369
  function column_actionType( $item ) {
370
  $bid = $this->button !== null ? $this->button->id : null;
412
  $actions['delete'] = '<a href="' . $delete_url . '">' . __( 'Delete' ) . '</a>';
413
  }
414
 
415
+ $actionTypes = ( new CnbAdminFunctions() )->cnb_get_action_types();
416
  $value = ! empty( $item->actionType ) ? esc_html( $actionTypes[ $item->actionType ] ) : '<em>No value</em>';
417
 
418
  return sprintf(
444
  'data' => $this->get_data(),
445
  );
446
 
447
+ /** @noinspection BadExpressionStatementJS */
448
  printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
449
  }
450
 
451
  function no_items() {
452
+ esc_html_e( 'This button has no actions yet. Let\'s add one!' );
453
  }
454
 
455
  function get_column_count() {
456
  $count = parent::get_column_count();
457
+ $data = $this->get_data();
458
  // We hide the draggable column if there are less than 2 items, so we need to account for that.
459
+ if ( $this->button && count( $data ) < 2 ) {
460
  return $count - 1;
461
  }
462
+
463
  return $count;
464
  }
465
  }
src/admin/api/CnbAdminCloud.php CHANGED
@@ -24,7 +24,7 @@ class CnbAdminCloud {
24
  public function is_api_key_valid( $api_key ) {
25
  global $cnb_api_key;
26
  $cnb_api_key = $api_key;
27
- $user_info = CnbAppRemote::cnb_remote_get_user_info();
28
  $cnb_api_key = null;
29
 
30
  return ! is_wp_error( $user_info );
@@ -41,7 +41,7 @@ class CnbAdminCloud {
41
  *
42
  * @return string The ID to use for the Cloud Button
43
  */
44
- public function getCloudUseId($options) {
45
  global $cnb_api_key;
46
  // Check if an ID has already been set. If so, use if and continue
47
  if ( isset( $options['cloud_use_id'] ) && ! empty( $options['cloud_use_id'] ) ) {
@@ -54,12 +54,12 @@ class CnbAdminCloud {
54
  }
55
 
56
  // Check if we can talk to the API via a key. If so, use the current user to be safe
57
- if ( $this->is_api_key_valid($options['api_key']) ) {
58
  // Set this API key as the global
59
  $cnb_api_key = $options['api_key'];
60
- $domain = CnbAppRemote::cnb_remote_get_wp_domain();
61
  $cnb_api_key = null;
62
- if ($domain instanceof CnbDomain) {
63
  return $domain->id;
64
  }
65
  }
@@ -463,10 +463,10 @@ class CnbAdminCloud {
463
  * @return CnbNotice A WordPress success notice with all details filled out
464
  */
465
  public static function cnb_admin_get_success_message( $verb, $type, $id ) {
466
- $cnb_options = get_option('cnb');
467
- $advanced = '';
468
  if ( isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ) {
469
- $advanced = ' at <strong>' . esc_html(CnbAppRemote::cnb_get_api_base()) . '</strong>';
470
  }
471
  $message = '<p>Your ' . $type . ' <strong>' . esc_html( $id ) . '</strong> has been ' . $verb . $advanced . '!</p>';
472
  $notice = new CnbNotice( 'success', $message );
24
  public function is_api_key_valid( $api_key ) {
25
  global $cnb_api_key;
26
  $cnb_api_key = $api_key;
27
+ $user_info = CnbAppRemote::cnb_remote_get_user_info();
28
  $cnb_api_key = null;
29
 
30
  return ! is_wp_error( $user_info );
41
  *
42
  * @return string The ID to use for the Cloud Button
43
  */
44
+ public function getCloudUseId( $options ) {
45
  global $cnb_api_key;
46
  // Check if an ID has already been set. If so, use if and continue
47
  if ( isset( $options['cloud_use_id'] ) && ! empty( $options['cloud_use_id'] ) ) {
54
  }
55
 
56
  // Check if we can talk to the API via a key. If so, use the current user to be safe
57
+ if ( $this->is_api_key_valid( $options['api_key'] ) ) {
58
  // Set this API key as the global
59
  $cnb_api_key = $options['api_key'];
60
+ $domain = CnbAppRemote::cnb_remote_get_wp_domain();
61
  $cnb_api_key = null;
62
+ if ( $domain instanceof CnbDomain ) {
63
  return $domain->id;
64
  }
65
  }
463
  * @return CnbNotice A WordPress success notice with all details filled out
464
  */
465
  public static function cnb_admin_get_success_message( $verb, $type, $id ) {
466
+ $cnb_options = get_option( 'cnb' );
467
+ $advanced = '';
468
  if ( isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ) {
469
+ $advanced = ' at <strong>' . esc_html( CnbAppRemote::cnb_get_api_base() ) . '</strong>';
470
  }
471
  $message = '<p>Your ' . $type . ' <strong>' . esc_html( $id ) . '</strong> has been ' . $verb . $advanced . '!</p>';
472
  $notice = new CnbNotice( 'success', $message );
src/admin/api/CnbAppRemote.php CHANGED
@@ -38,7 +38,7 @@ class CnbAppRemote {
38
  public function cnb_clean_site_url() {
39
  $siteUrl = $this->get_site_url();
40
 
41
- $url = parse_url( $siteUrl, PHP_URL_HOST );
42
  if ( $url ) {
43
  return
44
  preg_replace( '/^www\./', '',
@@ -59,7 +59,7 @@ class CnbAppRemote {
59
  preg_replace( '/^www\./', '',
60
  trim(
61
  strtolower( preg_replace( '/\/.*/', '',
62
- preg_replace( '/:[0-9]+/', '',
63
  preg_replace( '/.*\/\//', '', $siteUrl, 1 ), 1 ), 1 ) )
64
  )
65
  , 1 );
@@ -101,10 +101,14 @@ class CnbAppRemote {
101
  }
102
 
103
  /**
104
- * Increments the cache key with 1
 
 
105
  */
106
- public static function cnb_incr_transient_base() {
107
- set_transient( self::cnb_get_api_base(), self::cnb__get_transient_base() + 1 );
 
 
108
  }
109
 
110
  public static function cnb_get_transient_base() {
@@ -238,7 +242,7 @@ class CnbAppRemote {
238
  }
239
 
240
  if ( $body != null ) {
241
- $args['body'] = json_encode( $body );
242
  }
243
 
244
  $url = self::cnb_get_api_base() . $rest_endpoint;
@@ -255,7 +259,7 @@ class CnbAppRemote {
255
  }
256
 
257
  if ( $body != null ) {
258
- $args['body'] = json_encode( $body );
259
  }
260
 
261
  $url = self::cnb_get_api_base() . $rest_endpoint;
@@ -272,7 +276,7 @@ class CnbAppRemote {
272
  }
273
 
274
  if ( $body != null ) {
275
- $args['body'] = json_encode( $body );
276
  }
277
 
278
  $url = self::cnb_get_api_base() . $rest_endpoint;
38
  public function cnb_clean_site_url() {
39
  $siteUrl = $this->get_site_url();
40
 
41
+ $url = wp_parse_url( $siteUrl, PHP_URL_HOST );
42
  if ( $url ) {
43
  return
44
  preg_replace( '/^www\./', '',
59
  preg_replace( '/^www\./', '',
60
  trim(
61
  strtolower( preg_replace( '/\/.*/', '',
62
+ preg_replace( '/:\d+/', '',
63
  preg_replace( '/.*\/\//', '', $siteUrl, 1 ), 1 ), 1 ) )
64
  )
65
  , 1 );
101
  }
102
 
103
  /**
104
+ * Set the cache key.
105
+ *
106
+ * @param string|int|null $time Should not be added, but can be used to force a base (mostly used for testing).
107
  */
108
+ public static function cnb_incr_transient_base($time = null) {
109
+ /** @noinspection PhpTernaryExpressionCanBeReducedToShortVersionInspection */
110
+ $value = $time ? $time : time();
111
+ set_transient( self::cnb_get_api_base(), $value );
112
  }
113
 
114
  public static function cnb_get_transient_base() {
242
  }
243
 
244
  if ( $body != null ) {
245
+ $args['body'] = wp_json_encode( $body );
246
  }
247
 
248
  $url = self::cnb_get_api_base() . $rest_endpoint;
259
  }
260
 
261
  if ( $body != null ) {
262
+ $args['body'] = wp_json_encode( $body );
263
  }
264
 
265
  $url = self::cnb_get_api_base() . $rest_endpoint;
276
  }
277
 
278
  if ( $body != null ) {
279
+ $args['body'] = wp_json_encode( $body );
280
  }
281
 
282
  $url = self::cnb_get_api_base() . $rest_endpoint;
src/admin/api/CnbAppRemotePayment.php CHANGED
@@ -52,4 +52,4 @@ class CnbAppRemotePayment {
52
 
53
  return CnbAppRemote::cnb_remote_get( $rest_endpoint );
54
  }
55
- }
52
 
53
  return CnbAppRemote::cnb_remote_get( $rest_endpoint );
54
  }
55
+ }
src/admin/api/CnbDeleteResult.php CHANGED
@@ -40,11 +40,11 @@ class CnbDeleteResult {
40
  return $object;
41
  }
42
 
43
- $result = new CnbDeleteResult();
44
- // phpcs:ignore
45
- $result->success = boolval(CnbUtils::getPropertyOrNull( $object, 'success' ));
46
- $result->id = CnbUtils::getPropertyOrNull( $object, 'id' );
47
- $result->object = CnbUtils::getPropertyOrNull( $object, 'object' );
48
 
49
  return $result;
50
  }
@@ -56,16 +56,17 @@ class CnbDeleteResult {
56
  * @return bool
57
  */
58
  public function is_success() {
59
- return $this->success == true && !is_wp_error($this->object);
60
  }
61
 
62
  /**
63
  * @return WP_Error|null
64
  */
65
  public function get_error() {
66
- if (is_wp_error($this->object)) {
67
  return $this->object;
68
  }
 
69
  return null;
70
  }
71
- }
40
  return $object;
41
  }
42
 
43
+ $result = new CnbDeleteResult();
44
+ // phpcs:ignore PHPCompatibility.FunctionUse
45
+ $result->success = boolval( CnbUtils::getPropertyOrNull( $object, 'success' ) );
46
+ $result->id = CnbUtils::getPropertyOrNull( $object, 'id' );
47
+ $result->object = CnbUtils::getPropertyOrNull( $object, 'object' );
48
 
49
  return $result;
50
  }
56
  * @return bool
57
  */
58
  public function is_success() {
59
+ return $this->success == true && ! is_wp_error( $this->object );
60
  }
61
 
62
  /**
63
  * @return WP_Error|null
64
  */
65
  public function get_error() {
66
+ if ( is_wp_error( $this->object ) ) {
67
  return $this->object;
68
  }
69
+
70
  return null;
71
  }
72
+ }
src/admin/api/CnbGet.php CHANGED
@@ -12,7 +12,7 @@ class CnbGet {
12
  private $useCache = false;
13
 
14
  public function __construct() {
15
- $cnb_options = get_option('cnb');
16
  if ( $cnb_options['api_caching'] === 1 ) {
17
  $this->useCache = true;
18
  }
@@ -42,4 +42,4 @@ class CnbGet {
42
 
43
  return $this->add( $url, $response );
44
  }
45
- }
12
  private $useCache = false;
13
 
14
  public function __construct() {
15
+ $cnb_options = get_option( 'cnb' );
16
  if ( $cnb_options['api_caching'] === 1 ) {
17
  $this->useCache = true;
18
  }
42
 
43
  return $this->add( $url, $response );
44
  }
45
+ }
src/admin/api/CnbMigration.php CHANGED
@@ -18,21 +18,22 @@ class CnbMigration {
18
 
19
  /**
20
  * @param $cnbActivation CnbActivation
 
21
  * @return void
22
  */
23
- public function createOrUpdateDomainAndButton($cnbActivation) {
24
  // Patch domain
25
- $domain = $this->createOrUpdateDomain($cnbActivation);
26
  $cnbActivation->domain = $domain;
27
 
28
  // Only migrate if this domain does not have any buttons
29
  $button = null;
30
- if ($this->shouldCreateButton($domain)) {
31
  // Create / migrate legacy button
32
  $button = $this->createButton( $domain );
33
  }
34
- $cnbActivation->button = $button;
35
- $cnbActivation->success = !is_wp_error($domain) && !is_wp_error($button);
36
  }
37
 
38
  /**
@@ -42,14 +43,14 @@ class CnbMigration {
42
  *
43
  * @return bool
44
  */
45
- private function shouldCreateButton($domain) {
46
  if ( is_wp_error( $domain ) ) {
47
  return false;
48
  }
49
 
50
  // Check if any buttons are for the current WP domain
51
  $buttons = CnbAppRemote::cnb_remote_get_buttons();
52
- if ( is_wp_error($buttons) ) {
53
  // Could not retrieve Buttons
54
  return false;
55
  }
@@ -62,24 +63,27 @@ class CnbMigration {
62
  return $button->domain->id === $domain->id;
63
  } );
64
 
65
- return count($cnb_cloud_buttons_this_domain) === 0;
66
  }
67
 
68
  /**
69
  * Update the CallNowButton Cloud with a domain matching the WordPress Domain
70
  *
71
  * @param $cnbActivation CnbActivation
 
72
  * @return CnbDomain
73
  */
74
- public function createOrUpdateDomain($cnbActivation) {
75
  $cnb_cloud_notifications = array();
76
 
77
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
78
- if ( is_wp_error($domain) ) {
79
  $cnbActivation->domain_action = 'created';
 
80
  return $this->patchDomain( $cnb_cloud_notifications );
81
  }
82
  $cnbActivation->domain_action = 'updated';
 
83
  return $this->patchDomain( $cnb_cloud_notifications, $domain );
84
  }
85
 
@@ -92,7 +96,7 @@ class CnbMigration {
92
  * @return CnbDomain|WP_Error
93
  */
94
  private function patchDomain( &$cnb_cloud_notifications, $existing_domain = null ) {
95
- $cnb_options = get_option('cnb');
96
 
97
  $domain = $existing_domain !== null ? $existing_domain : new CnbDomain();
98
  $domain->name = ( new CnbAppRemote() )->cnb_clean_site_url();
@@ -100,13 +104,14 @@ class CnbMigration {
100
  $domain->trackConversion = isset( $cnb_options['conversions'] ) && $cnb_options['conversions'] != 0;
101
  $domain->properties = $existing_domain !== null ? $existing_domain->properties : new CnbDomainProperties();
102
  $domain->properties->allowMultipleButtons = $existing_domain !== null ? $existing_domain->properties->allowMultipleButtons : true;
103
- $domain->properties->zindex = (new CnbUtils())->zindex( $cnb_options['z-index'] );
104
  $domain->properties->scale = $cnb_options['zoom'];
105
 
106
- if ($existing_domain !== null ) {
107
  return CnbAdminCloud::cnb_update_domain( $cnb_cloud_notifications, $domain );
108
  }
109
- return CnbAdminCloud::cnb_create_domain($cnb_cloud_notifications, $domain);
 
110
  }
111
 
112
  /**
@@ -116,8 +121,8 @@ class CnbMigration {
116
  *
117
  * @return CnbButton
118
  */
119
- public function createButton($domain) {
120
- $cnb_options = get_option('cnb');
121
 
122
  // We can skip all this if the phonenumber is empty and the button is disabled
123
  if ( empty( $cnb_options['number'] ) ) {
@@ -255,7 +260,7 @@ class CnbMigration {
255
  $is_enabled = $options && array_key_exists( 'active', $options ) && $options['active'] == 1;
256
 
257
  $button = new CnbButton();
258
- $button->name = 'Button created via Wordpress plugin';
259
  $button->domain = $domain;
260
  $button->active = ( $is_enabled && $has_a_number );
261
  $button->actions = $actions;
18
 
19
  /**
20
  * @param $cnbActivation CnbActivation
21
+ *
22
  * @return void
23
  */
24
+ public function createOrUpdateDomainAndButton( $cnbActivation ) {
25
  // Patch domain
26
+ $domain = $this->createOrUpdateDomain( $cnbActivation );
27
  $cnbActivation->domain = $domain;
28
 
29
  // Only migrate if this domain does not have any buttons
30
  $button = null;
31
+ if ( $this->shouldCreateButton( $domain ) ) {
32
  // Create / migrate legacy button
33
  $button = $this->createButton( $domain );
34
  }
35
+ $cnbActivation->button = $button;
36
+ $cnbActivation->success = ! is_wp_error( $domain ) && ! is_wp_error( $button );
37
  }
38
 
39
  /**
43
  *
44
  * @return bool
45
  */
46
+ private function shouldCreateButton( $domain ) {
47
  if ( is_wp_error( $domain ) ) {
48
  return false;
49
  }
50
 
51
  // Check if any buttons are for the current WP domain
52
  $buttons = CnbAppRemote::cnb_remote_get_buttons();
53
+ if ( is_wp_error( $buttons ) ) {
54
  // Could not retrieve Buttons
55
  return false;
56
  }
63
  return $button->domain->id === $domain->id;
64
  } );
65
 
66
+ return count( $cnb_cloud_buttons_this_domain ) === 0;
67
  }
68
 
69
  /**
70
  * Update the CallNowButton Cloud with a domain matching the WordPress Domain
71
  *
72
  * @param $cnbActivation CnbActivation
73
+ *
74
  * @return CnbDomain
75
  */
76
+ public function createOrUpdateDomain( $cnbActivation ) {
77
  $cnb_cloud_notifications = array();
78
 
79
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
80
+ if ( is_wp_error( $domain ) ) {
81
  $cnbActivation->domain_action = 'created';
82
+
83
  return $this->patchDomain( $cnb_cloud_notifications );
84
  }
85
  $cnbActivation->domain_action = 'updated';
86
+
87
  return $this->patchDomain( $cnb_cloud_notifications, $domain );
88
  }
89
 
96
  * @return CnbDomain|WP_Error
97
  */
98
  private function patchDomain( &$cnb_cloud_notifications, $existing_domain = null ) {
99
+ $cnb_options = get_option( 'cnb' );
100
 
101
  $domain = $existing_domain !== null ? $existing_domain : new CnbDomain();
102
  $domain->name = ( new CnbAppRemote() )->cnb_clean_site_url();
104
  $domain->trackConversion = isset( $cnb_options['conversions'] ) && $cnb_options['conversions'] != 0;
105
  $domain->properties = $existing_domain !== null ? $existing_domain->properties : new CnbDomainProperties();
106
  $domain->properties->allowMultipleButtons = $existing_domain !== null ? $existing_domain->properties->allowMultipleButtons : true;
107
+ $domain->properties->zindex = ( new CnbUtils() )->zindex( $cnb_options['z-index'] );
108
  $domain->properties->scale = $cnb_options['zoom'];
109
 
110
+ if ( $existing_domain !== null ) {
111
  return CnbAdminCloud::cnb_update_domain( $cnb_cloud_notifications, $domain );
112
  }
113
+
114
+ return CnbAdminCloud::cnb_create_domain( $cnb_cloud_notifications, $domain );
115
  }
116
 
117
  /**
121
  *
122
  * @return CnbButton
123
  */
124
+ public function createButton( $domain ) {
125
+ $cnb_options = get_option( 'cnb' );
126
 
127
  // We can skip all this if the phonenumber is empty and the button is disabled
128
  if ( empty( $cnb_options['number'] ) ) {
260
  $is_enabled = $options && array_key_exists( 'active', $options ) && $options['active'] == 1;
261
 
262
  $button = new CnbButton();
263
+ $button->name = 'Button created via WordPress plugin';
264
  $button->domain = $domain;
265
  $button->active = ( $is_enabled && $has_a_number );
266
  $button->actions = $actions;
src/admin/api/RemoteTrace.php CHANGED
@@ -51,7 +51,7 @@ class RemoteTrace {
51
  * @param $cacheHit boolean
52
  */
53
  public function setCacheHit( $cacheHit ) {
54
- // phpcs:ignore
55
  $this->cacheHit = boolval( $cacheHit );
56
  }
57
 
51
  * @param $cacheHit boolean
52
  */
53
  public function setCacheHit( $cacheHit ) {
54
+ // phpcs:ignore PHPCompatibility.FunctionUse
55
  $this->cacheHit = boolval( $cacheHit );
56
  }
57
 
src/admin/apikey/CnbApiKeyController.php CHANGED
@@ -9,6 +9,7 @@ use cnb\admin\api\CnbAdminCloud;
9
  use cnb\admin\api\CnbAppRemote;
10
  use cnb\notices\CnbAdminNotices;
11
  use cnb\notices\CnbNotice;
 
12
 
13
  class CnbApiKeyController {
14
  /**
@@ -49,39 +50,60 @@ class CnbApiKeyController {
49
  wp_safe_redirect( $redirect_url );
50
  exit;
51
  } else {
52
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
53
  'response' => 403,
54
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
55
  ) );
56
  }
57
  }
58
 
 
 
 
 
 
 
 
59
  public function delete() {
60
- if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
61
- $id = ! empty( $_GET['id'] ) ? sanitize_text_field( $_GET['id'] ) : null;
62
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
63
- $action = 'cnb_delete_apikey';
 
 
 
 
 
 
 
64
 
65
- if ( wp_verify_nonce( $nonce, $action ) ) {
66
- $adminNotices = CnbAdminNotices::get_instance();
67
- $cnb_cloud_notifications = array();
68
- $apikey = new CnbApiKey();
69
- $apikey->id = $id;
70
- CnbAdminCloud::cnb_delete_apikey( $cnb_cloud_notifications, $apikey );
71
- foreach ( $cnb_cloud_notifications as $cnb_cloud_notification ) {
72
- $adminNotices->renderNotice( $cnb_cloud_notification );
73
- }
74
- }
75
  }
76
  }
77
 
78
- // nonce name via WP_List_Table = bulk-{plural}
79
- // so, bulk-cnb_list_apikeys
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  public static function handle_bulk_actions() {
81
- $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
82
- if ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $nonce, 'bulk-cnb_list_apikeys' ) ) {
 
 
 
83
  $entityIds = filter_input( INPUT_POST, 'cnb_list_apikey', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
84
- if ( $_REQUEST['bulk-action'] === 'delete' ) {
85
  foreach ( $entityIds as $entityId ) {
86
  $apikey = new CnbApiKey();
87
  $apikey->id = $entityId;
@@ -104,12 +126,26 @@ class CnbApiKeyController {
104
  $url );
105
  $redirect_url = esc_url_raw( $redirect_link );
106
  wp_safe_redirect( $redirect_url );
 
 
 
 
 
 
 
 
 
 
107
  }
108
  } else {
109
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
110
- 'response' => 403,
111
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
112
- ) );
 
 
 
 
113
  }
114
  }
115
  }
9
  use cnb\admin\api\CnbAppRemote;
10
  use cnb\notices\CnbAdminNotices;
11
  use cnb\notices\CnbNotice;
12
+ use cnb\utils\CnbUtils;
13
 
14
  class CnbApiKeyController {
15
  /**
50
  wp_safe_redirect( $redirect_url );
51
  exit;
52
  } else {
53
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
54
  'response' => 403,
55
+ 'back_link' => true,
56
  ) );
57
  }
58
  }
59
 
60
+ /**
61
+ * This is the quick action where they can delete a single Action
62
+ *
63
+ * It is always called via/with $_GET parameters
64
+ *
65
+ * @return void
66
+ */
67
  public function delete() {
68
+ $cnb_utils = new CnbUtils();
69
+ $id = $cnb_utils->get_query_val( 'id', null );
70
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
71
+ $action = 'cnb_delete_apikey';
72
+ $nonce_verified = wp_verify_nonce( $nonce, $action );
73
+ if ( $nonce_verified ) {
74
+ $cnb_cloud_notifications = array();
75
+ $apikey = new CnbApiKey();
76
+ $adminNotices = CnbAdminNotices::get_instance();
77
+ $apikey->id = $id;
78
+ CnbAdminCloud::cnb_delete_apikey( $cnb_cloud_notifications, $apikey );
79
 
80
+ $adminNotices->notices( $cnb_cloud_notifications );
 
 
 
 
 
 
 
 
 
81
  }
82
  }
83
 
84
+ /**
85
+ * This is very similar to the <code>delete()</code> function above.
86
+ *
87
+ * This always has to come via a $_POST request (specifically, via admin-post.php),
88
+ * so this should end in a redirect (or an error via wp_die)
89
+ *
90
+ * Big differences are:
91
+ * - This handles multiple IDs, versus 1
92
+ * - Instead of rendering the Notice, is it stored and the user redirected
93
+ *
94
+ * nonce name via WP_List_Table = bulk-{plural}
95
+ * so in this case: bulk-cnb_list_apikeys
96
+ *
97
+ * @return void
98
+ */
99
  public static function handle_bulk_actions() {
100
+ $cnb_utils = new CnbUtils();
101
+ $nonce = $cnb_utils->get_post_val( '_wpnonce' );
102
+ $action = 'bulk-cnb_list_apikeys';
103
+ $nonce_verified = wp_verify_nonce( $nonce, $action );
104
+ if ( $nonce_verified ) {
105
  $entityIds = filter_input( INPUT_POST, 'cnb_list_apikey', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
106
+ if ( $cnb_utils->get_post_val( 'bulk-action' ) === 'delete' ) {
107
  foreach ( $entityIds as $entityId ) {
108
  $apikey = new CnbApiKey();
109
  $apikey->id = $entityId;
126
  $url );
127
  $redirect_url = esc_url_raw( $redirect_link );
128
  wp_safe_redirect( $redirect_url );
129
+ } else {
130
+ wp_die(
131
+ esc_html__( 'Unknown Bulk action specified' ),
132
+ esc_html__( 'Cannot process Bulk action' ),
133
+ array(
134
+ 'response' => 403,
135
+ 'link_text' => esc_html( 'Go back to the API Key overview' ),
136
+ 'link_url' => esc_url_raw( admin_url( 'admin.php' ) . '?page=' . CNB_SLUG . '-apikeys' ),
137
+ )
138
+ );
139
  }
140
  } else {
141
+ wp_die(
142
+ esc_html__( 'Invalid nonce specified' ),
143
+ esc_html__( 'Error' ),
144
+ array(
145
+ 'response' => 403,
146
+ 'back_link' => true,
147
+ )
148
+ );
149
  }
150
  }
151
  }
src/admin/apikey/CnbApiKeyView.php CHANGED
@@ -22,10 +22,10 @@ class CnbApiKeyView {
22
  $url );
23
  printf(
24
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal page-title-action" data-title="%s">%s</a>',
25
- $new_link,
26
- __( 'Create new API key', CNB_NAME ),
27
- __( 'Create new API key', CNB_NAME ),
28
- __( 'Add New', CNB_NAME )
29
  );
30
  }
31
 
@@ -60,7 +60,8 @@ class CnbApiKeyView {
60
  <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
61
  <input type="hidden" name="page" value="call-now-button-apikeys"/>
62
  <input type="hidden" name="action" value="cnb_apikey_create"/>
63
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'cnb_apikey_create' ) ?>"/>
 
64
 
65
  <table>
66
  <tbody>
22
  $url );
23
  printf(
24
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal page-title-action" data-title="%s">%s</a>',
25
+ esc_url( $new_link ),
26
+ esc_html__( 'Create new API key' ),
27
+ esc_html__( 'Create new API key' ),
28
+ esc_html__( 'Add New' )
29
  );
30
  }
31
 
60
  <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
61
  <input type="hidden" name="page" value="call-now-button-apikeys"/>
62
  <input type="hidden" name="action" value="cnb_apikey_create"/>
63
+ <input type="hidden" name="_wpnonce"
64
+ value="<?php echo esc_attr( wp_create_nonce( 'cnb_apikey_create' ) ) ?>"/>
65
 
66
  <table>
67
  <tbody>
src/admin/apikey/Cnb_Apikey_List_Table.php CHANGED
@@ -6,7 +6,7 @@ namespace cnb\admin\apikey;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
@@ -16,6 +16,11 @@ use WP_List_Table;
16
 
17
  class Cnb_Apikey_List_Table extends WP_List_Table {
18
 
 
 
 
 
 
19
  /**
20
  * Constructor, we override the parent to pass our own arguments
21
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
@@ -27,6 +32,8 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
27
  'ajax' => false, //We don't support Ajax for this table
28
  'screen' => 'call-now-button-apikeys' // Screen name for bulk actions, etc
29
  ) );
 
 
30
  }
31
 
32
  /**
@@ -74,7 +81,7 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
74
  $totalitems = count( $data ); //return the total number of affected rows
75
  $per_page = 20; //How many to display per page?
76
  //Which page is this?
77
- $current_page = ! empty( $_GET['paged'] ) ? (int) sanitize_text_field( $_GET['paged'] ) : 1;
78
 
79
  //Page Number
80
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
@@ -123,7 +130,7 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
123
  case 'created':
124
  case 'lastUsed':
125
  case 'updateTime':
126
- return esc_html( (new CnbUtils())->cnb_timestamp_to_string( $item->$column_name ) );
127
  default:
128
  return '<em>Unknown column ' . esc_html( $column_name ) . '</em>';
129
  }
@@ -143,9 +150,9 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
143
  */
144
  private function sort_data( $a, $b ) {
145
  // If orderby is set, use this as the sort column
146
- $orderby = ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'name';
147
  // If order is set use this as the order
148
- $order = ! empty( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'asc';
149
 
150
  $result = strcmp( $a->$orderby, $b->$orderby );
151
 
@@ -178,6 +185,6 @@ class Cnb_Apikey_List_Table extends WP_List_Table {
178
  }
179
 
180
  function no_items() {
181
- _e( 'No API keys found.' );
182
  }
183
  }
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
16
 
17
  class Cnb_Apikey_List_Table extends WP_List_Table {
18
 
19
+ /**
20
+ * @var CnbUtils
21
+ */
22
+ private $cnb_utils;
23
+
24
  /**
25
  * Constructor, we override the parent to pass our own arguments
26
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
32
  'ajax' => false, //We don't support Ajax for this table
33
  'screen' => 'call-now-button-apikeys' // Screen name for bulk actions, etc
34
  ) );
35
+
36
+ $this->cnb_utils = new CnbUtils();
37
  }
38
 
39
  /**
81
  $totalitems = count( $data ); //return the total number of affected rows
82
  $per_page = 20; //How many to display per page?
83
  //Which page is this?
84
+ $current_page = (int) $this->cnb_utils->get_query_val( 'paged', '1' );
85
 
86
  //Page Number
87
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
130
  case 'created':
131
  case 'lastUsed':
132
  case 'updateTime':
133
+ return esc_html( ( new CnbUtils() )->cnb_timestamp_to_string( $item->$column_name ) );
134
  default:
135
  return '<em>Unknown column ' . esc_html( $column_name ) . '</em>';
136
  }
150
  */
151
  private function sort_data( $a, $b ) {
152
  // If orderby is set, use this as the sort column
153
+ $orderby = $this->cnb_utils->get_query_val( 'orderby', 'name' );
154
  // If order is set use this as the order
155
+ $order = $this->cnb_utils->get_query_val( 'order', 'asc' );
156
 
157
  $result = strcmp( $a->$orderby, $b->$orderby );
158
 
185
  }
186
 
187
  function no_items() {
188
+ esc_html_e( 'No API keys found.' );
189
  }
190
  }
src/admin/button/CnbButton.php CHANGED
@@ -93,13 +93,13 @@ class CnbButton implements JsonSerializable {
93
  *
94
  * @return void
95
  */
96
- private static function validate($button) {
97
  if ( strtoupper( $button->type ) !== 'FULL' ) {
98
  return;
99
  }
100
 
101
  // If empty, set a default for FULL
102
- if (empty($button->options->placement)) {
103
  $button->options->placement = 'BOTTOM_CENTER';
104
  }
105
 
@@ -113,7 +113,7 @@ class CnbButton implements JsonSerializable {
113
  // Actions should be string[]
114
  $actions = array();
115
  if ( is_array( $this->actions ) ) {
116
- $actions = (new CnbUtils())->cnb_array_column( $this->actions, 'id' );
117
  }
118
  $actions = array_filter( $actions, function ( $action ) {
119
  return ! empty( $action );
@@ -122,7 +122,7 @@ class CnbButton implements JsonSerializable {
122
  // Conditions should be string[]
123
  $conditions = array();
124
  if ( is_array( $this->conditions ) ) {
125
- $conditions = (new CnbUtils())->cnb_array_column( $this->conditions, 'id' );
126
  }
127
  $conditions = array_filter( $conditions, function ( $condition ) {
128
  return ! empty( $condition );
@@ -170,7 +170,7 @@ class CnbButton implements JsonSerializable {
170
 
171
  $button = new CnbButton();
172
  $button->id = CnbUtils::getPropertyOrNull( $object, 'id' );
173
- // phpcs:ignore
174
  $button->active = boolval( CnbUtils::getPropertyOrNull( $object, 'active' ) );
175
  $button->name = CnbUtils::getPropertyOrNull( $object, 'name' );
176
  $button->type = CnbUtils::getPropertyOrNull( $object, 'type' );
@@ -191,7 +191,8 @@ class CnbButton implements JsonSerializable {
191
  // Convert "stdClass" actions into Action classes
192
  $button->actions = CnbAction::fromObjects( $button->actions );
193
 
194
- self::validate($button);
 
195
  return $button;
196
  }
197
 
93
  *
94
  * @return void
95
  */
96
+ private static function validate( $button ) {
97
  if ( strtoupper( $button->type ) !== 'FULL' ) {
98
  return;
99
  }
100
 
101
  // If empty, set a default for FULL
102
+ if ( empty( $button->options->placement ) ) {
103
  $button->options->placement = 'BOTTOM_CENTER';
104
  }
105
 
113
  // Actions should be string[]
114
  $actions = array();
115
  if ( is_array( $this->actions ) ) {
116
+ $actions = ( new CnbUtils() )->cnb_array_column( $this->actions, 'id' );
117
  }
118
  $actions = array_filter( $actions, function ( $action ) {
119
  return ! empty( $action );
122
  // Conditions should be string[]
123
  $conditions = array();
124
  if ( is_array( $this->conditions ) ) {
125
+ $conditions = ( new CnbUtils() )->cnb_array_column( $this->conditions, 'id' );
126
  }
127
  $conditions = array_filter( $conditions, function ( $condition ) {
128
  return ! empty( $condition );
170
 
171
  $button = new CnbButton();
172
  $button->id = CnbUtils::getPropertyOrNull( $object, 'id' );
173
+ // phpcs:ignore PHPCompatibility.FunctionUse
174
  $button->active = boolval( CnbUtils::getPropertyOrNull( $object, 'active' ) );
175
  $button->name = CnbUtils::getPropertyOrNull( $object, 'name' );
176
  $button->type = CnbUtils::getPropertyOrNull( $object, 'type' );
191
  // Convert "stdClass" actions into Action classes
192
  $button->actions = CnbAction::fromObjects( $button->actions );
193
 
194
+ self::validate( $button );
195
+
196
  return $button;
197
  }
198
 
src/admin/button/CnbButtonController.php CHANGED
@@ -11,6 +11,7 @@ use cnb\admin\api\CnbAppRemote;
11
  use cnb\admin\condition\CnbCondition;
12
  use cnb\notices\CnbAdminNotices;
13
  use cnb\notices\CnbNotice;
 
14
 
15
  class CnbButtonController {
16
 
@@ -63,9 +64,9 @@ class CnbButtonController {
63
  $closure( $processed_button, $processed_actions, $processed_conditions );
64
  // end processing
65
  } else {
66
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
67
  'response' => 403,
68
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
69
  ) );
70
  }
71
 
@@ -164,29 +165,28 @@ class CnbButtonController {
164
  * @return void
165
  */
166
  public function enable_disable() {
 
167
  // "enable" or "disable"
168
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
169
- if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
170
- $id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
171
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
172
-
173
- if ( wp_verify_nonce( $nonce, 'cnb_enable_disable_button' ) ) {
174
- $active = $action === 'enable';
175
- $action_verb = $active ? 'enable' : 'disable';
176
- $action_name = __( $action_verb . 'd' );
177
 
178
- $button = CnbAppRemote::cnb_remote_get_button_full( $id );
179
- $button->active = $active;
180
 
181
- $updated_button = CnbAppRemote::cnb_remote_update_button( $button );
182
 
183
- if ( ! is_wp_error( $updated_button ) ) {
184
- $notice = new CnbNotice( 'success', '<p>Button <strong>' . esc_html( $updated_button->name ) . '</strong> ' . $action_name . '.</p>', true );
185
- } else {
186
- $notice = CnbAdminCloud::cnb_admin_get_error_message( $action_verb, 'button', $updated_button );
187
- }
188
- CnbAdminNotices::get_instance()->renderNotice( $notice );
189
  }
 
190
  }
191
  }
192
 
@@ -194,36 +194,53 @@ class CnbButtonController {
194
  * Via the quick actions, be able to delete a Condition
195
  *
196
  * This also means we CANNOT redirect, as we're already halfway into rendering the page,
197
- * so we show the notification immediatly
198
  *
199
  * @return void
200
  */
201
  public static function delete() {
202
- $id = ! empty( $_REQUEST['id'] ) ? sanitize_text_field( $_REQUEST['id'] ) : null;
203
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
 
204
  $action = 'cnb_delete_button';
205
  $nonce_verified = wp_verify_nonce( $nonce, $action );
206
 
207
  if ( $nonce_verified ) {
 
208
  $cnb_cloud_notifications = array();
209
  $button = new CnbButton();
210
  $button->id = $id;
211
  CnbAdminCloud::cnb_delete_button( $cnb_cloud_notifications, $button );
212
- CnbAdminNotices::get_instance()->renderNotices( $cnb_cloud_notifications );
213
  }
214
  }
215
 
216
  /**
217
- * called via admin-post, so this should end in a redirect (or error)
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  * @return void
219
  */
220
  public static function handle_bulk_actions() {
221
- $current_action = filter_input( INPUT_POST, 'bulk-action', FILTER_SANITIZE_STRING );
222
- $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
223
  $action = 'bulk-cnb_list_buttons';
224
  $nonce_verified = wp_verify_nonce( $nonce, $action );
 
225
  if ( $nonce_verified ) {
226
- $buttonIds = filter_input( INPUT_POST, 'cnb_list_button', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
 
227
 
228
  switch ( $current_action ) {
229
  case 'enable':
@@ -234,7 +251,7 @@ class CnbButtonController {
234
  $button->active = $current_action === 'enable';
235
  CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button );
236
  }
237
- $action_name = __( $current_action . 'd' );
238
 
239
  // Create notice for link (and yes - we ignore the content of $cnb_cloud_notifications here, we just use it to count)
240
  $notice = new CnbNotice( 'success', '<p>' . count( $cnb_cloud_notifications ) . ' Buttons ' . $action_name . '.</p>' );
@@ -247,6 +264,8 @@ class CnbButtonController {
247
  }
248
  $notice = new CnbNotice( 'success', '<p>' . count( $buttonIds ) . ' Button(s) deleted.</p>' );
249
  break;
 
 
250
  }
251
  $transient_id = null;
252
  if ( $notice ) {
@@ -266,11 +285,14 @@ class CnbButtonController {
266
  $redirect_url = esc_url_raw( $redirect_link );
267
  wp_safe_redirect( $redirect_url );
268
  } else {
269
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
270
- 'response' => 403,
271
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
272
- ) );
 
 
 
 
273
  }
274
  }
275
-
276
- }
11
  use cnb\admin\condition\CnbCondition;
12
  use cnb\notices\CnbAdminNotices;
13
  use cnb\notices\CnbNotice;
14
+ use cnb\utils\CnbUtils;
15
 
16
  class CnbButtonController {
17
 
64
  $closure( $processed_button, $processed_actions, $processed_conditions );
65
  // end processing
66
  } else {
67
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
68
  'response' => 403,
69
+ 'back_link' => true,
70
  ) );
71
  }
72
 
165
  * @return void
166
  */
167
  public function enable_disable() {
168
+ $cnb_utils = new CnbUtils();
169
  // "enable" or "disable"
170
+ $action = $cnb_utils->get_query_val( 'action', null );
171
+ $id = $cnb_utils->get_query_val( 'id', null );
172
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
173
+ $nonce_verified = wp_verify_nonce( $nonce, 'cnb_enable_disable_button' );
174
+ if ( $nonce_verified ) {
175
+ $active = $action === 'enable';
176
+ $action_verb = $active ? 'enable' : 'disable';
177
+ $action_name = $action_verb . 'd';
 
178
 
179
+ $button = CnbAppRemote::cnb_remote_get_button_full( $id );
180
+ $button->active = $active;
181
 
182
+ $updated_button = CnbAppRemote::cnb_remote_update_button( $button );
183
 
184
+ if ( ! is_wp_error( $updated_button ) ) {
185
+ $notice = new CnbNotice( 'success', '<p>Button <strong>' . esc_html( $updated_button->name ) . '</strong> ' . $action_name . '.</p>', true );
186
+ } else {
187
+ $notice = CnbAdminCloud::cnb_admin_get_error_message( $action_verb, 'button', $updated_button );
 
 
188
  }
189
+ CnbAdminNotices::get_instance()->notice( $notice );
190
  }
191
  }
192
 
194
  * Via the quick actions, be able to delete a Condition
195
  *
196
  * This also means we CANNOT redirect, as we're already halfway into rendering the page,
197
+ * so we add the notification to the adminNotices handler
198
  *
199
  * @return void
200
  */
201
  public static function delete() {
202
+ $cnb_utils = new CnbUtils();
203
+ $id = $cnb_utils->get_query_val( 'id', null );
204
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
205
  $action = 'cnb_delete_button';
206
  $nonce_verified = wp_verify_nonce( $nonce, $action );
207
 
208
  if ( $nonce_verified ) {
209
+ $adminNotices = CnbAdminNotices::get_instance();
210
  $cnb_cloud_notifications = array();
211
  $button = new CnbButton();
212
  $button->id = $id;
213
  CnbAdminCloud::cnb_delete_button( $cnb_cloud_notifications, $button );
214
+ $adminNotices->notices( $cnb_cloud_notifications );
215
  }
216
  }
217
 
218
  /**
219
+ * In addition to delete(), this also handles the bulk enable/disable action.
220
+ *
221
+ * This is very similar to the <code>delete()</code> function above.
222
+ *
223
+ * This always has to come via a $_POST request (specifically, via admin-post.php),
224
+ * so this should end in a redirect (or an error via wp_die)
225
+ *
226
+ * Big differences are:
227
+ * - This handles multiple IDs, versus 1
228
+ * - Instead of rendering the Notice, is it stored and the user redirected
229
+ *
230
+ * nonce name via WP_List_Table = bulk-{plural}
231
+ * so in this case: bulk-cnb_list_buttons
232
+ *
233
  * @return void
234
  */
235
  public static function handle_bulk_actions() {
236
+ $cnb_utils = new CnbUtils();
237
+ $nonce = $cnb_utils->get_post_val( '_wpnonce' );
238
  $action = 'bulk-cnb_list_buttons';
239
  $nonce_verified = wp_verify_nonce( $nonce, $action );
240
+
241
  if ( $nonce_verified ) {
242
+ $buttonIds = filter_input( INPUT_POST, 'cnb_list_button', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
243
+ $current_action = filter_input( INPUT_POST, 'bulk-action', FILTER_SANITIZE_STRING );
244
 
245
  switch ( $current_action ) {
246
  case 'enable':
251
  $button->active = $current_action === 'enable';
252
  CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button );
253
  }
254
+ $action_name = $current_action . 'd';
255
 
256
  // Create notice for link (and yes - we ignore the content of $cnb_cloud_notifications here, we just use it to count)
257
  $notice = new CnbNotice( 'success', '<p>' . count( $cnb_cloud_notifications ) . ' Buttons ' . $action_name . '.</p>' );
264
  }
265
  $notice = new CnbNotice( 'success', '<p>' . count( $buttonIds ) . ' Button(s) deleted.</p>' );
266
  break;
267
+ default:
268
+ $notice = null;
269
  }
270
  $transient_id = null;
271
  if ( $notice ) {
285
  $redirect_url = esc_url_raw( $redirect_link );
286
  wp_safe_redirect( $redirect_url );
287
  } else {
288
+ wp_die(
289
+ esc_html__( 'Invalid nonce specified' ),
290
+ esc_html__( 'Error' ),
291
+ array(
292
+ 'response' => 403,
293
+ 'back_link' => true,
294
+ )
295
+ );
296
  }
297
  }
298
+ }
 
src/admin/button/CnbButtonRouter.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace cnb\admin\button;
4
 
5
  // don't load directly
 
 
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  class CnbButtonRouter {
@@ -13,7 +15,7 @@ class CnbButtonRouter {
13
  * @return void
14
  */
15
  public static function render() {
16
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
17
  switch ( $action ) {
18
  case 'edit':
19
  ( new CnbButtonViewEdit() )->render();
3
  namespace cnb\admin\button;
4
 
5
  // don't load directly
6
+ use cnb\utils\CnbUtils;
7
+
8
  defined( 'ABSPATH' ) || die( '-1' );
9
 
10
  class CnbButtonRouter {
15
  * @return void
16
  */
17
  public static function render() {
18
+ $action = ( new CnbUtils() )->get_query_val( 'action', null );
19
  switch ( $action ) {
20
  case 'edit':
21
  ( new CnbButtonViewEdit() )->render();
src/admin/button/CnbButtonView.php CHANGED
@@ -38,10 +38,10 @@ class CnbButtonView {
38
  $url = $this->get_modal_link();
39
  printf(
40
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal %s" id="cnb-button-overview-modal-add-new" data-title="%s">%s</a>',
41
- $url,
42
- __( 'Create new button' ),
43
  'page-title-action',
44
- __( 'Choose a Button type' ),
45
  esc_html__( 'Add New' )
46
  );
47
  }
@@ -51,13 +51,13 @@ class CnbButtonView {
51
  *
52
  * @return void
53
  */
54
- public function get_lets_create_one_link() {
55
  $url = $this->get_modal_link();
56
  printf(
57
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal" id="cnb-button-overview-modal-add-new" data-title="%s">%s</a>',
58
- $url,
59
- __( 'Create new button' ),
60
- __( 'Choose a Button type' ),
61
  esc_html__( 'Let\'s create one!' )
62
  );
63
  }
@@ -69,7 +69,7 @@ class CnbButtonView {
69
  * @return void
70
  */
71
  private function set_button_filter( $domain, $table ) {
72
- $cnb_options = get_option('cnb');
73
  if ( isset( $cnb_options['show_all_buttons_for_domain'] )
74
  && $cnb_options['show_all_buttons_for_domain'] != 1
75
  && $domain != null
@@ -133,24 +133,24 @@ class CnbButtonView {
133
  }
134
 
135
  private function render_promos( $domain ) {
136
- $upgrade_url = (new CnbUtils())->get_cnb_domain_upgrade( $domain );
137
  if ( isset( $upgrade_url ) && $upgrade_url ) {
138
  echo '<div class="cnb-postbox-container cnb-side-column"> <!-- Sidebar promo boxes -->';
139
  if ( $domain !== null && ! ( $domain instanceof WP_Error ) && $domain->type === 'FREE' ) {
140
  echo '<!-- Sidebar messages -->';
141
- (new CnbAdminFunctions())->cnb_promobox(
142
- 'blue',
143
- 'Introduction offer',
144
  '<p>Remove the <em>powered by</em> branding from your buttons!</p>
145
- <p>Benefit from our introductory offer and enjoy unlimited access to all features without our branding.</p>',
146
  'flag',
147
  '<strong>&euro;<span class="eur-per-month"></span>/$<span class="usd-per-month"></span> per month</strong>',
148
  'Upgrade',
149
  $upgrade_url
150
  );
151
  }
152
- (new CnbAdminFunctions())->cnb_promobox(
153
- 'grey',
154
  'Need help?',
155
  '<p>Please head over to our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a> for all your questions.</p>
156
  <p>&check; <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a></p>
@@ -188,7 +188,8 @@ class CnbButtonView {
188
  }
189
 
190
  private function render_thickbox_quick_action() {
191
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
 
192
  if ( $action === 'new' ) {
193
  ?>
194
  <script>jQuery(function () {
@@ -209,4 +210,4 @@ class CnbButtonView {
209
  <?php
210
  }
211
  }
212
- }
38
  $url = $this->get_modal_link();
39
  printf(
40
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal %s" id="cnb-button-overview-modal-add-new" data-title="%s">%s</a>',
41
+ esc_url( $url ),
42
+ esc_html__( 'Create new button' ),
43
  'page-title-action',
44
+ esc_html__( 'Choose a Button type' ),
45
  esc_html__( 'Add New' )
46
  );
47
  }
51
  *
52
  * @return void
53
  */
54
+ public function render_lets_create_one_link() {
55
  $url = $this->get_modal_link();
56
  printf(
57
  '<a href="%s" title="%s" class="thickbox open-plugin-details-modal" id="cnb-button-overview-modal-add-new" data-title="%s">%s</a>',
58
+ esc_url( $url ),
59
+ esc_html__( 'Create new button' ),
60
+ esc_html__( 'Choose a Button type' ),
61
  esc_html__( 'Let\'s create one!' )
62
  );
63
  }
69
  * @return void
70
  */
71
  private function set_button_filter( $domain, $table ) {
72
+ $cnb_options = get_option( 'cnb' );
73
  if ( isset( $cnb_options['show_all_buttons_for_domain'] )
74
  && $cnb_options['show_all_buttons_for_domain'] != 1
75
  && $domain != null
133
  }
134
 
135
  private function render_promos( $domain ) {
136
+ $upgrade_url = ( new CnbUtils() )->get_cnb_domain_upgrade( $domain );
137
  if ( isset( $upgrade_url ) && $upgrade_url ) {
138
  echo '<div class="cnb-postbox-container cnb-side-column"> <!-- Sidebar promo boxes -->';
139
  if ( $domain !== null && ! ( $domain instanceof WP_Error ) && $domain->type === 'FREE' ) {
140
  echo '<!-- Sidebar messages -->';
141
+ ( new CnbAdminFunctions() )->cnb_promobox(
142
+ 'purple',
143
+ '50% off the annual plan!',
144
  '<p>Remove the <em>powered by</em> branding from your buttons!</p>
145
+ <p>Benefit from this temporary offer and enjoy unlimited access to all features and publish your buttons without branding.</p>',
146
  'flag',
147
  '<strong>&euro;<span class="eur-per-month"></span>/$<span class="usd-per-month"></span> per month</strong>',
148
  'Upgrade',
149
  $upgrade_url
150
  );
151
  }
152
+ ( new CnbAdminFunctions() )->cnb_promobox(
153
+ 'blue',
154
  'Need help?',
155
  '<p>Please head over to our <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a> for all your questions.</p>
156
  <p>&check; <a href="https://callnowbutton.com/support/" target="_blank">Help Center</a></p>
188
  }
189
 
190
  private function render_thickbox_quick_action() {
191
+ $cnb_utils = new CnbUtils();
192
+ $action = $cnb_utils->get_query_val( 'action', null );
193
  if ( $action === 'new' ) {
194
  ?>
195
  <script>jQuery(function () {
210
  <?php
211
  }
212
  }
213
+ }
src/admin/button/CnbButtonViewEdit.php CHANGED
@@ -18,11 +18,6 @@ use stdClass;
18
  use WP_Error;
19
 
20
  class CnbButtonViewEdit {
21
- function get_active_tab_name() {
22
- // using filter_var instead of filter_input, so we can do some "just in time" rewriting of the tab variable if needed
23
- return isset( $_GET['tab'] ) ? filter_var( $_GET['tab'], FILTER_SANITIZE_STRING ) : 'basic_options';
24
- }
25
-
26
  /**
27
  * Renders the "Edit <type>" header
28
  *
@@ -31,14 +26,14 @@ class CnbButtonViewEdit {
31
  function header( $button ) {
32
  $type = strtoupper( filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING ) );
33
  $name = 'New Button';
34
- if ( $button && !is_wp_error($button) ) {
35
  $type = $button->type;
36
  $name = $button->name;
37
  }
38
  $adminFunctions = new CnbAdminFunctions();
39
- $buttonTypes = $adminFunctions->cnb_get_button_types();
40
- $typeName = $buttonTypes[ $type ];
41
- echo __( 'Editing ' ) . esc_html( $typeName ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
42
  }
43
 
44
  /**
@@ -48,19 +43,17 @@ class CnbButtonViewEdit {
48
  * @return string
49
  */
50
  private function get_tab_url( $button, $tab ) {
51
- $url = admin_url( 'admin.php' );
52
- $tab_link =
53
- add_query_arg(
54
- array(
55
- 'page' => 'call-now-button',
56
- 'action' => 'edit',
57
- 'type' => strtolower( $button->type ),
58
- 'id' => $button->id,
59
- 'tab' => $tab
60
- ),
61
- $url );
62
-
63
- return esc_url( $tab_link );
64
  }
65
 
66
  /**
@@ -70,17 +63,17 @@ class CnbButtonViewEdit {
70
  * @param $button_id int
71
  * @param $button CnbButton
72
  * @param $default_domain CnbDomain|WP_Error
73
- * @param $options array
74
  *
75
  * @return void
76
  */
77
  public function render_form( $button_id, $button, $default_domain, $options = array() ) {
78
  $adminFunctions = new CnbAdminFunctions();
79
- $domains = CnbAppRemote::cnb_remote_get_domains();
80
 
81
- $cnb_single_image = esc_url( plugins_url( '../../../resources/images/button-new-single.png', __FILE__ ) );
82
- $cnb_multi_image = esc_url( plugins_url( '../../../resources/images/button-new-multi.png', __FILE__ ) );
83
- $cnb_full_image = esc_url( plugins_url( '../../../resources/images/button-new-full.png', __FILE__ ) );
84
 
85
  $submit_button_text = array_key_exists( 'submit_button_text', $options ) ? $options['submit_button_text'] : '';
86
  $hide_on_modal = array_key_exists( 'modal_view', $options ) && $options['modal_view'] === true;
@@ -100,7 +93,6 @@ class CnbButtonViewEdit {
100
  'bid' => $button->id
101
  ),
102
  $url );
103
- $new_action_url = esc_url( $new_action_link );
104
 
105
  $new_condition_link =
106
  add_query_arg(
@@ -111,7 +103,7 @@ class CnbButtonViewEdit {
111
  'bid' => $button->id
112
  ),
113
  $url );
114
- $new_condition_url = esc_url( $new_condition_link );
115
  // In case the API isn't working properly
116
  if ( $default_domain instanceof WP_Error ) {
117
  $default_domain = new CnbDomain();
@@ -130,15 +122,16 @@ class CnbButtonViewEdit {
130
  ?>
131
  <script>
132
  let cnb_css_root = '<?php echo esc_js( CnbAppRemote::cnb_get_static_base() ) ?>';
133
- let cnb_options = <?php echo json_encode( new stdClass() ) ?>;
134
  </script>
135
  <form class="cnb-container <?php if ( ! $hide_on_modal ) { ?>cnb-validation<?php } ?>"
136
  action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
137
  <input type="hidden" name="page" value="call-now-button"/>
138
  <input type="hidden" name="action"
139
- value="<?php echo $button_id === 'new' ? 'cnb_create_' . esc_attr(strtolower( $button->type )) . '_button' : 'cnb_update_' . esc_attr( strtolower( $button->type ) ) . '_button' ?>"/>
140
- <input type="hidden" name="_wpnonce_button" value="<?php echo wp_create_nonce( 'cnb-button-edit' ) ?>"/>
141
- <input type="hidden" name="tab" value="<?php echo esc_attr( $this->get_active_tab_name() ) ?>"/>
 
142
 
143
  <input type="hidden" name="button[id]" value="<?php echo esc_attr( $button->id ) ?>"/>
144
  <input type="hidden" name="button[type]" value="<?php echo esc_attr( $button->type ) ?>" id="button_type"/>
@@ -146,7 +139,7 @@ class CnbButtonViewEdit {
146
  <input type="hidden" name="button[domain]" value="<?php echo esc_attr( $default_domain->id ) ?>"/>
147
 
148
  <table class="form-table <?php if ( ! $hide_on_modal ) {
149
- echo $adminFunctions->is_active_tab( 'basic_options' );
150
  } else {
151
  echo 'nav-tab-only';
152
  } ?>" data-tab-name="basic_options">
@@ -186,7 +179,7 @@ class CnbButtonViewEdit {
186
  value="<?php echo esc_attr( $domain->id ) ?>">
187
  <?php echo esc_html( $domain->name ) ?>
188
  <?php if ( $domain->id == $default_domain->id ) {
189
- echo ' (current Wordpress domain)';
190
  } ?>
191
  </option>
192
  <?php } ?>
@@ -197,7 +190,7 @@ class CnbButtonViewEdit {
197
  <tr class="cnb_hide_on_modal">
198
  <th colspan="2" class="cnb_padding_0">
199
  <h2>
200
- Actions <?php echo '<a href="' . $new_action_url . '" class="page-title-action">Add Action</a>'; ?></h2>
201
  </th>
202
  </tr>
203
  <?php }
@@ -233,7 +226,7 @@ class CnbButtonViewEdit {
233
 
234
  <!-- This div exists to allow rendering the Action table outside the existing table -->
235
  <div data-tab-name="basic_options" class="cnb-button-edit-action-table <?php if ( $hide_on_modal ) {
236
- echo $adminFunctions->is_active_tab( 'basic_options' );
237
  } else {
238
  echo 'nav-tab-only';
239
  } ?>" <?php if ( ! $adminFunctions->is_active_tab( 'basic_options' ) ) {
@@ -243,14 +236,14 @@ class CnbButtonViewEdit {
243
  </div>
244
 
245
  <table class="form-table <?php if ( ! $hide_on_modal ) {
246
- echo $adminFunctions->is_active_tab( 'basic_options' );
247
  } else {
248
  echo 'nav-tab-only';
249
  } ?>"><?php
250
  } ?>
251
  <script>
252
- let cnb_actions = <?php echo json_encode( $button->actions ) ?>;
253
- let cnb_domain = <?php echo json_encode( $button->domain ) ?>;
254
  </script>
255
 
256
  <?php if ( $button_id === 'new' ) { ?>
@@ -263,17 +256,17 @@ class CnbButtonViewEdit {
263
  <div class="cnb_type_selector_item cnb_type_selector_single cnb_type_selector_active"
264
  data-cnb-selection="single">
265
  <img style="max-width:100%;" alt="Choose a Single button type"
266
- src="<?php echo $cnb_single_image ?>">
267
  <div style="text-align:center">Single button</div>
268
  </div>
269
  <div class="cnb_type_selector_item cnb_type_selector_multi" data-cnb-selection="multi">
270
  <img style="max-width:100%;" alt="Choose a Multibutton type"
271
- src="<?php echo $cnb_multi_image ?>">
272
  <div style="text-align:center">Multibutton</div>
273
  </div>
274
  <div class="cnb_type_selector_item cnb_type_selector_full" data-cnb-selection="full">
275
  <img style="max-width:100%;" alt="Choose a Full button type"
276
- src="<?php echo $cnb_full_image ?>">
277
  <div style="text-align:center">Buttonbar</div>
278
  </div>
279
  </div>
@@ -281,7 +274,8 @@ class CnbButtonViewEdit {
281
  </tr>
282
  <?php } ?>
283
  </table>
284
- <table class="form-table <?php echo $adminFunctions->is_active_tab( 'extra_options' ) ?>" data-tab-name="extra_options">
 
285
  <?php if ( $button->type === 'FULL' ) { ?>
286
  <tr>
287
  <th colspan="2">
@@ -475,7 +469,7 @@ class CnbButtonViewEdit {
475
  <?php } ?>
476
  <tr>
477
  <th scope="row">Position <a
478
- href="<?php echo CNB_SUPPORT; ?>button-position/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "button-position" ); ?>"
479
  target="_blank" class="cnb-nounderscore">
480
  <span class="dashicons dashicons-editor-help"></span>
481
  </a></th>
@@ -511,28 +505,28 @@ class CnbButtonViewEdit {
511
 
512
  <!-- Extra placement options -->
513
  <br class="cnb-extra-placement">
514
- <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == "MIDDLE_RIGHT" ? "cnb-extra-active" : ""; ?>">
515
  <input type="radio" id="appearance5" name="button[options][placement]"
516
  value="MIDDLE_RIGHT" <?php checked( 'MIDDLE_RIGHT', $button->options->placement ); ?>>
517
  <label title="middle-right" for="appearance5">Middle right</label>
518
  </div>
519
- <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == "MIDDLE_LEFT" ? "cnb-extra-active" : ""; ?>">
520
  <input type="radio" id="appearance6" name="button[options][placement]"
521
  value="MIDDLE_LEFT" <?php checked( 'MIDDLE_LEFT', $button->options->placement ); ?>>
522
  <label title="middle-left" for="appearance6">Middle left </label>
523
  </div>
524
  <br class="cnb-extra-placement">
525
- <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == "TOP_RIGHT" ? "cnb-extra-active" : ""; ?>">
526
  <input type="radio" id="appearance7" name="button[options][placement]"
527
  value="TOP_RIGHT" <?php checked( 'TOP_RIGHT', $button->options->placement ); ?>>
528
  <label title="top-right" for="appearance7">Top right corner</label>
529
  </div>
530
- <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == "TOP_LEFT" ? "cnb-extra-active" : ""; ?>">
531
  <input type="radio" id="appearance8" name="button[options][placement]"
532
  value="TOP_LEFT" <?php checked( 'TOP_LEFT', $button->options->placement ); ?>>
533
  <label title="top-left" for="appearance8">Top left corner</label>
534
  </div>
535
- <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == "TOP_CENTER" ? "cnb-extra-active" : ""; ?>">
536
  <input type="radio" id="appearance9" name="button[options][placement]"
537
  value="TOP_CENTER" <?php checked( 'TOP_CENTER', $button->options->placement ); ?>>
538
  <label title="top-center" for="appearance9">Center top</label>
@@ -546,7 +540,7 @@ class CnbButtonViewEdit {
546
  <?php if ( $button->type !== 'FULL' ) { ?>
547
  <tr>
548
  <th scope="row"><label for="button_options_animation">Button animation <a
549
- href="<?php echo CNB_SUPPORT; ?>wordpress/buttons/button-animation/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "button-animation" ); ?>"
550
  target="_blank" class="cnb-nounderscore">
551
  <span class="dashicons dashicons-editor-help"></span>
552
  </a></label></th>
@@ -560,7 +554,8 @@ class CnbButtonViewEdit {
560
  </tr>
561
  <?php } ?>
562
  </table>
563
- <table class="form-table <?php echo $adminFunctions->is_active_tab( 'visibility' ) ?>" data-tab-name="visibility">
 
564
  <tbody id="cnb_form_table_visibility">
565
  <tr>
566
  <th></th>
@@ -587,15 +582,15 @@ class CnbButtonViewEdit {
587
  <h2>Page rules</h2>
588
  </th>
589
  <td>
590
- <?php echo '<a href="' . $new_condition_url . '" class="button">Add page rule</a>'; ?>
591
  </td>
592
  </tr>
593
  </tbody>
594
  </table>
595
 
596
- <!-- This div exists to allow rendering the Conditions table outside the existing table -->
597
  <div data-tab-name="visibility" class="cnb-button-edit-conditions-table <?php if ( $hide_on_modal ) {
598
- echo $adminFunctions->is_active_tab( 'visibility' );
599
  } else {
600
  echo 'nav-tab-only';
601
  } ?>" <?php if ( ! $adminFunctions->is_active_tab( 'visibility' ) ) {
@@ -603,7 +598,7 @@ class CnbButtonViewEdit {
603
  } ?>>
604
  <?php
605
  $view = new CnbConditionView();
606
- $view->renderTable($button);
607
  ?>
608
  </div>
609
 
@@ -614,7 +609,7 @@ class CnbButtonViewEdit {
614
 
615
  function render() {
616
  global $wp_locale;
617
- $cnb_options = get_option('cnb');
618
 
619
  $button_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
620
  $button = new CnbButton();
@@ -628,7 +623,7 @@ class CnbButtonViewEdit {
628
  $button->type = strtoupper( filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING ) );
629
  $button->domain = $domain;
630
  }
631
- if ( is_wp_error($button) || $button->actions === null ) {
632
  $button->actions = array();
633
  }
634
 
@@ -644,7 +639,7 @@ class CnbButtonViewEdit {
644
 
645
  do_action( 'cnb_header' );
646
 
647
- if (is_wp_error($button)) {
648
  return;
649
  }
650
 
@@ -659,26 +654,25 @@ class CnbButtonViewEdit {
659
  $currentMinuteOfHour = ( $currentMinuteOfHour < 30 ) ? '15' : $currentMinuteOfHour;
660
  $currentMinuteOfHour = ( $currentMinuteOfHour < 15 ) ? '00' : $currentMinuteOfHour;
661
  // END Preview date picker details
662
-
663
  ?>
664
 
665
  <div class="cnb-two-column-section-preview">
666
  <div class="cnb-body-column">
667
  <div class="cnb-body-content">
668
  <h2 class="nav-tab-wrapper">
669
- <a href="<?php echo $this->get_tab_url( $button, 'basic_options' ) ?>"
670
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>"
671
  data-tab-name="basic_options">Basics</a>
672
  <?php if ( $button_id !== 'new' ) { ?>
673
- <a href="<?php echo $this->get_tab_url( $button, 'extra_options' ) ?>"
674
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'extra_options' ) ?>"
675
  data-tab-name="extra_options">Presentation</a>
676
- <a href="<?php echo $this->get_tab_url( $button, 'visibility' ) ?>"
677
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'visibility' ) ?>"
678
  data-tab-name="visibility">Visibility</a>
679
  <?php if ( $button->type === 'SINGLE' ) { ?>
680
- <a href="<?php echo $this->get_tab_url( $button, 'scheduler' ) ?>"
681
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'scheduler' ) ?>"
682
  data-tab-name="scheduler">Schedule</a>
683
  <?php } ?>
684
  <?php } else { ?>
@@ -699,7 +693,7 @@ class CnbButtonViewEdit {
699
  id="call-now-button-preview-selector-day">
700
  <?php $days = array( 1, 2, 3, 4, 5, 6, 0 );
701
  foreach ( $days as $day ) {
702
- echo '<option value="' . $day . '" ' . selected( $currentDayOfWeek, $day ) . '>' . $wp_locale->get_weekday( $day ) . '</option>';
703
  }
704
  ?>
705
  </select>
@@ -711,7 +705,7 @@ class CnbButtonViewEdit {
711
  <?php
712
  foreach ( range( 0, 23 ) as $number ) {
713
  $number = $number < 10 ? '0' . $number : $number;
714
- echo '<option ' . selected( $currentHourOfDay, $number ) . '>' . $number . '</option>';
715
  }
716
  ?>
717
  </select>
@@ -723,7 +717,7 @@ class CnbButtonViewEdit {
723
  <?php
724
  foreach ( range( 0, 45, 15 ) as $number ) {
725
  $number = $number < 10 ? '0' . $number : $number;
726
- echo '<option ' . selected( $currentMinuteOfHour, $number ) . '>' . $number . '</option>';
727
  }
728
  ?>
729
  </select>
18
  use WP_Error;
19
 
20
  class CnbButtonViewEdit {
 
 
 
 
 
21
  /**
22
  * Renders the "Edit <type>" header
23
  *
26
  function header( $button ) {
27
  $type = strtoupper( filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING ) );
28
  $name = 'New Button';
29
+ if ( $button && ! is_wp_error( $button ) ) {
30
  $type = $button->type;
31
  $name = $button->name;
32
  }
33
  $adminFunctions = new CnbAdminFunctions();
34
+ $buttonTypes = $adminFunctions->cnb_get_button_types();
35
+ $typeName = $buttonTypes[ $type ];
36
+ echo esc_html__( 'Editing ' ) . esc_html( $typeName ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
37
  }
38
 
39
  /**
43
  * @return string
44
  */
45
  private function get_tab_url( $button, $tab ) {
46
+ $url = admin_url( 'admin.php' );
47
+
48
+ return add_query_arg(
49
+ array(
50
+ 'page' => 'call-now-button',
51
+ 'action' => 'edit',
52
+ 'type' => strtolower( $button->type ),
53
+ 'id' => $button->id,
54
+ 'tab' => $tab
55
+ ),
56
+ $url );
 
 
57
  }
58
 
59
  /**
63
  * @param $button_id int
64
  * @param $button CnbButton
65
  * @param $default_domain CnbDomain|WP_Error
66
+ * @param $options array (modal_view (boolean), submit_button_text (string), advanced_view (boolean)
67
  *
68
  * @return void
69
  */
70
  public function render_form( $button_id, $button, $default_domain, $options = array() ) {
71
  $adminFunctions = new CnbAdminFunctions();
72
+ $domains = CnbAppRemote::cnb_remote_get_domains();
73
 
74
+ $cnb_single_image_url = plugins_url( '../../../resources/images/button-new-single.png', __FILE__ );
75
+ $cnb_multi_image_url = plugins_url( '../../../resources/images/button-new-multi.png', __FILE__ );
76
+ $cnb_full_image_url = plugins_url( '../../../resources/images/button-new-full.png', __FILE__ );
77
 
78
  $submit_button_text = array_key_exists( 'submit_button_text', $options ) ? $options['submit_button_text'] : '';
79
  $hide_on_modal = array_key_exists( 'modal_view', $options ) && $options['modal_view'] === true;
93
  'bid' => $button->id
94
  ),
95
  $url );
 
96
 
97
  $new_condition_link =
98
  add_query_arg(
103
  'bid' => $button->id
104
  ),
105
  $url );
106
+
107
  // In case the API isn't working properly
108
  if ( $default_domain instanceof WP_Error ) {
109
  $default_domain = new CnbDomain();
122
  ?>
123
  <script>
124
  let cnb_css_root = '<?php echo esc_js( CnbAppRemote::cnb_get_static_base() ) ?>';
125
+ let cnb_options = <?php echo wp_json_encode( new stdClass() ) ?>;
126
  </script>
127
  <form class="cnb-container <?php if ( ! $hide_on_modal ) { ?>cnb-validation<?php } ?>"
128
  action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
129
  <input type="hidden" name="page" value="call-now-button"/>
130
  <input type="hidden" name="action"
131
+ value="<?php echo $button_id === 'new' ? 'cnb_create_' . esc_attr( strtolower( $button->type ) ) . '_button' : 'cnb_update_' . esc_attr( strtolower( $button->type ) ) . '_button' ?>"/>
132
+ <input type="hidden" name="_wpnonce_button"
133
+ value="<?php echo esc_attr( wp_create_nonce( 'cnb-button-edit' ) ) ?>"/>
134
+ <input type="hidden" name="tab" value="<?php echo esc_attr( $adminFunctions->get_active_tab_name() ) ?>"/>
135
 
136
  <input type="hidden" name="button[id]" value="<?php echo esc_attr( $button->id ) ?>"/>
137
  <input type="hidden" name="button[type]" value="<?php echo esc_attr( $button->type ) ?>" id="button_type"/>
139
  <input type="hidden" name="button[domain]" value="<?php echo esc_attr( $default_domain->id ) ?>"/>
140
 
141
  <table class="form-table <?php if ( ! $hide_on_modal ) {
142
+ echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) );
143
  } else {
144
  echo 'nav-tab-only';
145
  } ?>" data-tab-name="basic_options">
179
  value="<?php echo esc_attr( $domain->id ) ?>">
180
  <?php echo esc_html( $domain->name ) ?>
181
  <?php if ( $domain->id == $default_domain->id ) {
182
+ echo ' (current WordPress domain)';
183
  } ?>
184
  </option>
185
  <?php } ?>
190
  <tr class="cnb_hide_on_modal">
191
  <th colspan="2" class="cnb_padding_0">
192
  <h2>
193
+ Actions <?php echo '<a href="' . esc_url( $new_action_link ) . '" class="page-title-action">Add Action</a>'; ?></h2>
194
  </th>
195
  </tr>
196
  <?php }
226
 
227
  <!-- This div exists to allow rendering the Action table outside the existing table -->
228
  <div data-tab-name="basic_options" class="cnb-button-edit-action-table <?php if ( $hide_on_modal ) {
229
+ echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) );
230
  } else {
231
  echo 'nav-tab-only';
232
  } ?>" <?php if ( ! $adminFunctions->is_active_tab( 'basic_options' ) ) {
236
  </div>
237
 
238
  <table class="form-table <?php if ( ! $hide_on_modal ) {
239
+ echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) );
240
  } else {
241
  echo 'nav-tab-only';
242
  } ?>"><?php
243
  } ?>
244
  <script>
245
+ let cnb_actions = <?php echo wp_json_encode( $button->actions ) ?>;
246
+ let cnb_domain = <?php echo wp_json_encode( $button->domain ) ?>;
247
  </script>
248
 
249
  <?php if ( $button_id === 'new' ) { ?>
256
  <div class="cnb_type_selector_item cnb_type_selector_single cnb_type_selector_active"
257
  data-cnb-selection="single">
258
  <img style="max-width:100%;" alt="Choose a Single button type"
259
+ src="<?php echo esc_url( $cnb_single_image_url ) ?>">
260
  <div style="text-align:center">Single button</div>
261
  </div>
262
  <div class="cnb_type_selector_item cnb_type_selector_multi" data-cnb-selection="multi">
263
  <img style="max-width:100%;" alt="Choose a Multibutton type"
264
+ src="<?php echo esc_url( $cnb_multi_image_url ) ?>">
265
  <div style="text-align:center">Multibutton</div>
266
  </div>
267
  <div class="cnb_type_selector_item cnb_type_selector_full" data-cnb-selection="full">
268
  <img style="max-width:100%;" alt="Choose a Full button type"
269
+ src="<?php echo esc_url( $cnb_full_image_url ) ?>">
270
  <div style="text-align:center">Buttonbar</div>
271
  </div>
272
  </div>
274
  </tr>
275
  <?php } ?>
276
  </table>
277
+ <table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
278
+ data-tab-name="extra_options">
279
  <?php if ( $button->type === 'FULL' ) { ?>
280
  <tr>
281
  <th colspan="2">
469
  <?php } ?>
470
  <tr>
471
  <th scope="row">Position <a
472
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>button-position/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'button-position' ) ); ?>"
473
  target="_blank" class="cnb-nounderscore">
474
  <span class="dashicons dashicons-editor-help"></span>
475
  </a></th>
505
 
506
  <!-- Extra placement options -->
507
  <br class="cnb-extra-placement">
508
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == 'MIDDLE_RIGHT' ? 'cnb-extra-active' : ''; ?>">
509
  <input type="radio" id="appearance5" name="button[options][placement]"
510
  value="MIDDLE_RIGHT" <?php checked( 'MIDDLE_RIGHT', $button->options->placement ); ?>>
511
  <label title="middle-right" for="appearance5">Middle right</label>
512
  </div>
513
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == 'MIDDLE_LEFT' ? 'cnb-extra-active' : ''; ?>">
514
  <input type="radio" id="appearance6" name="button[options][placement]"
515
  value="MIDDLE_LEFT" <?php checked( 'MIDDLE_LEFT', $button->options->placement ); ?>>
516
  <label title="middle-left" for="appearance6">Middle left </label>
517
  </div>
518
  <br class="cnb-extra-placement">
519
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == 'TOP_RIGHT' ? 'cnb-extra-active' : ''; ?>">
520
  <input type="radio" id="appearance7" name="button[options][placement]"
521
  value="TOP_RIGHT" <?php checked( 'TOP_RIGHT', $button->options->placement ); ?>>
522
  <label title="top-right" for="appearance7">Top right corner</label>
523
  </div>
524
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == 'TOP_LEFT' ? 'cnb-extra-active' : ''; ?>">
525
  <input type="radio" id="appearance8" name="button[options][placement]"
526
  value="TOP_LEFT" <?php checked( 'TOP_LEFT', $button->options->placement ); ?>>
527
  <label title="top-left" for="appearance8">Top left corner</label>
528
  </div>
529
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $button->options->placement == 'TOP_CENTER' ? 'cnb-extra-active' : ''; ?>">
530
  <input type="radio" id="appearance9" name="button[options][placement]"
531
  value="TOP_CENTER" <?php checked( 'TOP_CENTER', $button->options->placement ); ?>>
532
  <label title="top-center" for="appearance9">Center top</label>
540
  <?php if ( $button->type !== 'FULL' ) { ?>
541
  <tr>
542
  <th scope="row"><label for="button_options_animation">Button animation <a
543
+ href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress/buttons/button-animation/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'button-animation' ) ); ?>"
544
  target="_blank" class="cnb-nounderscore">
545
  <span class="dashicons dashicons-editor-help"></span>
546
  </a></label></th>
554
  </tr>
555
  <?php } ?>
556
  </table>
557
+ <table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'visibility' ) ) ?>"
558
+ data-tab-name="visibility">
559
  <tbody id="cnb_form_table_visibility">
560
  <tr>
561
  <th></th>
582
  <h2>Page rules</h2>
583
  </th>
584
  <td>
585
+ <?php echo '<a href="' . esc_url( $new_condition_link ) . '" class="button">Add page rule</a>'; ?>
586
  </td>
587
  </tr>
588
  </tbody>
589
  </table>
590
 
591
+ <!-- This div exists to allow rendering the Conditions' table outside the existing table -->
592
  <div data-tab-name="visibility" class="cnb-button-edit-conditions-table <?php if ( $hide_on_modal ) {
593
+ echo esc_attr( $adminFunctions->is_active_tab( 'visibility' ) );
594
  } else {
595
  echo 'nav-tab-only';
596
  } ?>" <?php if ( ! $adminFunctions->is_active_tab( 'visibility' ) ) {
598
  } ?>>
599
  <?php
600
  $view = new CnbConditionView();
601
+ $view->renderTable( $button );
602
  ?>
603
  </div>
604
 
609
 
610
  function render() {
611
  global $wp_locale;
612
+ $cnb_options = get_option( 'cnb' );
613
 
614
  $button_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
615
  $button = new CnbButton();
623
  $button->type = strtoupper( filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING ) );
624
  $button->domain = $domain;
625
  }
626
+ if ( is_wp_error( $button ) || $button->actions === null ) {
627
  $button->actions = array();
628
  }
629
 
639
 
640
  do_action( 'cnb_header' );
641
 
642
+ if ( is_wp_error( $button ) ) {
643
  return;
644
  }
645
 
654
  $currentMinuteOfHour = ( $currentMinuteOfHour < 30 ) ? '15' : $currentMinuteOfHour;
655
  $currentMinuteOfHour = ( $currentMinuteOfHour < 15 ) ? '00' : $currentMinuteOfHour;
656
  // END Preview date picker details
 
657
  ?>
658
 
659
  <div class="cnb-two-column-section-preview">
660
  <div class="cnb-body-column">
661
  <div class="cnb-body-content">
662
  <h2 class="nav-tab-wrapper">
663
+ <a href="<?php echo esc_url( $this->get_tab_url( $button, 'basic_options' ) ) ?>"
664
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>"
665
  data-tab-name="basic_options">Basics</a>
666
  <?php if ( $button_id !== 'new' ) { ?>
667
+ <a href="<?php echo esc_url( $this->get_tab_url( $button, 'extra_options' ) ) ?>"
668
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
669
  data-tab-name="extra_options">Presentation</a>
670
+ <a href="<?php echo esc_url( $this->get_tab_url( $button, 'visibility' ) ) ?>"
671
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'visibility' ) ) ?>"
672
  data-tab-name="visibility">Visibility</a>
673
  <?php if ( $button->type === 'SINGLE' ) { ?>
674
+ <a href="<?php echo esc_url( $this->get_tab_url( $button, 'scheduler' ) ) ?>"
675
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'scheduler' ) ) ?>"
676
  data-tab-name="scheduler">Schedule</a>
677
  <?php } ?>
678
  <?php } else { ?>
693
  id="call-now-button-preview-selector-day">
694
  <?php $days = array( 1, 2, 3, 4, 5, 6, 0 );
695
  foreach ( $days as $day ) {
696
+ echo '<option value="' . esc_attr( $day ) . '" ' . selected( $currentDayOfWeek, $day ) . '>' . esc_attr( $wp_locale->get_weekday( $day ) ) . '</option>';
697
  }
698
  ?>
699
  </select>
705
  <?php
706
  foreach ( range( 0, 23 ) as $number ) {
707
  $number = $number < 10 ? '0' . $number : $number;
708
+ echo '<option ' . selected( $currentHourOfDay, $number ) . '>' . esc_html( $number ) . '</option>';
709
  }
710
  ?>
711
  </select>
717
  <?php
718
  foreach ( range( 0, 45, 15 ) as $number ) {
719
  $number = $number < 10 ? '0' . $number : $number;
720
+ echo '<option ' . selected( $currentMinuteOfHour, $number ) . '>' . esc_html( $number ) . '</option>';
721
  }
722
  ?>
723
  </select>
src/admin/button/Cnb_Button_List_Table.php CHANGED
@@ -6,12 +6,13 @@ namespace cnb\admin\button;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
  }
11
 
12
  use cnb\admin\api\CnbAdminCloud;
13
  use cnb\admin\api\CnbAppRemote;
14
  use cnb\utils\CnbAdminFunctions;
 
15
  use WP_Error;
16
  use WP_List_Table;
17
 
@@ -25,6 +26,11 @@ class Cnb_Button_List_Table extends WP_List_Table {
25
  */
26
  private $data;
27
 
 
 
 
 
 
28
  private $options = array(
29
  'filter_buttons_for_domain' => null,
30
  );
@@ -40,6 +46,8 @@ class Cnb_Button_List_Table extends WP_List_Table {
40
  'ajax' => false, //We won't support Ajax for this table
41
  'screen' => 'call-now-button-buttons' // Screen name for bulk actions, etc
42
  ) );
 
 
43
  }
44
 
45
  function setOption( $optionName, $optionValue ) {
@@ -97,22 +105,20 @@ class Cnb_Button_List_Table extends WP_List_Table {
97
  $url = admin_url( 'admin.php' );
98
 
99
  // Which one is current?
100
- $current_view_is_active = isset( $_REQUEST['view'] ) && $_REQUEST['view'] === 'active';
101
  $all_link =
102
  add_query_arg(
103
  array( 'page' => 'call-now-button' ),
104
  $url );
105
- $all_url = esc_url( $all_link );
106
 
107
  $active_link =
108
  add_query_arg(
109
  array( 'page' => 'call-now-button', 'view' => 'active' ),
110
  $url );
111
- $active_url = esc_url( $active_link );
112
 
113
  return array(
114
- 'all' => "<a href='" . $all_url . "' " . ( ! $current_view_is_active ? "class='current'" : '' ) . "'>" . __( 'All' ) . $all_count_str . '</a>',
115
- 'active' => "<a href='" . $active_url . "' " . ( $current_view_is_active ? "class='current'" : '' ) . "'>" . __( 'Active' ) . $active_count_str . '</a>'
116
  );
117
  }
118
 
@@ -125,7 +131,7 @@ class Cnb_Button_List_Table extends WP_List_Table {
125
  }
126
 
127
  /* -- Filtering parameters -- */
128
- $current_view_is_active = isset( $_REQUEST['view'] ) && $_REQUEST['view'] === 'active';
129
  if ( $current_view_is_active ) {
130
  $data = array_filter( $data, function ( $el ) {
131
  return $el->active === true;
@@ -141,7 +147,7 @@ class Cnb_Button_List_Table extends WP_List_Table {
141
  $totalitems = count( $data ); //return the total number of affected rows
142
  $per_page = 20; //How many to display per page?
143
  //Which page is this?
144
- $current_page = ! empty( $_GET['paged'] ) ? (int) sanitize_text_field( $_GET['paged'] ) : 1;
145
 
146
  //Page Number
147
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
@@ -192,7 +198,7 @@ class Cnb_Button_List_Table extends WP_List_Table {
192
  case 'FULL':
193
  case 'MULTI':
194
  $adminFunctions = new CnbAdminFunctions();
195
- $button_types = $adminFunctions->cnb_get_button_types();
196
 
197
  return $button_types[ $item->type ];
198
  default:
@@ -217,9 +223,10 @@ class Cnb_Button_List_Table extends WP_List_Table {
217
  * @param $item CnbButton
218
  *
219
  * @return string
 
220
  */
221
  function column_actions( $item ) {
222
- $cnb_options = get_option('cnb');
223
 
224
  $items = '';
225
  $domain = '';
@@ -239,7 +246,7 @@ class Cnb_Button_List_Table extends WP_List_Table {
239
  $actions = CnbAdminCloud::cnb_wp_get_actions_for_button( $item );
240
  foreach ( $actions as $action ) {
241
  $actionValue = ! empty( $action->actionValue ) ? esc_html( $action->actionValue ) : '<em>No value</em>';
242
- $actionTypes = (new CnbAdminFunctions())->cnb_get_action_types();
243
  $actionType = $actionTypes[ $action->actionType ];
244
  $actionMsg .= "$actionType ($actionValue)<br />";
245
  }
@@ -297,9 +304,9 @@ class Cnb_Button_List_Table extends WP_List_Table {
297
  */
298
  private function sort_data( $a, $b ) {
299
  // If orderby is set, use this as the sort column
300
- $orderby = ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'name';
301
  // If order is set use this as the order
302
- $order = ! empty( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'asc';
303
 
304
  $result = strcmp( $a->$orderby, $b->$orderby );
305
 
@@ -395,9 +402,9 @@ class Cnb_Button_List_Table extends WP_List_Table {
395
  }
396
 
397
  function no_items() {
398
- _e( 'No buttons found. ' );
399
  if ( ! is_wp_error( $this->data ) ) {
400
- ( new CnbButtonView() )->get_lets_create_one_link();
401
  }
402
  }
403
  }
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10
  }
11
 
12
  use cnb\admin\api\CnbAdminCloud;
13
  use cnb\admin\api\CnbAppRemote;
14
  use cnb\utils\CnbAdminFunctions;
15
+ use cnb\utils\CnbUtils;
16
  use WP_Error;
17
  use WP_List_Table;
18
 
26
  */
27
  private $data;
28
 
29
+ /**
30
+ * @var CnbUtils
31
+ */
32
+ private $cnb_utils;
33
+
34
  private $options = array(
35
  'filter_buttons_for_domain' => null,
36
  );
46
  'ajax' => false, //We won't support Ajax for this table
47
  'screen' => 'call-now-button-buttons' // Screen name for bulk actions, etc
48
  ) );
49
+
50
+ $this->cnb_utils = new CnbUtils();
51
  }
52
 
53
  function setOption( $optionName, $optionValue ) {
105
  $url = admin_url( 'admin.php' );
106
 
107
  // Which one is current?
108
+ $current_view_is_active = $this->cnb_utils->get_query_val( 'view' ) === 'active';
109
  $all_link =
110
  add_query_arg(
111
  array( 'page' => 'call-now-button' ),
112
  $url );
 
113
 
114
  $active_link =
115
  add_query_arg(
116
  array( 'page' => 'call-now-button', 'view' => 'active' ),
117
  $url );
 
118
 
119
  return array(
120
+ 'all' => "<a href='" . esc_url( $all_link ) . "' " . ( ! $current_view_is_active ? "class='current'" : '' ) . "'>" . __( 'All' ) . $all_count_str . '</a>',
121
+ 'active' => "<a href='" . esc_url( $active_link ) . "' " . ( $current_view_is_active ? "class='current'" : '' ) . "'>" . __( 'Active' ) . $active_count_str . '</a>'
122
  );
123
  }
124
 
131
  }
132
 
133
  /* -- Filtering parameters -- */
134
+ $current_view_is_active = $this->cnb_utils->get_query_val( 'view' ) === 'active';
135
  if ( $current_view_is_active ) {
136
  $data = array_filter( $data, function ( $el ) {
137
  return $el->active === true;
147
  $totalitems = count( $data ); //return the total number of affected rows
148
  $per_page = 20; //How many to display per page?
149
  //Which page is this?
150
+ $current_page = (int) $this->cnb_utils->get_query_val( 'paged', '1' );
151
 
152
  //Page Number
153
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
198
  case 'FULL':
199
  case 'MULTI':
200
  $adminFunctions = new CnbAdminFunctions();
201
+ $button_types = $adminFunctions->cnb_get_button_types();
202
 
203
  return $button_types[ $item->type ];
204
  default:
223
  * @param $item CnbButton
224
  *
225
  * @return string
226
+ * @noinspection PhpUnused
227
  */
228
  function column_actions( $item ) {
229
+ $cnb_options = get_option( 'cnb' );
230
 
231
  $items = '';
232
  $domain = '';
246
  $actions = CnbAdminCloud::cnb_wp_get_actions_for_button( $item );
247
  foreach ( $actions as $action ) {
248
  $actionValue = ! empty( $action->actionValue ) ? esc_html( $action->actionValue ) : '<em>No value</em>';
249
+ $actionTypes = ( new CnbAdminFunctions() )->cnb_get_action_types();
250
  $actionType = $actionTypes[ $action->actionType ];
251
  $actionMsg .= "$actionType ($actionValue)<br />";
252
  }
304
  */
305
  private function sort_data( $a, $b ) {
306
  // If orderby is set, use this as the sort column
307
+ $orderby = $this->cnb_utils->get_query_val( 'orderby', 'name' );
308
  // If order is set use this as the order
309
+ $order = $this->cnb_utils->get_query_val( 'order', 'asc' );
310
 
311
  $result = strcmp( $a->$orderby, $b->$orderby );
312
 
402
  }
403
 
404
  function no_items() {
405
+ esc_html_e( 'No buttons found. ' );
406
  if ( ! is_wp_error( $this->data ) ) {
407
+ ( new CnbButtonView() )->render_lets_create_one_link();
408
  }
409
  }
410
  }
src/admin/condition/CnbCondition.php CHANGED
@@ -76,6 +76,7 @@ class CnbCondition implements JsonSerializable {
76
  $objects
77
  );
78
  }
 
79
  public function toArray() {
80
  // Note, we do not export "delete", since that is only used internally
81
  return array(
76
  $objects
77
  );
78
  }
79
+
80
  public function toArray() {
81
  // Note, we do not export "delete", since that is only used internally
82
  return array(
src/admin/condition/CnbConditionController.php CHANGED
@@ -21,46 +21,59 @@ class CnbConditionController {
21
  *
22
  * @return CnbCondition|WP_Error|null
23
  */
24
- private function deleteWithId( $condition_id) {
25
- if ( (new CnbUtils())->cnb_check_ajax_referer( 'cnb_delete_condition' ) ) {
26
  $condition = new CnbCondition();
27
  $condition->id = $condition_id;
28
 
29
  $ignore_notifications = array();
 
30
  return CnbAdminCloud::cnb_delete_condition( $ignore_notifications, $condition );
31
  }
32
 
33
  return null;
34
  }
 
35
  /**
36
  * Via the quick actions, be able to delete a Condition
37
  *
38
- * This also means we CANNOT redirect, as we're already halfway into rendering the page.
 
39
  *
40
  * @return CnbCondition
41
  */
42
  function delete() {
43
- $id = ! empty( $_REQUEST['id'] ) ? sanitize_text_field( $_REQUEST['id'] ) : null;
44
- $nonce = ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : null;
 
45
  $action = 'cnb_delete_condition';
46
  $nonce_verified = wp_verify_nonce( $nonce, $action );
47
 
48
  if ( $nonce_verified ) {
 
49
  $cnb_cloud_notifications = array();
50
  $condition = new CnbCondition();
51
  $condition->id = $id;
52
- $result = CnbAdminCloud::cnb_delete_condition( $cnb_cloud_notifications, $condition );
53
- CnbAdminNotices::get_instance()->notices( $cnb_cloud_notifications );
 
54
  return $result;
55
  }
 
56
  return null;
57
  }
58
 
 
 
 
 
 
59
  public static function delete_ajax() {
60
- $condition_id = ! empty( $_REQUEST['id'] ) ? sanitize_text_field( $_REQUEST['id'] ) : null;
 
61
 
62
  $controller = new CnbConditionController();
63
- $result = $controller->deleteWithId($condition_id);
64
  // Instead of sending just the actual result (which is currently ignored anyway)
65
  // We sent both the result and an updated button so the preview code can re-render the button
66
  $return = array(
@@ -77,14 +90,16 @@ class CnbConditionController {
77
  * @return void
78
  */
79
  private static function create_and_update_post( $cnb_cloud_notifications, $conditions ) {
 
 
80
  // redirect the user to the appropriate page
81
  $transient_id = 'cnb-' . wp_generate_uuid4();
82
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
83
 
84
  // Create link
85
- $bid = ! empty( $_REQUEST['bid'] ) ? sanitize_text_field( $_REQUEST['bid'] ) : null;
86
  $url = admin_url( 'admin.php' );
87
- if ( ! empty( $bid ) ) {
88
  $redirect_link =
89
  add_query_arg(
90
  array(
@@ -132,15 +147,15 @@ class CnbConditionController {
132
 
133
  $closure( $processed_conditions );
134
  } else {
135
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
136
  'response' => 403,
137
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
138
  ) );
139
  }
140
  }
141
 
142
  /**
143
- * This is called to create the condition
144
  * via `call-now-button.php#cnb_admin_create_condition`
145
  */
146
  public static function create() {
@@ -150,21 +165,24 @@ class CnbConditionController {
150
  * @return void
151
  */
152
  $inner = function ( $conditions ) {
 
153
  $cnb_cloud_notifications = array();
154
  /** @var $result CnbCondition[] */
155
- $result = array();
156
  foreach ( $conditions as $condition ) {
157
  // do the processing
158
  $result[] = CnbAdminCloud::cnb_create_condition( $cnb_cloud_notifications, $condition );
159
  }
160
 
161
- $bid = ! empty( $_REQUEST['bid'] ) ? sanitize_text_field( $_REQUEST['bid'] ) : null;
162
- if (!empty($bid)) {
163
  // we don't care about the Condition success notification..
164
- $cnb_cloud_notifications = array_filter($cnb_cloud_notifications, function($item) { return $item->type != 'success'; });
165
- $button = CnbAppRemote::cnb_remote_get_button_full($bid);
166
- $button->conditions = array_merge($button->conditions, $result);
167
- CnbAdminCloud::cnb_update_button($cnb_cloud_notifications, $button);
 
 
168
  }
169
 
170
  self::create_and_update_post( $cnb_cloud_notifications, $result );
@@ -200,19 +218,27 @@ class CnbConditionController {
200
  /**
201
  * This is very similar to the <code>delete()</code> function above.
202
  *
 
 
 
203
  * Big differences are:
204
  * - This handles multiple IDs, versus 1
205
  * - Instead of rendering the Notice, is it stored and the user redirected
206
  *
 
 
 
207
  * @return void
208
  */
209
  public static function handle_bulk_actions() {
210
- $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
 
211
  $action = 'bulk-cnb_list_conditions';
212
  $nonce_verified = wp_verify_nonce( $nonce, $action );
 
213
  if ( $nonce_verified ) {
214
  $entityIds = filter_input( INPUT_POST, 'cnb_list_condition', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
215
- if ( $_REQUEST['bulk-action'] === 'delete' ) {
216
  $cnb_cloud_notifications = array();
217
  foreach ( $entityIds as $entityId ) {
218
  $condition = new CnbCondition();
@@ -236,12 +262,26 @@ class CnbConditionController {
236
  $url );
237
  $redirect_url = esc_url_raw( $redirect_link );
238
  wp_safe_redirect( $redirect_url );
 
 
 
 
 
 
 
 
 
 
239
  }
240
  } else {
241
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
242
- 'response' => 403,
243
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
244
- ) );
 
 
 
 
245
  }
246
  }
247
  }
21
  *
22
  * @return CnbCondition|WP_Error|null
23
  */
24
+ private function deleteWithId( $condition_id ) {
25
+ if ( ( new CnbUtils() )->cnb_check_ajax_referer( 'cnb_delete_condition' ) ) {
26
  $condition = new CnbCondition();
27
  $condition->id = $condition_id;
28
 
29
  $ignore_notifications = array();
30
+
31
  return CnbAdminCloud::cnb_delete_condition( $ignore_notifications, $condition );
32
  }
33
 
34
  return null;
35
  }
36
+
37
  /**
38
  * Via the quick actions, be able to delete a Condition
39
  *
40
+ * This also means we CANNOT redirect, as we're already halfway into rendering the page,
41
+ * so we add the notification to the adminNotices handler
42
  *
43
  * @return CnbCondition
44
  */
45
  function delete() {
46
+ $cnb_utils = new CnbUtils();
47
+ $id = $cnb_utils->get_query_val( 'id', null );
48
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
49
  $action = 'cnb_delete_condition';
50
  $nonce_verified = wp_verify_nonce( $nonce, $action );
51
 
52
  if ( $nonce_verified ) {
53
+ $adminNotices = CnbAdminNotices::get_instance();
54
  $cnb_cloud_notifications = array();
55
  $condition = new CnbCondition();
56
  $condition->id = $id;
57
+ $result = CnbAdminCloud::cnb_delete_condition( $cnb_cloud_notifications, $condition );
58
+ $adminNotices->notices( $cnb_cloud_notifications );
59
+
60
  return $result;
61
  }
62
+
63
  return null;
64
  }
65
 
66
+ /**
67
+ * Called via jQuery.post
68
+ *
69
+ * @return void
70
+ */
71
  public static function delete_ajax() {
72
+ $cnb_utils = new CnbUtils();
73
+ $id = $cnb_utils->get_post_val( 'id', null );
74
 
75
  $controller = new CnbConditionController();
76
+ $result = $controller->deleteWithId( $id );
77
  // Instead of sending just the actual result (which is currently ignored anyway)
78
  // We sent both the result and an updated button so the preview code can re-render the button
79
  $return = array(
90
  * @return void
91
  */
92
  private static function create_and_update_post( $cnb_cloud_notifications, $conditions ) {
93
+ $cnb_utils = new CnbUtils();
94
+
95
  // redirect the user to the appropriate page
96
  $transient_id = 'cnb-' . wp_generate_uuid4();
97
  set_transient( $transient_id, $cnb_cloud_notifications, HOUR_IN_SECONDS );
98
 
99
  // Create link
100
+ $bid = $cnb_utils->get_post_val( 'bid', null );
101
  $url = admin_url( 'admin.php' );
102
+ if ( $bid ) {
103
  $redirect_link =
104
  add_query_arg(
105
  array(
147
 
148
  $closure( $processed_conditions );
149
  } else {
150
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
151
  'response' => 403,
152
+ 'back_link' => true,
153
  ) );
154
  }
155
  }
156
 
157
  /**
158
+ * This is called to create the condition (via POST admin-post.php)
159
  * via `call-now-button.php#cnb_admin_create_condition`
160
  */
161
  public static function create() {
165
  * @return void
166
  */
167
  $inner = function ( $conditions ) {
168
+ $cnb_utils = new CnbUtils();
169
  $cnb_cloud_notifications = array();
170
  /** @var $result CnbCondition[] */
171
+ $result = array();
172
  foreach ( $conditions as $condition ) {
173
  // do the processing
174
  $result[] = CnbAdminCloud::cnb_create_condition( $cnb_cloud_notifications, $condition );
175
  }
176
 
177
+ $bid = $cnb_utils->get_post_val( 'bid', null );
178
+ if ( $bid ) {
179
  // we don't care about the Condition success notification..
180
+ $cnb_cloud_notifications = array_filter( $cnb_cloud_notifications, function ( $item ) {
181
+ return $item->type != 'success';
182
+ } );
183
+ $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
184
+ $button->conditions = array_merge( $button->conditions, $result );
185
+ CnbAdminCloud::cnb_update_button( $cnb_cloud_notifications, $button );
186
  }
187
 
188
  self::create_and_update_post( $cnb_cloud_notifications, $result );
218
  /**
219
  * This is very similar to the <code>delete()</code> function above.
220
  *
221
+ * This always has to come via a $_POST request (specifically, via admin-post.php),
222
+ * so this should end in a redirect (or an error via wp_die)
223
+ *
224
  * Big differences are:
225
  * - This handles multiple IDs, versus 1
226
  * - Instead of rendering the Notice, is it stored and the user redirected
227
  *
228
+ * nonce name via WP_List_Table = bulk-{plural}
229
+ * so in this case: bulk-cnb_list_conditions
230
+ *
231
  * @return void
232
  */
233
  public static function handle_bulk_actions() {
234
+ $cnb_utils = new CnbUtils();
235
+ $nonce = $cnb_utils->get_post_val( '_wpnonce' );
236
  $action = 'bulk-cnb_list_conditions';
237
  $nonce_verified = wp_verify_nonce( $nonce, $action );
238
+
239
  if ( $nonce_verified ) {
240
  $entityIds = filter_input( INPUT_POST, 'cnb_list_condition', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
241
+ if ( $cnb_utils->get_post_val( 'bulk-action' ) === 'delete' ) {
242
  $cnb_cloud_notifications = array();
243
  foreach ( $entityIds as $entityId ) {
244
  $condition = new CnbCondition();
262
  $url );
263
  $redirect_url = esc_url_raw( $redirect_link );
264
  wp_safe_redirect( $redirect_url );
265
+ } else {
266
+ wp_die(
267
+ esc_html__( 'Unknown Bulk action specified' ),
268
+ esc_html__( 'Cannot process Bulk action' ),
269
+ array(
270
+ 'response' => 403,
271
+ 'link_text' => esc_html( 'Go back to the Conditions overview' ),
272
+ 'link_url' => esc_url_raw( admin_url( 'admin.php' ) . '?page=' . CNB_SLUG . '-conditions' ),
273
+ )
274
+ );
275
  }
276
  } else {
277
+ wp_die(
278
+ esc_html__( 'Invalid nonce specified' ),
279
+ esc_html__( 'Error' ),
280
+ array(
281
+ 'response' => 403,
282
+ 'back_link' => true,
283
+ )
284
+ );
285
  }
286
  }
287
  }
src/admin/condition/CnbConditionRouter.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace cnb\admin\condition;
4
 
5
  // don't load directly
 
 
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  class CnbConditionRouter {
@@ -12,7 +14,7 @@ class CnbConditionRouter {
12
  * @return void
13
  */
14
  public static function render() {
15
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
16
  switch ( $action ) {
17
  case 'new':
18
  case 'edit':
3
  namespace cnb\admin\condition;
4
 
5
  // don't load directly
6
+ use cnb\utils\CnbUtils;
7
+
8
  defined( 'ABSPATH' ) || die( '-1' );
9
 
10
  class CnbConditionRouter {
14
  * @return void
15
  */
16
  public static function render() {
17
+ $action = ( new CnbUtils() )->get_query_val( 'action', null );
18
  switch ( $action ) {
19
  case 'new':
20
  case 'edit':
src/admin/condition/CnbConditionView.php CHANGED
@@ -8,10 +8,17 @@ defined( 'ABSPATH' ) || die( '-1' );
8
  use cnb\admin\api\CnbAppRemote;
9
  use cnb\admin\button\CnbButton;
10
  use cnb\notices\CnbAdminNotices;
 
11
  use WP_Error;
12
 
13
  class CnbConditionView {
14
 
 
 
 
 
 
 
15
  function header() {
16
  echo 'Conditions ';
17
  }
@@ -22,9 +29,9 @@ class CnbConditionView {
22
  * @return void
23
  */
24
  function add_new_link() {
25
- $id = ! empty( $_GET['id'] ) ? sanitize_text_field( $_GET['id'] ) : null;
26
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
27
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
28
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
29
  // Create link
30
  $url = admin_url( 'admin.php' );
@@ -37,9 +44,8 @@ class CnbConditionView {
37
  'bid' => $bid
38
  ),
39
  $url );
40
- $new_url = esc_url( $new_link );
41
 
42
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
43
  }
44
  }
45
 
@@ -48,8 +54,8 @@ class CnbConditionView {
48
  * @return CnbButton|null
49
  */
50
  private function get_button() {
51
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
52
- if ( $bid !== null ) {
53
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
54
 
55
  if ( $button && ! ( $button instanceof WP_Error ) ) {
@@ -72,6 +78,7 @@ class CnbConditionView {
72
  $wp_list_table->prepare_items();
73
  $wp_list_table->display();
74
  }
 
75
  function render() {
76
  $wp_list_table = new Cnb_Condition_List_Table( $this->get_button() );
77
  $data = $wp_list_table->prepare_items();
8
  use cnb\admin\api\CnbAppRemote;
9
  use cnb\admin\button\CnbButton;
10
  use cnb\notices\CnbAdminNotices;
11
+ use cnb\utils\CnbUtils;
12
  use WP_Error;
13
 
14
  class CnbConditionView {
15
 
16
+ private $cnb_utils;
17
+
18
+ public function __construct() {
19
+ $this->cnb_utils = new CnbUtils();
20
+ }
21
+
22
  function header() {
23
  echo 'Conditions ';
24
  }
29
  * @return void
30
  */
31
  function add_new_link() {
32
+ $id = $this->cnb_utils->get_query_val( 'id', null );
33
+ $action = $this->cnb_utils->get_query_val( 'action', null );
34
+ $bid = $this->cnb_utils->get_query_val( 'bid', null );
35
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
36
  // Create link
37
  $url = admin_url( 'admin.php' );
44
  'bid' => $bid
45
  ),
46
  $url );
 
47
 
48
+ echo '<a href="' . esc_url( $new_link ) . '" class="page-title-action">Add New</a>';
49
  }
50
  }
51
 
54
  * @return CnbButton|null
55
  */
56
  private function get_button() {
57
+ $bid = $this->cnb_utils->get_query_val( 'bid', null );
58
+ if ( $bid ) {
59
  $button = CnbAppRemote::cnb_remote_get_button_full( $bid );
60
 
61
  if ( $button && ! ( $button instanceof WP_Error ) ) {
78
  $wp_list_table->prepare_items();
79
  $wp_list_table->display();
80
  }
81
+
82
  function render() {
83
  $wp_list_table = new Cnb_Condition_List_Table( $this->get_button() );
84
  $data = $wp_list_table->prepare_items();
src/admin/condition/CnbConditionViewEdit.php CHANGED
@@ -6,9 +6,9 @@ namespace cnb\admin\condition;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  use cnb\admin\api\CnbAppRemote;
9
- use cnb\admin\button\CnbButton;
10
  use cnb\utils\CnbAdminFunctions;
11
  use cnb\notices\CnbAdminNotices;
 
12
 
13
  class CnbConditionViewEdit {
14
 
@@ -23,36 +23,12 @@ class CnbConditionViewEdit {
23
  if ( $condition->matchValue ) {
24
  $name = $condition->matchValue;
25
  }
26
- echo __( 'Editing condition' ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
27
  } else {
28
- echo __( 'Add condition' );
29
  }
30
  }
31
 
32
- /**
33
- * Return a safe URL where to edit the Condition for a button
34
- *
35
- * @param CnbButton $button
36
- * @param string $tab
37
- *
38
- * @return string
39
- */
40
- function create_tab_url( $button, $tab ) {
41
- $url = admin_url( 'admin.php' );
42
- $tab_link =
43
- add_query_arg(
44
- array(
45
- 'page' => 'call-now-button',
46
- 'action' => 'edit',
47
- 'type' => strtolower( $button->type ),
48
- 'id' => $button->id,
49
- 'tab' => $tab
50
- ),
51
- $url );
52
-
53
- return esc_url( $tab_link );
54
- }
55
-
56
  /**
57
  * Create the over table for Conditions
58
  *
@@ -79,7 +55,7 @@ class CnbConditionViewEdit {
79
  <td>
80
  <select id="cnb_condition_filter_type"
81
  name="conditions[<?php echo esc_attr( $condition->id ) ?>][filterType]">
82
- <?php foreach ( (new CnbAdminFunctions())->cnb_get_condition_filter_types() as $condition_filter_type_key => $condition_filter_type_value ) { ?>
83
  <option value="<?php echo esc_attr( $condition_filter_type_key ) ?>"<?php selected( $condition_filter_type_key, $condition->filterType ) ?>>
84
  <?php echo esc_html( $condition_filter_type_value ) ?>
85
  </option>
@@ -92,7 +68,7 @@ class CnbConditionViewEdit {
92
  <td>
93
  <select id="cnb_condition_match_type"
94
  name="conditions[<?php echo esc_attr( $condition->id ) ?>][matchType]">
95
- <?php foreach ( (new CnbAdminFunctions())->cnb_get_condition_match_types() as $condition_match_type_key => $condition_match_type_value ) { ?>
96
  <option value="<?php echo esc_attr( $condition_match_type_key ) ?>"<?php selected( $condition_match_type_key, $condition->matchType ) ?>>
97
  <?php echo esc_html( $condition_match_type_value ) ?>
98
  </option>
@@ -114,6 +90,7 @@ class CnbConditionViewEdit {
114
  }
115
 
116
  function render() {
 
117
  $condition_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
118
  $condition = new CnbCondition();
119
  if ( strlen( $condition_id ) > 0 && $condition_id !== 'new' ) {
@@ -122,12 +99,12 @@ class CnbConditionViewEdit {
122
  $condition->id = 'new';
123
  }
124
 
125
- wp_enqueue_script(CNB_SLUG . '-condition-edit');
126
  add_action( 'cnb_header_name', function () use ( $condition ) {
127
  $this->add_header( $condition );
128
  } );
129
 
130
- $bid = ! empty( $_GET['bid'] ) ? sanitize_text_field( $_GET['bid'] ) : null;
131
  if ( $bid !== null ) {
132
  // Create back link
133
  $url = admin_url( 'admin.php' );
@@ -142,25 +119,22 @@ class CnbConditionViewEdit {
142
  $url ) );
143
 
144
  $action_verb = $condition->id === 'new' ? 'adding' : 'editing';
145
- $message = '<p><strong>You are ' . $action_verb . ' a Condition</strong>.
146
  Click <a href="' . $redirect_link . '">here</a> to go back to continue configuring the Button.</p>';
147
  CnbAdminNotices::get_instance()->renderInfo( $message );
148
  }
149
 
150
- $url = admin_url( 'admin-post.php' );
151
- $form_action = esc_url( $url );
152
-
153
  do_action( 'cnb_header' );
154
  ?>
155
 
156
- <form action="<?php echo $form_action; ?>" method="post">
157
  <input type="hidden" name="page" value="call-now-button-conditions"/>
158
  <input type="hidden" name="bid" value="<?php echo esc_attr( $bid ) ?>"/>
159
  <input type="hidden" name="condition_id" value="<?php echo esc_attr( $condition->id ) ?>"/>
160
  <input type="hidden" name="action"
161
  value="<?php echo $condition_id === 'new' ? 'cnb_create_condition' : 'cnb_update_condition' ?>"/>
162
  <input type="hidden" name="_wpnonce"
163
- value="<?php echo wp_create_nonce( $condition->id === 'new' ? 'cnb_create_condition' : 'cnb_update_condition' ) ?>"/>
164
  <?php
165
  $this->render_table( $condition );
166
  submit_button();
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  use cnb\admin\api\CnbAppRemote;
 
9
  use cnb\utils\CnbAdminFunctions;
10
  use cnb\notices\CnbAdminNotices;
11
+ use cnb\utils\CnbUtils;
12
 
13
  class CnbConditionViewEdit {
14
 
23
  if ( $condition->matchValue ) {
24
  $name = $condition->matchValue;
25
  }
26
+ echo esc_html__( 'Editing condition' ) . ' <span class="cnb_button_name">' . esc_html( $name ) . '</span>';
27
  } else {
28
+ echo esc_html__( 'Add condition' );
29
  }
30
  }
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  /**
33
  * Create the over table for Conditions
34
  *
55
  <td>
56
  <select id="cnb_condition_filter_type"
57
  name="conditions[<?php echo esc_attr( $condition->id ) ?>][filterType]">
58
+ <?php foreach ( ( new CnbAdminFunctions() )->cnb_get_condition_filter_types() as $condition_filter_type_key => $condition_filter_type_value ) { ?>
59
  <option value="<?php echo esc_attr( $condition_filter_type_key ) ?>"<?php selected( $condition_filter_type_key, $condition->filterType ) ?>>
60
  <?php echo esc_html( $condition_filter_type_value ) ?>
61
  </option>
68
  <td>
69
  <select id="cnb_condition_match_type"
70
  name="conditions[<?php echo esc_attr( $condition->id ) ?>][matchType]">
71
+ <?php foreach ( ( new CnbAdminFunctions() )->cnb_get_condition_match_types() as $condition_match_type_key => $condition_match_type_value ) { ?>
72
  <option value="<?php echo esc_attr( $condition_match_type_key ) ?>"<?php selected( $condition_match_type_key, $condition->matchType ) ?>>
73
  <?php echo esc_html( $condition_match_type_value ) ?>
74
  </option>
90
  }
91
 
92
  function render() {
93
+ $cnb_utils = new CnbUtils();
94
  $condition_id = filter_input( INPUT_GET, 'id', FILTER_SANITIZE_STRING );
95
  $condition = new CnbCondition();
96
  if ( strlen( $condition_id ) > 0 && $condition_id !== 'new' ) {
99
  $condition->id = 'new';
100
  }
101
 
102
+ wp_enqueue_script( CNB_SLUG . '-condition-edit' );
103
  add_action( 'cnb_header_name', function () use ( $condition ) {
104
  $this->add_header( $condition );
105
  } );
106
 
107
+ $bid = $cnb_utils->get_query_val( 'bid' );
108
  if ( $bid !== null ) {
109
  // Create back link
110
  $url = admin_url( 'admin.php' );
119
  $url ) );
120
 
121
  $action_verb = $condition->id === 'new' ? 'adding' : 'editing';
122
+ $message = '<p><strong>You are ' . $action_verb . ' a Condition</strong>.
123
  Click <a href="' . $redirect_link . '">here</a> to go back to continue configuring the Button.</p>';
124
  CnbAdminNotices::get_instance()->renderInfo( $message );
125
  }
126
 
 
 
 
127
  do_action( 'cnb_header' );
128
  ?>
129
 
130
+ <form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post">
131
  <input type="hidden" name="page" value="call-now-button-conditions"/>
132
  <input type="hidden" name="bid" value="<?php echo esc_attr( $bid ) ?>"/>
133
  <input type="hidden" name="condition_id" value="<?php echo esc_attr( $condition->id ) ?>"/>
134
  <input type="hidden" name="action"
135
  value="<?php echo $condition_id === 'new' ? 'cnb_create_condition' : 'cnb_update_condition' ?>"/>
136
  <input type="hidden" name="_wpnonce"
137
+ value="<?php echo esc_attr( wp_create_nonce( $condition->id === 'new' ? 'cnb_create_condition' : 'cnb_update_condition' ) ) ?>"/>
138
  <?php
139
  $this->render_table( $condition );
140
  submit_button();
src/admin/condition/Cnb_Condition_List_Table.php CHANGED
@@ -6,11 +6,12 @@ namespace cnb\admin\condition;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
13
  use cnb\admin\button\CnbButton;
 
14
  use WP_Error;
15
  use WP_List_Table;
16
 
@@ -24,6 +25,11 @@ class Cnb_Condition_List_Table extends WP_List_Table {
24
  */
25
  public $button;
26
 
 
 
 
 
 
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.
@@ -31,16 +37,17 @@ class Cnb_Condition_List_Table extends WP_List_Table {
31
  * @param CnbButton $button
32
  */
33
  function __construct( $button = null ) {
34
- if ( $button instanceof CnbButton ) {
35
- $this->button = $button;
36
- }
37
-
38
  parent::__construct( array(
39
  'singular' => 'cnb_list_condition', //Singular label
40
  'plural' => 'cnb_list_conditions', //plural label, also this well be one of the table css class
41
  'ajax' => false, //We won't support Ajax for this table
42
  'screen' => 'call-now-button-conditions' // Screen name for bulk actions, etc
43
  ) );
 
 
 
 
 
44
  }
45
 
46
  /**
@@ -48,8 +55,8 @@ class Cnb_Condition_List_Table extends WP_List_Table {
48
  * @return array $columns, the array of columns to use with the table
49
  */
50
  function get_columns() {
51
- $cnb_options = get_option('cnb');
52
- $columns = array(
53
  'cb' => '<input type="checkbox">',
54
  'id' => __( 'ID' ),
55
  'filterType' => __( 'Filter type' ),
@@ -100,7 +107,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
100
  $totalitems = count( $data ); //return the total number of affected rows
101
  $per_page = 20; //How many to display per page?
102
  //Which page is this?
103
- $current_page = ! empty( $_GET['paged'] ) ? (int) sanitize_text_field( $_GET['paged'] ) : 1;
104
 
105
  //Page Number
106
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
@@ -146,17 +153,19 @@ class Cnb_Condition_List_Table extends WP_List_Table {
146
  // Also add the ID input
147
  $id = '<input type="hidden" name="conditions[][id]" value="' . esc_attr( $item->id ) . '" />';
148
  $value = ! empty( $item->id ) ? esc_html( $item->id ) : '<em>No value</em>';
 
149
  return $id . $value;
150
  case 'filterType':
151
- $actions = $this->get_quick_actions($item);
152
- $edit_url = $this->get_edit_link($item);
153
- $value = ucfirst(strtolower($item->filterType));
 
154
  return sprintf(
155
  '%1$s %2$s',
156
- '<strong><a class="row-title" href="' . $edit_url . '">' . esc_html( $value ) .'</a></strong>',
157
- $this->row_actions( $actions ));
158
  case 'matchType':
159
- switch ($item->matchType) {
160
  case 'SIMPLE':
161
  return 'Page path is';
162
  case 'EXACT':
@@ -166,6 +175,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
166
  case 'REGEX':
167
  return 'Page URL matches RegEx';
168
  }
 
169
  return '<code>' . esc_html( $item->matchType ) . '</code>';
170
  case 'matchValue':
171
  return ! empty( $item->matchValue ) ? esc_html( $item->matchValue ) : '<em>No value</em>';
@@ -193,7 +203,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
193
  }
194
 
195
  private function get_data() {
196
- $cnb_options = get_option('cnb');
197
  if ( $this->button === null ) {
198
  $entities = CnbAppRemote::cnb_remote_get_conditions();
199
  } else {
@@ -229,9 +239,9 @@ class Cnb_Condition_List_Table extends WP_List_Table {
229
  */
230
  private function sort_data( $a, $b ) {
231
  // If orderby is set, use this as the sort column
232
- $orderby = ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'conditionType';
233
  // If order is set use this as the order
234
- $order = ! empty( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'asc';
235
 
236
  $result = strcmp( $a->$orderby, $b->$orderby );
237
 
@@ -257,9 +267,9 @@ class Cnb_Condition_List_Table extends WP_List_Table {
257
  );
258
  }
259
 
260
- private function get_edit_link($condition) {
261
- $bid = $this->button !== null ? $this->button->id : null;
262
- $tab = $this->button !== null ? 'visibility' : null;
263
  $url = admin_url( 'admin.php' );
264
  $edit_link =
265
  add_query_arg(
@@ -271,21 +281,22 @@ class Cnb_Condition_List_Table extends WP_List_Table {
271
  'tab' => $tab
272
  ),
273
  $url );
 
274
  return esc_url( $edit_link );
275
  }
 
276
  /**
277
  * @param $condition CnbCondition
278
  *
279
  * @return string[]
280
  */
281
- private function get_quick_actions($condition) {
282
  $bid = $this->button !== null ? $this->button->id : null;
283
- $tab = $this->button !== null ? 'visibility' : null;
284
 
285
  // Let's build a link
286
- $url = admin_url( 'admin.php' );
287
- $edit_url = $this->get_edit_link($condition);
288
- $actions = array(
289
  'edit' => '<a href="' . $edit_url . '">Edit</a>',
290
  );
291
 
@@ -314,6 +325,7 @@ class Cnb_Condition_List_Table extends WP_List_Table {
314
  $delete_url = esc_url( $delete_link );
315
  $actions['delete'] = '<a href="' . $delete_url . '">' . __( 'Delete' ) . '</a>';
316
  }
 
317
  return $actions;
318
  }
319
 
@@ -321,11 +333,10 @@ class Cnb_Condition_List_Table extends WP_List_Table {
321
  * @param CnbCondition $item
322
  *
323
  * @return string
 
324
  */
325
  function column_conditionType( $item ) {
326
- $value = ! empty( $item->conditionType ) ? $item->conditionType : '<em>No value</em>';
327
-
328
- return esc_html( $value );
329
  }
330
 
331
  function get_bulk_actions() {
@@ -342,12 +353,13 @@ class Cnb_Condition_List_Table extends WP_List_Table {
342
  }
343
 
344
  function no_items() {
345
- if ($this->button) {
346
- _e('<p class="cnb_paragraph">You have no page visibility rules set up. This means that your button will show on all pages.</p>
347
- <p class="cnb_paragraph">Click the <code>Add page rule</code> button above to limit the appearance. You can freely mix and match rules to meet your requirements.</p>');
 
348
  return;
349
  }
350
- _e( 'No conditions found.' );
351
 
352
  }
353
  }
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
13
  use cnb\admin\button\CnbButton;
14
+ use cnb\utils\CnbUtils;
15
  use WP_Error;
16
  use WP_List_Table;
17
 
25
  */
26
  public $button;
27
 
28
+ /**
29
+ * @var CnbUtils
30
+ */
31
+ private $cnb_utils;
32
+
33
  /**
34
  * Constructor, we override the parent to pass our own arguments
35
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
37
  * @param CnbButton $button
38
  */
39
  function __construct( $button = null ) {
 
 
 
 
40
  parent::__construct( array(
41
  'singular' => 'cnb_list_condition', //Singular label
42
  'plural' => 'cnb_list_conditions', //plural label, also this well be one of the table css class
43
  'ajax' => false, //We won't support Ajax for this table
44
  'screen' => 'call-now-button-conditions' // Screen name for bulk actions, etc
45
  ) );
46
+
47
+ $this->cnb_utils = new CnbUtils();
48
+ if ( $button instanceof CnbButton ) {
49
+ $this->button = $button;
50
+ }
51
  }
52
 
53
  /**
55
  * @return array $columns, the array of columns to use with the table
56
  */
57
  function get_columns() {
58
+ $cnb_options = get_option( 'cnb' );
59
+ $columns = array(
60
  'cb' => '<input type="checkbox">',
61
  'id' => __( 'ID' ),
62
  'filterType' => __( 'Filter type' ),
107
  $totalitems = count( $data ); //return the total number of affected rows
108
  $per_page = 20; //How many to display per page?
109
  //Which page is this?
110
+ $current_page = intval( $this->cnb_utils->get_query_val( 'paged', 1 ) );
111
 
112
  //Page Number
113
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
153
  // Also add the ID input
154
  $id = '<input type="hidden" name="conditions[][id]" value="' . esc_attr( $item->id ) . '" />';
155
  $value = ! empty( $item->id ) ? esc_html( $item->id ) : '<em>No value</em>';
156
+
157
  return $id . $value;
158
  case 'filterType':
159
+ $actions = $this->get_quick_actions( $item );
160
+ $edit_url = $this->get_edit_link( $item );
161
+ $value = ucfirst( strtolower( $item->filterType ) );
162
+
163
  return sprintf(
164
  '%1$s %2$s',
165
+ '<strong><a class="row-title" href="' . $edit_url . '">' . esc_html( $value ) . '</a></strong>',
166
+ $this->row_actions( $actions ) );
167
  case 'matchType':
168
+ switch ( $item->matchType ) {
169
  case 'SIMPLE':
170
  return 'Page path is';
171
  case 'EXACT':
175
  case 'REGEX':
176
  return 'Page URL matches RegEx';
177
  }
178
+
179
  return '<code>' . esc_html( $item->matchType ) . '</code>';
180
  case 'matchValue':
181
  return ! empty( $item->matchValue ) ? esc_html( $item->matchValue ) : '<em>No value</em>';
203
  }
204
 
205
  private function get_data() {
206
+ $cnb_options = get_option( 'cnb' );
207
  if ( $this->button === null ) {
208
  $entities = CnbAppRemote::cnb_remote_get_conditions();
209
  } else {
239
  */
240
  private function sort_data( $a, $b ) {
241
  // If orderby is set, use this as the sort column
242
+ $orderby = $this->cnb_utils->get_query_val( 'orderby', 'conditionType' );
243
  // If order is set use this as the order
244
+ $order = $this->cnb_utils->get_query_val( 'order', 'asc' );
245
 
246
  $result = strcmp( $a->$orderby, $b->$orderby );
247
 
267
  );
268
  }
269
 
270
+ private function get_edit_link( $condition ) {
271
+ $bid = $this->button !== null ? $this->button->id : null;
272
+ $tab = $this->button !== null ? 'visibility' : null;
273
  $url = admin_url( 'admin.php' );
274
  $edit_link =
275
  add_query_arg(
281
  'tab' => $tab
282
  ),
283
  $url );
284
+
285
  return esc_url( $edit_link );
286
  }
287
+
288
  /**
289
  * @param $condition CnbCondition
290
  *
291
  * @return string[]
292
  */
293
+ private function get_quick_actions( $condition ) {
294
  $bid = $this->button !== null ? $this->button->id : null;
 
295
 
296
  // Let's build a link
297
+ $url = admin_url( 'admin.php' );
298
+ $edit_url = $this->get_edit_link( $condition );
299
+ $actions = array(
300
  'edit' => '<a href="' . $edit_url . '">Edit</a>',
301
  );
302
 
325
  $delete_url = esc_url( $delete_link );
326
  $actions['delete'] = '<a href="' . $delete_url . '">' . __( 'Delete' ) . '</a>';
327
  }
328
+
329
  return $actions;
330
  }
331
 
333
  * @param CnbCondition $item
334
  *
335
  * @return string
336
+ * @noinspection PhpUnused
337
  */
338
  function column_conditionType( $item ) {
339
+ return ! empty( $item->conditionType ) ? esc_html( $item->conditionType ) : '<em>No value</em>';
 
 
340
  }
341
 
342
  function get_bulk_actions() {
353
  }
354
 
355
  function no_items() {
356
+ if ( $this->button ) {
357
+ echo '<p class="cnb_paragraph">You have no page visibility rules set up. This means that your button will show on all pages.</p>';
358
+ echo '<p class="cnb_paragraph">Click the <code>Add page rule</code> button above to limit the appearance. You can freely mix and match rules to meet your requirements.</p>';
359
+
360
  return;
361
  }
362
+ esc_html_e( 'No conditions found.' );
363
 
364
  }
365
  }
src/admin/domain/CnbDomainController.php CHANGED
@@ -31,7 +31,7 @@ class CnbDomainController {
31
 
32
  $processed_domain = CnbDomain::fromObject( $domain );
33
  // Alligator alert - this is different from other update functions!!
34
- $processed_domain->properties->zindex = (new CnbUtils())->zindex( $processed_domain->properties->zindex );
35
  // do the processing
36
  $result = CnbAdminCloud::cnb_create_domain( $cnb_cloud_notifications, $processed_domain );
37
 
@@ -55,9 +55,9 @@ class CnbDomainController {
55
  wp_safe_redirect( $redirect_url );
56
  exit;
57
  } else {
58
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
59
  'response' => 403,
60
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
61
  ) );
62
  }
63
  }
@@ -72,7 +72,7 @@ class CnbDomainController {
72
 
73
  $processed_domain = CnbDomain::fromObject( $domain );
74
  // Alligator alert - this is different from other update functions!!
75
- $processed_domain->properties->zindex = (new CnbUtils())->zindex( $processed_domain->properties->zindex );
76
 
77
  return $processed_domain;
78
  }
@@ -116,9 +116,9 @@ class CnbDomainController {
116
  wp_safe_redirect( $redirect_url );
117
  exit;
118
  } else {
119
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
120
  'response' => 403,
121
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
122
  ) );
123
  }
124
  }
@@ -128,51 +128,82 @@ class CnbDomainController {
128
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
129
  $action = 'cnb_update_domain_timezone';
130
  if ( wp_verify_nonce( $nonce, $action ) ) {
131
- $timezone = filter_input( INPUT_POST, 'timezone', FILTER_SANITIZE_STRING );
132
- $domain = CnbAppRemote::cnb_remote_get_wp_domain();
133
  $domain->timezone = $timezone;
134
- $notifications = array();
135
- CnbAdminCloud::cnb_update_domain($notifications, $domain);
136
- wp_send_json(array('success' => true, 'domain' => $domain, 'notification' => $notifications, 'timezone' => esc_html($timezone)));
 
 
 
 
 
137
  return;
138
  }
139
- wp_send_json(array('success' => false, 'reason' => 'nonce fail'));
 
140
  return;
141
  }
142
- wp_send_json(array('success' => false, 'reason' => 'no nonce'));
143
  }
144
 
145
- public static function delete() {
146
- if ( isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ) {
147
- $id = ! empty( $_GET['id'] ) ? sanitize_text_field( $_GET['id'] ) : null;
148
- $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING );
149
- $action = 'cnb_delete_domain';
150
-
151
- if ( wp_verify_nonce( $nonce, $action ) ) {
152
- $adminNotices = CnbAdminNotices::get_instance();
 
 
 
 
 
 
153
 
154
- $cnb_cloud_notifications = array();
155
- $domain = new CnbDomain();
156
- $domain->id = $id;
157
- CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $domain );
158
- $adminNotices->renderNotices( $cnb_cloud_notifications );
159
- }
 
160
  }
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  public static function handle_bulk_actions() {
164
- $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
 
165
  $action = 'bulk-cnb_list_domains';
166
  $nonce_verified = wp_verify_nonce( $nonce, $action );
 
167
  if ( $nonce_verified ) {
168
  $domainIds = filter_input( INPUT_POST, 'cnb_list_domain', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
169
- if ( $_REQUEST['bulk-action'] == 'delete' ) {
170
  $cnb_cloud_notifications = array();
171
  foreach ( $domainIds as $domainId ) {
172
  $domain = new CnbDomain();
173
  $domain->id = $domainId;
174
  CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $domain );
175
  }
 
176
  // Create notice for link (and yes - we ignore the content of $cnb_cloud_notifications here, we just use it to count)
177
  $notice = new CnbNotice( 'success', '<p>' . count( $cnb_cloud_notifications ) . ' Domain(s) deleted.</p>' );
178
  $transient_id = 'cnb-' . wp_generate_uuid4();
@@ -189,12 +220,26 @@ class CnbDomainController {
189
  $url );
190
  $redirect_url = esc_url_raw( $redirect_link );
191
  wp_safe_redirect( $redirect_url );
 
 
 
 
 
 
 
 
 
 
192
  }
193
  } else {
194
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
195
- 'response' => 403,
196
- 'back_link' => 'admin.php?page=' . CNB_SLUG,
197
- ) );
 
 
 
 
198
  }
199
  }
200
  }
31
 
32
  $processed_domain = CnbDomain::fromObject( $domain );
33
  // Alligator alert - this is different from other update functions!!
34
+ $processed_domain->properties->zindex = ( new CnbUtils() )->zindex( $processed_domain->properties->zindex );
35
  // do the processing
36
  $result = CnbAdminCloud::cnb_create_domain( $cnb_cloud_notifications, $processed_domain );
37
 
55
  wp_safe_redirect( $redirect_url );
56
  exit;
57
  } else {
58
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
59
  'response' => 403,
60
+ 'back_link' => true,
61
  ) );
62
  }
63
  }
72
 
73
  $processed_domain = CnbDomain::fromObject( $domain );
74
  // Alligator alert - this is different from other update functions!!
75
+ $processed_domain->properties->zindex = ( new CnbUtils() )->zindex( $processed_domain->properties->zindex );
76
 
77
  return $processed_domain;
78
  }
116
  wp_safe_redirect( $redirect_url );
117
  exit;
118
  } else {
119
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
120
  'response' => 403,
121
+ 'back_link' => true,
122
  ) );
123
  }
124
  }
128
  $nonce = filter_input( INPUT_POST, '_wpnonce', FILTER_SANITIZE_STRING );
129
  $action = 'cnb_update_domain_timezone';
130
  if ( wp_verify_nonce( $nonce, $action ) ) {
131
+ $timezone = filter_input( INPUT_POST, 'timezone', FILTER_SANITIZE_STRING );
132
+ $domain = CnbAppRemote::cnb_remote_get_wp_domain();
133
  $domain->timezone = $timezone;
134
+ $notifications = array();
135
+ CnbAdminCloud::cnb_update_domain( $notifications, $domain );
136
+ wp_send_json( array( 'success' => true,
137
+ 'domain' => $domain,
138
+ 'notification' => $notifications,
139
+ 'timezone' => esc_html( $timezone )
140
+ ) );
141
+
142
  return;
143
  }
144
+ wp_send_json( array( 'success' => false, 'reason' => 'nonce fail' ) );
145
+
146
  return;
147
  }
148
+ wp_send_json( array( 'success' => false, 'reason' => 'no nonce' ) );
149
  }
150
 
151
+ /**
152
+ * Via the quick actions, be able to delete a Domain
153
+ *
154
+ * This also means we CANNOT redirect, as we're already halfway into rendering the page,
155
+ * so we add the notification to the adminNotices handler
156
+ *
157
+ * @return void
158
+ */
159
+ public function delete() {
160
+ $cnb_utils = new CnbUtils();
161
+ $id = $cnb_utils->get_query_val( 'id', null );
162
+ $nonce = $cnb_utils->get_query_val( '_wpnonce', null );
163
+ $action = 'cnb_delete_domain';
164
+ $nonce_verified = wp_verify_nonce( $nonce, $action );
165
 
166
+ if ( $nonce_verified ) {
167
+ $adminNotices = CnbAdminNotices::get_instance();
168
+ $cnb_cloud_notifications = array();
169
+ $domain = new CnbDomain();
170
+ $domain->id = $id;
171
+ CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $domain );
172
+ $adminNotices->notices( $cnb_cloud_notifications );
173
  }
174
  }
175
 
176
+ /**
177
+ * This is very similar to the <code>delete()</code> function above.
178
+ *
179
+ * This always has to come via a $_POST request (specifically, via admin-post.php),
180
+ * so this should end in a redirect (or an error via wp_die)
181
+ *
182
+ * Big differences are:
183
+ * - This handles multiple IDs, versus 1
184
+ * - Instead of rendering the Notice, is it stored and the user redirected
185
+ *
186
+ * nonce name via WP_List_Table = bulk-{plural}
187
+ * so in this case: bulk-cnb_list_domains
188
+ *
189
+ * @return void
190
+ */
191
  public static function handle_bulk_actions() {
192
+ $cnb_utils = new CnbUtils();
193
+ $nonce = $cnb_utils->get_post_val( '_wpnonce' );
194
  $action = 'bulk-cnb_list_domains';
195
  $nonce_verified = wp_verify_nonce( $nonce, $action );
196
+
197
  if ( $nonce_verified ) {
198
  $domainIds = filter_input( INPUT_POST, 'cnb_list_domain', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
199
+ if ( $cnb_utils->get_post_val( 'bulk-action' ) === 'delete' ) {
200
  $cnb_cloud_notifications = array();
201
  foreach ( $domainIds as $domainId ) {
202
  $domain = new CnbDomain();
203
  $domain->id = $domainId;
204
  CnbAdminCloud::cnb_delete_domain( $cnb_cloud_notifications, $domain );
205
  }
206
+
207
  // Create notice for link (and yes - we ignore the content of $cnb_cloud_notifications here, we just use it to count)
208
  $notice = new CnbNotice( 'success', '<p>' . count( $cnb_cloud_notifications ) . ' Domain(s) deleted.</p>' );
209
  $transient_id = 'cnb-' . wp_generate_uuid4();
220
  $url );
221
  $redirect_url = esc_url_raw( $redirect_link );
222
  wp_safe_redirect( $redirect_url );
223
+ } else {
224
+ wp_die(
225
+ esc_html__( 'Unknown Bulk action specified' ),
226
+ esc_html__( 'Cannot process Bulk action' ),
227
+ array(
228
+ 'response' => 403,
229
+ 'link_text' => esc_html( 'Go back to the Domains overview' ),
230
+ 'link_url' => esc_url_raw( admin_url( 'admin.php' ) . '?page=' . CNB_SLUG . '-domains' ),
231
+ )
232
+ );
233
  }
234
  } else {
235
+ wp_die(
236
+ esc_html__( 'Invalid nonce specified' ),
237
+ esc_html__( 'Error' ),
238
+ array(
239
+ 'response' => 403,
240
+ 'back_link' => true,
241
+ )
242
+ );
243
  }
244
  }
245
  }
src/admin/domain/CnbDomainRouter.php CHANGED
@@ -3,6 +3,8 @@
3
  namespace cnb\admin\domain;
4
 
5
  // don't load directly
 
 
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  class CnbDomainRouter {
@@ -12,13 +14,13 @@ class CnbDomainRouter {
12
  * @return void
13
  */
14
  public static function render() {
15
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
16
  switch ( $action ) {
17
  case 'new':
18
  case 'edit':
19
  ( new CnbDomainViewEdit() )->render();
20
  break;
21
- // This is the quick action where they can delete a single Condidion
22
  case 'delete':
23
  ( new CnbDomainController() )->delete();
24
  ( new CnbDomainView() )->render();
@@ -31,4 +33,4 @@ class CnbDomainRouter {
31
  break;
32
  }
33
  }
34
- }
3
  namespace cnb\admin\domain;
4
 
5
  // don't load directly
6
+ use cnb\utils\CnbUtils;
7
+
8
  defined( 'ABSPATH' ) || die( '-1' );
9
 
10
  class CnbDomainRouter {
14
  * @return void
15
  */
16
  public static function render() {
17
+ $action = ( new CnbUtils() )->get_query_val( 'action', null );
18
  switch ( $action ) {
19
  case 'new':
20
  case 'edit':
21
  ( new CnbDomainViewEdit() )->render();
22
  break;
23
+ // This is the quick action where they can delete a single Domain
24
  case 'delete':
25
  ( new CnbDomainController() )->delete();
26
  ( new CnbDomainView() )->render();
33
  break;
34
  }
35
  }
36
+ }
src/admin/domain/CnbDomainView.php CHANGED
@@ -3,9 +3,18 @@
3
  namespace cnb\admin\domain;
4
 
5
  // don't load directly
 
 
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  class CnbDomainView {
 
 
 
 
 
 
 
9
  function header() {
10
  echo 'Domains ';
11
  }
@@ -16,8 +25,8 @@ class CnbDomainView {
16
  * @return void
17
  */
18
  function add_modal() {
19
- $id = ! empty( $_GET['id'] ) ? sanitize_text_field( $_GET['id'] ) : null;
20
- $action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : null;
21
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
22
  // Create link
23
  $url = admin_url( 'admin.php' );
@@ -29,9 +38,8 @@ class CnbDomainView {
29
  'id' => 'new'
30
  ),
31
  $url );
32
- $new_url = esc_url( $new_link );
33
 
34
- echo '<a href="' . $new_url . '" class="page-title-action">Add New</a>';
35
  }
36
  }
37
 
3
  namespace cnb\admin\domain;
4
 
5
  // don't load directly
6
+ use cnb\utils\CnbUtils;
7
+
8
  defined( 'ABSPATH' ) || die( '-1' );
9
 
10
  class CnbDomainView {
11
+
12
+ private $cnb_utils;
13
+
14
+ public function __construct() {
15
+ $this->cnb_utils = new CnbUtils();
16
+ }
17
+
18
  function header() {
19
  echo 'Domains ';
20
  }
25
  * @return void
26
  */
27
  function add_modal() {
28
+ $id = $this->cnb_utils->get_query_val( 'id', null );
29
+ $action = $this->cnb_utils->get_query_val( 'action', null );
30
  if ( $id === null || ( $action != 'new' && $action != 'edit' ) ) {
31
  // Create link
32
  $url = admin_url( 'admin.php' );
38
  'id' => 'new'
39
  ),
40
  $url );
 
41
 
42
+ echo '<a href="' . esc_url( $new_link ) . '" class="page-title-action">Add New</a>';
43
  }
44
  }
45
 
src/admin/domain/CnbDomainViewEdit.php CHANGED
@@ -16,13 +16,12 @@ class CnbDomainViewEdit {
16
  */
17
  private function header( $domain ) {
18
  if ( $domain->name ) {
19
- echo __( 'Editing domain' ) . ' <span class="cnb_button_name">' . esc_html( $domain->name ) . '</span>';
20
  } else {
21
- echo __( 'Add domain' );
22
  }
23
  }
24
 
25
-
26
  /**
27
  * Main entrypoint, used by `domain-overview.php`.
28
  */
@@ -51,7 +50,7 @@ class CnbDomainViewEdit {
51
  <input type="hidden" name="action"
52
  value="<?php echo $domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain' ?>"/>
53
  <input type="hidden" name="_wpnonce"
54
- value="<?php echo wp_create_nonce( $domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain' ) ?>"/>
55
 
56
  <table class="form-table nav-tab-active" role="presentation">
57
  <?php $this->render_form( $domain ) ?>
@@ -73,7 +72,6 @@ class CnbDomainViewEdit {
73
  'id' => $domain->id
74
  ),
75
  $url );
76
- $upgrade_url = esc_url( $upgrade_link );
77
  ?>
78
  <tr>
79
  <th>Plan</th>
@@ -81,7 +79,7 @@ class CnbDomainViewEdit {
81
  <code><?php echo esc_html( $domain->type ) ?></code>
82
  <?php
83
  if ( $domain->type !== 'PRO' && ! empty( $domain->id ) ) {
84
- echo '<a href="' . $upgrade_url . '">Upgrade!</a>
85
  <p class="description">The FREE plan offers all features but adds delicate branding to your buttons.</p>';
86
  }
87
  ?>
@@ -101,7 +99,7 @@ class CnbDomainViewEdit {
101
  <p class="description" id="domain_expires-description">
102
  Your subscription will
103
  <?php echo $domain->renew == 1 ? ' renew automatically ' : ' expire '; ?>
104
- on <?php echo date( 'F d, Y', strtotime( esc_html( $domain->expires ) ) ); ?>.
105
  </p>
106
  <?php } ?>
107
  </td>
@@ -126,8 +124,8 @@ class CnbDomainViewEdit {
126
  <p class="description">
127
  Supports Classic, Universal Analytics and Global site tag (v3 and v4).<br>
128
  Using Google Tag Manager? Set up click tracking in GTM. <a
129
- href="<?php echo CNB_SUPPORT ?>web-app/domains/tracking-button-clicks-gtm/" target="_blank">Here's
130
- how...</a>
131
  </p>
132
  </td>
133
  </tr>
@@ -151,7 +149,7 @@ class CnbDomainViewEdit {
151
  }
152
 
153
  function render_form_button_display( $domain ) {
154
- $domain_properties_zindex_order = (new CnbUtils())->zindexToOrder( $domain->properties->zindex );
155
  ?>
156
  <tr>
157
  <th colspan="2"><h2>Button display</h2></th>
@@ -171,7 +169,7 @@ class CnbDomainViewEdit {
171
  </tr>
172
  <tr class="z-index">
173
  <th scope="row"><label for="cnb_order_slider">Order (<span id="cnb_order_value"></span>)</label> <a
174
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/set-order/" target="_blank"
175
  class="cnb-nounderscore">
176
  <span class="dashicons dashicons-editor-help"></span>
177
  </a></th>
@@ -219,7 +217,7 @@ class CnbDomainViewEdit {
219
  * @return void
220
  */
221
  function render_form_advanced( $domain, $header = true ) {
222
- $cnb_options = get_option('cnb');
223
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
224
 
225
  if ( $header ) { ?>
@@ -253,7 +251,10 @@ class CnbDomainViewEdit {
253
  <tr>
254
  <th scope="row"><label for="domain_timezone">Timezone</label></th>
255
  <td>
256
- <?php echo $this->getTimezoneSelect($domain); ?>
 
 
 
257
  </td>
258
  </tr>
259
  <tr>
@@ -275,21 +276,22 @@ class CnbDomainViewEdit {
275
  <?php
276
  }
277
 
278
- public function getTimezoneSelect($domain) {
279
- $result = '<select name="domain[timezone]" id="domain_timezone" class="cnb_timezone_picker">';
280
  $result .= wp_timezone_choice( $domain->timezone );
281
  $result .= '</select>';
282
  $result .= '<p class="description" id="domain_timezone-description">';
283
  if ( empty( $domain->timezone ) ) {
284
- $result .= 'This is important for the scheduler to function.';
285
- $wordpress_timezone_string = wp_timezone_string();
286
- if ( (new CnbUtils())->is_valid_timezone_string( $wordpress_timezone_string ) ) {
287
- $result .= '<br/>WordPress is set to: <code>' . $wordpress_timezone_string . '</code>';
288
- }
289
  } else {
290
- $result .= 'Set to <code>' . esc_html( $domain->timezone ) .'</code>';
291
  }
292
  $result .= '</p>';
 
293
  return $result;
294
  }
295
 
16
  */
17
  private function header( $domain ) {
18
  if ( $domain->name ) {
19
+ echo esc_html__( 'Editing domain' ) . ' <span class="cnb_button_name">' . esc_html( $domain->name ) . '</span>';
20
  } else {
21
+ echo esc_html__( 'Add domain' );
22
  }
23
  }
24
 
 
25
  /**
26
  * Main entrypoint, used by `domain-overview.php`.
27
  */
50
  <input type="hidden" name="action"
51
  value="<?php echo $domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain' ?>"/>
52
  <input type="hidden" name="_wpnonce"
53
+ value="<?php echo esc_attr( wp_create_nonce( $domain_id === 'new' ? 'cnb_create_domain' : 'cnb_update_domain' ) ) ?>"/>
54
 
55
  <table class="form-table nav-tab-active" role="presentation">
56
  <?php $this->render_form( $domain ) ?>
72
  'id' => $domain->id
73
  ),
74
  $url );
 
75
  ?>
76
  <tr>
77
  <th>Plan</th>
79
  <code><?php echo esc_html( $domain->type ) ?></code>
80
  <?php
81
  if ( $domain->type !== 'PRO' && ! empty( $domain->id ) ) {
82
+ echo '<a href="' . esc_url( $upgrade_link ) . '">Upgrade!</a>
83
  <p class="description">The FREE plan offers all features but adds delicate branding to your buttons.</p>';
84
  }
85
  ?>
99
  <p class="description" id="domain_expires-description">
100
  Your subscription will
101
  <?php echo $domain->renew == 1 ? ' renew automatically ' : ' expire '; ?>
102
+ on <?php echo esc_html( date( 'F d, Y', strtotime( $domain->expires ) ) ) ?>.
103
  </p>
104
  <?php } ?>
105
  </td>
124
  <p class="description">
125
  Supports Classic, Universal Analytics and Global site tag (v3 and v4).<br>
126
  Using Google Tag Manager? Set up click tracking in GTM. <a
127
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>web-app/domains/tracking-button-clicks-gtm/"
128
+ target="_blank">Here's how...</a>
129
  </p>
130
  </td>
131
  </tr>
149
  }
150
 
151
  function render_form_button_display( $domain ) {
152
+ $domain_properties_zindex_order = ( new CnbUtils() )->zindexToOrder( $domain->properties->zindex );
153
  ?>
154
  <tr>
155
  <th colspan="2"><h2>Button display</h2></th>
169
  </tr>
170
  <tr class="z-index">
171
  <th scope="row"><label for="cnb_order_slider">Order (<span id="cnb_order_value"></span>)</label> <a
172
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/set-order/" target="_blank"
173
  class="cnb-nounderscore">
174
  <span class="dashicons dashicons-editor-help"></span>
175
  </a></th>
217
  * @return void
218
  */
219
  function render_form_advanced( $domain, $header = true ) {
220
+ $cnb_options = get_option( 'cnb' );
221
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
222
 
223
  if ( $header ) { ?>
251
  <tr>
252
  <th scope="row"><label for="domain_timezone">Timezone</label></th>
253
  <td>
254
+ <?php
255
+ // phpcs:ignore WordPress.Security
256
+ echo $this->getTimezoneSelect( $domain );
257
+ ?>
258
  </td>
259
  </tr>
260
  <tr>
276
  <?php
277
  }
278
 
279
+ public function getTimezoneSelect( $domain ) {
280
+ $result = '<select name="domain[timezone]" id="domain_timezone" class="cnb_timezone_picker">';
281
  $result .= wp_timezone_choice( $domain->timezone );
282
  $result .= '</select>';
283
  $result .= '<p class="description" id="domain_timezone-description">';
284
  if ( empty( $domain->timezone ) ) {
285
+ $result .= 'This is important for the scheduler to function.';
286
+ $wordpress_timezone_string = wp_timezone_string();
287
+ if ( ( new CnbUtils() )->is_valid_timezone_string( $wordpress_timezone_string ) ) {
288
+ $result .= '<br/>WordPress is set to: <code>' . $wordpress_timezone_string . '</code>';
289
+ }
290
  } else {
291
+ $result .= 'Set to <code>' . esc_html( $domain->timezone ) . '</code>';
292
  }
293
  $result .= '</p>';
294
+
295
  return $result;
296
  }
297
 
src/admin/domain/CnbDomainViewUpgrade.php CHANGED
@@ -48,7 +48,7 @@ class CnbDomainViewUpgrade {
48
 
49
  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>' );
50
  } else {
51
- return new CnbNotice( 'warning', '<p>Something is going on upgrading domain <strong>' . esc_html( $domain->name ) . '</strong>.</p><p>Error: ' . esc_html($session->get_error_message()) . '!</p>' );
52
  }
53
  }
54
 
@@ -78,7 +78,7 @@ class CnbDomainViewUpgrade {
78
  } else if ( $domain->type == 'PRO' ) {
79
  ( new CnbDomainViewUpgradeFinished() )->render( $domain, $notice );
80
  } else {
81
- ( new CnbDomainViewUpgradeOverview )->render( $domain );
82
  }
83
  }
84
 
48
 
49
  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>' );
50
  } else {
51
+ return new CnbNotice( 'warning', '<p>Something is going on upgrading domain <strong>' . esc_html( $domain->name ) . '</strong>.</p><p>Error: ' . esc_html( $session->get_error_message() ) . '!</p>' );
52
  }
53
  }
54
 
78
  } else if ( $domain->type == 'PRO' ) {
79
  ( new CnbDomainViewUpgradeFinished() )->render( $domain, $notice );
80
  } else {
81
+ ( new CnbDomainViewUpgradeOverview() )->render( $domain );
82
  }
83
  }
84
 
src/admin/domain/Cnb_Domain_List_Table.php CHANGED
@@ -6,15 +6,21 @@ namespace cnb\admin\domain;
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
 
13
  use WP_Error;
14
  use WP_List_Table;
15
 
16
  class Cnb_Domain_List_Table extends WP_List_Table {
17
 
 
 
 
 
 
18
  /**
19
  * Constructor, we override the parent to pass our own arguments
20
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
@@ -26,6 +32,8 @@ class Cnb_Domain_List_Table extends WP_List_Table {
26
  'ajax' => false, //We won't support Ajax for this table
27
  'screen' => 'call-now-button-domains' // Screen name for bulk actions, etc
28
  ) );
 
 
29
  }
30
 
31
  /**
@@ -74,7 +82,7 @@ class Cnb_Domain_List_Table extends WP_List_Table {
74
  $totalitems = count( $data ); //return the total number of affected rows
75
  $per_page = 20; //How many to display per page?
76
  //Which page is this?
77
- $current_page = ! empty( $_GET['paged'] ) ? (int) sanitize_text_field( $_GET['paged'] ) : 1;
78
 
79
  //Page Number
80
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
@@ -154,9 +162,9 @@ class Cnb_Domain_List_Table extends WP_List_Table {
154
  */
155
  private function sort_data( $a, $b ) {
156
  // If orderby is set, use this as the sort column
157
- $orderby = ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'name';
158
  // If order is set use this as the order
159
- $order = ! empty( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'asc';
160
 
161
  $result = strcmp( $a->$orderby, $b->$orderby );
162
 
@@ -236,6 +244,6 @@ class Cnb_Domain_List_Table extends WP_List_Table {
236
  }
237
 
238
  function no_items() {
239
- _e( 'No domains found.' );
240
  }
241
  }
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  if ( ! class_exists( 'WP_List_Table' ) ) {
9
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
10
  }
11
 
12
  use cnb\admin\api\CnbAppRemote;
13
+ use cnb\utils\CnbUtils;
14
  use WP_Error;
15
  use WP_List_Table;
16
 
17
  class Cnb_Domain_List_Table extends WP_List_Table {
18
 
19
+ /**
20
+ * @var CnbUtils
21
+ */
22
+ private $cnb_utils;
23
+
24
  /**
25
  * Constructor, we override the parent to pass our own arguments
26
  * We usually focus on three parameters: singular and plural labels, as well as whether the class supports AJAX.
32
  'ajax' => false, //We won't support Ajax for this table
33
  'screen' => 'call-now-button-domains' // Screen name for bulk actions, etc
34
  ) );
35
+
36
+ $this->cnb_utils = new CnbUtils();
37
  }
38
 
39
  /**
82
  $totalitems = count( $data ); //return the total number of affected rows
83
  $per_page = 20; //How many to display per page?
84
  //Which page is this?
85
+ $current_page = (int) $this->cnb_utils->get_query_val( 'paged', '1' );
86
 
87
  //Page Number
88
  if ( empty( $current_page ) || ! is_numeric( $current_page ) || $current_page <= 0 ) {
162
  */
163
  private function sort_data( $a, $b ) {
164
  // If orderby is set, use this as the sort column
165
+ $orderby = $this->cnb_utils->get_query_val( 'orderby', 'name' );
166
  // If order is set use this as the order
167
+ $order = $this->cnb_utils->get_query_val( 'order', 'asc' );
168
 
169
  $result = strcmp( $a->$orderby, $b->$orderby );
170
 
244
  }
245
 
246
  function no_items() {
247
+ esc_html_e( 'No domains found.' );
248
  }
249
  }
src/admin/domain/partials/CnbDomainViewUpgradeFinished.php CHANGED
@@ -27,12 +27,12 @@ class CnbDomainViewUpgradeFinished {
27
  }
28
 
29
  /**
30
- * SVG wrapped in a div with a big, nice and pretty "Yay!"
31
  *
32
- * @return string
33
  */
34
- public function getBigYaySvg() {
35
- return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 561 309"><path d="M107.373,301.9a109.773,109.773,0,0,0,19.32-5.52,155.59,155.59,0,0,0,36.6-20.16,121,121,0,0,0,30.12-31.44q18.477-.241,34.68-0.96t25.08-4.32q9.837-4.083,14.04-10.44t4.2-11.4a10.559,10.559,0,0,0-.12-1.68,10.242,10.242,0,0,0-.36-1.44q-1.2-3.841-2.16-3.84-0.72,0-.72,2.16v1.44q0,6.959-3.96,10.2a92.727,92.727,0,0,1-11.88,7.8q-6.723,3.837-21.96,5.04t-33,1.2a290.972,290.972,0,0,0,12.84-27.48q6.356-15.48,12-32.4t10.2-33.36q4.555-16.435,7.68-30.36,2.16-9.837,2.16-14.64t-1.32-6.72a3.863,3.863,0,0,0-3.24-1.92q-2.88,0-6,2.88t-3.6,5.04q-2.16,7.443-6.24,18.48t-9.84,23.64q-5.76,12.6-12.96,24.96a184.347,184.347,0,0,1-15.48,22.68,84.992,84.992,0,0,1-17.16,16.56q-11.284,7.92-21.36,7.92a14.461,14.461,0,0,1-10.32-3.84q-4.085-3.836-4.08-12.24,0-1.917.24-4.32a48.082,48.082,0,0,1,.72-4.8,149.376,149.376,0,0,1,8.16-24.96q5.76-13.916,13.56-28.8t15.96-28.56a174.627,174.627,0,0,0,14.16-30.12,87.036,87.036,0,0,0,5.52-29.16,46.691,46.691,0,0,0-5.28-22.2q-5.283-9.956-18-15.48a41.469,41.469,0,0,0-11.52-3.72,77.4,77.4,0,0,0-13.2-1.08q-16.083,0-34.32,6.12a162.671,162.671,0,0,0-35.88,17.4,176.481,176.481,0,0,0-32.28,26.52A129.268,129.268,0,0,0,14.853,88.3a108.621,108.621,0,0,0-6.96,18.6,70.9,70.9,0,0,0-2.4,18.36q0,15.363,6.48,26.64a46.526,46.526,0,0,0,16.92,17.4,43.619,43.619,0,0,0,22.44,6.12,45.766,45.766,0,0,0,17.76-3.6,82.446,82.446,0,0,0,27.12-17.64,88.512,88.512,0,0,0,17.4-23.52q6.12-12.357,6.12-22.44,0-8.64-4.56-14.16t-14.4-5.52a51.739,51.739,0,0,0-11.76,1.68,6.733,6.733,0,0,0-3.12,1.32q-1.44,1.08-1.44,1.56,0,0.962,2.16.96h1.2a6.994,6.994,0,0,0,1.68-.24,29.9,29.9,0,0,1,6.24-.72q7.92,0,11.4,4.44t3.48,11.4a46.527,46.527,0,0,1-3.12,15.6,78.488,78.488,0,0,1-8.76,17.04,83.89,83.89,0,0,1-12.96,15.12,44.622,44.622,0,0,1-15.72,9.6,46.932,46.932,0,0,1-15.36,2.64,36.88,36.88,0,0,1-17.52-4.32,33.31,33.31,0,0,1-13.2-12.84q-5.04-8.516-5.04-21.48a73.287,73.287,0,0,1,2.04-16.32,119.309,119.309,0,0,1,6.36-19.2,125.152,125.152,0,0,1,19.68-31.44,165.561,165.561,0,0,1,28.92-27,156.037,156.037,0,0,1,33.24-18.84q17.037-6.958,32.4-6.96,14.4,0,24.96,6.72a16.293,16.293,0,0,1,6.6,8.28,34.892,34.892,0,0,1,2.04,12.36,85.436,85.436,0,0,1-3.12,21.12,162.259,162.259,0,0,1-8.88,24.96,215.654,215.654,0,0,1-13.44,25.44q-6.48,10.8-14.04,24.36a280.918,280.918,0,0,0-13.44,27.48,112.986,112.986,0,0,0-7.8,25.92q-0.243,1.683-.36,3.36c-0.083,1.122-.12,2.16-0.12,3.12q0,13.923,7.92,20.4a28.988,28.988,0,0,0,18.96,6.48q14.877,0,28.8-9.36a95.478,95.478,0,0,0,20.64-19.32,189.687,189.687,0,0,0,16.56-24.12,232.159,232.159,0,0,0,11.52-22.32q-6.48,24-14.88,47.04t-17.76,46.32a523.566,523.566,0,0,0-54.48,2.76,175.855,175.855,0,0,0-49.92,12.6q-15.362,6.239-22.2,13.92t-6.84,14.16q0,8.877,10.44,15.12t27.24,6.24A97.719,97.719,0,0,0,107.373,301.9Zm-34.08-8.16q-7.324-3.122-7.32-8.4,0-4.083,4.68-9.36t15.48-11.28a130.694,130.694,0,0,1,46.56-16.2,334.727,334.727,0,0,1,49.44-3.72,101.744,101.744,0,0,1-27,28.92,137.241,137.241,0,0,1-32.28,17.4,95.658,95.658,0,0,1-16.08,4.32,87.429,87.429,0,0,1-15.12,1.44Q80.611,296.863,73.293,293.743ZM429.57,163.9q-6.245,12.483-11.16,21a75.586,75.586,0,0,1-10.8,14.64,60.436,60.436,0,0,1-14.28,10.8,156.273,156.273,0,0,1-21.36,9.48q-5.76,10.317-13.08,21.48a148.749,148.749,0,0,1-16.56,20.88,83.473,83.473,0,0,1-20.4,15.84,50.308,50.308,0,0,1-24.6,6.12q-12.477,0-17.76-4.92a15.412,15.412,0,0,1-5.28-11.64,18.313,18.313,0,0,1,.96-6.24q0.962-2.643,2.88-6.72a35.934,35.934,0,0,1,9.36-12,55.137,55.137,0,0,1,12.96-8.16,142.837,142.837,0,0,1,28.44-9.36q15.957-3.6,30.6-7.92a124.05,124.05,0,0,0,8.4-18.12q3.836-10.2,6.96-19.92t5.04-15.96q-2.88,5.283-7.32,12.84a145.514,145.514,0,0,1-9.96,14.76,62.714,62.714,0,0,1-11.88,12,21.791,21.791,0,0,1-13.32,4.8,21.187,21.187,0,0,1-6.36-1.2,14.088,14.088,0,0,1-6.48-4.44q-2.763-3.24-2.76-9.72a26.341,26.341,0,0,1,3-12.12c1.191-2.336,2.327-4.617,3.434-6.869-0.6,1.142-1.224,2.308-1.872,3.509a169.966,169.966,0,0,1-8.88,14.64,65.146,65.146,0,0,1-9.96,11.76q-5.163,4.68-10.44,5.16a12.548,12.548,0,0,1-6-1.2,13.526,13.526,0,0,1-5.88-5.28q-2.52-3.836-2.52-10.8a55.888,55.888,0,0,1,2.16-13.92q-2.88,4.563-7.44,11.16a74.782,74.782,0,0,1-9.84,11.64,34.073,34.073,0,0,1-8.64,6.24,17.655,17.655,0,0,1-7.44,1.92q-6.243,0-10.08-5.64t-3.84-14.76q0-9.6,4.8-21.84t15.6-25.44a53.97,53.97,0,0,1,16.92-13.56,42.337,42.337,0,0,1,19.56-5.16,31.164,31.164,0,0,1,10.56,1.8,22.469,22.469,0,0,1,8.88,5.88,5.3,5.3,0,0,1,1.68,3.84,2.954,2.954,0,0,1-1.2,2.4,3.412,3.412,0,0,1-3.12.48q-2.643-8.4-11.28-8.4a21.446,21.446,0,0,0-9.36,2.64q-8.162,4.32-16.92,14.16a144,144,0,0,0-15.24,20.4,59.659,59.659,0,0,0-3,5.52q-2.041,4.084-3.96,9.12a47.329,47.329,0,0,0-2.64,9.84,14.3,14.3,0,0,0-.24,2.04v1.8q0,7.92,6,7.92,7.2,0,16.32-10.56a138.065,138.065,0,0,0,11.28-16.08q5.04-8.4,10.32-18a109.441,109.441,0,0,1,6.72-10.8,10.3,10.3,0,0,1,8.88-4.32,20.007,20.007,0,0,1,5.28.72,12.723,12.723,0,0,0,5.52.24,42.9,42.9,0,0,0-5.16,7.2q-3.24,5.283-6.84,12t-6.48,13.68a82,82,0,0,0-4.08,12q-0.242,1.44-.6,4.08a32.118,32.118,0,0,0-.36,3.84q0,6.723,3.84,6.72t8.28-4.56a71.612,71.612,0,0,0,8.76-11.28q4.32-6.716,7.92-13.56t5.76-11.16a4.008,4.008,0,0,1,1.5-2.013c0.487-.979.953-1.979,1.373-3.027q3.6-7.436,7.2-14.28t6.24-12.12q2.637-5.276,9.12-5.28h14.88q-1.683,1.44-4.2,3.24a17.671,17.671,0,0,0-4.68,5.4q-6.48,11.043-11.28,21.24t-10.32,21.72a57.607,57.607,0,0,0-3.84,10.08,31.653,31.653,0,0,0-1.2,7.92q0,7.92,5.28,7.92,5.76,0,13.92-9.36a162.607,162.607,0,0,0,13.56-18.84q6.84-10.917,13.2-22.56t11.16-21.48q2.637-5.276,9.36-5.28h13.2a31.662,31.662,0,0,0-10.68,12.48q-3.725,7.684-8.28,19.68-5.04,13.2-9.48,27.24t-9.96,28.2a108.823,108.823,0,0,0,17.88-8.16,49.041,49.041,0,0,0,16.92-15.84,164.176,164.176,0,0,0,9.48-15.72q3.96-7.56,5.64-10.92c0.637-1.6,1.518-2.4,2.64-2.4s1.68,0.72,1.68,2.16A5.964,5.964,0,0,1,429.57,163.9ZM329.13,231.7a165.51,165.51,0,0,0-24.36,8.28,42.165,42.165,0,0,0-18.12,13.68q-6.6,8.877-6.6,15.84a9.6,9.6,0,0,0,2.76,7.08q2.762,2.757,8.76,2.76,7.92,0,16.32-4.8a89.765,89.765,0,0,0,16.32-12.12,195.3,195.3,0,0,0,14.52-14.88q6.6-7.56,10.68-13.32a43.594,43.594,0,0,0,2.64-4.32q1.44-2.643,2.88-5.04Q343.167,227.98,329.13,231.7Zm139.916-60.36q5.159-7.677,12.36-18.24t15.36-22.44q8.157-11.88,16.08-23.76t14.52-21.84q6.6-9.956,10.8-16.56t4.68-8.28l-0.48-1.2-1.2-.72h-7.68a34.313,34.313,0,0,0-7.2.72,7.142,7.142,0,0,0-5.04,4.08l-61.44,116.88-0.24,1.44,2.4,0.48Q463.885,179.023,469.046,171.343Zm-11.04,36.24a11.089,11.089,0,0,0,3.72-8.16,7.76,7.76,0,0,0-2.4-5.88,8.7,8.7,0,0,0-6.24-2.28,12.445,12.445,0,0,0-7.44,2.64,9.635,9.635,0,0,0-4.08,6.96,10.481,10.481,0,0,0,1.56,7.2q2.037,3.117,6.6,3.12A11.656,11.656,0,0,0,458.006,207.583Z"/></svg>';
36
  }
37
 
38
  /**
@@ -52,7 +52,7 @@ class CnbDomainViewUpgradeFinished {
52
  CnbAdminNotices::get_instance()->renderNotice( $notice );
53
  // Big "Yay!"
54
  echo '<div style="width:200px; height:auto">';
55
- echo $this->getBigYaySvg();
56
  echo '</div>';
57
  echo '<h1><strong>' . esc_html( $domain->name ) . '</strong> has been successfully upgraded!</h1>';
58
  echo '<h3>All branding has been removed from your buttons and you\'ll enjoy:</h3>';
@@ -70,7 +70,7 @@ class CnbDomainViewUpgradeFinished {
70
  if ( ! empty( $domain->expires ) ) {
71
  echo 'Your subscription will';
72
  echo $domain->renew == 1 ? ' renew automatically ' : ' expire ';
73
- echo 'on ' . date( 'F d, Y', strtotime( esc_html( $domain->expires ) ) ) . '.';
74
  }
75
  echo 'You can change this on the <a href="' . esc_attr( $this->get_settings_url() ) . '">settings page</a>.</p>';
76
  echo '<p>You can access and download your invoice via <a href="' . esc_attr( $portal_url->url ) . '">the invoice dashboard</a>. ';
27
  }
28
 
29
  /**
30
+ * print SVG wrapped in a div with a big, nice and pretty "Yay!"
31
  *
32
+ * @return void
33
  */
34
+ public function echoBigYaySvg() {
35
+ echo '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 561 309"><path d="M107.373,301.9a109.773,109.773,0,0,0,19.32-5.52,155.59,155.59,0,0,0,36.6-20.16,121,121,0,0,0,30.12-31.44q18.477-.241,34.68-0.96t25.08-4.32q9.837-4.083,14.04-10.44t4.2-11.4a10.559,10.559,0,0,0-.12-1.68,10.242,10.242,0,0,0-.36-1.44q-1.2-3.841-2.16-3.84-0.72,0-.72,2.16v1.44q0,6.959-3.96,10.2a92.727,92.727,0,0,1-11.88,7.8q-6.723,3.837-21.96,5.04t-33,1.2a290.972,290.972,0,0,0,12.84-27.48q6.356-15.48,12-32.4t10.2-33.36q4.555-16.435,7.68-30.36,2.16-9.837,2.16-14.64t-1.32-6.72a3.863,3.863,0,0,0-3.24-1.92q-2.88,0-6,2.88t-3.6,5.04q-2.16,7.443-6.24,18.48t-9.84,23.64q-5.76,12.6-12.96,24.96a184.347,184.347,0,0,1-15.48,22.68,84.992,84.992,0,0,1-17.16,16.56q-11.284,7.92-21.36,7.92a14.461,14.461,0,0,1-10.32-3.84q-4.085-3.836-4.08-12.24,0-1.917.24-4.32a48.082,48.082,0,0,1,.72-4.8,149.376,149.376,0,0,1,8.16-24.96q5.76-13.916,13.56-28.8t15.96-28.56a174.627,174.627,0,0,0,14.16-30.12,87.036,87.036,0,0,0,5.52-29.16,46.691,46.691,0,0,0-5.28-22.2q-5.283-9.956-18-15.48a41.469,41.469,0,0,0-11.52-3.72,77.4,77.4,0,0,0-13.2-1.08q-16.083,0-34.32,6.12a162.671,162.671,0,0,0-35.88,17.4,176.481,176.481,0,0,0-32.28,26.52A129.268,129.268,0,0,0,14.853,88.3a108.621,108.621,0,0,0-6.96,18.6,70.9,70.9,0,0,0-2.4,18.36q0,15.363,6.48,26.64a46.526,46.526,0,0,0,16.92,17.4,43.619,43.619,0,0,0,22.44,6.12,45.766,45.766,0,0,0,17.76-3.6,82.446,82.446,0,0,0,27.12-17.64,88.512,88.512,0,0,0,17.4-23.52q6.12-12.357,6.12-22.44,0-8.64-4.56-14.16t-14.4-5.52a51.739,51.739,0,0,0-11.76,1.68,6.733,6.733,0,0,0-3.12,1.32q-1.44,1.08-1.44,1.56,0,0.962,2.16.96h1.2a6.994,6.994,0,0,0,1.68-.24,29.9,29.9,0,0,1,6.24-.72q7.92,0,11.4,4.44t3.48,11.4a46.527,46.527,0,0,1-3.12,15.6,78.488,78.488,0,0,1-8.76,17.04,83.89,83.89,0,0,1-12.96,15.12,44.622,44.622,0,0,1-15.72,9.6,46.932,46.932,0,0,1-15.36,2.64,36.88,36.88,0,0,1-17.52-4.32,33.31,33.31,0,0,1-13.2-12.84q-5.04-8.516-5.04-21.48a73.287,73.287,0,0,1,2.04-16.32,119.309,119.309,0,0,1,6.36-19.2,125.152,125.152,0,0,1,19.68-31.44,165.561,165.561,0,0,1,28.92-27,156.037,156.037,0,0,1,33.24-18.84q17.037-6.958,32.4-6.96,14.4,0,24.96,6.72a16.293,16.293,0,0,1,6.6,8.28,34.892,34.892,0,0,1,2.04,12.36,85.436,85.436,0,0,1-3.12,21.12,162.259,162.259,0,0,1-8.88,24.96,215.654,215.654,0,0,1-13.44,25.44q-6.48,10.8-14.04,24.36a280.918,280.918,0,0,0-13.44,27.48,112.986,112.986,0,0,0-7.8,25.92q-0.243,1.683-.36,3.36c-0.083,1.122-.12,2.16-0.12,3.12q0,13.923,7.92,20.4a28.988,28.988,0,0,0,18.96,6.48q14.877,0,28.8-9.36a95.478,95.478,0,0,0,20.64-19.32,189.687,189.687,0,0,0,16.56-24.12,232.159,232.159,0,0,0,11.52-22.32q-6.48,24-14.88,47.04t-17.76,46.32a523.566,523.566,0,0,0-54.48,2.76,175.855,175.855,0,0,0-49.92,12.6q-15.362,6.239-22.2,13.92t-6.84,14.16q0,8.877,10.44,15.12t27.24,6.24A97.719,97.719,0,0,0,107.373,301.9Zm-34.08-8.16q-7.324-3.122-7.32-8.4,0-4.083,4.68-9.36t15.48-11.28a130.694,130.694,0,0,1,46.56-16.2,334.727,334.727,0,0,1,49.44-3.72,101.744,101.744,0,0,1-27,28.92,137.241,137.241,0,0,1-32.28,17.4,95.658,95.658,0,0,1-16.08,4.32,87.429,87.429,0,0,1-15.12,1.44Q80.611,296.863,73.293,293.743ZM429.57,163.9q-6.245,12.483-11.16,21a75.586,75.586,0,0,1-10.8,14.64,60.436,60.436,0,0,1-14.28,10.8,156.273,156.273,0,0,1-21.36,9.48q-5.76,10.317-13.08,21.48a148.749,148.749,0,0,1-16.56,20.88,83.473,83.473,0,0,1-20.4,15.84,50.308,50.308,0,0,1-24.6,6.12q-12.477,0-17.76-4.92a15.412,15.412,0,0,1-5.28-11.64,18.313,18.313,0,0,1,.96-6.24q0.962-2.643,2.88-6.72a35.934,35.934,0,0,1,9.36-12,55.137,55.137,0,0,1,12.96-8.16,142.837,142.837,0,0,1,28.44-9.36q15.957-3.6,30.6-7.92a124.05,124.05,0,0,0,8.4-18.12q3.836-10.2,6.96-19.92t5.04-15.96q-2.88,5.283-7.32,12.84a145.514,145.514,0,0,1-9.96,14.76,62.714,62.714,0,0,1-11.88,12,21.791,21.791,0,0,1-13.32,4.8,21.187,21.187,0,0,1-6.36-1.2,14.088,14.088,0,0,1-6.48-4.44q-2.763-3.24-2.76-9.72a26.341,26.341,0,0,1,3-12.12c1.191-2.336,2.327-4.617,3.434-6.869-0.6,1.142-1.224,2.308-1.872,3.509a169.966,169.966,0,0,1-8.88,14.64,65.146,65.146,0,0,1-9.96,11.76q-5.163,4.68-10.44,5.16a12.548,12.548,0,0,1-6-1.2,13.526,13.526,0,0,1-5.88-5.28q-2.52-3.836-2.52-10.8a55.888,55.888,0,0,1,2.16-13.92q-2.88,4.563-7.44,11.16a74.782,74.782,0,0,1-9.84,11.64,34.073,34.073,0,0,1-8.64,6.24,17.655,17.655,0,0,1-7.44,1.92q-6.243,0-10.08-5.64t-3.84-14.76q0-9.6,4.8-21.84t15.6-25.44a53.97,53.97,0,0,1,16.92-13.56,42.337,42.337,0,0,1,19.56-5.16,31.164,31.164,0,0,1,10.56,1.8,22.469,22.469,0,0,1,8.88,5.88,5.3,5.3,0,0,1,1.68,3.84,2.954,2.954,0,0,1-1.2,2.4,3.412,3.412,0,0,1-3.12.48q-2.643-8.4-11.28-8.4a21.446,21.446,0,0,0-9.36,2.64q-8.162,4.32-16.92,14.16a144,144,0,0,0-15.24,20.4,59.659,59.659,0,0,0-3,5.52q-2.041,4.084-3.96,9.12a47.329,47.329,0,0,0-2.64,9.84,14.3,14.3,0,0,0-.24,2.04v1.8q0,7.92,6,7.92,7.2,0,16.32-10.56a138.065,138.065,0,0,0,11.28-16.08q5.04-8.4,10.32-18a109.441,109.441,0,0,1,6.72-10.8,10.3,10.3,0,0,1,8.88-4.32,20.007,20.007,0,0,1,5.28.72,12.723,12.723,0,0,0,5.52.24,42.9,42.9,0,0,0-5.16,7.2q-3.24,5.283-6.84,12t-6.48,13.68a82,82,0,0,0-4.08,12q-0.242,1.44-.6,4.08a32.118,32.118,0,0,0-.36,3.84q0,6.723,3.84,6.72t8.28-4.56a71.612,71.612,0,0,0,8.76-11.28q4.32-6.716,7.92-13.56t5.76-11.16a4.008,4.008,0,0,1,1.5-2.013c0.487-.979.953-1.979,1.373-3.027q3.6-7.436,7.2-14.28t6.24-12.12q2.637-5.276,9.12-5.28h14.88q-1.683,1.44-4.2,3.24a17.671,17.671,0,0,0-4.68,5.4q-6.48,11.043-11.28,21.24t-10.32,21.72a57.607,57.607,0,0,0-3.84,10.08,31.653,31.653,0,0,0-1.2,7.92q0,7.92,5.28,7.92,5.76,0,13.92-9.36a162.607,162.607,0,0,0,13.56-18.84q6.84-10.917,13.2-22.56t11.16-21.48q2.637-5.276,9.36-5.28h13.2a31.662,31.662,0,0,0-10.68,12.48q-3.725,7.684-8.28,19.68-5.04,13.2-9.48,27.24t-9.96,28.2a108.823,108.823,0,0,0,17.88-8.16,49.041,49.041,0,0,0,16.92-15.84,164.176,164.176,0,0,0,9.48-15.72q3.96-7.56,5.64-10.92c0.637-1.6,1.518-2.4,2.64-2.4s1.68,0.72,1.68,2.16A5.964,5.964,0,0,1,429.57,163.9ZM329.13,231.7a165.51,165.51,0,0,0-24.36,8.28,42.165,42.165,0,0,0-18.12,13.68q-6.6,8.877-6.6,15.84a9.6,9.6,0,0,0,2.76,7.08q2.762,2.757,8.76,2.76,7.92,0,16.32-4.8a89.765,89.765,0,0,0,16.32-12.12,195.3,195.3,0,0,0,14.52-14.88q6.6-7.56,10.68-13.32a43.594,43.594,0,0,0,2.64-4.32q1.44-2.643,2.88-5.04Q343.167,227.98,329.13,231.7Zm139.916-60.36q5.159-7.677,12.36-18.24t15.36-22.44q8.157-11.88,16.08-23.76t14.52-21.84q6.6-9.956,10.8-16.56t4.68-8.28l-0.48-1.2-1.2-.72h-7.68a34.313,34.313,0,0,0-7.2.72,7.142,7.142,0,0,0-5.04,4.08l-61.44,116.88-0.24,1.44,2.4,0.48Q463.885,179.023,469.046,171.343Zm-11.04,36.24a11.089,11.089,0,0,0,3.72-8.16,7.76,7.76,0,0,0-2.4-5.88,8.7,8.7,0,0,0-6.24-2.28,12.445,12.445,0,0,0-7.44,2.64,9.635,9.635,0,0,0-4.08,6.96,10.481,10.481,0,0,0,1.56,7.2q2.037,3.117,6.6,3.12A11.656,11.656,0,0,0,458.006,207.583Z"/></svg>';
36
  }
37
 
38
  /**
52
  CnbAdminNotices::get_instance()->renderNotice( $notice );
53
  // Big "Yay!"
54
  echo '<div style="width:200px; height:auto">';
55
+ $this->echoBigYaySvg();
56
  echo '</div>';
57
  echo '<h1><strong>' . esc_html( $domain->name ) . '</strong> has been successfully upgraded!</h1>';
58
  echo '<h3>All branding has been removed from your buttons and you\'ll enjoy:</h3>';
70
  if ( ! empty( $domain->expires ) ) {
71
  echo 'Your subscription will';
72
  echo $domain->renew == 1 ? ' renew automatically ' : ' expire ';
73
+ echo 'on ' . esc_html( date( 'F d, Y', strtotime( $domain->expires ) ) ) . '.';
74
  }
75
  echo 'You can change this on the <a href="' . esc_attr( $this->get_settings_url() ) . '">settings page</a>.</p>';
76
  echo '<p>You can access and download your invoice via <a href="' . esc_attr( $portal_url->url ) . '">the invoice dashboard</a>. ';
src/admin/domain/partials/CnbDomainViewUpgradeOverview.php CHANGED
@@ -7,16 +7,16 @@ defined( 'ABSPATH' ) || die( '-1' );
7
 
8
  use cnb\admin\api\CnbAppRemotePayment;
9
  use cnb\admin\models\CnbPlan;
10
- use cnb\admin\models\CnbUser;
11
  use cnb\admin\profile\CnbProfileEdit;
12
 
13
  class CnbDomainViewUpgradeOverview {
14
 
15
- private function getActiveCurrency($user) {
16
  $active_currency = null;
17
  if ( $user && ! is_wp_error( $user ) && isset( $user->stripeDetails ) && ! empty( $user->stripeDetails->currency ) ) {
18
  $active_currency = $user->stripeDetails->currency;
19
  }
 
20
  return $active_currency;
21
  }
22
 
@@ -29,6 +29,7 @@ class CnbDomainViewUpgradeOverview {
29
 
30
  return $user;
31
  }
 
32
  /**
33
  * Render upgrade form
34
  *
@@ -37,7 +38,7 @@ class CnbDomainViewUpgradeOverview {
37
  * @return void
38
  */
39
  function render( $domain ) {
40
- if ( $domain->type !== "FREE" ) { ?><p>Your domain is currently on the Premium
41
  <code><?php echo esc_html( $domain->type ) ?></code> plan.</p>
42
  <?php } ?>
43
 
@@ -45,17 +46,17 @@ class CnbDomainViewUpgradeOverview {
45
  <?php
46
  $this->renderUpgradeForm( $domain );
47
  echo '<h3 class="cnb-center">All plans contain the following features:</h3>';
48
- echo $this->getBenefits();
49
  }
50
 
51
- private function renderJsForUpgradeForm($user) {
52
- $active_currency = $this->getActiveCurrency($user);
53
- $profile_set = false;
54
  if ( $user && ! is_wp_error( $user ) && isset( $user->address ) && ! empty( $user->address->country ) ) {
55
  $profile_set = true;
56
  }
57
  echo '<script>';
58
- if (! $profile_set) {
59
  // Unless a profile hasn't been set yet, in which case, ensure we ask customers for that first
60
  echo "
61
  jQuery(() => {
@@ -69,7 +70,7 @@ class CnbDomainViewUpgradeOverview {
69
  })";
70
  }
71
 
72
- if ($active_currency) {
73
  // We already know the currency, so a "select currency" tab menu makes no sense
74
  echo "
75
  jQuery(() => {
@@ -81,6 +82,7 @@ class CnbDomainViewUpgradeOverview {
81
 
82
  private function renderStripeJs() {
83
  // Stripe integration
 
84
  echo '<script src="https://js.stripe.com/v3/"></script>';
85
  echo '<script>
86
  jQuery(() => {
@@ -97,6 +99,7 @@ class CnbDomainViewUpgradeOverview {
97
  });
98
  </script>';
99
  }
 
100
  /**
101
  * @param $domain CnbDomain
102
  *
@@ -105,9 +108,9 @@ class CnbDomainViewUpgradeOverview {
105
  public function renderUpgradeForm( $domain ) {
106
  $user = $this->render_hidden_profile();
107
  $this->renderStripeJs();
108
- $this->renderJsForUpgradeForm($user);
109
- $plans = CnbAppRemotePayment::cnb_remote_get_plans();
110
- $active_currency = $this->getActiveCurrency($user);
111
  ?>
112
  <form id="wp_domain_upgrade" method="post">
113
  <input type="hidden" name="cnb_domain_id" id="cnb_domain_id" value="<?php echo esc_attr( $domain->id ) ?>">
@@ -134,17 +137,22 @@ class CnbDomainViewUpgradeOverview {
134
  cnb-flexbox
135
  <?php if ( $active_currency !== 'usd' ) { ?>currency-box-active<?php } ?>">
136
  <?php
137
- $plan = $this->get_plan( $plans, 'powered-by-eur-yearly' );
138
- $plan_x = floor($plan->price / 12.0);
139
- $plan_y = round(($plan->price /12.0) - floor($plan->price / 12.0), 2) * 100;
 
 
 
140
  ?>
141
  <div class="pricebox">
142
- <h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly</h3>
143
  <div class="benefit">All button branding removed</div>
144
- <div class="plan-amount"><span class="currency">€</span><span class="euros"><?php echo esc_html($plan_x) ?></span><span
145
- class="cents">.<?php echo esc_html($plan_y) ?></span><span class="timeframe">/month</span></div>
 
 
146
  <div class="billingprice">
147
- Billed at €<?php echo esc_html($plan->price); ?> annually
148
  </div>
149
  <?php $this->get_profile_edit_modal_link(
150
  'button button-primary',
@@ -156,15 +164,17 @@ class CnbDomainViewUpgradeOverview {
156
  </div>
157
 
158
  <?php
159
- $plan = $this->get_plan( $plans, 'powered-by-eur-monthly' );
160
- $plan_x = floor($plan->price);
161
- $plan_y = round(($plan->price) - floor($plan->price), 2) * 100;
162
  ?>
163
  <div class="pricebox">
164
  <h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
165
  <div class="benefit">All button branding removed</div>
166
- <div class="plan-amount"><span class="currency">€</span><span class="euros"><?php echo esc_html($plan_x) ?></span><span
167
- class="cents">.<?php echo esc_html($plan_y) ?></span><span class="timeframe">/month</span></div>
 
 
168
  <div class="billingprice">
169
  Billed monthly
170
  </div>
@@ -182,17 +192,22 @@ class CnbDomainViewUpgradeOverview {
182
  cnb-flexbox
183
  <?php if ( $active_currency === 'usd' ) { ?>currency-box-active<?php } ?>">
184
  <?php
185
- $plan = $this->get_plan( $plans, 'powered-by-usd-yearly' );
186
- $plan_x = floor($plan->price / 12.0);
187
- $plan_y = round(($plan->price /12.0) - floor($plan->price / 12.0), 2) * 100;
 
 
 
188
  ?>
189
  <div class="pricebox">
190
- <h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly</h3>
191
  <div class="benefit">All button branding removed</div>
192
- <div class="plan-amount"><span class="currency">$</span><span class="euros"><?php echo esc_html($plan_x) ?></span><span
193
- class="cents">.<?php echo esc_html($plan_y) ?></span><span class="timeframe">/month</span></div>
 
 
194
  <div class="billingprice">
195
- Billed at $<?php echo esc_html($plan->price) ?> annually
196
  </div>
197
  <?php $this->get_profile_edit_modal_link(
198
  'button button-primary',
@@ -203,15 +218,17 @@ class CnbDomainViewUpgradeOverview {
203
  onclick="cnb_get_checkout('<?php echo esc_js( $plan->id ) ?>')">Upgrade</a>
204
  </div>
205
  <?php
206
- $plan = $this->get_plan( $plans, 'powered-by-usd-monthly' );
207
- $plan_x = floor($plan->price);
208
- $plan_y = round(($plan->price) - floor($plan->price), 2) * 100;
209
  ?>
210
  <div class="pricebox">
211
  <h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
212
  <div class="benefit">All button branding removed</div>
213
- <div class="plan-amount"><span class="currency">$</span><span class="euros"><?php echo esc_html($plan_x) ?></span><span
214
- class="cents">.<?php echo esc_html($plan_y) ?></span><span class="timeframe">/month</span></div>
 
 
215
  <div class="billingprice">
216
  Billed monthly
217
  </div>
@@ -229,16 +246,20 @@ class CnbDomainViewUpgradeOverview {
229
  <?php
230
  }
231
 
232
- public function getBenefits() {
233
- return '
234
  <div class="cnb-flexbox cnb-plan-features">
235
  <ul class="cnb-checklist">
236
  <li><strong>Phone</strong> <span class="only-big-screens">buttons</span></li>
237
  <li><strong>Email</strong> <span class="only-big-screens">buttons</span></li>
238
  <li><strong>SMS/text</strong> <span class="only-big-screens">buttons</span></li>
239
  <li><strong>WhatsApp</strong> <span class="only-big-screens">buttons</span></li>
 
 
 
240
  <li><strong>Location</strong> <span class="only-big-screens">buttons</span></li>
241
  <li><strong>Links</strong> <span class="only-big-screens">buttons</span></li>
 
242
  </ul>
243
  <ul class="cnb-checklist">
244
  <li><strong>Multiple buttons</strong><br>Add up to 8 buttons to a single page!</li>
@@ -252,6 +273,8 @@ class CnbDomainViewUpgradeOverview {
252
  <li><strong>Button animations</strong><br>Draw more attention to your buttons with subtle
253
  animations
254
  </li>
 
 
255
  <li><strong>Advanced page targeting options</strong><br>Ability to select full URLs, entire
256
  folders or even url parameters
257
  </li>
@@ -260,6 +283,7 @@ class CnbDomainViewUpgradeOverview {
260
  </ul>
261
  </div>';
262
  }
 
263
  /**
264
  * @param $plans CnbPlan[]
265
  * @param $name string
@@ -305,11 +329,11 @@ class CnbDomainViewUpgradeOverview {
305
  $url );
306
  printf(
307
  '<a href="%1$s" title="%2$s" class="thickbox open-profile-details-modal %4$s" onclick="cnb_btn=\'%5$s\'">%3$s</a>',
308
- $full_url,
309
- esc_html__( $modal_header ),
310
- esc_html__( $link_text ),
311
  esc_attr( $additional_classes ),
312
- esc_attr__( $data_title )
313
  );
314
  }
315
  }
7
 
8
  use cnb\admin\api\CnbAppRemotePayment;
9
  use cnb\admin\models\CnbPlan;
 
10
  use cnb\admin\profile\CnbProfileEdit;
11
 
12
  class CnbDomainViewUpgradeOverview {
13
 
14
+ private function getActiveCurrency( $user ) {
15
  $active_currency = null;
16
  if ( $user && ! is_wp_error( $user ) && isset( $user->stripeDetails ) && ! empty( $user->stripeDetails->currency ) ) {
17
  $active_currency = $user->stripeDetails->currency;
18
  }
19
+
20
  return $active_currency;
21
  }
22
 
29
 
30
  return $user;
31
  }
32
+
33
  /**
34
  * Render upgrade form
35
  *
38
  * @return void
39
  */
40
  function render( $domain ) {
41
+ if ( $domain->type !== 'FREE' ) { ?><p>Your domain is currently on the Premium
42
  <code><?php echo esc_html( $domain->type ) ?></code> plan.</p>
43
  <?php } ?>
44
 
46
  <?php
47
  $this->renderUpgradeForm( $domain );
48
  echo '<h3 class="cnb-center">All plans contain the following features:</h3>';
49
+ $this->renderBenefits();
50
  }
51
 
52
+ private function renderJsForUpgradeForm( $user ) {
53
+ $active_currency = $this->getActiveCurrency( $user );
54
+ $profile_set = false;
55
  if ( $user && ! is_wp_error( $user ) && isset( $user->address ) && ! empty( $user->address->country ) ) {
56
  $profile_set = true;
57
  }
58
  echo '<script>';
59
+ if ( ! $profile_set ) {
60
  // Unless a profile hasn't been set yet, in which case, ensure we ask customers for that first
61
  echo "
62
  jQuery(() => {
70
  })";
71
  }
72
 
73
+ if ( $active_currency ) {
74
  // We already know the currency, so a "select currency" tab menu makes no sense
75
  echo "
76
  jQuery(() => {
82
 
83
  private function renderStripeJs() {
84
  // Stripe integration
85
+ // phpcs:ignore WordPress.WP
86
  echo '<script src="https://js.stripe.com/v3/"></script>';
87
  echo '<script>
88
  jQuery(() => {
99
  });
100
  </script>';
101
  }
102
+
103
  /**
104
  * @param $domain CnbDomain
105
  *
108
  public function renderUpgradeForm( $domain ) {
109
  $user = $this->render_hidden_profile();
110
  $this->renderStripeJs();
111
+ $this->renderJsForUpgradeForm( $user );
112
+ $plans = CnbAppRemotePayment::cnb_remote_get_plans();
113
+ $active_currency = $this->getActiveCurrency( $user );
114
  ?>
115
  <form id="wp_domain_upgrade" method="post">
116
  <input type="hidden" name="cnb_domain_id" id="cnb_domain_id" value="<?php echo esc_attr( $domain->id ) ?>">
137
  cnb-flexbox
138
  <?php if ( $active_currency !== 'usd' ) { ?>currency-box-active<?php } ?>">
139
  <?php
140
+ $plan = $this->get_plan( $plans, 'powered-by-eur-yearly' );
141
+ $plan_x = floor( $plan->price / 12.0 );
142
+ $plan_y = round( ( $plan->price / 12.0 ) - floor( $plan->price / 12.0 ), 2 ) * 100;
143
+
144
+ $plan_month = $this->get_plan( $plans, 'powered-by-eur-monthly' );
145
+ $annual_discount = $plan->price/(12*$plan_month->price)*100;
146
  ?>
147
  <div class="pricebox">
148
+ <h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
149
  <div class="benefit">All button branding removed</div>
150
+ <div class="plan-amount"><span class="currency">€</span><span
151
+ class="euros"><?php echo esc_html( $plan_x ) ?></span><span
152
+ class="cents">.<?php echo esc_html( $plan_y ) ?></span><span class="timeframe">/month</span>
153
+ </div>
154
  <div class="billingprice">
155
+ Billed at €<?php echo esc_html( $plan->price ); ?> annually
156
  </div>
157
  <?php $this->get_profile_edit_modal_link(
158
  'button button-primary',
164
  </div>
165
 
166
  <?php
167
+ $plan = $this->get_plan( $plans, 'powered-by-eur-monthly' );
168
+ $plan_x = floor( $plan->price );
169
+ $plan_y = round( ( $plan->price ) - floor( $plan->price ), 2 ) * 100;
170
  ?>
171
  <div class="pricebox">
172
  <h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
173
  <div class="benefit">All button branding removed</div>
174
+ <div class="plan-amount"><span class="currency">€</span><span
175
+ class="euros"><?php echo esc_html( $plan_x ) ?></span><span
176
+ class="cents">.<?php echo esc_html( $plan_y ) ?></span><span class="timeframe">/month</span>
177
+ </div>
178
  <div class="billingprice">
179
  Billed monthly
180
  </div>
192
  cnb-flexbox
193
  <?php if ( $active_currency === 'usd' ) { ?>currency-box-active<?php } ?>">
194
  <?php
195
+ $plan = $this->get_plan( $plans, 'powered-by-usd-yearly' );
196
+ $plan_x = floor( $plan->price / 12.0 );
197
+ $plan_y = round( ( $plan->price / 12.0 ) - floor( $plan->price / 12.0 ), 2 ) * 100;
198
+
199
+ $plan_month = $this->get_plan( $plans, 'powered-by-usd-monthly' );
200
+ $annual_discount = $plan->price/(12*$plan_month->price)*100;
201
  ?>
202
  <div class="pricebox">
203
+ <h3 class="yearly"><span class="cnb-premium-label">PRO </span>Yearly <span class="cnb-green">Save <?php echo esc_html( $annual_discount ); ?>%!</span></h3>
204
  <div class="benefit">All button branding removed</div>
205
+ <div class="plan-amount"><span class="currency">$</span><span
206
+ class="euros"><?php echo esc_html( $plan_x ) ?></span><span
207
+ class="cents">.<?php echo esc_html( $plan_y ) ?></span><span class="timeframe">/month</span>
208
+ </div>
209
  <div class="billingprice">
210
+ Billed at $<?php echo esc_html( $plan->price ) ?> annually
211
  </div>
212
  <?php $this->get_profile_edit_modal_link(
213
  'button button-primary',
218
  onclick="cnb_get_checkout('<?php echo esc_js( $plan->id ) ?>')">Upgrade</a>
219
  </div>
220
  <?php
221
+ $plan = $this->get_plan( $plans, 'powered-by-usd-monthly' );
222
+ $plan_x = floor( $plan->price );
223
+ $plan_y = round( ( $plan->price ) - floor( $plan->price ), 2 ) * 100;
224
  ?>
225
  <div class="pricebox">
226
  <h3 class="monthly"><span class="cnb-premium-label">PRO </span>Monthly</h3>
227
  <div class="benefit">All button branding removed</div>
228
+ <div class="plan-amount"><span class="currency">$</span><span
229
+ class="euros"><?php echo esc_html( $plan_x ) ?></span><span
230
+ class="cents">.<?php echo esc_html( $plan_y ) ?></span><span class="timeframe">/month</span>
231
+ </div>
232
  <div class="billingprice">
233
  Billed monthly
234
  </div>
246
  <?php
247
  }
248
 
249
+ public function renderBenefits() {
250
+ echo '
251
  <div class="cnb-flexbox cnb-plan-features">
252
  <ul class="cnb-checklist">
253
  <li><strong>Phone</strong> <span class="only-big-screens">buttons</span></li>
254
  <li><strong>Email</strong> <span class="only-big-screens">buttons</span></li>
255
  <li><strong>SMS/text</strong> <span class="only-big-screens">buttons</span></li>
256
  <li><strong>WhatsApp</strong> <span class="only-big-screens">buttons</span></li>
257
+ <li><strong>Messenger</strong> <span class="only-big-screens">buttons</span></li>
258
+ <li><strong>Signal</strong> <span class="only-big-screens">buttons</span></li>
259
+ <li><strong>Telegram</strong> <span class="only-big-screens">buttons</span></li>
260
  <li><strong>Location</strong> <span class="only-big-screens">buttons</span></li>
261
  <li><strong>Links</strong> <span class="only-big-screens">buttons</span></li>
262
+ <li><strong>Smooth scroll</strong> <span class="only-big-screens">buttons</span></li>
263
  </ul>
264
  <ul class="cnb-checklist">
265
  <li><strong>Multiple buttons</strong><br>Add up to 8 buttons to a single page!</li>
273
  <li><strong>Button animations</strong><br>Draw more attention to your buttons with subtle
274
  animations
275
  </li>
276
+ <li><strong>Buttons slide-in</strong><br>Buttons don\'t just appear but smoothly slide into the page.
277
+ </li>
278
  <li><strong>Advanced page targeting options</strong><br>Ability to select full URLs, entire
279
  folders or even url parameters
280
  </li>
283
  </ul>
284
  </div>';
285
  }
286
+
287
  /**
288
  * @param $plans CnbPlan[]
289
  * @param $name string
329
  $url );
330
  printf(
331
  '<a href="%1$s" title="%2$s" class="thickbox open-profile-details-modal %4$s" onclick="cnb_btn=\'%5$s\'">%3$s</a>',
332
+ esc_url( $full_url ),
333
+ esc_html( $modal_header ),
334
+ esc_html( $link_text ),
335
  esc_attr( $additional_classes ),
336
+ esc_attr( $data_title )
337
  );
338
  }
339
  }
src/admin/legacy/CnbLegacyController.php CHANGED
@@ -16,4 +16,4 @@ class CnbLegacyController {
16
 
17
  return ! $is_dismissed;
18
  }
19
- }
16
 
17
  return ! $is_dismissed;
18
  }
19
+ }
src/admin/legacy/CnbLegacyEdit.php CHANGED
@@ -2,16 +2,16 @@
2
 
3
  namespace cnb\admin\legacy;
4
 
5
- // don't load directly
6
  use cnb\utils\CnbAdminFunctions;
7
  use cnb\utils\CnbUtils;
8
 
 
9
  defined( 'ABSPATH' ) || die( '-1' );
10
 
11
  class CnbLegacyEdit {
12
  public static function render() {
13
- $cnb_options = get_option('cnb');
14
- $view = new CnbLegacyEdit();
15
  $adminFunctions = new CnbAdminFunctions();
16
 
17
  wp_enqueue_script( CNB_SLUG . '-legacy-edit' );
@@ -25,18 +25,18 @@ class CnbLegacyEdit {
25
  <div class="cnb-body-content">
26
 
27
  <h2 class="nav-tab-wrapper">
28
- <a href="<?php echo $view->create_tab_url( 'basic_options' ) ?>"
29
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>"
30
  data-tab-name="basic_options">Basics</a>
31
- <a href="<?php echo $view->create_tab_url( 'extra_options' ) ?>"
32
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'extra_options' ) ?>"
33
  data-tab-name="extra_options">Presentation</a>
34
  </h2>
35
 
36
  <form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ); ?>"
37
  class="cnb-container">
38
  <?php settings_fields( 'cnb_options' ); ?>
39
- <table class="form-table <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>"
40
  data-tab-name="basic_options">
41
  <tr>
42
  <th colspan="2"></th>
@@ -52,7 +52,7 @@ class CnbLegacyEdit {
52
  </tr>
53
  <tr>
54
  <th scope="row"><label for="cnb-number">Phone number</label> <a
55
- href="<?php echo CNB_SUPPORT ?>wordpress-free/basics/phone-number/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "phone-number" ); ?>"
56
  target="_blank" class="cnb-nounderscore">
57
  <span class="dashicons dashicons-editor-help"></span>
58
  </a></th>
@@ -62,7 +62,7 @@ class CnbLegacyEdit {
62
  <tr class="button-text">
63
  <th scope="row"><label for="buttonTextField">Button text</label> <small
64
  style="font-weight: 400">(optional)</small> <a
65
- href="<?php echo CNB_SUPPORT ?>wordpress-free/basics/using-text-buttons/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "using-text-buttons" ); ?>"
66
  target="_blank" class="cnb-nounderscore">
67
  <span class="dashicons dashicons-editor-help"></span>
68
  </a></th>
@@ -74,7 +74,7 @@ class CnbLegacyEdit {
74
  </tr>
75
  </table>
76
 
77
- <table class="form-table <?php echo $adminFunctions->is_active_tab( 'extra_options' ) ?>"
78
  data-tab-name="extra_options">
79
  <tr>
80
  <th colspan="2"></th>
@@ -94,7 +94,7 @@ class CnbLegacyEdit {
94
  </tr>
95
  <tr>
96
  <th scope="row">Position <a
97
- href="<?php echo CNB_SUPPORT ?>wordpress-free/presentation/button-position/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "button-position" ); ?>"
98
  target="_blank" class="cnb-nounderscore">
99
  <span class="dashicons dashicons-editor-help"></span>
100
  </a></th>
@@ -123,33 +123,33 @@ class CnbLegacyEdit {
123
 
124
  <!-- Extra placement options -->
125
  <br class="cnb-extra-placement">
126
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "mright" ? "cnb-extra-active" : ""; ?>">
127
  <input type="radio" id="appearance5" name="cnb[appearance]"
128
  value="mright" <?php checked( 'mright', $cnb_options['appearance'] ); ?>>
129
  <label title="mright" for="appearance5">Middle right</label>
130
  </div>
131
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "mleft" ? "cnb-extra-active" : ""; ?>">
132
  <input type="radio" id="appearance6" name="cnb[appearance]"
133
  value="mleft" <?php checked( 'mleft', $cnb_options['appearance'] ); ?>>
134
  <label title="mleft" for="appearance6">Middle left </label>
135
  </div>
136
  <br class="cnb-extra-placement">
137
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "tright" ? "cnb-extra-active" : ""; ?>">
138
  <input type="radio" id="appearance7" name="cnb[appearance]"
139
  value="tright" <?php checked( 'tright', $cnb_options['appearance'] ); ?>>
140
  <label title="tright" for="appearance7">Top right corner</label>
141
  </div>
142
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "tleft" ? "cnb-extra-active" : ""; ?>">
143
  <input type="radio" id="appearance8" name="cnb[appearance]"
144
  value="tleft" <?php checked( 'tleft', $cnb_options['appearance'] ); ?>>
145
  <label title="tleft" for="appearance8">Top left corner</label>
146
  </div>
147
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "tmiddle" ? "cnb-extra-active" : ""; ?>">
148
  <input type="radio" id="appearance9" name="cnb[appearance]"
149
  value="tmiddle" <?php checked( 'tmiddle', $cnb_options['appearance'] ); ?>>
150
  <label title="tmiddle" for="appearance9">Center top</label>
151
  </div>
152
- <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == "tfull" ? "cnb-extra-active" : ""; ?>">
153
  <input type="radio" id="appearance10" name="cnb[appearance]"
154
  value="tfull" <?php checked( 'tfull', $cnb_options['appearance'] ); ?>>
155
  <label title="tfull" for="appearance10">Full top</label>
@@ -169,7 +169,7 @@ class CnbLegacyEdit {
169
  </tr>
170
  <tr class="appearance">
171
  <th scope="row"><label for="cnb-show">Limit appearance</label> <a
172
- href="<?php echo CNB_SUPPORT ?>wordpress-free/presentation/limit-appearance/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "limit-appearance" ); ?>"
173
  target="_blank" class="cnb-nounderscore">
174
  <span class="dashicons dashicons-editor-help"></span>
175
  </a></th>
@@ -179,7 +179,7 @@ class CnbLegacyEdit {
179
  placeholder="E.g. 14, 345"/>
180
  <p class="description">Enter IDs of the posts &amp; pages, separated by commas
181
  (leave blank for all). <a
182
- href="<?php echo CNB_SUPPORT ?>wordpress-free/presentation/limit-appearance/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "limit-appearance" ); ?>"
183
  target="_blank">Learn more...</a></p>
184
  <div class="cnb-radio-item">
185
  <input id="limit1" type="radio" name="cnb[limit]"
@@ -201,7 +201,7 @@ class CnbLegacyEdit {
201
  </td>
202
  </tr>
203
  </table>
204
- <table class="form-table <?php echo $adminFunctions->is_active_tab( 'advanced_options' ) ?>">
205
  <tr>
206
  <th colspan="2"><h2>Advanced Settings</h2></th>
207
  </tr>
@@ -210,22 +210,7 @@ class CnbLegacyEdit {
210
  $view->render_conversions();
211
  $view->render_zoom();
212
  $view->render_zindex();
213
-
214
- if ( $cnb_options['classic'] == 1 ) { ?>
215
- <tr class="classic">
216
- <th scope="row">Classic button <a
217
- href="https://callnowbutton.com/new-button-design/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "new-button-design" ); ?>"
218
- target="_blank" class="cnb-nounderscore">
219
- <span class="dashicons dashicons-editor-help"></span>
220
- </a></th>
221
- <td>
222
- <input type="hidden" name="cnb[classic]" value="0"/>
223
- <input id="classic" name="cnb[classic]" type="checkbox"
224
- value="1" <?php checked( '1', $cnb_options['classic'] ); ?> /> <label
225
- title="Enable" for="classic">Active</label>
226
- </td>
227
- </tr>
228
- <?php } ?>
229
  </table>
230
  <?php submit_button(); ?>
231
 
@@ -233,46 +218,48 @@ class CnbLegacyEdit {
233
  </div>
234
  </div>
235
  <div class="cnb-postbox-container cnb-side-column">
236
- <div class="cnb-on-active-tab <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>">
237
  <?php
238
- (new CnbAdminFunctions())->cnb_promobox(
239
- 'blue',
240
  'Unlock extra power',
241
- '<p>&check; More buttons<br>
242
- &check; Text/SMS, Email, Links, Maps<br>
243
- &check; WhatsApp with Chat modal<br>
244
- &check; More buttons on a page<br>
245
- &check; Scheduling<br>
246
- &check; Multi action buttons<br>
247
- &check; Button animations<br>
248
- &check; Live previews</p>
 
249
  <p>Get all of this and much more in <strong>Premium</strong></p>',
250
  'unlock',
251
  '',
252
  'Get Premium Free',
253
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
254
  );
255
  ?>
256
  <?php
257
- (new CnbAdminFunctions())->cnb_promobox(
258
- 'blue',
259
- 'Add more actions!',
260
  '<p>&check; SMS/Text<br>
261
  &check; Email<br>
 
262
  &check; WhatsApp with Chat modal<br>
263
  &check; Directions<br>
264
- &check; Links</p>
265
- <p>And combine them in a multi action button.</p>',
266
- 'email',
267
  '<strong>It\'s all in Premium!</strong>',
268
  'Learn more',
269
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
270
  );
271
  ?>
272
  </div>
273
- <div class="cnb-on-active-tab <?php echo $adminFunctions->is_active_tab( 'extra_options' ) ?>">
274
  <?php
275
- (new CnbAdminFunctions())->cnb_promobox(
276
  'blue',
277
  'Powerful page targeting',
278
  '<p>Do you need more flexibility in selecting the pages where you want a button to appear?</p>
@@ -284,9 +271,9 @@ class CnbLegacyEdit {
284
  'visibility',
285
  '',
286
  'Learn more',
287
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
288
  );
289
- (new CnbAdminFunctions())->cnb_promobox(
290
  'blue',
291
  'Go Premium for FREE!',
292
  'Premium adds a ton of extra power to the Call Now Button.</p>
@@ -295,7 +282,7 @@ class CnbLegacyEdit {
295
  'money-alt',
296
  '',
297
  'Try Premium',
298
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
299
  );
300
  ?>
301
  </div>
@@ -307,25 +294,23 @@ class CnbLegacyEdit {
307
  }
308
 
309
  function create_tab_url( $tab ) {
310
- $url = admin_url( 'admin.php' );
311
- $tab_link =
312
- add_query_arg(
313
- array(
314
- 'page' => 'call-now-button',
315
- 'action' => 'edit',
316
- 'tab' => $tab
317
- ),
318
- $url );
319
 
320
- return esc_url( $tab_link );
 
 
 
 
 
 
321
  }
322
 
323
  function render_tracking() {
324
- $cnb_options = get_option('cnb');
325
  ?>
326
  <tr>
327
  <th scope="row">Click tracking <a
328
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/click-tracking/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "click-tracking" ); ?>"
329
  target="_blank" class="cnb-nounderscore">
330
  <span class="dashicons dashicons-editor-help"></span>
331
  </a></th>
@@ -351,7 +336,7 @@ class CnbLegacyEdit {
351
  <label for="tracking2">Classic Google Analytics (ga.js)</label>
352
  </div>
353
  <p class="description">Using Google Tag Manager? Set up click tracking in GTM. <a
354
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/google-tag-manager-event-tracking/<?php (new CnbUtils())->cnb_utm_params( "description_link", "google-tag-manager-event-tracking" ); ?>"
355
  target="_blank">Learn how to do this...</a></p>
356
  </td>
357
  </tr>
@@ -359,11 +344,11 @@ class CnbLegacyEdit {
359
  }
360
 
361
  function render_conversions() {
362
- $cnb_options = get_option('cnb');
363
  ?>
364
  <tr>
365
  <th scope="row">Google Ads <a
366
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/google-ads/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "google-ads" ); ?>"
367
  target="_blank" class="cnb-nounderscore">
368
  <span class="dashicons dashicons-editor-help"></span>
369
  </a></th>
@@ -385,7 +370,7 @@ class CnbLegacyEdit {
385
  </div>
386
  <p class="description">Select this option if you want to track clicks on the button as Google Ads
387
  conversions. This option requires the Event snippet to be present on the page. <a
388
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/google-ads/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "google-ads" ); ?>"
389
  target="_blank">Learn more...</a></p>
390
  </td>
391
  </tr>
@@ -393,7 +378,7 @@ class CnbLegacyEdit {
393
  }
394
 
395
  function render_zoom() {
396
- $cnb_options = get_option('cnb');
397
  ?>
398
  <tr class="zoom">
399
  <th scope="row"><label for="cnb_slider">Button size <span id="cnb_slider_value"></span></label></th>
@@ -408,11 +393,11 @@ class CnbLegacyEdit {
408
  }
409
 
410
  function render_zindex() {
411
- $cnb_options = get_option('cnb');
412
  ?>
413
  <tr class="z-index">
414
  <th scope="row"><label for="cnb_order_slider">Order (<span id="cnb_order_value"></span>)</label> <a
415
- href="<?php echo CNB_SUPPORT ?>wordpress-free/settings/set-order/" target="_blank"
416
  class="cnb-nounderscore">
417
  <span class="dashicons dashicons-editor-help"></span>
418
  </a></th>
@@ -433,7 +418,7 @@ class CnbLegacyEdit {
433
  }
434
 
435
  function header() {
436
- echo CNB_NAME . ' <span class="cnb-version">v' . CNB_VERSION . '</span>';
437
  }
438
 
439
  function render_welcome_banner() {
@@ -448,18 +433,15 @@ class CnbLegacyEdit {
448
  add_query_arg(
449
  array( 'page' => 'call-now-button-upgrade' ),
450
  $url );
451
- $upgrade_url = esc_url( $upgrade_link );
452
 
453
- $dismiss_data_url = '';
454
- $dismiss_url = add_query_arg( array(
455
  CNB_SLUG . '_dismiss' => $dismiss_value
456
  ), $url );
457
 
458
- $dismiss_data_url .= ' data-dismiss-url="' . esc_url( $dismiss_url ) . '"';
459
-
460
  ?>
461
  <div id="welcome-banner"
462
- class="welcome-banner is-dismissible notice-call-now-button" <?php echo $dismiss_data_url ?>>
 
463
  <div class="welcome-banner-content">
464
  <h2>Welcome to Call&nbsp;Now&nbsp;Button version&nbsp;1.1</h2>
465
  <div class="welcome-banner-column-container">
@@ -485,18 +467,18 @@ class CnbLegacyEdit {
485
  <p class="cnb-mobile-inline">+ Live preview</p>
486
  </div>
487
  <div class="welcome-banner-column">
488
- <a class="button button-primary button-hero" href="<?php echo $upgrade_url ?>">Get Premium
489
- Free</a>
490
 
491
- <p><a href="<?php echo $upgrade_url ?>">More info about Premium</a></p>
492
  <h3>Other resources</h3>
493
- <p><a href="<?php echo CNB_SUPPORT; ?>wordpress-free/">Help center</a></p>
494
- <p><a href="<?php echo CNB_SUPPORT; ?>wordpress-free/#faq">FAQ</a></p>
495
  </div>
496
  </div>
497
  </div>
498
  <button type="button" class="notice-dismiss"><span
499
- class="screen-reader-text"><?php _e( 'Dismiss this notice.' ) ?></span></button>
500
  </div>
501
  <?php }
502
 
2
 
3
  namespace cnb\admin\legacy;
4
 
 
5
  use cnb\utils\CnbAdminFunctions;
6
  use cnb\utils\CnbUtils;
7
 
8
+ // don't load directly
9
  defined( 'ABSPATH' ) || die( '-1' );
10
 
11
  class CnbLegacyEdit {
12
  public static function render() {
13
+ $cnb_options = get_option( 'cnb' );
14
+ $view = new CnbLegacyEdit();
15
  $adminFunctions = new CnbAdminFunctions();
16
 
17
  wp_enqueue_script( CNB_SLUG . '-legacy-edit' );
25
  <div class="cnb-body-content">
26
 
27
  <h2 class="nav-tab-wrapper">
28
+ <a href="<?php echo esc_url( $view->create_tab_url( 'basic_options' ) ) ?>"
29
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>"
30
  data-tab-name="basic_options">Basics</a>
31
+ <a href="<?php echo esc_url( $view->create_tab_url( 'extra_options' ) ) ?>"
32
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
33
  data-tab-name="extra_options">Presentation</a>
34
  </h2>
35
 
36
  <form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ); ?>"
37
  class="cnb-container">
38
  <?php settings_fields( 'cnb_options' ); ?>
39
+ <table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>"
40
  data-tab-name="basic_options">
41
  <tr>
42
  <th colspan="2"></th>
52
  </tr>
53
  <tr>
54
  <th scope="row"><label for="cnb-number">Phone number</label> <a
55
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/basics/phone-number/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'phone-number' ) ); ?>"
56
  target="_blank" class="cnb-nounderscore">
57
  <span class="dashicons dashicons-editor-help"></span>
58
  </a></th>
62
  <tr class="button-text">
63
  <th scope="row"><label for="buttonTextField">Button text</label> <small
64
  style="font-weight: 400">(optional)</small> <a
65
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/basics/using-text-buttons/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'using-text-buttons' ) ); ?>"
66
  target="_blank" class="cnb-nounderscore">
67
  <span class="dashicons dashicons-editor-help"></span>
68
  </a></th>
74
  </tr>
75
  </table>
76
 
77
+ <table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>"
78
  data-tab-name="extra_options">
79
  <tr>
80
  <th colspan="2"></th>
94
  </tr>
95
  <tr>
96
  <th scope="row">Position <a
97
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/presentation/button-position/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'button-position' ) ); ?>"
98
  target="_blank" class="cnb-nounderscore">
99
  <span class="dashicons dashicons-editor-help"></span>
100
  </a></th>
123
 
124
  <!-- Extra placement options -->
125
  <br class="cnb-extra-placement">
126
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'mright' ? 'cnb-extra-active' : ''; ?>">
127
  <input type="radio" id="appearance5" name="cnb[appearance]"
128
  value="mright" <?php checked( 'mright', $cnb_options['appearance'] ); ?>>
129
  <label title="mright" for="appearance5">Middle right</label>
130
  </div>
131
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'mleft' ? 'cnb-extra-active' : ''; ?>">
132
  <input type="radio" id="appearance6" name="cnb[appearance]"
133
  value="mleft" <?php checked( 'mleft', $cnb_options['appearance'] ); ?>>
134
  <label title="mleft" for="appearance6">Middle left </label>
135
  </div>
136
  <br class="cnb-extra-placement">
137
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'tright' ? 'cnb-extra-active' : ''; ?>">
138
  <input type="radio" id="appearance7" name="cnb[appearance]"
139
  value="tright" <?php checked( 'tright', $cnb_options['appearance'] ); ?>>
140
  <label title="tright" for="appearance7">Top right corner</label>
141
  </div>
142
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'tleft' ? 'cnb-extra-active' : ''; ?>">
143
  <input type="radio" id="appearance8" name="cnb[appearance]"
144
  value="tleft" <?php checked( 'tleft', $cnb_options['appearance'] ); ?>>
145
  <label title="tleft" for="appearance8">Top left corner</label>
146
  </div>
147
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'tmiddle' ? 'cnb-extra-active' : ''; ?>">
148
  <input type="radio" id="appearance9" name="cnb[appearance]"
149
  value="tmiddle" <?php checked( 'tmiddle', $cnb_options['appearance'] ); ?>>
150
  <label title="tmiddle" for="appearance9">Center top</label>
151
  </div>
152
+ <div class="cnb-radio-item cnb-extra-placement <?php echo $cnb_options['appearance'] == 'tfull' ? 'cnb-extra-active' : ''; ?>">
153
  <input type="radio" id="appearance10" name="cnb[appearance]"
154
  value="tfull" <?php checked( 'tfull', $cnb_options['appearance'] ); ?>>
155
  <label title="tfull" for="appearance10">Full top</label>
169
  </tr>
170
  <tr class="appearance">
171
  <th scope="row"><label for="cnb-show">Limit appearance</label> <a
172
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/presentation/limit-appearance/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'limit-appearance' ) ); ?>"
173
  target="_blank" class="cnb-nounderscore">
174
  <span class="dashicons dashicons-editor-help"></span>
175
  </a></th>
179
  placeholder="E.g. 14, 345"/>
180
  <p class="description">Enter IDs of the posts &amp; pages, separated by commas
181
  (leave blank for all). <a
182
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/presentation/limit-appearance/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'limit-appearance' ) ); ?>"
183
  target="_blank">Learn more...</a></p>
184
  <div class="cnb-radio-item">
185
  <input id="limit1" type="radio" name="cnb[limit]"
201
  </td>
202
  </tr>
203
  </table>
204
+ <table class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'advanced_options' ) ) ?>">
205
  <tr>
206
  <th colspan="2"><h2>Advanced Settings</h2></th>
207
  </tr>
210
  $view->render_conversions();
211
  $view->render_zoom();
212
  $view->render_zindex();
213
+ ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  </table>
215
  <?php submit_button(); ?>
216
 
218
  </div>
219
  </div>
220
  <div class="cnb-postbox-container cnb-side-column">
221
+ <div class="cnb-on-active-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>">
222
  <?php
223
+ ( new CnbAdminFunctions() )->cnb_promobox(
224
+ 'purple',
225
  'Unlock extra power',
226
+ '<p><span class="cnb-purple">&check;</span> More buttons<br>
227
+ <span class="cnb-purple">&check;</span> Text/SMS, Email, Links, Directions<br>
228
+ <span class="cnb-purple">&check;</span> Signal, Telegram, FB Messenger<br>
229
+ <span class="cnb-purple">&check;</span> WhatsApp with Chat modal<br>
230
+ <span class="cnb-purple">&check;</span> Scheduling<br>
231
+ <span class="cnb-purple">&check;</span> Multi action buttons<br>
232
+ <span class="cnb-purple">&check;</span> Change icons<br>
233
+ <span class="cnb-purple">&check;</span> Button animations<br>
234
+ <span class="cnb-purple">&check;</span> Live previews</p>
235
  <p>Get all of this and much more in <strong>Premium</strong></p>',
236
  'unlock',
237
  '',
238
  'Get Premium Free',
239
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
240
  );
241
  ?>
242
  <?php
243
+ ( new CnbAdminFunctions() )->cnb_promobox(
244
+ 'green',
245
+ 'A button for everything!',
246
  '<p>&check; SMS/Text<br>
247
  &check; Email<br>
248
+ &check; Messenger, Telegram, Signal<br>
249
  &check; WhatsApp with Chat modal<br>
250
  &check; Directions<br>
251
+ &check; Smooth scroll anchors<br>
252
+ &check; Links</p>',
253
+ 'format-chat',
254
  '<strong>It\'s all in Premium!</strong>',
255
  'Learn more',
256
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
257
  );
258
  ?>
259
  </div>
260
+ <div class="cnb-on-active-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'extra_options' ) ) ?>">
261
  <?php
262
+ ( new CnbAdminFunctions() )->cnb_promobox(
263
  'blue',
264
  'Powerful page targeting',
265
  '<p>Do you need more flexibility in selecting the pages where you want a button to appear?</p>
271
  'visibility',
272
  '',
273
  'Learn more',
274
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
275
  );
276
+ ( new CnbAdminFunctions() )->cnb_promobox(
277
  'blue',
278
  'Go Premium for FREE!',
279
  'Premium adds a ton of extra power to the Call Now Button.</p>
282
  'money-alt',
283
  '',
284
  'Try Premium',
285
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
286
  );
287
  ?>
288
  </div>
294
  }
295
 
296
  function create_tab_url( $tab ) {
297
+ $url = admin_url( 'admin.php' );
 
 
 
 
 
 
 
 
298
 
299
+ return add_query_arg(
300
+ array(
301
+ 'page' => 'call-now-button',
302
+ 'action' => 'edit',
303
+ 'tab' => $tab
304
+ ),
305
+ $url );
306
  }
307
 
308
  function render_tracking() {
309
+ $cnb_options = get_option( 'cnb' );
310
  ?>
311
  <tr>
312
  <th scope="row">Click tracking <a
313
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/click-tracking/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'click-tracking' ) ); ?>"
314
  target="_blank" class="cnb-nounderscore">
315
  <span class="dashicons dashicons-editor-help"></span>
316
  </a></th>
336
  <label for="tracking2">Classic Google Analytics (ga.js)</label>
337
  </div>
338
  <p class="description">Using Google Tag Manager? Set up click tracking in GTM. <a
339
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/google-tag-manager-event-tracking/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'description_link', 'google-tag-manager-event-tracking' ) ); ?>"
340
  target="_blank">Learn how to do this...</a></p>
341
  </td>
342
  </tr>
344
  }
345
 
346
  function render_conversions() {
347
+ $cnb_options = get_option( 'cnb' );
348
  ?>
349
  <tr>
350
  <th scope="row">Google Ads <a
351
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/google-ads/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'google-ads' ) ); ?>"
352
  target="_blank" class="cnb-nounderscore">
353
  <span class="dashicons dashicons-editor-help"></span>
354
  </a></th>
370
  </div>
371
  <p class="description">Select this option if you want to track clicks on the button as Google Ads
372
  conversions. This option requires the Event snippet to be present on the page. <a
373
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/google-ads/<?php echo esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'google-ads' ) ); ?>"
374
  target="_blank">Learn more...</a></p>
375
  </td>
376
  </tr>
378
  }
379
 
380
  function render_zoom() {
381
+ $cnb_options = get_option( 'cnb' );
382
  ?>
383
  <tr class="zoom">
384
  <th scope="row"><label for="cnb_slider">Button size <span id="cnb_slider_value"></span></label></th>
393
  }
394
 
395
  function render_zindex() {
396
+ $cnb_options = get_option( 'cnb' );
397
  ?>
398
  <tr class="z-index">
399
  <th scope="row"><label for="cnb_order_slider">Order (<span id="cnb_order_value"></span>)</label> <a
400
+ href="<?php echo esc_attr( CNB_SUPPORT ) ?>wordpress-free/settings/set-order/" target="_blank"
401
  class="cnb-nounderscore">
402
  <span class="dashicons dashicons-editor-help"></span>
403
  </a></th>
418
  }
419
 
420
  function header() {
421
+ echo esc_html( CNB_NAME ) . ' <span class="cnb-version">v' . esc_html( CNB_VERSION ) . '</span>';
422
  }
423
 
424
  function render_welcome_banner() {
433
  add_query_arg(
434
  array( 'page' => 'call-now-button-upgrade' ),
435
  $url );
 
436
 
437
+ $dismiss_url = add_query_arg( array(
 
438
  CNB_SLUG . '_dismiss' => $dismiss_value
439
  ), $url );
440
 
 
 
441
  ?>
442
  <div id="welcome-banner"
443
+ class="welcome-banner is-dismissible notice-call-now-button"
444
+ data-dismiss-url="<?php echo esc_url( $dismiss_url ) ?>">
445
  <div class="welcome-banner-content">
446
  <h2>Welcome to Call&nbsp;Now&nbsp;Button version&nbsp;1.1</h2>
447
  <div class="welcome-banner-column-container">
467
  <p class="cnb-mobile-inline">+ Live preview</p>
468
  </div>
469
  <div class="welcome-banner-column">
470
+ <a class="button button-primary button-hero" href="<?php echo esc_url( $upgrade_link ) ?>">Get
471
+ Premium Free</a>
472
 
473
+ <p><a href="<?php echo esc_url( $upgrade_link ) ?>">More info about Premium</a></p>
474
  <h3>Other resources</h3>
475
+ <p><a href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress-free/">Help center</a></p>
476
+ <p><a href="<?php echo esc_attr( CNB_SUPPORT ); ?>wordpress-free/#faq">FAQ</a></p>
477
  </div>
478
  </div>
479
  </div>
480
  <button type="button" class="notice-dismiss"><span
481
+ class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.' ) ?></span></button>
482
  </div>
483
  <?php }
484
 
src/admin/legacy/CnbLegacyUpgrade.php CHANGED
@@ -18,11 +18,11 @@ class CnbLegacyUpgrade {
18
  ?>
19
  <div class="cnb-body-column hide-on-mobile">
20
  <?php
21
- (new CnbAdminFunctions())->cnb_promobox(
22
  'grey',
23
  'Standard plugin',
24
  '<p>&check; One button<br>
25
- &check; Phone<br>
26
  &check; Circular (single action)<br>
27
  &check; Buttonbar (single action)<br>
28
  &check; Action label<br>
@@ -60,16 +60,17 @@ class CnbLegacyUpgrade {
60
  function premium_plugin_promobox() { ?>
61
  <div class="cnb-body-column">
62
  <?php
63
- (new CnbAdminFunctions())->cnb_promobox(
64
- 'blue',
65
  'Premium',
66
  '
67
  <p><strong>&check; Lots of buttons!</strong><br>
68
- &check; Phone, SMS/Text, Email, WhatsApp, Maps, URLs<br>
 
69
  &check; Circular button (single & multi action)<br>
70
  &check; Buttonbar (multi action)<br>
71
- &check; Actions labels<br>
72
- &check; WhatsApp chat modal<a href="' . CNB_SUPPORT . 'wordpress/buttons/whatsapp-modal/' . (new CnbUtils())->cnb_utm_params( "question-mark", "whatsapp-modal", false ) . '" target="_blank" class="cnb-nounderscore"><span class="dashicons dashicons-editor-help"></span></a><br>
73
  </p>
74
  <hr>
75
  <p>
@@ -140,4 +141,4 @@ class CnbLegacyUpgrade {
140
  <?php
141
  do_action( 'cnb_footer' );
142
  }
143
- }
18
  ?>
19
  <div class="cnb-body-column hide-on-mobile">
20
  <?php
21
+ ( new CnbAdminFunctions() )->cnb_promobox(
22
  'grey',
23
  'Standard plugin',
24
  '<p>&check; One button<br>
25
+ &check; Phone<br><br>
26
  &check; Circular (single action)<br>
27
  &check; Buttonbar (single action)<br>
28
  &check; Action label<br>
60
  function premium_plugin_promobox() { ?>
61
  <div class="cnb-body-column">
62
  <?php
63
+ ( new CnbAdminFunctions() )->cnb_promobox(
64
+ 'purple',
65
  'Premium',
66
  '
67
  <p><strong>&check; Lots of buttons!</strong><br>
68
+ &check; Phone, SMS/Text, Email, Maps, URLs, Anchors (with smooth scroll)<br>
69
+ &check; WhatsApp, Facebook Messenger, Telegram, Signal<br>
70
  &check; Circular button (single & multi action)<br>
71
  &check; Buttonbar (multi action)<br>
72
+ &check; Action labels<br>
73
+ &check; WhatsApp chat modal<a href="' . CNB_SUPPORT . 'wordpress/buttons/whatsapp-modal/' . esc_attr( ( new CnbUtils() )->cnb_utm_params( 'question-mark', 'whatsapp-modal', false ) ) . '" target="_blank" class="cnb-nounderscore"><span class="dashicons dashicons-editor-help"></span></a><br>
74
  </p>
75
  <hr>
76
  <p>
141
  <?php
142
  do_action( 'cnb_footer' );
143
  }
144
+ }
src/admin/models/CnbActivation.php CHANGED
@@ -48,8 +48,8 @@ class CnbActivation {
48
  */
49
  public function __construct( $activation_attempt = false, $success = false, CnbDomain $domain = null, CnbButton $button = null ) {
50
  $this->activation_attempt = $activation_attempt;
51
- $this->success = $success;
52
- $this->domain = $domain;
53
- $this->button = $button;
54
  }
55
  }
48
  */
49
  public function __construct( $activation_attempt = false, $success = false, CnbDomain $domain = null, CnbButton $button = null ) {
50
  $this->activation_attempt = $activation_attempt;
51
+ $this->success = $success;
52
+ $this->domain = $domain;
53
+ $this->button = $button;
54
  }
55
  }
src/admin/models/CnbPlan.php CHANGED
@@ -51,13 +51,13 @@ class CnbPlan {
51
  return $object;
52
  }
53
 
54
- $plan = new CnbPlan();
55
- $plan->id = CnbUtils::getPropertyOrNull( $object, 'id' );
56
- $plan->nickname = CnbUtils::getPropertyOrNull( $object, 'nickname' );
57
  $plan->domainType = CnbUtils::getPropertyOrNull( $object, 'domainType' );
58
- $plan->currency = CnbUtils::getPropertyOrNull( $object, 'currency' );
59
- $plan->interval = CnbUtils::getPropertyOrNull( $object, 'interval' );
60
- $plan->price = floatval(CnbUtils::getPropertyOrNull( $object, 'price' ));
61
 
62
  return $plan;
63
  }
51
  return $object;
52
  }
53
 
54
+ $plan = new CnbPlan();
55
+ $plan->id = CnbUtils::getPropertyOrNull( $object, 'id' );
56
+ $plan->nickname = CnbUtils::getPropertyOrNull( $object, 'nickname' );
57
  $plan->domainType = CnbUtils::getPropertyOrNull( $object, 'domainType' );
58
+ $plan->currency = CnbUtils::getPropertyOrNull( $object, 'currency' );
59
+ $plan->interval = CnbUtils::getPropertyOrNull( $object, 'interval' );
60
+ $plan->price = floatval( CnbUtils::getPropertyOrNull( $object, 'price' ) );
61
 
62
  return $plan;
63
  }
src/admin/models/CnbUser.php CHANGED
@@ -71,20 +71,21 @@ class CnbUser implements JsonSerializable {
71
  return $object;
72
  }
73
 
74
- $user = new CnbUser();
75
- $user->active = CnbUtils::getPropertyOrNull( $object, 'active' );
76
- $user->id = CnbUtils::getPropertyOrNull( $object, 'id' );
77
- $user->name = CnbUtils::getPropertyOrNull( $object, 'name' );
78
- $user->email = CnbUtils::getPropertyOrNull( $object, 'email' );
79
- $user->companyName = CnbUtils::getPropertyOrNull( $object, 'companyName' );
80
- $address = CnbUserAddress::fromObject( CnbUtils::getPropertyOrNull( $object, 'address' ) );
81
- $user->address = $address;
82
- $taxIds = CnbUserTaxId::fromObject( CnbUtils::getPropertyOrNull( $object, 'taxIds' ) );
83
- $user->taxIds = $taxIds;
84
  // This is only set via the form, but is used for some checks (but not submitted to the API)
85
  $user->euvatbusiness = CnbUtils::getPropertyOrNull( $object, 'euvatbusiness' );
86
- $stripeDetails = CnbUserStripeDetails::fromObject( CnbUtils::getPropertyOrNull( $object, 'stripeDetails' ));
87
  $user->stripeDetails = $stripeDetails;
 
88
  return $user;
89
  }
90
 
@@ -239,21 +240,21 @@ class CnbUserStripeDetails implements JsonSerializable {
239
  return $object;
240
  }
241
  $stripeDetails = new CnbUserStripeDetails();
242
- $stripeDetails->customerId = CnbUtils::getPropertyOrNull( $object, 'customerId' );
243
- $stripeDetails->currency = CnbUtils::getPropertyOrNull( $object, 'currency' );
244
 
245
  return $stripeDetails;
246
  }
247
 
248
  public function toArray() {
249
  return array(
250
- 'customerId' => $this->customerId,
251
- 'subscriptions' => $this->subscriptions,
252
- 'currency' => $this->currency,
253
  );
254
  }
255
 
256
  public function jsonSerialize() {
257
  return $this->toArray();
258
  }
259
- }
71
  return $object;
72
  }
73
 
74
+ $user = new CnbUser();
75
+ $user->active = CnbUtils::getPropertyOrNull( $object, 'active' );
76
+ $user->id = CnbUtils::getPropertyOrNull( $object, 'id' );
77
+ $user->name = CnbUtils::getPropertyOrNull( $object, 'name' );
78
+ $user->email = CnbUtils::getPropertyOrNull( $object, 'email' );
79
+ $user->companyName = CnbUtils::getPropertyOrNull( $object, 'companyName' );
80
+ $address = CnbUserAddress::fromObject( CnbUtils::getPropertyOrNull( $object, 'address' ) );
81
+ $user->address = $address;
82
+ $taxIds = CnbUserTaxId::fromObject( CnbUtils::getPropertyOrNull( $object, 'taxIds' ) );
83
+ $user->taxIds = $taxIds;
84
  // This is only set via the form, but is used for some checks (but not submitted to the API)
85
  $user->euvatbusiness = CnbUtils::getPropertyOrNull( $object, 'euvatbusiness' );
86
+ $stripeDetails = CnbUserStripeDetails::fromObject( CnbUtils::getPropertyOrNull( $object, 'stripeDetails' ) );
87
  $user->stripeDetails = $stripeDetails;
88
+
89
  return $user;
90
  }
91
 
240
  return $object;
241
  }
242
  $stripeDetails = new CnbUserStripeDetails();
243
+ $stripeDetails->customerId = CnbUtils::getPropertyOrNull( $object, 'customerId' );
244
+ $stripeDetails->currency = CnbUtils::getPropertyOrNull( $object, 'currency' );
245
 
246
  return $stripeDetails;
247
  }
248
 
249
  public function toArray() {
250
  return array(
251
+ 'customerId' => $this->customerId,
252
+ 'subscriptions' => $this->subscriptions,
253
+ 'currency' => $this->currency,
254
  );
255
  }
256
 
257
  public function jsonSerialize() {
258
  return $this->toArray();
259
  }
260
+ }
src/admin/partials/CnbFooter.php CHANGED
@@ -16,30 +16,33 @@ class CnbFooter {
16
  }
17
 
18
  private static function cnb_show_feedback_collection() {
19
- $cnb_options = get_option('cnb');
 
20
 
21
  $url = admin_url( 'admin.php' );
22
  $upgrade_link =
23
  add_query_arg(
24
  array( 'page' => 'call-now-button-upgrade' ),
25
  $url );
26
- $upgrade_url = esc_url( $upgrade_link );
27
- $utils = new CnbUtils(); ?>
28
  <div class="feedback-collection">
29
  <div class="cnb-clear"></div>
30
  <p class="cnb-url cnb-center"><a
31
- href="<?php echo CNB_WEBSITE; ?><?php $utils->cnb_utm_params( "footer-links", "branding" ); ?>"
32
- target="_blank">Call Now Button<?php if ( $utils->isCloudActive($cnb_options) ) {
33
  echo '<span class="cnb_footer_beta">PREMIUM</span>';
34
  } ?></a></p>
35
- <p class="cnb-center">Version <?php echo CNB_VERSION; ?>
36
  <p class="cnb-center cnb-spacing">
37
- <a href="<?php echo CNB_SUPPORT;
38
- $utils->cnb_utm_params( "footer-links", "support" ); ?>" target="_blank" title="Support">Support</a> &middot;
39
- <a href="<?php echo CNB_SUPPORT; ?>feature-request/<?php $utils->cnb_utm_params( "footer-links", "suggestions" ); ?>"
 
40
  target="_blank" title="Feature Requests">Suggestions</a>
41
- <?php if ( ! $utils->isCloudActive($cnb_options) ) { ?>
42
- &middot; <strong><a href="<?php echo $upgrade_url ?>" title="Unlock features">Upgrade</a></strong>
 
43
  <?php } ?>
44
  </p>
45
  </div>
@@ -47,7 +50,7 @@ class CnbFooter {
47
  }
48
 
49
  private static function cnb_show_api_traces() {
50
- $cnb_options = get_option('cnb');
51
  if ( isset( $cnb_options['footer_show_traces'] ) && $cnb_options['footer_show_traces'] == 1 &&
52
  isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ) {
53
  $cnb_remoted_traces = RemoteTracer::getInstance();
@@ -59,12 +62,12 @@ class CnbFooter {
59
  foreach ( $traces as $trace ) {
60
  $totaltime += (float) $trace->getTime();
61
  }
62
- echo ' in <strong>' . $totaltime . '</strong>sec:<br />';
63
 
64
  echo '<ul>';
65
  foreach ( $traces as $trace ) {
66
  echo '<li>';
67
- echo '<code>' . $trace->getEndpoint() . '</code> in <strong>' . $trace->getTime() . '</strong>sec';
68
  if ( $trace->isCacheHit() ) {
69
  echo ' (from cache)';
70
  }
@@ -76,4 +79,4 @@ class CnbFooter {
76
  }
77
  }
78
  }
79
- }
16
  }
17
 
18
  private static function cnb_show_feedback_collection() {
19
+ $cnb_options = get_option( 'cnb' );
20
+ $cnb_utils = new CnbUtils();
21
 
22
  $url = admin_url( 'admin.php' );
23
  $upgrade_link =
24
  add_query_arg(
25
  array( 'page' => 'call-now-button-upgrade' ),
26
  $url );
27
+
28
+ ?>
29
  <div class="feedback-collection">
30
  <div class="cnb-clear"></div>
31
  <p class="cnb-url cnb-center"><a
32
+ href="<?php echo esc_attr( CNB_WEBSITE ) ?><?php echo esc_attr( $cnb_utils->cnb_utm_params( 'footer-links', 'branding' ) ); ?>"
33
+ target="_blank">Call Now Button<?php if ( $cnb_utils->isCloudActive( $cnb_options ) ) {
34
  echo '<span class="cnb_footer_beta">PREMIUM</span>';
35
  } ?></a></p>
36
+ <p class="cnb-center">Version <?php echo esc_attr( CNB_VERSION ) ?>
37
  <p class="cnb-center cnb-spacing">
38
+ <a href="<?php echo esc_attr( CNB_SUPPORT );
39
+ esc_attr( $cnb_utils->cnb_utm_params( 'footer-links', 'support' ) ); ?>" target="_blank"
40
+ title="Support">Support</a> &middot;
41
+ <a href="<?php echo esc_attr( CNB_SUPPORT ); ?>feature-request/<?php echo esc_attr( $cnb_utils->cnb_utm_params( 'footer-links', 'suggestions' ) ); ?>"
42
  target="_blank" title="Feature Requests">Suggestions</a>
43
+ <?php if ( ! $cnb_utils->isCloudActive( $cnb_options ) ) { ?>
44
+ &middot; <strong><a href="<?php echo esc_url( $upgrade_link ) ?>"
45
+ title="Unlock features">Upgrade</a></strong>
46
  <?php } ?>
47
  </p>
48
  </div>
50
  }
51
 
52
  private static function cnb_show_api_traces() {
53
+ $cnb_options = get_option( 'cnb' );
54
  if ( isset( $cnb_options['footer_show_traces'] ) && $cnb_options['footer_show_traces'] == 1 &&
55
  isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ) {
56
  $cnb_remoted_traces = RemoteTracer::getInstance();
62
  foreach ( $traces as $trace ) {
63
  $totaltime += (float) $trace->getTime();
64
  }
65
+ echo ' in <strong>' . esc_html( $totaltime ) . '</strong>sec:<br />';
66
 
67
  echo '<ul>';
68
  foreach ( $traces as $trace ) {
69
  echo '<li>';
70
+ echo '<code>' . esc_html( $trace->getEndpoint() ) . '</code> in <strong>' . esc_html( $trace->getTime() ) . '</strong>sec';
71
  if ( $trace->isCacheHit() ) {
72
  echo ' (from cache)';
73
  }
79
  }
80
  }
81
  }
82
+ }
src/admin/partials/CnbHeader.php CHANGED
@@ -26,12 +26,12 @@ class CnbHeader {
26
  echo '<div class="wrap call-now-button-plugin">'; // This is closed in CnbFooter::render
27
 
28
  echo '<!--## NOTIFICATION BARS ## -->';
29
- $noticeHandler = new CnbHeaderNotices();
30
 
31
  $noticeHandler->get_cloud_notices();
32
  $cnb_cloud_notifications = $noticeHandler->get_notices();
33
  $noticeHandler->add_button_is_disabled_notice( $cnb_cloud_notifications );
34
- $noticeHandler->cnb_button_classic_enabled_but_no_number_notice( $cnb_cloud_notifications );
35
  $noticeHandler->warn_about_caching_plugins( $cnb_cloud_notifications );
36
  $noticeHandler->upgrade_notice( $cnb_cloud_notifications );
37
  $noticeHandler->cnb_show_advanced( $cnb_cloud_notifications );
26
  echo '<div class="wrap call-now-button-plugin">'; // This is closed in CnbFooter::render
27
 
28
  echo '<!--## NOTIFICATION BARS ## -->';
29
+ $noticeHandler = new CnbHeaderNotices();
30
 
31
  $noticeHandler->get_cloud_notices();
32
  $cnb_cloud_notifications = $noticeHandler->get_notices();
33
  $noticeHandler->add_button_is_disabled_notice( $cnb_cloud_notifications );
34
+ $noticeHandler->cnb_button_legacy_enabled_but_no_number_notice( $cnb_cloud_notifications );
35
  $noticeHandler->warn_about_caching_plugins( $cnb_cloud_notifications );
36
  $noticeHandler->upgrade_notice( $cnb_cloud_notifications );
37
  $noticeHandler->cnb_show_advanced( $cnb_cloud_notifications );
src/admin/partials/CnbHeaderNotices.php CHANGED
@@ -11,7 +11,6 @@ use cnb\admin\domain\CnbDomain;
11
  use cnb\admin\settings\CnbSettingsController;
12
  use cnb\notices\CnbAdminNotices;
13
  use cnb\notices\CnbNotice;
14
- use cnb\utils\CnbAdminFunctions;
15
  use cnb\utils\CnbUtils;
16
  use WP_Error;
17
 
@@ -47,13 +46,13 @@ class CnbHeaderNotices {
47
  *
48
  */
49
  public function get_cloud_notices() {
50
- $cnb_options = get_option('cnb');
51
 
52
- if ( (new CnbUtils())->isCloudActive($cnb_options)) {
53
 
54
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
55
 
56
- if ( is_wp_error($cnb_user) ) {
57
  if ( $cnb_user->get_error_code() === 'CNB_API_NOT_SETUP_YET' ) {
58
  // Notice: You're almost there! (enter API key)
59
  $this->cnb_settings_get_account_missing_notice();
@@ -66,7 +65,7 @@ class CnbHeaderNotices {
66
  }
67
  }
68
 
69
- $cnb_cloud_domain = null;
70
  if ( ! is_wp_error( $cnb_user ) ) {
71
  $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
72
  }
@@ -86,7 +85,7 @@ class CnbHeaderNotices {
86
  $message .= '<hr>';
87
  $message .= '<h4>Option 2: Web activation (manual process)</h4>';
88
  $message .= '<ol>';
89
- $message .= '<li>Create your account at <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>';
90
  $message .= '<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>';
91
  $message .= '<li>Copy the API key that appears, paste it into the field below and click <strong>Store API key</strong>.</li>';
92
  $message .= '</ol>';
@@ -105,7 +104,7 @@ class CnbHeaderNotices {
105
  $message .= '<hr>';
106
  $message .= '<h4>Option 2: Web activation (manual process)</h4>';
107
  $message .= '<ol>';
108
- $message .= '<li>Create your account at <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>';
109
  $message .= '<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>';
110
  $message .= '<li>Copy the API key that appears, paste it into the field below and click <strong>Store API key</strong>.</li>';
111
  $message .= '</ol>';
@@ -121,18 +120,18 @@ class CnbHeaderNotices {
121
  $message .= '<div id="cnb_email_activation_alternate_formd">';
122
  $message .= '<p style="margin-top: 0;"><strong>Email address</strong> (for sending you an activation link):</p>';
123
  $message .= '<input type="text" required="required" class="cnb_activation_input_field" name="cnb_email_activation_alternate_address" id="cnb_email_activation_alternate_address" placeholder="Your email address" /> ';
124
- $message .= get_submit_button( __( 'Activate Premium' ), 'primary', 'cnb_email_activation_alternate', false);
125
  $message .= '</div>';
126
  $message .= '<p id="cnb_email_activation"></p>';
127
 
128
  $message .= '<p class="nonessential">By clicking <u>Activate Premium</u> an account will be created with your email address on callnowbutton.com and you agree to our <a href="https://callnowbutton.com/terms.html" target="_blank">Terms & Conditions</a> and <a href="https://callnowbutton.com/privacy.html" target="_blank">Privacy statement</a>.</p>';
129
- $message .= "</form>";
130
 
131
  return $message;
132
  }
133
 
134
  private function cnb_settings_api_key_input() {
135
- $message = sprintf('<form action="%1s" class="cnb-container">', esc_url( admin_url( 'admin.php' ) ));
136
  $message .= '<input type="hidden" name="page" value="call-now-button-settings" />';
137
  $message .= '<div>';
138
  $message .= '<input type="text" class="cnb_activation_input_field" name="api_key" placeholder="Paste API key here"/>';
@@ -151,8 +150,8 @@ class CnbHeaderNotices {
151
  * @return void
152
  */
153
  public function add_button_is_disabled_notice( &$notices ) {
154
- $cnb_options = get_option('cnb');
155
- $status = CnbSettingsController::getStatus($cnb_options);
156
  if ( $cnb_options['active'] != 1 && ! empty( $cnb_options['number'] ) && $status != 'cloud' ) {
157
  $message = '<p>The Call Now Button is currently <strong>inactive</strong>.';
158
  $notice = new CnbNotice( 'warning', $message );
@@ -165,9 +164,9 @@ class CnbHeaderNotices {
165
  *
166
  * @return void
167
  */
168
- function cnb_button_classic_enabled_but_no_number_notice( &$notices ) {
169
- $cnb_options = get_option('cnb');
170
- $status = CnbSettingsController::getStatus($cnb_options);
171
 
172
  if ( $cnb_options['active'] == 1 && $status == 'enabled' && empty( $cnb_options['number'] ) ) {
173
  $url = admin_url( 'admin.php' );
@@ -187,6 +186,52 @@ class CnbHeaderNotices {
187
  }
188
  }
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  /**
191
  * Inform existing users about updates to the button
192
  *
@@ -197,19 +242,15 @@ class CnbHeaderNotices {
197
  * @return boolean
198
  */
199
  public function upgrade_notice( &$notices = array() ) {
200
- $cnb_options = get_option('cnb');
201
- $adminFunctions = new CnbAdminFunctions();
202
- $cnb_changelog = $adminFunctions->cnb_get_changelog();
203
- $changelog = $this->cnb_get_changelog_message( $cnb_changelog, $adminFunctions->get_changelog_version( $cnb_options ) );
204
 
205
- if ( empty( $changelog ) ) {
206
  return false;
207
  }
208
 
209
- $message = '<h3 id="cnb_is_updated">' . CNB_NAME . ' has been updated!</h3><h4>What\'s new?</h4>';
210
- $message .= $changelog;
211
-
212
- $notices[] = new CnbNotice( 'warning', $message, true, $this->cnb_get_upgrade_notice_dismiss_name() );
213
 
214
  return true;
215
  }
@@ -226,16 +267,11 @@ class CnbHeaderNotices {
226
  */
227
  private function cnb_get_changelog_message( $cnb_changelog, $cnb_old_version ) {
228
  $message = '';
229
- foreach ( $cnb_changelog as $key => $value ) {
230
- if ( $key > $cnb_old_version ) {
231
- $message .= '<h3>' . esc_html( $key ) . '</h3>';
232
- if ( is_array( $value ) ) {
233
- foreach ( $value as $item ) {
234
- $message .= '<p><span class="dashicons dashicons-yes"></span> ' . esc_html( $item ) . '</p>';
235
- }
236
- } else {
237
- $message .= '<p><span class="dashicons dashicons-yes"></span> ' . esc_html( $value ) . '</p>';
238
- }
239
  }
240
  }
241
 
@@ -248,7 +284,7 @@ class CnbHeaderNotices {
248
  * @return void
249
  */
250
  public function cnb_show_advanced( &$notices ) {
251
- $cnb_options = get_option('cnb');
252
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
253
  if ( ! $show_advanced_view_only ) {
254
  return;
@@ -327,14 +363,15 @@ class CnbHeaderNotices {
327
  ),
328
  $url );
329
  $redirect_url = esc_url( $redirect_link );
330
- $message = sprintf( '<p>Please set your timezone in the <a href="%1s">Advanced settings</a> tab to avoid unpredictable behavior when using the scheduler.</p>', $redirect_url );
331
  CnbAdminNotices::get_instance()->warning( $message );
332
  }
333
 
334
  public function is_timezone_valid( $domain ) {
335
  if ( $domain && ! is_wp_error( $domain ) && ! empty( $domain->timezone ) ) {
336
- return (new CnbUtils())->is_valid_timezone_string( $domain->timezone );
337
  }
 
338
  return true;
339
  }
340
 
@@ -358,8 +395,8 @@ class CnbHeaderNotices {
358
  $url );
359
  $redirect_url = esc_url( $redirect_link );
360
  $message = "<p id='cnb-notice-domain-timezone-unsupported'>Please fix your timezone in the ";
361
- $message .= "<a href=\"" . $redirect_url . "\">Advanced settings</a> tab ";
362
- $message .= "to avoid unpredictable behavior when using the scheduler.</p>";
363
  CnbAdminNotices::get_instance()->warning( $message );
364
 
365
  return false;
@@ -373,7 +410,7 @@ class CnbHeaderNotices {
373
  * @return void
374
  */
375
  private function render_is_debug_mode_enabled( $domain ) {
376
- if (!$domain || is_wp_error($domain) || !$domain->properties->debug) {
377
  return;
378
  }
379
 
@@ -386,8 +423,8 @@ class CnbHeaderNotices {
386
  ),
387
  $url );
388
  $redirect_url = esc_url( $redirect_link );
389
- $message = "<p>Your plugin is currently in DEBUG MODE. ";
390
- $message .= "Go to <a href=\"" . $redirect_url . "\">Advanced settings</a> to turn this off.</p>";
391
  CnbAdminNotices::get_instance()->error( $message );
392
  }
393
 
@@ -405,4 +442,4 @@ class CnbHeaderNotices {
405
  $adminNotices = CnbAdminNotices::get_instance();
406
  $adminNotices->warning( $message );
407
  }
408
- }
11
  use cnb\admin\settings\CnbSettingsController;
12
  use cnb\notices\CnbAdminNotices;
13
  use cnb\notices\CnbNotice;
 
14
  use cnb\utils\CnbUtils;
15
  use WP_Error;
16
 
46
  *
47
  */
48
  public function get_cloud_notices() {
49
+ $cnb_options = get_option( 'cnb' );
50
 
51
+ if ( ( new CnbUtils() )->isCloudActive( $cnb_options ) ) {
52
 
53
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
54
 
55
+ if ( is_wp_error( $cnb_user ) ) {
56
  if ( $cnb_user->get_error_code() === 'CNB_API_NOT_SETUP_YET' ) {
57
  // Notice: You're almost there! (enter API key)
58
  $this->cnb_settings_get_account_missing_notice();
65
  }
66
  }
67
 
68
+ $cnb_cloud_domain = null;
69
  if ( ! is_wp_error( $cnb_user ) ) {
70
  $cnb_cloud_domain = CnbAppRemote::cnb_remote_get_wp_domain();
71
  }
85
  $message .= '<hr>';
86
  $message .= '<h4>Option 2: Web activation (manual process)</h4>';
87
  $message .= '<ol>';
88
+ $message .= '<li>Create your account at <a href="https://app.callnowbutton.com?utm_source=wp-plugin_' . CNB_VERSION . '&utm_medium=referral&utm_campaign=manual_activation&utm_term=sign-up-for-api">https://app.callnowbutton.com</a></li>';
89
  $message .= '<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>';
90
  $message .= '<li>Copy the API key that appears, paste it into the field below and click <strong>Store API key</strong>.</li>';
91
  $message .= '</ol>';
104
  $message .= '<hr>';
105
  $message .= '<h4>Option 2: Web activation (manual process)</h4>';
106
  $message .= '<ol>';
107
+ $message .= '<li>Create your account at <a href="https://app.callnowbutton.com?utm_source=wp-plugin_' . CNB_VERSION . '&utm_medium=referral&utm_campaign=manual_activation&utm_term=sign-up-for-api">https://app.callnowbutton.com</a></li>';
108
  $message .= '<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>';
109
  $message .= '<li>Copy the API key that appears, paste it into the field below and click <strong>Store API key</strong>.</li>';
110
  $message .= '</ol>';
120
  $message .= '<div id="cnb_email_activation_alternate_formd">';
121
  $message .= '<p style="margin-top: 0;"><strong>Email address</strong> (for sending you an activation link):</p>';
122
  $message .= '<input type="text" required="required" class="cnb_activation_input_field" name="cnb_email_activation_alternate_address" id="cnb_email_activation_alternate_address" placeholder="Your email address" /> ';
123
+ $message .= get_submit_button( __( 'Activate Premium' ), 'primary', 'cnb_email_activation_alternate', false );
124
  $message .= '</div>';
125
  $message .= '<p id="cnb_email_activation"></p>';
126
 
127
  $message .= '<p class="nonessential">By clicking <u>Activate Premium</u> an account will be created with your email address on callnowbutton.com and you agree to our <a href="https://callnowbutton.com/terms.html" target="_blank">Terms & Conditions</a> and <a href="https://callnowbutton.com/privacy.html" target="_blank">Privacy statement</a>.</p>';
128
+ $message .= '</form>';
129
 
130
  return $message;
131
  }
132
 
133
  private function cnb_settings_api_key_input() {
134
+ $message = sprintf( '<form action="%1$s" class="cnb-container">', esc_url( admin_url( 'admin.php' ) ) );
135
  $message .= '<input type="hidden" name="page" value="call-now-button-settings" />';
136
  $message .= '<div>';
137
  $message .= '<input type="text" class="cnb_activation_input_field" name="api_key" placeholder="Paste API key here"/>';
150
  * @return void
151
  */
152
  public function add_button_is_disabled_notice( &$notices ) {
153
+ $cnb_options = get_option( 'cnb' );
154
+ $status = CnbSettingsController::getStatus( $cnb_options );
155
  if ( $cnb_options['active'] != 1 && ! empty( $cnb_options['number'] ) && $status != 'cloud' ) {
156
  $message = '<p>The Call Now Button is currently <strong>inactive</strong>.';
157
  $notice = new CnbNotice( 'warning', $message );
164
  *
165
  * @return void
166
  */
167
+ function cnb_button_legacy_enabled_but_no_number_notice( &$notices ) {
168
+ $cnb_options = get_option( 'cnb' );
169
+ $status = CnbSettingsController::getStatus( $cnb_options );
170
 
171
  if ( $cnb_options['active'] == 1 && $status == 'enabled' && empty( $cnb_options['number'] ) ) {
172
  $url = admin_url( 'admin.php' );
186
  }
187
  }
188
 
189
+ function get_changelog_version( $cnb_options ) {
190
+ if ( ! $cnb_options ) {
191
+ return CNB_VERSION;
192
+ }
193
+
194
+ if ( ! key_exists( 'changelog_version', $cnb_options ) ) {
195
+ // Get 1 version behind, so new users always get the latest
196
+ $changelog = $this->get_show_changelog_versions();
197
+
198
+ return $changelog[1];
199
+ }
200
+
201
+ return $cnb_options['changelog_version'];
202
+ }
203
+
204
+ /**
205
+ * A list of versions to show the "Your plugin has been updated" message for
206
+ *
207
+ * @return string[]
208
+ */
209
+ function get_show_changelog_versions() {
210
+ return array(
211
+ '1.1.4',
212
+ '1.0.6'
213
+ );
214
+ }
215
+
216
+ function get_generic_changelog_message() {
217
+ $changelog_url = 'https://callnowbutton.com/wordpress/changelog/';
218
+ $changelog_link = add_query_arg(
219
+ array(
220
+ 'utm_source' => 'wp-plugin_' . CNB_VERSION,
221
+ 'utm_campaign' => 'update_notice',
222
+ 'utm_medium' => 'referral',
223
+ ),
224
+ $changelog_url
225
+ );
226
+ $changelog_message = '<a href="' . esc_url( $changelog_link ) . '">Click here to see what changed</a>';
227
+ $message = '<p><span class="dashicons dashicons-yes"></span> ';
228
+ $message .= 'The plugin has been updated. ';
229
+ $message .= $changelog_message;
230
+ $message .= '</p>';
231
+
232
+ return $message;
233
+ }
234
+
235
  /**
236
  * Inform existing users about updates to the button
237
  *
242
  * @return boolean
243
  */
244
  public function upgrade_notice( &$notices = array() ) {
245
+ $cnb_options = get_option( 'cnb' );
246
+ $cnb_changelog = $this->get_show_changelog_versions();
247
+ $message = $this->cnb_get_changelog_message( $cnb_changelog, $this->get_changelog_version( $cnb_options ) );
 
248
 
249
+ if ( empty( $message ) ) {
250
  return false;
251
  }
252
 
253
+ $notices[] = new CnbNotice( 'success', $message, true, $this->cnb_get_upgrade_notice_dismiss_name() );
 
 
 
254
 
255
  return true;
256
  }
267
  */
268
  private function cnb_get_changelog_message( $cnb_changelog, $cnb_old_version ) {
269
  $message = '';
270
+ foreach ( $cnb_changelog as $value ) {
271
+ if ( version_compare( $value, $cnb_old_version, '>' ) ) {
272
+ $message .= $this->get_generic_changelog_message();
273
+ // so, instead of showing ALL updates (which at this point , we just stop here.
274
+ break;
 
 
 
 
 
275
  }
276
  }
277
 
284
  * @return void
285
  */
286
  public function cnb_show_advanced( &$notices ) {
287
+ $cnb_options = get_option( 'cnb' );
288
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
289
  if ( ! $show_advanced_view_only ) {
290
  return;
363
  ),
364
  $url );
365
  $redirect_url = esc_url( $redirect_link );
366
+ $message = sprintf( '<p>Please set your timezone in the <a href="%1$s">Advanced settings</a> tab to avoid unpredictable behavior when using the scheduler.</p>', $redirect_url );
367
  CnbAdminNotices::get_instance()->warning( $message );
368
  }
369
 
370
  public function is_timezone_valid( $domain ) {
371
  if ( $domain && ! is_wp_error( $domain ) && ! empty( $domain->timezone ) ) {
372
+ return ( new CnbUtils() )->is_valid_timezone_string( $domain->timezone );
373
  }
374
+
375
  return true;
376
  }
377
 
395
  $url );
396
  $redirect_url = esc_url( $redirect_link );
397
  $message = "<p id='cnb-notice-domain-timezone-unsupported'>Please fix your timezone in the ";
398
+ $message .= '<a href="' . $redirect_url . '">Advanced settings</a> tab ';
399
+ $message .= 'to avoid unpredictable behavior when using the scheduler.</p>';
400
  CnbAdminNotices::get_instance()->warning( $message );
401
 
402
  return false;
410
  * @return void
411
  */
412
  private function render_is_debug_mode_enabled( $domain ) {
413
+ if ( ! $domain || is_wp_error( $domain ) || ! $domain->properties->debug ) {
414
  return;
415
  }
416
 
423
  ),
424
  $url );
425
  $redirect_url = esc_url( $redirect_link );
426
+ $message = '<p>Your plugin is currently in DEBUG MODE. ';
427
+ $message .= 'Go to <a href="' . $redirect_url . '">Advanced settings</a> to turn this off.</p>';
428
  CnbAdminNotices::get_instance()->error( $message );
429
  }
430
 
442
  $adminNotices = CnbAdminNotices::get_instance();
443
  $adminNotices->warning( $message );
444
  }
445
+ }
src/admin/profile/CnbProfileController.php CHANGED
@@ -17,244 +17,244 @@ class CnbProfileController {
17
  // https://sanctionsmap.eu/#/main
18
  function get_stripe_countries() {
19
  return array(
20
- array( "country" => 'Afghanistan', "code" => 'AF' ),
21
- array( "country" => 'Åland Islands', "code" => 'AX' ),
22
- array( "country" => 'Albania', "code" => 'AL' ),
23
- array( "country" => 'Algeria', "code" => 'DZ' ),
24
- array( "country" => 'American Samoa', "code" => 'AS' ),
25
- array( "country" => 'Andorra', "code" => 'AD' ),
26
- array( "country" => 'Angola', "code" => 'AO' ),
27
- array( "country" => 'Anguilla', "code" => 'AI' ),
28
- array( "country" => 'Antarctica', "code" => 'AQ' ),
29
- array( "country" => 'Antigua and Barbuda', "code" => 'AG' ),
30
- array( "country" => 'Argentina', "code" => 'AR' ),
31
- array( "country" => 'Armenia', "code" => 'AM' ),
32
- array( "country" => 'Aruba', "code" => 'AW' ),
33
- array( "country" => 'Australia', "code" => 'AU' ),
34
- array( "country" => 'Austria', "code" => 'AT' ),
35
- array( "country" => 'Azerbaijan', "code" => 'AZ' ),
36
- array( "country" => 'Bahamas', "code" => 'BS' ),
37
- array( "country" => 'Bahrain', "code" => 'BH' ),
38
- array( "country" => 'Bangladesh', "code" => 'BD' ),
39
- array( "country" => 'Barbados', "code" => 'BB' ),
40
- array( "country" => 'Belarus', "code" => 'BY' ),
41
- array( "country" => 'Belgium', "code" => 'BE' ),
42
- array( "country" => 'Belize', "code" => 'BZ' ),
43
- array( "country" => 'Benin', "code" => 'BJ' ),
44
- array( "country" => 'Bermuda', "code" => 'BM' ),
45
- array( "country" => 'Bhutan', "code" => 'BT' ),
46
- array( "country" => 'Bolivia', "code" => 'BO' ),
47
- array( "country" => 'Bonaire, Sint Eustatius and Saba', "code" => 'BQ' ),
48
- array( "country" => 'Bosnia and Herzegovina', "code" => 'BA' ),
49
- array( "country" => 'Botswana', "code" => 'BW' ),
50
- array( "country" => 'Bouvet Island', "code" => 'BV' ),
51
- array( "country" => 'Brazil', "code" => 'BR' ),
52
- array( "country" => 'British Indian Ocean Territory', "code" => 'IO' ),
53
- array( "country" => 'Brunei Darussalam', "code" => 'BN' ),
54
- array( "country" => 'Bulgaria', "code" => 'BG' ),
55
- array( "country" => 'Burkina Faso', "code" => 'BF' ),
56
- array( "country" => 'Burundi', "code" => 'BI' ),
57
- array( "country" => 'Cabo Verde', "code" => 'CV' ),
58
- array( "country" => 'Cambodia', "code" => 'KH' ),
59
- array( "country" => 'Cameroon', "code" => 'CM' ),
60
- array( "country" => 'Canada', "code" => 'CA' ),
61
- array( "country" => 'Cayman Islands', "code" => 'KY' ),
62
- array( "country" => 'Central African Republic', "code" => 'CF' ),
63
- array( "country" => 'Chad', "code" => 'TD' ),
64
- array( "country" => 'Chile', "code" => 'CL' ),
65
- array( "country" => 'China', "code" => 'CN' ),
66
- array( "country" => 'Christmas Island', "code" => 'CX' ),
67
- array( "country" => 'Cocos (Keeling) Islands', "code" => 'CC' ),
68
- array( "country" => 'Colombia', "code" => 'CO' ),
69
- array( "country" => 'Comoros', "code" => 'KM' ),
70
- array( "country" => 'Congo', "code" => 'CG' ),
71
- array( "country" => 'Cook Islands', "code" => 'CK' ),
72
- array( "country" => 'Costa Rica', "code" => 'CR' ),
73
- array( "country" => 'Côte d\'Ivoire', "code" => 'CI' ),
74
- array( "country" => 'Croatia', "code" => 'HR' ),
75
- array( "country" => 'Cuba', "code" => 'CU' ),
76
- array( "country" => 'Curaçao', "code" => 'CW' ),
77
- array( "country" => 'Cyprus', "code" => 'CY' ),
78
- array( "country" => 'Czechia', "code" => 'CZ' ),
79
- array( "country" => 'Denmark', "code" => 'DK' ),
80
- array( "country" => 'Djibouti', "code" => 'DJ' ),
81
- array( "country" => 'Dominica', "code" => 'DM' ),
82
- array( "country" => 'Dominican Republic', "code" => 'DO' ),
83
- array( "country" => 'Ecuador', "code" => 'EC' ),
84
- array( "country" => 'Egypt', "code" => 'EG' ),
85
- array( "country" => 'El Salvador', "code" => 'SV' ),
86
- array( "country" => 'Equatorial Guinea', "code" => 'GQ' ),
87
- array( "country" => 'Eritrea', "code" => 'ER' ),
88
- array( "country" => 'Estonia', "code" => 'EE' ),
89
- array( "country" => 'Eswatini', "code" => 'SZ' ),
90
- array( "country" => 'Ethiopia', "code" => 'ET' ),
91
- array( "country" => 'Falkland Islands (Malvinas)', "code" => 'FK' ),
92
- array( "country" => 'Faroe Islands', "code" => 'FO' ),
93
- array( "country" => 'Fiji', "code" => 'FJ' ),
94
- array( "country" => 'Finland', "code" => 'FI' ),
95
- array( "country" => 'France', "code" => 'FR' ),
96
- array( "country" => 'French Guiana', "code" => 'GF' ),
97
- array( "country" => 'French Polynesia', "code" => 'PF' ),
98
- array( "country" => 'French Southern Territories', "code" => 'TF' ),
99
- array( "country" => 'Gabon', "code" => 'GA' ),
100
- array( "country" => 'Gambia', "code" => 'GM' ),
101
- array( "country" => 'Georgia', "code" => 'GE' ),
102
- array( "country" => 'Germany', "code" => 'DE' ),
103
- array( "country" => 'Ghana', "code" => 'GH' ),
104
- array( "country" => 'Gibraltar', "code" => 'GI' ),
105
- array( "country" => 'Greece', "code" => 'GR' ),
106
- array( "country" => 'Greenland', "code" => 'GL' ),
107
- array( "country" => 'Grenada', "code" => 'GD' ),
108
- array( "country" => 'Guadeloupe', "code" => 'GP' ),
109
- array( "country" => 'Guam', "code" => 'GU' ),
110
- array( "country" => 'Guatemala', "code" => 'GT' ),
111
- array( "country" => 'Guernsey', "code" => 'GG' ),
112
- array( "country" => 'Guinea-Bissau', "code" => 'GW' ),
113
- array( "country" => 'Guyana', "code" => 'GY' ),
114
- array( "country" => 'Haiti', "code" => 'HT' ),
115
- array( "country" => 'Heard Island and McDonald Islands', "code" => 'HM' ),
116
- array( "country" => 'Holy See', "code" => 'VA' ),
117
- array( "country" => 'Honduras', "code" => 'HN' ),
118
- array( "country" => 'Hong Kong', "code" => 'HK' ),
119
- array( "country" => 'Hungary', "code" => 'HU' ),
120
- array( "country" => 'Iceland', "code" => 'IS' ),
121
- array( "country" => 'India', "code" => 'IN' ),
122
- array( "country" => 'Indonesia', "code" => 'ID' ),
123
- array( "country" => 'Iraq', "code" => 'IQ' ),
124
- array( "country" => 'Ireland', "code" => 'IE' ),
125
- array( "country" => 'Isle of Man', "code" => 'IM' ),
126
- array( "country" => 'Israel', "code" => 'IL' ),
127
- array( "country" => 'Italy', "code" => 'IT' ),
128
- array( "country" => 'Jamaica', "code" => 'JM' ),
129
- array( "country" => 'Japan', "code" => 'JP' ),
130
- array( "country" => 'Jersey', "code" => 'JE' ),
131
- array( "country" => 'Jordan', "code" => 'JO' ),
132
- array( "country" => 'Kazakhstan', "code" => 'KZ' ),
133
- array( "country" => 'Kenya', "code" => 'KE' ),
134
- array( "country" => 'Kiribati', "code" => 'KI' ),
135
- array( "country" => 'Korea, Republic of', "code" => 'KR' ),
136
- array( "country" => 'Kuwait', "code" => 'KW' ),
137
- array( "country" => 'Kyrgyzstan', "code" => 'KG' ),
138
- array( "country" => 'Lao', "code" => 'LA' ),
139
- array( "country" => 'Latvia', "code" => 'LV' ),
140
- array( "country" => 'Lebanon', "code" => 'LB' ),
141
- array( "country" => 'Lesotho', "code" => 'LS' ),
142
- array( "country" => 'Liberia', "code" => 'LR' ),
143
- array( "country" => 'Liechtenstein', "code" => 'LI' ),
144
- array( "country" => 'Lithuania', "code" => 'LT' ),
145
- array( "country" => 'Luxembourg', "code" => 'LU' ),
146
- array( "country" => 'Macao', "code" => 'MO' ),
147
- array( "country" => 'Madagascar', "code" => 'MG' ),
148
- array( "country" => 'Malawi', "code" => 'MW' ),
149
- array( "country" => 'Malaysia', "code" => 'MY' ),
150
- array( "country" => 'Maldives', "code" => 'MV' ),
151
- array( "country" => 'Malta', "code" => 'MT' ),
152
- array( "country" => 'Marshall Islands', "code" => 'MH' ),
153
- array( "country" => 'Martinique', "code" => 'MQ' ),
154
- array( "country" => 'Mauritania', "code" => 'MR' ),
155
- array( "country" => 'Mauritius', "code" => 'MU' ),
156
- array( "country" => 'Mayotte', "code" => 'YT' ),
157
- array( "country" => 'Mexico', "code" => 'MX' ),
158
- array( "country" => 'Micronesia', "code" => 'FM' ),
159
- array( "country" => 'Moldova', "code" => 'MD' ),
160
- array( "country" => 'Monaco', "code" => 'MC' ),
161
- array( "country" => 'Mongolia', "code" => 'MN' ),
162
- array( "country" => 'Montenegro', "code" => 'ME' ),
163
- array( "country" => 'Montserrat', "code" => 'MS' ),
164
- array( "country" => 'Morocco', "code" => 'MA' ),
165
- array( "country" => 'Mozambique', "code" => 'MZ' ),
166
- array( "country" => 'Namibia', "code" => 'NA' ),
167
- array( "country" => 'Nauru', "code" => 'NR' ),
168
- array( "country" => 'Nepal', "code" => 'NP' ),
169
- array( "country" => 'Netherlands', "code" => 'NL' ),
170
- array( "country" => 'New Caledonia', "code" => 'NC' ),
171
- array( "country" => 'New Zealand', "code" => 'NZ' ),
172
- array( "country" => 'Nicaragua', "code" => 'NI' ),
173
- array( "country" => 'Niger', "code" => 'NE' ),
174
- array( "country" => 'Nigeria', "code" => 'NG' ),
175
- array( "country" => 'Niue', "code" => 'NU' ),
176
- array( "country" => 'Norfolk Island', "code" => 'NF' ),
177
- array( "country" => 'North Macedonia', "code" => 'MK' ),
178
- array( "country" => 'Northern Mariana Islands', "code" => 'MP' ),
179
- array( "country" => 'Norway', "code" => 'NO' ),
180
- array( "country" => 'Oman', "code" => 'OM' ),
181
- array( "country" => 'Pakistan', "code" => 'PK' ),
182
- array( "country" => 'Palau', "code" => 'PW' ),
183
- array( "country" => 'Palestine', "code" => 'PS' ),
184
- array( "country" => 'Panama', "code" => 'PA' ),
185
- array( "country" => 'Papua New Guinea', "code" => 'PG' ),
186
- array( "country" => 'Paraguay', "code" => 'PY' ),
187
- array( "country" => 'Peru', "code" => 'PE' ),
188
- array( "country" => 'Philippines', "code" => 'PH' ),
189
- array( "country" => 'Pitcairn', "code" => 'PN' ),
190
- array( "country" => 'Poland', "code" => 'PL' ),
191
- array( "country" => 'Portugal', "code" => 'PT' ),
192
- array( "country" => 'Puerto Rico', "code" => 'PR' ),
193
- array( "country" => 'Qatar', "code" => 'QA' ),
194
- array( "country" => 'Réunion', "code" => 'RE' ),
195
- array( "country" => 'Romania', "code" => 'RO' ),
196
- array( "country" => 'Rwanda', "code" => 'RW' ),
197
- array( "country" => 'Saint Barthélemy', "code" => 'BL' ),
198
- array( "country" => 'Saint Helena, Ascension and Tristan da Cunha', "code" => 'SH' ),
199
- array( "country" => 'Saint Kitts and Nevis', "code" => 'KN' ),
200
- array( "country" => 'Saint Lucia', "code" => 'LC' ),
201
- array( "country" => 'Saint Martin (French part)', "code" => 'MF' ),
202
- array( "country" => 'Saint Pierre and Miquelon', "code" => 'PM' ),
203
- array( "country" => 'Saint Vincent and the Grenadines', "code" => 'VC' ),
204
- array( "country" => 'Samoa', "code" => 'WS' ),
205
- array( "country" => 'San Marino', "code" => 'SM' ),
206
- array( "country" => 'Sao Tome and Principe', "code" => 'ST' ),
207
- array( "country" => 'Saudi Arabia', "code" => 'SA' ),
208
- array( "country" => 'Senegal', "code" => 'SN' ),
209
- array( "country" => 'Serbia', "code" => 'RS' ),
210
- array( "country" => 'Seychelles', "code" => 'SC' ),
211
- array( "country" => 'Sierra Leone', "code" => 'SL' ),
212
- array( "country" => 'Singapore', "code" => 'SG' ),
213
- array( "country" => 'Sint Maarten (Dutch part)', "code" => 'SX' ),
214
- array( "country" => 'Slovakia', "code" => 'SK' ),
215
- array( "country" => 'Slovenia', "code" => 'SI' ),
216
- array( "country" => 'Solomon Islands', "code" => 'SB' ),
217
- array( "country" => 'Somalia', "code" => 'SO' ),
218
- array( "country" => 'South Africa', "code" => 'ZA' ),
219
- array( "country" => 'South Georgia + South Sandwich Isl.', "code" => 'GS' ),
220
- array( "country" => 'Spain', "code" => 'ES' ),
221
- array( "country" => 'Sri Lanka', "code" => 'LK' ),
222
- array( "country" => 'Suriname', "code" => 'SR' ),
223
- array( "country" => 'Svalbard and Jan Mayen', "code" => 'SJ' ),
224
- array( "country" => 'Sweden', "code" => 'SE' ),
225
- array( "country" => 'Switzerland', "code" => 'CH' ),
226
- array( "country" => 'Syrian Arab Republic', "code" => 'SY' ),
227
- array( "country" => 'Taiwan, Province of China', "code" => 'TW' ),
228
- array( "country" => 'Tajikistan', "code" => 'TJ' ),
229
- array( "country" => 'Tanzania, United Republic of', "code" => 'TZ' ),
230
- array( "country" => 'Thailand', "code" => 'TH' ),
231
- array( "country" => 'Timor-Leste', "code" => 'TL' ),
232
- array( "country" => 'Togo', "code" => 'TG' ),
233
- array( "country" => 'Tokelau', "code" => 'TK' ),
234
- array( "country" => 'Tonga', "code" => 'TO' ),
235
- array( "country" => 'Trinidad and Tobago', "code" => 'TT' ),
236
- array( "country" => 'Tunisia', "code" => 'TN' ),
237
- array( "country" => 'Turkey', "code" => 'TR' ),
238
- array( "country" => 'Turkmenistan', "code" => 'TM' ),
239
- array( "country" => 'Turks and Caicos Islands', "code" => 'TC' ),
240
- array( "country" => 'Tuvalu', "code" => 'TV' ),
241
- array( "country" => 'Uganda', "code" => 'UG' ),
242
- array( "country" => 'Ukraine', "code" => 'UA' ),
243
- array( "country" => 'United Arab Emirates', "code" => 'AE' ),
244
- array( "country" => 'United Kingdom', "code" => 'GB' ),
245
- array( "country" => 'United States Minor Outlying Islands', "code" => 'UM' ),
246
- array( "country" => 'United States of America', "code" => 'US' ),
247
- array( "country" => 'Uruguay', "code" => 'UY' ),
248
- array( "country" => 'Uzbekistan', "code" => 'UZ' ),
249
- array( "country" => 'Vanuatu', "code" => 'VU' ),
250
- array( "country" => 'Venezuela (Bolivarian Republic of)', "code" => 'VE' ),
251
- array( "country" => 'Viet Nam', "code" => 'VN' ),
252
- array( "country" => 'Virgin Islands (British)', "code" => 'VG' ),
253
- array( "country" => 'Virgin Islands (U.S.)', "code" => 'VI' ),
254
- array( "country" => 'Wallis and Futuna', "code" => 'WF' ),
255
- array( "country" => 'Western Sahara', "code" => 'EH' ),
256
- array( "country" => 'Yemen', "code" => 'YE' ),
257
- array( "country" => 'Zambia', "code" => 'ZM' )
258
  );
259
  }
260
 
@@ -318,12 +318,10 @@ class CnbProfileController {
318
  $redirect_url = esc_url_raw( $redirect_link );
319
  wp_safe_redirect( $redirect_url );
320
  } else {
321
- wp_die( __( 'Invalid nonce specified', CNB_NAME ), __( 'Error', CNB_NAME ), array(
322
  'response' => 403,
323
- 'back_link' => 'admin.php?page=' . CNB_SLUG . '-profile',
324
  ) );
325
  }
326
-
327
  }
328
-
329
- }
17
  // https://sanctionsmap.eu/#/main
18
  function get_stripe_countries() {
19
  return array(
20
+ array( 'country' => 'Afghanistan', 'code' => 'AF' ),
21
+ array( 'country' => 'Åland Islands', 'code' => 'AX' ),
22
+ array( 'country' => 'Albania', 'code' => 'AL' ),
23
+ array( 'country' => 'Algeria', 'code' => 'DZ' ),
24
+ array( 'country' => 'American Samoa', 'code' => 'AS' ),
25
+ array( 'country' => 'Andorra', 'code' => 'AD' ),
26
+ array( 'country' => 'Angola', 'code' => 'AO' ),
27
+ array( 'country' => 'Anguilla', 'code' => 'AI' ),
28
+ array( 'country' => 'Antarctica', 'code' => 'AQ' ),
29
+ array( 'country' => 'Antigua and Barbuda', 'code' => 'AG' ),
30
+ array( 'country' => 'Argentina', 'code' => 'AR' ),
31
+ array( 'country' => 'Armenia', 'code' => 'AM' ),
32
+ array( 'country' => 'Aruba', 'code' => 'AW' ),
33
+ array( 'country' => 'Australia', 'code' => 'AU' ),
34
+ array( 'country' => 'Austria', 'code' => 'AT' ),
35
+ array( 'country' => 'Azerbaijan', 'code' => 'AZ' ),
36
+ array( 'country' => 'Bahamas', 'code' => 'BS' ),
37
+ array( 'country' => 'Bahrain', 'code' => 'BH' ),
38
+ array( 'country' => 'Bangladesh', 'code' => 'BD' ),
39
+ array( 'country' => 'Barbados', 'code' => 'BB' ),
40
+ array( 'country' => 'Belarus', 'code' => 'BY' ),
41
+ array( 'country' => 'Belgium', 'code' => 'BE' ),
42
+ array( 'country' => 'Belize', 'code' => 'BZ' ),
43
+ array( 'country' => 'Benin', 'code' => 'BJ' ),
44
+ array( 'country' => 'Bermuda', 'code' => 'BM' ),
45
+ array( 'country' => 'Bhutan', 'code' => 'BT' ),
46
+ array( 'country' => 'Bolivia', 'code' => 'BO' ),
47
+ array( 'country' => 'Bonaire, Sint Eustatius and Saba', 'code' => 'BQ' ),
48
+ array( 'country' => 'Bosnia and Herzegovina', 'code' => 'BA' ),
49
+ array( 'country' => 'Botswana', 'code' => 'BW' ),
50
+ array( 'country' => 'Bouvet Island', 'code' => 'BV' ),
51
+ array( 'country' => 'Brazil', 'code' => 'BR' ),
52
+ array( 'country' => 'British Indian Ocean Territory', 'code' => 'IO' ),
53
+ array( 'country' => 'Brunei Darussalam', 'code' => 'BN' ),
54
+ array( 'country' => 'Bulgaria', 'code' => 'BG' ),
55
+ array( 'country' => 'Burkina Faso', 'code' => 'BF' ),
56
+ array( 'country' => 'Burundi', 'code' => 'BI' ),
57
+ array( 'country' => 'Cabo Verde', 'code' => 'CV' ),
58
+ array( 'country' => 'Cambodia', 'code' => 'KH' ),
59
+ array( 'country' => 'Cameroon', 'code' => 'CM' ),
60
+ array( 'country' => 'Canada', 'code' => 'CA' ),
61
+ array( 'country' => 'Cayman Islands', 'code' => 'KY' ),
62
+ array( 'country' => 'Central African Republic', 'code' => 'CF' ),
63
+ array( 'country' => 'Chad', 'code' => 'TD' ),
64
+ array( 'country' => 'Chile', 'code' => 'CL' ),
65
+ array( 'country' => 'China', 'code' => 'CN' ),
66
+ array( 'country' => 'Christmas Island', 'code' => 'CX' ),
67
+ array( 'country' => 'Cocos (Keeling) Islands', 'code' => 'CC' ),
68
+ array( 'country' => 'Colombia', 'code' => 'CO' ),
69
+ array( 'country' => 'Comoros', 'code' => 'KM' ),
70
+ array( 'country' => 'Congo', 'code' => 'CG' ),
71
+ array( 'country' => 'Cook Islands', 'code' => 'CK' ),
72
+ array( 'country' => 'Costa Rica', 'code' => 'CR' ),
73
+ array( 'country' => 'Côte d\'Ivoire', 'code' => 'CI' ),
74
+ array( 'country' => 'Croatia', 'code' => 'HR' ),
75
+ array( 'country' => 'Cuba', 'code' => 'CU' ),
76
+ array( 'country' => 'Curaçao', 'code' => 'CW' ),
77
+ array( 'country' => 'Cyprus', 'code' => 'CY' ),
78
+ array( 'country' => 'Czechia', 'code' => 'CZ' ),
79
+ array( 'country' => 'Denmark', 'code' => 'DK' ),
80
+ array( 'country' => 'Djibouti', 'code' => 'DJ' ),
81
+ array( 'country' => 'Dominica', 'code' => 'DM' ),
82
+ array( 'country' => 'Dominican Republic', 'code' => 'DO' ),
83
+ array( 'country' => 'Ecuador', 'code' => 'EC' ),
84
+ array( 'country' => 'Egypt', 'code' => 'EG' ),
85
+ array( 'country' => 'El Salvador', 'code' => 'SV' ),
86
+ array( 'country' => 'Equatorial Guinea', 'code' => 'GQ' ),
87
+ array( 'country' => 'Eritrea', 'code' => 'ER' ),
88
+ array( 'country' => 'Estonia', 'code' => 'EE' ),
89
+ array( 'country' => 'Eswatini', 'code' => 'SZ' ),
90
+ array( 'country' => 'Ethiopia', 'code' => 'ET' ),
91
+ array( 'country' => 'Falkland Islands (Malvinas)', 'code' => 'FK' ),
92
+ array( 'country' => 'Faroe Islands', 'code' => 'FO' ),
93
+ array( 'country' => 'Fiji', 'code' => 'FJ' ),
94
+ array( 'country' => 'Finland', 'code' => 'FI' ),
95
+ array( 'country' => 'France', 'code' => 'FR' ),
96
+ array( 'country' => 'French Guiana', 'code' => 'GF' ),
97
+ array( 'country' => 'French Polynesia', 'code' => 'PF' ),
98
+ array( 'country' => 'French Southern Territories', 'code' => 'TF' ),
99
+ array( 'country' => 'Gabon', 'code' => 'GA' ),
100
+ array( 'country' => 'Gambia', 'code' => 'GM' ),
101
+ array( 'country' => 'Georgia', 'code' => 'GE' ),
102
+ array( 'country' => 'Germany', 'code' => 'DE' ),
103
+ array( 'country' => 'Ghana', 'code' => 'GH' ),
104
+ array( 'country' => 'Gibraltar', 'code' => 'GI' ),
105
+ array( 'country' => 'Greece', 'code' => 'GR' ),
106
+ array( 'country' => 'Greenland', 'code' => 'GL' ),
107
+ array( 'country' => 'Grenada', 'code' => 'GD' ),
108
+ array( 'country' => 'Guadeloupe', 'code' => 'GP' ),
109
+ array( 'country' => 'Guam', 'code' => 'GU' ),
110
+ array( 'country' => 'Guatemala', 'code' => 'GT' ),
111
+ array( 'country' => 'Guernsey', 'code' => 'GG' ),
112
+ array( 'country' => 'Guinea-Bissau', 'code' => 'GW' ),
113
+ array( 'country' => 'Guyana', 'code' => 'GY' ),
114
+ array( 'country' => 'Haiti', 'code' => 'HT' ),
115
+ array( 'country' => 'Heard Island and McDonald Islands', 'code' => 'HM' ),
116
+ array( 'country' => 'Holy See', 'code' => 'VA' ),
117
+ array( 'country' => 'Honduras', 'code' => 'HN' ),
118
+ array( 'country' => 'Hong Kong', 'code' => 'HK' ),
119
+ array( 'country' => 'Hungary', 'code' => 'HU' ),
120
+ array( 'country' => 'Iceland', 'code' => 'IS' ),
121
+ array( 'country' => 'India', 'code' => 'IN' ),
122
+ array( 'country' => 'Indonesia', 'code' => 'ID' ),
123
+ array( 'country' => 'Iraq', 'code' => 'IQ' ),
124
+ array( 'country' => 'Ireland', 'code' => 'IE' ),
125
+ array( 'country' => 'Isle of Man', 'code' => 'IM' ),
126
+ array( 'country' => 'Israel', 'code' => 'IL' ),
127
+ array( 'country' => 'Italy', 'code' => 'IT' ),
128
+ array( 'country' => 'Jamaica', 'code' => 'JM' ),
129
+ array( 'country' => 'Japan', 'code' => 'JP' ),
130
+ array( 'country' => 'Jersey', 'code' => 'JE' ),
131
+ array( 'country' => 'Jordan', 'code' => 'JO' ),
132
+ array( 'country' => 'Kazakhstan', 'code' => 'KZ' ),
133
+ array( 'country' => 'Kenya', 'code' => 'KE' ),
134
+ array( 'country' => 'Kiribati', 'code' => 'KI' ),
135
+ array( 'country' => 'Korea, Republic of', 'code' => 'KR' ),
136
+ array( 'country' => 'Kuwait', 'code' => 'KW' ),
137
+ array( 'country' => 'Kyrgyzstan', 'code' => 'KG' ),
138
+ array( 'country' => 'Lao', 'code' => 'LA' ),
139
+ array( 'country' => 'Latvia', 'code' => 'LV' ),
140
+ array( 'country' => 'Lebanon', 'code' => 'LB' ),
141
+ array( 'country' => 'Lesotho', 'code' => 'LS' ),
142
+ array( 'country' => 'Liberia', 'code' => 'LR' ),
143
+ array( 'country' => 'Liechtenstein', 'code' => 'LI' ),
144
+ array( 'country' => 'Lithuania', 'code' => 'LT' ),
145
+ array( 'country' => 'Luxembourg', 'code' => 'LU' ),
146
+ array( 'country' => 'Macao', 'code' => 'MO' ),
147
+ array( 'country' => 'Madagascar', 'code' => 'MG' ),
148
+ array( 'country' => 'Malawi', 'code' => 'MW' ),
149
+ array( 'country' => 'Malaysia', 'code' => 'MY' ),
150
+ array( 'country' => 'Maldives', 'code' => 'MV' ),
151
+ array( 'country' => 'Malta', 'code' => 'MT' ),
152
+ array( 'country' => 'Marshall Islands', 'code' => 'MH' ),
153
+ array( 'country' => 'Martinique', 'code' => 'MQ' ),
154
+ array( 'country' => 'Mauritania', 'code' => 'MR' ),
155
+ array( 'country' => 'Mauritius', 'code' => 'MU' ),
156
+ array( 'country' => 'Mayotte', 'code' => 'YT' ),
157
+ array( 'country' => 'Mexico', 'code' => 'MX' ),
158
+ array( 'country' => 'Micronesia', 'code' => 'FM' ),
159
+ array( 'country' => 'Moldova', 'code' => 'MD' ),
160
+ array( 'country' => 'Monaco', 'code' => 'MC' ),
161
+ array( 'country' => 'Mongolia', 'code' => 'MN' ),
162
+ array( 'country' => 'Montenegro', 'code' => 'ME' ),
163
+ array( 'country' => 'Montserrat', 'code' => 'MS' ),
164
+ array( 'country' => 'Morocco', 'code' => 'MA' ),
165
+ array( 'country' => 'Mozambique', 'code' => 'MZ' ),
166
+ array( 'country' => 'Namibia', 'code' => 'NA' ),
167
+ array( 'country' => 'Nauru', 'code' => 'NR' ),
168
+ array( 'country' => 'Nepal', 'code' => 'NP' ),
169
+ array( 'country' => 'Netherlands', 'code' => 'NL' ),
170
+ array( 'country' => 'New Caledonia', 'code' => 'NC' ),
171
+ array( 'country' => 'New Zealand', 'code' => 'NZ' ),
172
+ array( 'country' => 'Nicaragua', 'code' => 'NI' ),
173
+ array( 'country' => 'Niger', 'code' => 'NE' ),
174
+ array( 'country' => 'Nigeria', 'code' => 'NG' ),
175
+ array( 'country' => 'Niue', 'code' => 'NU' ),
176
+ array( 'country' => 'Norfolk Island', 'code' => 'NF' ),
177
+ array( 'country' => 'North Macedonia', 'code' => 'MK' ),
178
+ array( 'country' => 'Northern Mariana Islands', 'code' => 'MP' ),
179
+ array( 'country' => 'Norway', 'code' => 'NO' ),
180
+ array( 'country' => 'Oman', 'code' => 'OM' ),
181
+ array( 'country' => 'Pakistan', 'code' => 'PK' ),
182
+ array( 'country' => 'Palau', 'code' => 'PW' ),
183
+ array( 'country' => 'Palestine', 'code' => 'PS' ),
184
+ array( 'country' => 'Panama', 'code' => 'PA' ),
185
+ array( 'country' => 'Papua New Guinea', 'code' => 'PG' ),
186
+ array( 'country' => 'Paraguay', 'code' => 'PY' ),
187
+ array( 'country' => 'Peru', 'code' => 'PE' ),
188
+ array( 'country' => 'Philippines', 'code' => 'PH' ),
189
+ array( 'country' => 'Pitcairn', 'code' => 'PN' ),
190
+ array( 'country' => 'Poland', 'code' => 'PL' ),
191
+ array( 'country' => 'Portugal', 'code' => 'PT' ),
192
+ array( 'country' => 'Puerto Rico', 'code' => 'PR' ),
193
+ array( 'country' => 'Qatar', 'code' => 'QA' ),
194
+ array( 'country' => 'Réunion', 'code' => 'RE' ),
195
+ array( 'country' => 'Romania', 'code' => 'RO' ),
196
+ array( 'country' => 'Rwanda', 'code' => 'RW' ),
197
+ array( 'country' => 'Saint Barthélemy', 'code' => 'BL' ),
198
+ array( 'country' => 'Saint Helena, Ascension and Tristan da Cunha', 'code' => 'SH' ),
199
+ array( 'country' => 'Saint Kitts and Nevis', 'code' => 'KN' ),
200
+ array( 'country' => 'Saint Lucia', 'code' => 'LC' ),
201
+ array( 'country' => 'Saint Martin (French part)', 'code' => 'MF' ),
202
+ array( 'country' => 'Saint Pierre and Miquelon', 'code' => 'PM' ),
203
+ array( 'country' => 'Saint Vincent and the Grenadines', 'code' => 'VC' ),
204
+ array( 'country' => 'Samoa', 'code' => 'WS' ),
205
+ array( 'country' => 'San Marino', 'code' => 'SM' ),
206
+ array( 'country' => 'Sao Tome and Principe', 'code' => 'ST' ),
207
+ array( 'country' => 'Saudi Arabia', 'code' => 'SA' ),
208
+ array( 'country' => 'Senegal', 'code' => 'SN' ),
209
+ array( 'country' => 'Serbia', 'code' => 'RS' ),
210
+ array( 'country' => 'Seychelles', 'code' => 'SC' ),
211
+ array( 'country' => 'Sierra Leone', 'code' => 'SL' ),
212
+ array( 'country' => 'Singapore', 'code' => 'SG' ),
213
+ array( 'country' => 'Sint Maarten (Dutch part)', 'code' => 'SX' ),
214
+ array( 'country' => 'Slovakia', 'code' => 'SK' ),
215
+ array( 'country' => 'Slovenia', 'code' => 'SI' ),
216
+ array( 'country' => 'Solomon Islands', 'code' => 'SB' ),
217
+ array( 'country' => 'Somalia', 'code' => 'SO' ),
218
+ array( 'country' => 'South Africa', 'code' => 'ZA' ),
219
+ array( 'country' => 'South Georgia + South Sandwich Isl.', 'code' => 'GS' ),
220
+ array( 'country' => 'Spain', 'code' => 'ES' ),
221
+ array( 'country' => 'Sri Lanka', 'code' => 'LK' ),
222
+ array( 'country' => 'Suriname', 'code' => 'SR' ),
223
+ array( 'country' => 'Svalbard and Jan Mayen', 'code' => 'SJ' ),
224
+ array( 'country' => 'Sweden', 'code' => 'SE' ),
225
+ array( 'country' => 'Switzerland', 'code' => 'CH' ),
226
+ array( 'country' => 'Syrian Arab Republic', 'code' => 'SY' ),
227
+ array( 'country' => 'Taiwan, Province of China', 'code' => 'TW' ),
228
+ array( 'country' => 'Tajikistan', 'code' => 'TJ' ),
229
+ array( 'country' => 'Tanzania, United Republic of', 'code' => 'TZ' ),
230
+ array( 'country' => 'Thailand', 'code' => 'TH' ),
231
+ array( 'country' => 'Timor-Leste', 'code' => 'TL' ),
232
+ array( 'country' => 'Togo', 'code' => 'TG' ),
233
+ array( 'country' => 'Tokelau', 'code' => 'TK' ),
234
+ array( 'country' => 'Tonga', 'code' => 'TO' ),
235
+ array( 'country' => 'Trinidad and Tobago', 'code' => 'TT' ),
236
+ array( 'country' => 'Tunisia', 'code' => 'TN' ),
237
+ array( 'country' => 'Turkey', 'code' => 'TR' ),
238
+ array( 'country' => 'Turkmenistan', 'code' => 'TM' ),
239
+ array( 'country' => 'Turks and Caicos Islands', 'code' => 'TC' ),
240
+ array( 'country' => 'Tuvalu', 'code' => 'TV' ),
241
+ array( 'country' => 'Uganda', 'code' => 'UG' ),
242
+ array( 'country' => 'Ukraine', 'code' => 'UA' ),
243
+ array( 'country' => 'United Arab Emirates', 'code' => 'AE' ),
244
+ array( 'country' => 'United Kingdom', 'code' => 'GB' ),
245
+ array( 'country' => 'United States Minor Outlying Islands', 'code' => 'UM' ),
246
+ array( 'country' => 'United States of America', 'code' => 'US' ),
247
+ array( 'country' => 'Uruguay', 'code' => 'UY' ),
248
+ array( 'country' => 'Uzbekistan', 'code' => 'UZ' ),
249
+ array( 'country' => 'Vanuatu', 'code' => 'VU' ),
250
+ array( 'country' => 'Venezuela (Bolivarian Republic of)', 'code' => 'VE' ),
251
+ array( 'country' => 'Viet Nam', 'code' => 'VN' ),
252
+ array( 'country' => 'Virgin Islands (British)', 'code' => 'VG' ),
253
+ array( 'country' => 'Virgin Islands (U.S.)', 'code' => 'VI' ),
254
+ array( 'country' => 'Wallis and Futuna', 'code' => 'WF' ),
255
+ array( 'country' => 'Western Sahara', 'code' => 'EH' ),
256
+ array( 'country' => 'Yemen', 'code' => 'YE' ),
257
+ array( 'country' => 'Zambia', 'code' => 'ZM' )
258
  );
259
  }
260
 
318
  $redirect_url = esc_url_raw( $redirect_link );
319
  wp_safe_redirect( $redirect_url );
320
  } else {
321
+ wp_die( esc_html__( 'Invalid nonce specified' ), esc_html__( 'Error' ), array(
322
  'response' => 403,
323
+ 'back_link' => true,
324
  ) );
325
  }
 
326
  }
327
+ }
 
src/admin/profile/CnbProfileEdit.php CHANGED
@@ -100,11 +100,16 @@ class CnbProfileEdit {
100
  <option value=""></option>
101
  <?php
102
  foreach ( $controller->get_stripe_countries() as $country ) {
103
- $selected = '';
104
  if ( isset( $cnb_user->address ) ) {
105
- $selected = $country['code'] === $cnb_user->address->country ? ' selected="selected"' : '';
106
  }
107
- echo '<option value="' . $country['code'] . '"' . $selected . '>' . $country['country'] . '</option>' . "\n";
 
 
 
 
 
108
  }
109
  ?>
110
  </select>
@@ -117,7 +122,7 @@ class CnbProfileEdit {
117
  <td>
118
  <input type="hidden" name="user[euvatbusiness]" value="0">
119
  <input id="cnb-euvatbusiness" type="checkbox" name="user[euvatbusiness]" value="1"
120
- <?php if ( ! empty( $cnb_user->taxIds[0]->value ) ) { ?>checked="checked"<?php } ?>
121
  class="ltr cnb_eu_values_only">
122
  <label for="cnb-euvatbusiness">Yes</label>
123
  </td>
100
  <option value=""></option>
101
  <?php
102
  foreach ( $controller->get_stripe_countries() as $country ) {
103
+ $user_country = '';
104
  if ( isset( $cnb_user->address ) ) {
105
+ $user_country = $cnb_user->address->country;
106
  }
107
+ /** @noinspection HtmlUnknownAttribute */
108
+ echo sprintf( '<option value="%1$s"%2$s>%3$s</option>',
109
+ esc_attr( $country['code'] ),
110
+ selected( $country['code'], $user_country ),
111
+ esc_html( $country['country'] )
112
+ );
113
  }
114
  ?>
115
  </select>
122
  <td>
123
  <input type="hidden" name="user[euvatbusiness]" value="0">
124
  <input id="cnb-euvatbusiness" type="checkbox" name="user[euvatbusiness]" value="1"
125
+ <?php checked( ! empty( $cnb_user->taxIds[0]->value ) ) ?>
126
  class="ltr cnb_eu_values_only">
127
  <label for="cnb-euvatbusiness">Yes</label>
128
  </td>
src/admin/settings/CnbApiKeyActivatedView.php CHANGED
@@ -38,40 +38,38 @@ class CnbApiKeyActivatedView {
38
  */
39
  private function renderButtonCreated() {
40
  $message = '<p>Your existing button has been migrated.</p>';
41
- CnbAdminNotices::get_instance()->renderSuccess($message);
42
  }
43
 
44
  private function getAllButtonsLink() {
45
- $url = admin_url( 'admin.php' );
46
- $new_link =
47
- add_query_arg(
48
- array(
49
- 'page' => 'call-now-button',
50
- ),
51
- $url );
52
- return esc_url( $new_link );
53
  }
54
 
55
  private function getNewButtonLink() {
56
- $url = admin_url( 'admin.php' );
57
- $new_link =
58
- add_query_arg(
59
- array(
60
- 'page' => 'call-now-button',
61
- 'action' => 'new'
62
- ),
63
- $url );
64
- return esc_url( $new_link );
65
  }
66
 
67
  private function getSettingsLink() {
68
- $url = admin_url( 'admin.php' );
69
- $new_link = add_query_arg(
 
70
  array(
71
  'page' => 'call-now-button-settings',
72
  ),
73
  $url );
74
- return esc_url( $new_link );
75
  }
76
 
77
  private function renderButtonInfo() {
@@ -97,7 +95,7 @@ class CnbApiKeyActivatedView {
97
  private function renderActivationSuccess() {
98
  echo '<div style="text-align: center;">';
99
  echo '<div style="width:200px;margin: 0 auto;">';
100
- echo ( new CnbDomainViewUpgradeFinished() )->getBigYaySvg();
101
  echo '</div>';
102
  echo '<h1>You have successfully upgraded to Call Now Button PREMIUM</h1>';
103
  echo '</div>';
@@ -105,12 +103,12 @@ class CnbApiKeyActivatedView {
105
 
106
  private function renderGetStarted() {
107
  $domain = $this->activation->domain;
108
- if ($domain === null) {
109
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
110
  }
111
- $nonce_field = wp_nonce_field('cnb_update_domain_timezone', '_wpnonce', true, false);
112
- $timezoneSelect =(new CnbDomainViewEdit())->getTimezoneSelect($domain);
113
- echo sprintf('
114
  <div class="cnb-get-started cnb-plan-features cnb-center top-50">
115
  <h1 class="cnb-center">Let\'s get started</h1>
116
  <div class="cnb-flexbox">
@@ -135,7 +133,13 @@ class CnbApiKeyActivatedView {
135
  </div>
136
  </div>
137
  </div>',
138
- $this->getNewButtonLink(), $this->getAllButtonsLink(), $this->getSettingsLink(), $timezoneSelect, $nonce_field);
 
 
 
 
 
 
139
  }
140
 
141
  /**
@@ -144,16 +148,16 @@ class CnbApiKeyActivatedView {
144
  */
145
  private function renderUpgradeToPro() {
146
  $domain = $this->activation->domain;
147
- if ($domain === null) {
148
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
149
  }
150
- if ($domain->type !== "FREE") {
151
  // Already upgraded, so skip all of this
152
  return;
153
  }
154
  echo '<div class="cnb-plan-features cnb-center top-50">';
155
  echo '<h1>Upgrade to PRO to remove the branding</h1>';
156
- (new CnbDomainViewUpgradeOverview())->renderUpgradeForm( $domain );
157
  echo '</div>';
158
  }
159
 
@@ -162,9 +166,10 @@ class CnbApiKeyActivatedView {
162
  *
163
  * @return void
164
  */
165
- private function renderActivationFailure($user) {
166
  if ( ! is_wp_error( $user ) ) {
167
  echo '<div style="text-align: center"><h2>Premium is already active</h2></div>';
 
168
  return;
169
  }
170
 
@@ -174,19 +179,19 @@ class CnbApiKeyActivatedView {
174
  private function renderBenefits() {
175
  echo '<div>';
176
  echo '<h2 class="cnb-center">You now have access to the following functionality:</h2>';
177
- echo (new CnbDomainViewUpgradeOverview())->getBenefits();
178
  echo '</div>';
179
  }
180
 
181
  private function renderActivationStatus() {
182
  $user = CnbAppRemote::cnb_remote_get_user_info();
183
- if ( $this->activation->success) {
184
  $this->renderActivationSuccess();
185
  }
186
- if ( !$this->activation->success && !is_wp_error($user)) {
187
  echo '<div style="text-align: center"><h1>Call Now Button Premium is already active</h1></div>';
188
  }
189
- if ( $this->activation->success || !is_wp_error($user) ) {
190
  $this->renderBenefits();
191
  $this->renderGetStarted();
192
  $this->renderUpgradeToPro();
@@ -197,7 +202,7 @@ class CnbApiKeyActivatedView {
197
 
198
  public function render() {
199
  add_action( 'cnb_header_name', array( $this, 'header' ) );
200
- wp_enqueue_script(CNB_SLUG . '-settings-activated');
201
  wp_enqueue_script( CNB_SLUG . '-profile' );
202
  wp_enqueue_script( CNB_SLUG . '-domain-upgrade' );
203
  wp_enqueue_script( CNB_SLUG . '-timezone-picker-fix' );
38
  */
39
  private function renderButtonCreated() {
40
  $message = '<p>Your existing button has been migrated.</p>';
41
+ CnbAdminNotices::get_instance()->renderSuccess( $message );
42
  }
43
 
44
  private function getAllButtonsLink() {
45
+ $url = admin_url( 'admin.php' );
46
+
47
+ return add_query_arg(
48
+ array(
49
+ 'page' => 'call-now-button',
50
+ ),
51
+ $url );
 
52
  }
53
 
54
  private function getNewButtonLink() {
55
+ $url = admin_url( 'admin.php' );
56
+
57
+ return add_query_arg(
58
+ array(
59
+ 'page' => 'call-now-button',
60
+ 'action' => 'new'
61
+ ),
62
+ $url );
 
63
  }
64
 
65
  private function getSettingsLink() {
66
+ $url = admin_url( 'admin.php' );
67
+
68
+ return add_query_arg(
69
  array(
70
  'page' => 'call-now-button-settings',
71
  ),
72
  $url );
 
73
  }
74
 
75
  private function renderButtonInfo() {
95
  private function renderActivationSuccess() {
96
  echo '<div style="text-align: center;">';
97
  echo '<div style="width:200px;margin: 0 auto;">';
98
+ ( new CnbDomainViewUpgradeFinished() )->echoBigYaySvg();
99
  echo '</div>';
100
  echo '<h1>You have successfully upgraded to Call Now Button PREMIUM</h1>';
101
  echo '</div>';
103
 
104
  private function renderGetStarted() {
105
  $domain = $this->activation->domain;
106
+ if ( $domain === null ) {
107
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
108
  }
109
+ $nonce_field = wp_nonce_field( 'cnb_update_domain_timezone', '_wpnonce', true, false );
110
+ $timezoneSelect = ( new CnbDomainViewEdit() )->getTimezoneSelect( $domain );
111
+ echo sprintf( '
112
  <div class="cnb-get-started cnb-plan-features cnb-center top-50">
113
  <h1 class="cnb-center">Let\'s get started</h1>
114
  <div class="cnb-flexbox">
133
  </div>
134
  </div>
135
  </div>',
136
+ esc_url( $this->getNewButtonLink() ),
137
+ esc_url( $this->getAllButtonsLink() ),
138
+ esc_url( $this->getSettingsLink() ),
139
+ // phpcs:ignore WordPress.Security
140
+ $timezoneSelect,
141
+ // phpcs:ignore WordPress.Security
142
+ $nonce_field );
143
  }
144
 
145
  /**
148
  */
149
  private function renderUpgradeToPro() {
150
  $domain = $this->activation->domain;
151
+ if ( $domain === null ) {
152
  $domain = CnbAppRemote::cnb_remote_get_wp_domain();
153
  }
154
+ if ( $domain->type !== 'FREE' ) {
155
  // Already upgraded, so skip all of this
156
  return;
157
  }
158
  echo '<div class="cnb-plan-features cnb-center top-50">';
159
  echo '<h1>Upgrade to PRO to remove the branding</h1>';
160
+ ( new CnbDomainViewUpgradeOverview() )->renderUpgradeForm( $domain );
161
  echo '</div>';
162
  }
163
 
166
  *
167
  * @return void
168
  */
169
+ private function renderActivationFailure( $user ) {
170
  if ( ! is_wp_error( $user ) ) {
171
  echo '<div style="text-align: center"><h2>Premium is already active</h2></div>';
172
+
173
  return;
174
  }
175
 
179
  private function renderBenefits() {
180
  echo '<div>';
181
  echo '<h2 class="cnb-center">You now have access to the following functionality:</h2>';
182
+ ( new CnbDomainViewUpgradeOverview() )->renderBenefits();
183
  echo '</div>';
184
  }
185
 
186
  private function renderActivationStatus() {
187
  $user = CnbAppRemote::cnb_remote_get_user_info();
188
+ if ( $this->activation->success ) {
189
  $this->renderActivationSuccess();
190
  }
191
+ if ( ! $this->activation->success && ! is_wp_error( $user ) ) {
192
  echo '<div style="text-align: center"><h1>Call Now Button Premium is already active</h1></div>';
193
  }
194
+ if ( $this->activation->success || ! is_wp_error( $user ) ) {
195
  $this->renderBenefits();
196
  $this->renderGetStarted();
197
  $this->renderUpgradeToPro();
202
 
203
  public function render() {
204
  add_action( 'cnb_header_name', array( $this, 'header' ) );
205
+ wp_enqueue_script( CNB_SLUG . '-settings-activated' );
206
  wp_enqueue_script( CNB_SLUG . '-profile' );
207
  wp_enqueue_script( CNB_SLUG . '-domain-upgrade' );
208
  wp_enqueue_script( CNB_SLUG . '-timezone-picker-fix' );
src/admin/settings/CnbSettingsController.php CHANGED
@@ -26,38 +26,36 @@ class CnbSettingsController {
26
  */
27
  public static function get_defaults() {
28
  $defaults = array(
29
- 'active' => 0,
30
- 'number' => '',
31
- 'text' => '',
32
- 'color' => '#00bb00',
33
- 'iconcolor' => '#ffffff',
34
- 'appearance' => 'right',
35
- 'hideIcon' => 0,
36
- 'limit' => 'include',
37
- 'frontpage' => 0,
38
- 'conversions' => 0,
39
- 'zoom' => 1,
40
- 'z-index' => 10,
41
- 'tracking' => 0,
42
- 'show' => '',
43
- 'version' => CNB_VERSION,
44
- 'changelog_version' => CNB_VERSION,
45
- 'cloud_enabled' => 0,
46
- 'classic' => 0,
47
- 'advanced_view' => 0,
48
  'show_all_buttons_for_domain' => 0,
49
- 'footer_show_traces' => 0,
50
- 'api_caching' => 0,
51
 
52
  );
53
 
54
- return self::post_option_cnb($defaults);
55
  }
56
 
57
  /**
58
  * This gets the current Call Now Button settings and fixes some entries to be properly cast to their type.
59
  * For example, active will be an int (1 or 2), regardless of the DB has it as an int or string.
60
-
61
  * There are a few global used throughout the plugin.
62
  *
63
  * All are named `cnb_*` so not to collide with others.
@@ -66,9 +64,8 @@ class CnbSettingsController {
66
  *
67
  * @return array
68
  */
69
- public static function post_option_cnb($cnb_options) {
70
  $cnb_options['active'] = isset( $cnb_options['active'] ) && $cnb_options['active'] == 1 ? 1 : 0;
71
- $cnb_options['classic'] = isset( $cnb_options['classic'] ) && $cnb_options['classic'] == 1 ? 1 : 0;
72
  $cnb_options['hideIcon'] = isset( $cnb_options['hideIcon'] ) && $cnb_options['hideIcon'] == 1 ? 1 : 0;
73
  $cnb_options['frontpage'] = isset( $cnb_options['frontpage'] ) && $cnb_options['frontpage'] == 1 ? 1 : 0;
74
  $cnb_options['advanced_view'] = isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ? 1 : 0;
@@ -76,7 +73,7 @@ class CnbSettingsController {
76
  $cnb_options['footer_show_traces'] = isset( $cnb_options['footer_show_traces'] ) && $cnb_options['footer_show_traces'] == 1 ? 1 : 0;
77
  $cnb_options['api_caching'] = isset( $cnb_options['api_caching'] ) && $cnb_options['api_caching'] == 1 ? 1 : 0;
78
  $cnb_options['conversions'] = isset( $cnb_options['conversions'] ) && ( $cnb_options['conversions'] == 1 || $cnb_options['conversions'] == 2 ) ? (int) $cnb_options['conversions'] : 0;
79
- $cnb_options['cloud_enabled'] = (new CnbUtils())->isCloudActive($cnb_options );
80
 
81
  return $cnb_options;
82
  }
@@ -86,7 +83,7 @@ class CnbSettingsController {
86
  *
87
  * @return string cloud, enabled or legacy
88
  */
89
- public static function getStatus($cnb_options) {
90
  return $cnb_options['cloud_enabled'] ? 'cloud' : ( $cnb_options['active'] ? 'enabled' : 'disabled' );
91
  }
92
 
@@ -102,6 +99,7 @@ class CnbSettingsController {
102
  $messages = array();
103
 
104
  // Cloud Domain settings can be set here as well
 
105
  if ( array_key_exists( 'domain', $_POST ) &&
106
  array_key_exists( 'cloud_enabled', $input ) &&
107
  $input['cloud_enabled'] == 1 ) {
@@ -180,7 +178,7 @@ class CnbSettingsController {
180
  set_transient( $transient_id, $messages, HOUR_IN_SECONDS );
181
 
182
  // We do not actually store this value in the DB!
183
- unset($updated_options['status']);
184
 
185
  return $updated_options;
186
  }
@@ -198,6 +196,7 @@ class CnbSettingsController {
198
  if ( $input['active'] == 1 && $cloud_enabled == 0 && empty( $number ) ) {
199
  return new WP_Error( 'CNB_PHONE_NUMBER_MISSING', 'Please enter a phone number before enabling your button.' );
200
  }
 
201
  return null;
202
  }
203
 
@@ -206,32 +205,34 @@ class CnbSettingsController {
206
  *
207
  * @return mixed|string|null
208
  */
209
- private function getApiKey($result) {
210
  // Parse special header(s)
211
- $api_key = null;
212
  $api_key_direct = filter_input( INPUT_GET, 'api_key', FILTER_SANITIZE_STRING );
213
  $api_key_ott = filter_input( INPUT_GET, 'api_key_ott', FILTER_SANITIZE_STRING );
214
 
215
  if ( ! empty( $api_key_direct ) ) {
216
- $api_key = $api_key_direct;
217
  $result->activation_attempt = true;
218
  }
219
 
220
  if ( ! empty( $api_key_ott ) ) {
221
- $api_key = $this->get_api_key_from_ott( $api_key_ott );
222
  $result->activation_attempt = true;
223
  }
 
224
  return $api_key;
225
  }
 
226
  /**
227
  * @return CnbActivation
228
  */
229
  public function parseApiAndOttHeader() {
230
- $cnb_options = get_option('cnb');
231
- $adminCloud = new CnbAdminCloud();
232
- $result = new CnbActivation();
233
 
234
- $api_key = $this->getApiKey($result);
235
 
236
  // In case:
237
  // - there already is an API key (so no need to update)
@@ -239,8 +240,8 @@ class CnbSettingsController {
239
  // - the cloud is disabled (for some reason)
240
  // Then this re-enables it (and shows a warning that we did that)
241
  if ( ! empty( $cnb_options['api_key'] ) && $api_key && $cnb_options['cloud_enabled'] != 1 ) {
242
- CnbAdminNotices::get_instance()->warning( "<p>You have followed a link, but an API key is already present or the token has expired.</p><p>We have enabled <strong>Premium</strong>, but did not change the already present API key.</p>" );
243
- $options = array();
244
  $options['cloud_enabled'] = 1;
245
  update_option( 'cnb', $options );
246
 
@@ -256,8 +257,8 @@ class CnbSettingsController {
256
  // - Check the key for validity
257
  // - If valid, enable cloud, set the API key, update domain/button
258
  if ( empty( $cnb_options['api_key'] ) && $api_key ) {
259
- if ( !$api_key_valid ) {
260
- CnbAdminNotices::get_instance()->error( "<p>This API key is invalid.</p>" );
261
  $result->activation_attempt = true;
262
  $result->success = false;
263
 
@@ -273,13 +274,13 @@ class CnbSettingsController {
273
  // set "migration done"
274
  // We should really only do this once, so we need to save something in the settings to stop continuous migration.
275
  add_option( 'cnb_cloud_migration_done', true );
276
- CnbAdminNotices::get_instance()->success( '<p>Successfully connected to your Call Now Button account.</p>');
277
  }
278
 
279
  // If an API key was passed (no matter the status of activation)
280
- if ($api_key && $api_key_valid) {
281
  $migration = new CnbMigration();
282
- $migration->createOrUpdateDomainAndButton($result);
283
  }
284
 
285
  return $result;
@@ -298,7 +299,7 @@ class CnbSettingsController {
298
  }
299
 
300
  // Special case for expired OTTs
301
- if (is_wp_error($api_key_obj)) {
302
  $code = 'CNB_ERROR';
303
  if ( $api_key_obj->get_error_code() === $code ) {
304
  $messages = $api_key_obj->get_error_messages( $code );
26
  */
27
  public static function get_defaults() {
28
  $defaults = array(
29
+ 'active' => 0,
30
+ 'number' => '',
31
+ 'text' => '',
32
+ 'color' => '#00bb00',
33
+ 'iconcolor' => '#ffffff',
34
+ 'appearance' => 'right',
35
+ 'hideIcon' => 0,
36
+ 'limit' => 'include',
37
+ 'frontpage' => 0,
38
+ 'conversions' => 0,
39
+ 'zoom' => 1,
40
+ 'z-index' => 10,
41
+ 'tracking' => 0,
42
+ 'show' => '',
43
+ 'version' => CNB_VERSION,
44
+ 'changelog_version' => CNB_VERSION,
45
+ 'cloud_enabled' => 0,
46
+ 'advanced_view' => 0,
 
47
  'show_all_buttons_for_domain' => 0,
48
+ 'footer_show_traces' => 0,
49
+ 'api_caching' => 0,
50
 
51
  );
52
 
53
+ return self::post_option_cnb( $defaults );
54
  }
55
 
56
  /**
57
  * This gets the current Call Now Button settings and fixes some entries to be properly cast to their type.
58
  * For example, active will be an int (1 or 2), regardless of the DB has it as an int or string.
 
59
  * There are a few global used throughout the plugin.
60
  *
61
  * All are named `cnb_*` so not to collide with others.
64
  *
65
  * @return array
66
  */
67
+ public static function post_option_cnb( $cnb_options ) {
68
  $cnb_options['active'] = isset( $cnb_options['active'] ) && $cnb_options['active'] == 1 ? 1 : 0;
 
69
  $cnb_options['hideIcon'] = isset( $cnb_options['hideIcon'] ) && $cnb_options['hideIcon'] == 1 ? 1 : 0;
70
  $cnb_options['frontpage'] = isset( $cnb_options['frontpage'] ) && $cnb_options['frontpage'] == 1 ? 1 : 0;
71
  $cnb_options['advanced_view'] = isset( $cnb_options['advanced_view'] ) && $cnb_options['advanced_view'] == 1 ? 1 : 0;
73
  $cnb_options['footer_show_traces'] = isset( $cnb_options['footer_show_traces'] ) && $cnb_options['footer_show_traces'] == 1 ? 1 : 0;
74
  $cnb_options['api_caching'] = isset( $cnb_options['api_caching'] ) && $cnb_options['api_caching'] == 1 ? 1 : 0;
75
  $cnb_options['conversions'] = isset( $cnb_options['conversions'] ) && ( $cnb_options['conversions'] == 1 || $cnb_options['conversions'] == 2 ) ? (int) $cnb_options['conversions'] : 0;
76
+ $cnb_options['cloud_enabled'] = ( new CnbUtils() )->isCloudActive( $cnb_options );
77
 
78
  return $cnb_options;
79
  }
83
  *
84
  * @return string cloud, enabled or legacy
85
  */
86
+ public static function getStatus( $cnb_options ) {
87
  return $cnb_options['cloud_enabled'] ? 'cloud' : ( $cnb_options['active'] ? 'enabled' : 'disabled' );
88
  }
89
 
99
  $messages = array();
100
 
101
  // Cloud Domain settings can be set here as well
102
+ // phpcs:ignore WordPress.Security
103
  if ( array_key_exists( 'domain', $_POST ) &&
104
  array_key_exists( 'cloud_enabled', $input ) &&
105
  $input['cloud_enabled'] == 1 ) {
178
  set_transient( $transient_id, $messages, HOUR_IN_SECONDS );
179
 
180
  // We do not actually store this value in the DB!
181
+ unset( $updated_options['status'] );
182
 
183
  return $updated_options;
184
  }
196
  if ( $input['active'] == 1 && $cloud_enabled == 0 && empty( $number ) ) {
197
  return new WP_Error( 'CNB_PHONE_NUMBER_MISSING', 'Please enter a phone number before enabling your button.' );
198
  }
199
+
200
  return null;
201
  }
202
 
205
  *
206
  * @return mixed|string|null
207
  */
208
+ private function getApiKey( $result ) {
209
  // Parse special header(s)
210
+ $api_key = null;
211
  $api_key_direct = filter_input( INPUT_GET, 'api_key', FILTER_SANITIZE_STRING );
212
  $api_key_ott = filter_input( INPUT_GET, 'api_key_ott', FILTER_SANITIZE_STRING );
213
 
214
  if ( ! empty( $api_key_direct ) ) {
215
+ $api_key = $api_key_direct;
216
  $result->activation_attempt = true;
217
  }
218
 
219
  if ( ! empty( $api_key_ott ) ) {
220
+ $api_key = $this->get_api_key_from_ott( $api_key_ott );
221
  $result->activation_attempt = true;
222
  }
223
+
224
  return $api_key;
225
  }
226
+
227
  /**
228
  * @return CnbActivation
229
  */
230
  public function parseApiAndOttHeader() {
231
+ $cnb_options = get_option( 'cnb' );
232
+ $adminCloud = new CnbAdminCloud();
233
+ $result = new CnbActivation();
234
 
235
+ $api_key = $this->getApiKey( $result );
236
 
237
  // In case:
238
  // - there already is an API key (so no need to update)
240
  // - the cloud is disabled (for some reason)
241
  // Then this re-enables it (and shows a warning that we did that)
242
  if ( ! empty( $cnb_options['api_key'] ) && $api_key && $cnb_options['cloud_enabled'] != 1 ) {
243
+ CnbAdminNotices::get_instance()->warning( '<p>You have followed a link, but an API key is already present or the token has expired.</p><p>We have enabled <strong>Premium</strong>, but did not change the already present API key.</p>' );
244
+ $options = array();
245
  $options['cloud_enabled'] = 1;
246
  update_option( 'cnb', $options );
247
 
257
  // - Check the key for validity
258
  // - If valid, enable cloud, set the API key, update domain/button
259
  if ( empty( $cnb_options['api_key'] ) && $api_key ) {
260
+ if ( ! $api_key_valid ) {
261
+ CnbAdminNotices::get_instance()->error( '<p>This API key is invalid.</p>' );
262
  $result->activation_attempt = true;
263
  $result->success = false;
264
 
274
  // set "migration done"
275
  // We should really only do this once, so we need to save something in the settings to stop continuous migration.
276
  add_option( 'cnb_cloud_migration_done', true );
277
+ CnbAdminNotices::get_instance()->success( '<p>Successfully connected to your Call Now Button account.</p>' );
278
  }
279
 
280
  // If an API key was passed (no matter the status of activation)
281
+ if ( $api_key && $api_key_valid ) {
282
  $migration = new CnbMigration();
283
+ $migration->createOrUpdateDomainAndButton( $result );
284
  }
285
 
286
  return $result;
299
  }
300
 
301
  // Special case for expired OTTs
302
+ if ( is_wp_error( $api_key_obj ) ) {
303
  $code = 'CNB_ERROR';
304
  if ( $api_key_obj->get_error_code() === $code ) {
305
  $messages = $api_key_obj->get_error_messages( $code );
src/admin/settings/CnbSettingsRouter.php CHANGED
@@ -17,10 +17,11 @@ class CnbSettingsRouter {
17
 
18
  $activation = $controller->parseApiAndOttHeader();
19
 
20
- if ($activation->activation_attempt) {
21
  $view = new CnbApiKeyActivatedView();
22
- $view->setActivation($activation);
23
  $view->render();
 
24
  return;
25
  }
26
 
17
 
18
  $activation = $controller->parseApiAndOttHeader();
19
 
20
+ if ( $activation->activation_attempt ) {
21
  $view = new CnbApiKeyActivatedView();
22
+ $view->setActivation( $activation );
23
  $view->render();
24
+
25
  return;
26
  }
27
 
src/admin/settings/CnbSettingsViewEdit.php CHANGED
@@ -21,26 +21,23 @@ class CnbSettingsViewEdit {
21
  }
22
 
23
  private function create_tab_url( $tab ) {
24
- $url = admin_url( 'admin.php' );
25
- $tab_link =
26
- add_query_arg(
27
- array(
28
- 'page' => 'call-now-button-settings',
29
- 'tab' => $tab
30
- ),
31
- $url );
32
-
33
- return esc_url_raw( $tab_link );
34
  }
35
 
36
- /**
37
  * This is only rendered on the /legacy/ version of the Plugin
38
  *
39
- * @return void
40
- */
41
  private function render_legacy_options() {
42
- $cnb_options = get_option('cnb');
43
- $view = new CnbLegacyEdit();
44
  ?>
45
  <tr>
46
  <th colspan="2"><h2>Tracking</h2></th>
@@ -55,23 +52,6 @@ class CnbSettingsViewEdit {
55
  <?php
56
  $view->render_zoom();
57
  $view->render_zindex();
58
-
59
- if ( $cnb_options['classic'] == 1 ) { ?>
60
- <tr class="classic">
61
- <th scope="row">Classic button: <a
62
- href="https://callnowbutton.com/new-button-design/<?php (new CnbUtils())->cnb_utm_params( "question-mark", "new-button-design" ); ?>"
63
- target="_blank" class="cnb-nounderscore">
64
- <span class="dashicons dashicons-editor-help"></span>
65
- </a></th>
66
- <td>
67
- <input type="hidden" name="cnb[classic]" value="0"/>
68
- <input id="classic" name="cnb[classic]" type="checkbox"
69
- value="1" <?php checked( '1', $cnb_options['classic'] ); ?> /> <label
70
- title="Enable" for="classic">Active</label>
71
- </td>
72
- </tr>
73
- <?php
74
- }
75
  }
76
 
77
  /**
@@ -81,13 +61,13 @@ class CnbSettingsViewEdit {
81
  */
82
  private function render_account_options( $cnb_user ) {
83
  global $wp_version;
84
- $cnb_options = get_option('cnb');
85
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
86
- $adminFunctions = new CnbAdminFunctions();
87
 
88
  ?>
89
  <table data-tab-name="account_options"
90
- class="form-table <?php echo $adminFunctions->is_active_tab( 'account_options' ); ?>">
91
  <tr>
92
  <th colspan="2"></th>
93
  </tr>
@@ -101,7 +81,7 @@ class CnbSettingsViewEdit {
101
  placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/>
102
  </label>
103
  <p class="description">Get your API key at <a
104
- href="<?php echo CNB_WEBSITE ?>"><?php echo CNB_WEBSITE ?></a>
105
  </p>
106
  <?php } ?>
107
  <?php if ( is_wp_error( $cnb_user ) && ! empty( $cnb_options['api_key'] ) ) { ?>
@@ -114,14 +94,14 @@ class CnbSettingsViewEdit {
114
  <br>
115
  <input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
116
  class="button button-link"
117
- value="<?php _e( 'Disconnect account' ) ?>"
118
  onclick="return cnb_delete_apikey();">
119
  </p>
120
  <?php } ?>
121
  <?php if ( ! is_wp_error( $cnb_user ) && isset( $cnb_options['api_key'] ) ) {
122
  $icon = version_compare( $wp_version, '5.5.0', '<' ) ? 'dashicons-yes' : 'dashicons-saved';
123
  ?>
124
- <p><strong><span class="dashicons <?php echo $icon ?>"></span>Success!</strong>
125
  <Br>The plugin is connected to your callnowbutton.com account.</p>
126
  <p class="description">Clicking "Disconnect account" will drop the API key
127
  and disconnect the plugin from your account. You will lose access to
@@ -130,7 +110,7 @@ class CnbSettingsViewEdit {
130
  <br>
131
  <input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
132
  class="button button-link"
133
- value="<?php _e( 'Disconnect account' ) ?>"
134
  onclick="return cnb_delete_apikey();">
135
  </p>
136
  <input type="hidden" name="cnb[api_key]" id="cnb_api_key" value="delete_me"
@@ -160,16 +140,16 @@ class CnbSettingsViewEdit {
160
  }
161
 
162
  private function render_advanced_options( $cnb_cloud_domain, $cnb_user ) {
163
- $cnb_options = get_option('cnb');
164
 
165
- $adminFunctions = new CnbAdminFunctions();
166
  $cnbAppRemote = new CnbAppRemote();
167
  $cnb_clean_site_url = $cnbAppRemote->cnb_clean_site_url();
168
  $cnb_cloud_domains = CnbAppRemote::cnb_remote_get_domains();
169
- $status = CnbSettingsController::getStatus($cnb_options);
170
  ?>
171
  <table data-tab-name="advanced_options"
172
- class="form-table <?php echo $adminFunctions->is_active_tab( 'advanced_options' ); ?>">
173
  <?php if ( isset( $cnb_cloud_domain ) && ! ( $cnb_cloud_domain instanceof WP_Error ) && $status === 'cloud' ) {
174
  ?>
175
  <tr>
@@ -225,28 +205,36 @@ class CnbSettingsViewEdit {
225
  <label><select name="cnb[cloud_use_id]" id="cnb[cloud_use_id]">
226
 
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  <option
229
- value="<?php echo esc_attr( $cnb_user->id ) ?>"
230
- <?php selected( $cnb_user->id, $cnb_options['cloud_use_id'] ) ?>
231
  >
232
- Full account (all domains)
 
233
  </option>
234
-
235
- <?php
236
- $loop_domains = array_filter($cnb_cloud_domains, function($domain) use ( $cnb_options, $cnb_clean_site_url ) {
237
- if ($cnb_options['advanced_view'] != 0) return true; // In case of advanced mode, show all
238
- if ($domain->name === $cnb_clean_site_url) return true; // Always show the current domain
239
- if ($domain->id === $cnb_options['cloud_use_id']) return true; // If a previous weird option was selected, allow it
240
- return false;
241
- });
242
- foreach ( $loop_domains as $domain ) { ?>
243
- <option
244
- value="<?php echo esc_attr( $domain->id ) ?>"
245
- <?php selected( $domain->id, $cnb_options['cloud_use_id'] ) ?>
246
- >
247
- <?php echo esc_html( $domain->name ) ?>
248
- (single domain)</option>
249
- <?php } ?>
250
 
251
  </select></label>
252
  <?php } ?>
@@ -275,7 +263,7 @@ class CnbSettingsViewEdit {
275
  <td><label>
276
  <input type="text" id="cnb[api_base]" name="cnb[api_base]"
277
  class="regular-text"
278
- value="<?php echo CnbAppRemote::cnb_get_api_base() ?>"/>
279
  </label>
280
  <p class="description">The API endpoint to use to communicate with the
281
  CallNowButton Cloud service.<br/>
@@ -312,28 +300,28 @@ class CnbSettingsViewEdit {
312
  private function render_promos( $use_cloud, $cnb_cloud_domain ) {
313
  echo '<div class="cnb-postbox-container cnb-side-column">';
314
  if ( ! $use_cloud ) {
315
- (new CnbAdminFunctions())->cnb_promobox(
316
- 'blue',
317
  'Phones off at 6pm?',
318
  '<p>Sign up to enable a scheduler that allows you to set the days and hours that you are available.</p>' .
319
  '<p>You can even replace it with an email button during your off-hours so people can still contact you.</p>',
320
  'clock',
321
- '<strong>Try it, it\'s free!</strong>',
322
  'Learn more',
323
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
324
  );
325
- (new CnbAdminFunctions())->cnb_promobox(
326
- 'blue',
327
  'More buttons!',
328
  'Switch to Premium to enable lots of buttons. Coupled with advanced page selection options you can get really creative.</p>' .
329
  '<p>If you need more phone numbers on a single page, then the Multibutton&trade; and the Buttonbar&trade; give you exactly what you need.</p>',
330
  'cloud',
331
  '<strong>Try it out!</strong>',
332
  'Learn more',
333
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
334
  );
335
- (new CnbAdminFunctions())->cnb_promobox(
336
- 'blue',
337
  'Get Premium for FREE!',
338
  'Premium adds a ton of extra power to the Call Now Button.</p>' .
339
  '<p>The Premium Free plan shows a little branding with your buttons but gives you access to all features.</p>' .
@@ -341,19 +329,19 @@ class CnbSettingsViewEdit {
341
  'money-alt',
342
  '',
343
  'See what\'s incuded',
344
- (new CnbAdminFunctions())->cnb_legacy_upgrade_page()
345
  );
346
  }
347
  if ( $use_cloud && isset( $cnb_cloud_domain ) && ! is_wp_error( $cnb_cloud_domain ) && $cnb_cloud_domain->type !== 'PRO' ) {
348
- (new CnbAdminFunctions())->cnb_promobox(
349
- 'blue',
350
- 'Introduction offer',
351
  '<p>Remove the <em>powered by</em> branding from your buttons!</p>' .
352
- '<p>Benefit from our introductory offer and enjoy unlimited access to all features without our branding.</p>',
353
  'flag',
354
  '<strong>&euro;<span class="eur-per-month"></span>/$<span class="usd-per-month"></span> per month</strong>',
355
  'Upgrade',
356
- (new CnbUtils())->get_cnb_domain_upgrade( $cnb_cloud_domain )
357
  );
358
  }
359
  echo '</div>';
@@ -366,7 +354,7 @@ class CnbSettingsViewEdit {
366
  * @return void
367
  */
368
  private function render_premium_option( $cloud_successful, $cnb_cloud_domain ) {
369
- $cnb_options = get_option('cnb');
370
  ?>
371
  <tr>
372
  <th colspan="2"></th>
@@ -375,7 +363,8 @@ class CnbSettingsViewEdit {
375
  <th scope="row">
376
  <label for="cnb_cloud_enabled">Premium
377
  <?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
378
- <a href="<?php echo (new CnbAdminFunctions())->cnb_legacy_upgrade_page(); ?>" class="cnb-nounderscore">
 
379
  <span class="dashicons dashicons-editor-help"></span>
380
  </a>
381
  <?php } ?>
@@ -393,13 +382,15 @@ class CnbSettingsViewEdit {
393
  class="cnb_toggle_state cnb_toggle_true">Active</span>
394
  <?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
395
  <p class="description">Free and paid options available.
396
- <a href="<?php echo (new CnbAdminFunctions())->cnb_legacy_upgrade_page(); ?>">Learn more</a>
 
397
  </p>
398
  <?php } ?>
399
 
400
  <?php if ( $cnb_options['cloud_enabled'] == 1 && $cloud_successful && $cnb_cloud_domain->type !== 'PRO' ) { ?>
401
  <p class="description">Free and paid options available.
402
- <a href="<?php echo (new CnbUtils())->get_cnb_domain_upgrade( $cnb_cloud_domain ); ?>">Learn more</a>
 
403
  </p>
404
  <?php } ?>
405
  </td>
@@ -408,7 +399,7 @@ class CnbSettingsViewEdit {
408
  }
409
 
410
  function render() {
411
- $cnb_options = get_option('cnb');
412
 
413
  $adminFunctions = new CnbAdminFunctions();
414
 
@@ -419,8 +410,8 @@ class CnbSettingsViewEdit {
419
 
420
  $cnb_cloud_domain = null;
421
  $cnb_user = null;
422
- $use_cloud = (new CnbUtils())->is_use_cloud( $cnb_options );
423
- $status = CnbSettingsController::getStatus($cnb_options);
424
 
425
  if ( $use_cloud ) {
426
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
@@ -451,22 +442,22 @@ class CnbSettingsViewEdit {
451
  <div class="cnb-body-content">
452
  <h2 class="nav-tab-wrapper">
453
  <a data-tab-name="basic_options"
454
- href="<?php echo $this->create_tab_url( 'basic_options' ) ?>"
455
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'basic_options' ) ?>">General</a>
456
  <?php if ( $use_cloud ) { ?>
457
  <a data-tab-name="account_options"
458
- href="<?php echo $this->create_tab_url( 'account_options' ) ?>"
459
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'account_options' ) ?>">Account</a>
460
  <a data-tab-name="advanced_options"
461
- href="<?php echo $this->create_tab_url( 'advanced_options' ) ?>"
462
- class="nav-tab <?php echo $adminFunctions->is_active_tab( 'advanced_options' ) ?>">Advanced</a>
463
  <?php } ?>
464
  </h2>
465
  <form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ); ?>"
466
  class="cnb-container">
467
  <?php settings_fields( 'cnb_options' ); ?>
468
  <table data-tab-name="basic_options"
469
- class="form-table <?php echo $adminFunctions->is_active_tab( 'basic_options' ); ?>">
470
  <?php
471
  $this->render_premium_option( $cloud_successful, $cnb_cloud_domain );
472
  if ( $status !== 'cloud' ) {
21
  }
22
 
23
  private function create_tab_url( $tab ) {
24
+ $url = admin_url( 'admin.php' );
25
+
26
+ return add_query_arg(
27
+ array(
28
+ 'page' => 'call-now-button-settings',
29
+ 'tab' => $tab
30
+ ),
31
+ $url );
 
 
32
  }
33
 
34
+ /**
35
  * This is only rendered on the /legacy/ version of the Plugin
36
  *
37
+ * @return void
38
+ */
39
  private function render_legacy_options() {
40
+ $view = new CnbLegacyEdit();
 
41
  ?>
42
  <tr>
43
  <th colspan="2"><h2>Tracking</h2></th>
52
  <?php
53
  $view->render_zoom();
54
  $view->render_zindex();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
56
 
57
  /**
61
  */
62
  private function render_account_options( $cnb_user ) {
63
  global $wp_version;
64
+ $cnb_options = get_option( 'cnb' );
65
  $show_advanced_view_only = array_key_exists( 'advanced_view', $cnb_options ) && $cnb_options['advanced_view'] === 1;
66
+ $adminFunctions = new CnbAdminFunctions();
67
 
68
  ?>
69
  <table data-tab-name="account_options"
70
+ class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'account_options' ) ); ?>">
71
  <tr>
72
  <th colspan="2"></th>
73
  </tr>
81
  placeholder="e.g. b52c3f83-38dc-4493-bc90-642da5be7e39"/>
82
  </label>
83
  <p class="description">Get your API key at <a
84
+ href="<?php echo esc_attr( CNB_WEBSITE ) ?>"><?php echo esc_html( CNB_WEBSITE ) ?></a>
85
  </p>
86
  <?php } ?>
87
  <?php if ( is_wp_error( $cnb_user ) && ! empty( $cnb_options['api_key'] ) ) { ?>
94
  <br>
95
  <input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
96
  class="button button-link"
97
+ value="<?php esc_attr_e( 'Disconnect account' ) ?>"
98
  onclick="return cnb_delete_apikey();">
99
  </p>
100
  <?php } ?>
101
  <?php if ( ! is_wp_error( $cnb_user ) && isset( $cnb_options['api_key'] ) ) {
102
  $icon = version_compare( $wp_version, '5.5.0', '<' ) ? 'dashicons-yes' : 'dashicons-saved';
103
  ?>
104
+ <p><strong><span class="dashicons <?php echo esc_attr( $icon ) ?>"></span>Success!</strong>
105
  <Br>The plugin is connected to your callnowbutton.com account.</p>
106
  <p class="description">Clicking "Disconnect account" will drop the API key
107
  and disconnect the plugin from your account. You will lose access to
110
  <br>
111
  <input type="button" name="cnb_api_key_delete" id="cnb_api_key_delete"
112
  class="button button-link"
113
+ value="<?php esc_attr_e( 'Disconnect account' ) ?>"
114
  onclick="return cnb_delete_apikey();">
115
  </p>
116
  <input type="hidden" name="cnb[api_key]" id="cnb_api_key" value="delete_me"
140
  }
141
 
142
  private function render_advanced_options( $cnb_cloud_domain, $cnb_user ) {
143
+ $cnb_options = get_option( 'cnb' );
144
 
145
+ $adminFunctions = new CnbAdminFunctions();
146
  $cnbAppRemote = new CnbAppRemote();
147
  $cnb_clean_site_url = $cnbAppRemote->cnb_clean_site_url();
148
  $cnb_cloud_domains = CnbAppRemote::cnb_remote_get_domains();
149
+ $status = CnbSettingsController::getStatus( $cnb_options );
150
  ?>
151
  <table data-tab-name="advanced_options"
152
+ class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'advanced_options' ) ); ?>">
153
  <?php if ( isset( $cnb_cloud_domain ) && ! ( $cnb_cloud_domain instanceof WP_Error ) && $status === 'cloud' ) {
154
  ?>
155
  <tr>
205
  <label><select name="cnb[cloud_use_id]" id="cnb[cloud_use_id]">
206
 
207
 
208
+ <option
209
+ value="<?php echo esc_attr( $cnb_user->id ) ?>"
210
+ <?php selected( $cnb_user->id, $cnb_options['cloud_use_id'] ) ?>
211
+ >
212
+ Full account (all domains)
213
+ </option>
214
+
215
+ <?php
216
+ $loop_domains = array_filter( $cnb_cloud_domains, function ( $domain ) use ( $cnb_options, $cnb_clean_site_url ) {
217
+ if ( $cnb_options['advanced_view'] != 0 ) {
218
+ return true;
219
+ } // In case of advanced mode, show all
220
+ if ( $domain->name === $cnb_clean_site_url ) {
221
+ return true;
222
+ } // Always show the current domain
223
+ if ( $domain->id === $cnb_options['cloud_use_id'] ) {
224
+ return true;
225
+ } // If a previous weird option was selected, allow it
226
+
227
+ return false;
228
+ } );
229
+ foreach ( $loop_domains as $domain ) { ?>
230
  <option
231
+ value="<?php echo esc_attr( $domain->id ) ?>"
232
+ <?php selected( $domain->id, $cnb_options['cloud_use_id'] ) ?>
233
  >
234
+ <?php echo esc_html( $domain->name ) ?>
235
+ (single domain)
236
  </option>
237
+ <?php } ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
  </select></label>
240
  <?php } ?>
263
  <td><label>
264
  <input type="text" id="cnb[api_base]" name="cnb[api_base]"
265
  class="regular-text"
266
+ value="<?php echo esc_attr( CnbAppRemote::cnb_get_api_base() ) ?>"/>
267
  </label>
268
  <p class="description">The API endpoint to use to communicate with the
269
  CallNowButton Cloud service.<br/>
300
  private function render_promos( $use_cloud, $cnb_cloud_domain ) {
301
  echo '<div class="cnb-postbox-container cnb-side-column">';
302
  if ( ! $use_cloud ) {
303
+ ( new CnbAdminFunctions() )->cnb_promobox(
304
+ 'purple',
305
  'Phones off at 6pm?',
306
  '<p>Sign up to enable a scheduler that allows you to set the days and hours that you are available.</p>' .
307
  '<p>You can even replace it with an email button during your off-hours so people can still contact you.</p>',
308
  'clock',
309
+ '<strong>Use the scheduler!</strong>',
310
  'Learn more',
311
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
312
  );
313
+ ( new CnbAdminFunctions() )->cnb_promobox(
314
+ 'green',
315
  'More buttons!',
316
  'Switch to Premium to enable lots of buttons. Coupled with advanced page selection options you can get really creative.</p>' .
317
  '<p>If you need more phone numbers on a single page, then the Multibutton&trade; and the Buttonbar&trade; give you exactly what you need.</p>',
318
  'cloud',
319
  '<strong>Try it out!</strong>',
320
  'Learn more',
321
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
322
  );
323
+ ( new CnbAdminFunctions() )->cnb_promobox(
324
+ 'brown',
325
  'Get Premium for FREE!',
326
  'Premium adds a ton of extra power to the Call Now Button.</p>' .
327
  '<p>The Premium Free plan shows a little branding with your buttons but gives you access to all features.</p>' .
329
  'money-alt',
330
  '',
331
  'See what\'s incuded',
332
+ ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page()
333
  );
334
  }
335
  if ( $use_cloud && isset( $cnb_cloud_domain ) && ! is_wp_error( $cnb_cloud_domain ) && $cnb_cloud_domain->type !== 'PRO' ) {
336
+ ( new CnbAdminFunctions() )->cnb_promobox(
337
+ 'purple',
338
+ '50% off the annual plan!',
339
  '<p>Remove the <em>powered by</em> branding from your buttons!</p>' .
340
+ '<p>Benefit from this temporary offer and enjoy unlimited access to all features and publish your buttons without branding.</p>',
341
  'flag',
342
  '<strong>&euro;<span class="eur-per-month"></span>/$<span class="usd-per-month"></span> per month</strong>',
343
  'Upgrade',
344
+ ( new CnbUtils() )->get_cnb_domain_upgrade( $cnb_cloud_domain )
345
  );
346
  }
347
  echo '</div>';
354
  * @return void
355
  */
356
  private function render_premium_option( $cloud_successful, $cnb_cloud_domain ) {
357
+ $cnb_options = get_option( 'cnb' );
358
  ?>
359
  <tr>
360
  <th colspan="2"></th>
363
  <th scope="row">
364
  <label for="cnb_cloud_enabled">Premium
365
  <?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
366
+ <a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>"
367
+ class="cnb-nounderscore">
368
  <span class="dashicons dashicons-editor-help"></span>
369
  </a>
370
  <?php } ?>
382
  class="cnb_toggle_state cnb_toggle_true">Active</span>
383
  <?php if ( $cnb_options['cloud_enabled'] == 0 ) { ?>
384
  <p class="description">Free and paid options available.
385
+ <a href="<?php echo esc_url( ( new CnbAdminFunctions() )->cnb_legacy_upgrade_page() ) ?>">Learn
386
+ more</a>
387
  </p>
388
  <?php } ?>
389
 
390
  <?php if ( $cnb_options['cloud_enabled'] == 1 && $cloud_successful && $cnb_cloud_domain->type !== 'PRO' ) { ?>
391
  <p class="description">Free and paid options available.
392
+ <a href="<?php echo esc_url( ( new CnbUtils() )->get_cnb_domain_upgrade( $cnb_cloud_domain ) ); ?>">Learn
393
+ more</a>
394
  </p>
395
  <?php } ?>
396
  </td>
399
  }
400
 
401
  function render() {
402
+ $cnb_options = get_option( 'cnb' );
403
 
404
  $adminFunctions = new CnbAdminFunctions();
405
 
410
 
411
  $cnb_cloud_domain = null;
412
  $cnb_user = null;
413
+ $use_cloud = ( new CnbUtils() )->is_use_cloud( $cnb_options );
414
+ $status = CnbSettingsController::getStatus( $cnb_options );
415
 
416
  if ( $use_cloud ) {
417
  $cnb_user = CnbAppRemote::cnb_remote_get_user_info();
442
  <div class="cnb-body-content">
443
  <h2 class="nav-tab-wrapper">
444
  <a data-tab-name="basic_options"
445
+ href="<?php echo esc_url( $this->create_tab_url( 'basic_options' ) ) ?>"
446
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ) ?>">General</a>
447
  <?php if ( $use_cloud ) { ?>
448
  <a data-tab-name="account_options"
449
+ href="<?php echo esc_url( $this->create_tab_url( 'account_options' ) ) ?>"
450
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'account_options' ) ) ?>">Account</a>
451
  <a data-tab-name="advanced_options"
452
+ href="<?php echo esc_url( $this->create_tab_url( 'advanced_options' ) ) ?>"
453
+ class="nav-tab <?php echo esc_attr( $adminFunctions->is_active_tab( 'advanced_options' ) ) ?>">Advanced</a>
454
  <?php } ?>
455
  </h2>
456
  <form method="post" action="<?php echo esc_url( admin_url( 'options.php' ) ); ?>"
457
  class="cnb-container">
458
  <?php settings_fields( 'cnb_options' ); ?>
459
  <table data-tab-name="basic_options"
460
+ class="form-table <?php echo esc_attr( $adminFunctions->is_active_tab( 'basic_options' ) ); ?>">
461
  <?php
462
  $this->render_premium_option( $cloud_successful, $cnb_cloud_domain );
463
  if ( $status !== 'cloud' ) {
src/autoload.php CHANGED
@@ -61,6 +61,7 @@ spl_autoload_register(
61
  'cnb\\admin\\models\\cnbplan' => '/admin/models/CnbPlan.php',
62
  'cnb\\admin\\models\\cnbuser' => '/admin/models/CnbUser.php',
63
  'cnb\\admin\\models\\cnbuseraddress' => '/admin/models/CnbUser.php',
 
64
  'cnb\\admin\\models\\cnbusertaxid' => '/admin/models/CnbUser.php',
65
  'cnb\\admin\\models\\cnbusertaxidverification' => '/admin/models/CnbUser.php',
66
  'cnb\\admin\\profile\\cnbprofilecontroller' => '/admin/profile/CnbProfileController.php',
@@ -80,6 +81,11 @@ spl_autoload_register(
80
  'cnb\\notices\\cnbadminnotices' => '/notices/CnbAdminNotices.php',
81
  'cnb\\notices\\cnbnotice' => '/notices/CnbNotice.php',
82
  'cnb\\notices\\cnbnotices' => '/notices/CnbNotices.php',
 
 
 
 
 
83
  'cnb\\utils\\cnbadminfunctions' => '/utils/CnbAdminFunctions.php',
84
  'cnb\\utils\\cnbutils' => '/utils/CnbUtils.php',
85
  'wp_cli' => '/cli/mocks/WP_CLI.class.php',
61
  'cnb\\admin\\models\\cnbplan' => '/admin/models/CnbPlan.php',
62
  'cnb\\admin\\models\\cnbuser' => '/admin/models/CnbUser.php',
63
  'cnb\\admin\\models\\cnbuseraddress' => '/admin/models/CnbUser.php',
64
+ 'cnb\\admin\\models\\cnbuserstripedetails' => '/admin/models/CnbUser.php',
65
  'cnb\\admin\\models\\cnbusertaxid' => '/admin/models/CnbUser.php',
66
  'cnb\\admin\\models\\cnbusertaxidverification' => '/admin/models/CnbUser.php',
67
  'cnb\\admin\\profile\\cnbprofilecontroller' => '/admin/profile/CnbProfileController.php',
81
  'cnb\\notices\\cnbadminnotices' => '/notices/CnbAdminNotices.php',
82
  'cnb\\notices\\cnbnotice' => '/notices/CnbNotice.php',
83
  'cnb\\notices\\cnbnotices' => '/notices/CnbNotices.php',
84
+ 'cnb\\renderer\\cloudrenderer' => '/renderers/cloud/class-cloudrenderer.php',
85
+ 'cnb\\renderer\\modernrenderer' => '/renderers/modern/class-modernrenderer.php',
86
+ 'cnb\\renderer\\nooprenderer' => '/renderers/noop/class-nooprenderer.php',
87
+ 'cnb\\renderer\\renderer' => '/renderers/class-renderer.php',
88
+ 'cnb\\renderer\\rendererfactory' => '/renderers/class-rendererfactory.php',
89
  'cnb\\utils\\cnbadminfunctions' => '/utils/CnbAdminFunctions.php',
90
  'cnb\\utils\\cnbutils' => '/utils/CnbUtils.php',
91
  'wp_cli' => '/cli/mocks/WP_CLI.class.php',
src/call-now-button.php CHANGED
@@ -5,7 +5,6 @@ defined( 'ABSPATH' ) || die( '-1' );
5
 
6
  require_once dirname( __FILE__ ) . '/autoload.php';
7
  require_once dirname( __FILE__ ) . '/utils/cnb-backwards-compatible.php';
8
- require_once dirname( __FILE__ ) . '/renderers/render.php';
9
 
10
  // Only include the WP_CLI suite when it is available
11
  if ( class_exists( 'WP_CLI' ) && class_exists( 'WP_CLI_Command' ) ) {
@@ -16,3 +15,6 @@ add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerGlobalActions
16
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerHeaderAndFooter' ) );
17
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerPostActions' ) );
18
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerAjax' ) );
 
 
 
5
 
6
  require_once dirname( __FILE__ ) . '/autoload.php';
7
  require_once dirname( __FILE__ ) . '/utils/cnb-backwards-compatible.php';
 
8
 
9
  // Only include the WP_CLI suite when it is available
10
  if ( class_exists( 'WP_CLI' ) && class_exists( 'WP_CLI_Command' ) ) {
15
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerHeaderAndFooter' ) );
16
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerPostActions' ) );
17
  add_action( 'plugins_loaded', array( 'cnb\CallNowButton', 'registerAjax' ) );
18
+
19
+ // This queues the front-end to be rendered (`wp_loaded` should only fire on the front-end facing site)
20
+ add_action( 'wp_loaded', array( 'cnb\renderer\RendererFactory', 'register' ) );
src/cli/mocks/WP_CLI_Utils.class.php CHANGED
@@ -12,4 +12,4 @@ function get_flag_value( $array, $value, $default ) {
12
  }
13
 
14
  function format_items( $format, $items, $fields ) {
15
- }
12
  }
13
 
14
  function format_items( $format, $items, $fields ) {
15
+ }
src/notices/CnbAdminNotices.php CHANGED
@@ -40,7 +40,7 @@ class CnbAdminNotices {
40
  update_option( CNB_SLUG . '_dismissed_' . $dismiss_option, true );
41
  do_action( $dismiss_option );
42
  wp_die(
43
- __( 'Dismissed notice: ' . $dismiss_option, CNB_NAME ), __( 'Dismissed notice', CNB_NAME ),
44
  array(
45
  'response' => 200,
46
  )
@@ -67,16 +67,14 @@ class CnbAdminNotices {
67
  return;
68
  }
69
 
70
- $dismiss_classes = '';
71
- $dismiss_data_url = '';
72
  if ( $notice->dismiss_option ) {
73
  $notice->dismissable = true;
74
  $url = admin_url( 'admin.php' );
75
  $dismiss_url = add_query_arg( array(
76
  CNB_SLUG . '_dismiss' => $notice->dismiss_option
77
  ), $url );
78
-
79
- $dismiss_data_url .= ' data-dismiss-url="' . esc_url( $dismiss_url ) . '"';
80
  }
81
 
82
  if ( $notice->dismissable ) {
@@ -86,7 +84,15 @@ class CnbAdminNotices {
86
  // Check if this particular Notice has already been dismissed
87
  $option = CNB_SLUG . '_dismissed_' . $notice->dismiss_option;
88
  if ( ! $notice->dismiss_option || ! get_option( $option ) ) {
89
- echo '<div class="notice notice-' . CNB_SLUG . ' notice-' . esc_attr($notice->type) . $dismiss_classes . '"' . $dismiss_data_url . '>';
 
 
 
 
 
 
 
 
90
  echo $notice->message;
91
  echo '</div>';
92
  }
@@ -112,6 +118,8 @@ class CnbAdminNotices {
112
  }
113
 
114
  /**
 
 
115
  * @param $notices CnbNotice[]|string[]
116
  */
117
  public function notices( $notices ) {
40
  update_option( CNB_SLUG . '_dismissed_' . $dismiss_option, true );
41
  do_action( $dismiss_option );
42
  wp_die(
43
+ esc_html( 'Dismissed notice: ' . $dismiss_option ), esc_html__( 'Dismissed notice' ),
44
  array(
45
  'response' => 200,
46
  )
67
  return;
68
  }
69
 
70
+ $dismiss_classes = '';
71
+ $dismiss_url = '';
72
  if ( $notice->dismiss_option ) {
73
  $notice->dismissable = true;
74
  $url = admin_url( 'admin.php' );
75
  $dismiss_url = add_query_arg( array(
76
  CNB_SLUG . '_dismiss' => $notice->dismiss_option
77
  ), $url );
 
 
78
  }
79
 
80
  if ( $notice->dismissable ) {
84
  // Check if this particular Notice has already been dismissed
85
  $option = CNB_SLUG . '_dismissed_' . $notice->dismiss_option;
86
  if ( ! $notice->dismiss_option || ! get_option( $option ) ) {
87
+ echo '<div class="notice notice-' . esc_attr( CNB_SLUG ) . ' notice-' . esc_attr( $notice->type ) .
88
+ esc_attr( $dismiss_classes ) .
89
+ '"' .
90
+ // phpcs:ignore WordPress.Security
91
+ ( $notice->dismissable === true
92
+ ? ' data-dismiss-url="' . esc_url( $dismiss_url ) . '"'
93
+ : ''
94
+ ) . '>';
95
+ // phpcs:ignore WordPress.Security
96
  echo $notice->message;
97
  echo '</div>';
98
  }
118
  }
119
 
120
  /**
121
+ * Add Notices to be rendered inside the header.
122
+ *
123
  * @param $notices CnbNotice[]|string[]
124
  */
125
  public function notices( $notices ) {
src/renderers/class-renderer.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cnb\renderer;
4
+
5
+ // don't load directly
6
+ defined( 'ABSPATH' ) || die( '-1' );
7
+
8
+ /**
9
+ * A Renderer is a concept that allows the Call Now Button to have various render formats.
10
+ *
11
+ * At the moment, that would be a "modern" renderer (a local, non-Cloud version)
12
+ * and a "cloud" renderer (which makes use of Call Now Button Premium)
13
+ */
14
+ abstract class Renderer {
15
+ /**
16
+ * A renderer should register the various filters required for rendering
17
+ *
18
+ * @return void
19
+ */
20
+ abstract function register();
21
+ }
src/renderers/class-rendererfactory.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cnb\renderer;
4
+
5
+ use cnb\utils\CnbUtils;
6
+
7
+ // don't load directly
8
+ defined( 'ABSPATH' ) || die( '-1' );
9
+
10
+ class RendererFactory {
11
+
12
+ /**
13
+ * @return string
14
+ */
15
+ function getRenderer() {
16
+ $cnb_options = get_option( 'cnb' );
17
+
18
+ return ( new CnbUtils() )->is_use_cloud( $cnb_options ) ? 'cloud' : 'modern';
19
+ }
20
+
21
+ /**
22
+ * If we're in the "wp_loaded" hook, we don't NEED is_admin(), but it's good to have as a safety check
23
+ *
24
+ * @return bool
25
+ */
26
+ function shouldRender() {
27
+ $cnb_options = get_option( 'cnb' );
28
+
29
+ return ! is_admin() && ( new CnbUtils() )->isButtonActive( $cnb_options );
30
+ }
31
+
32
+ /**
33
+ * Find the proper renderer and load it. The renderer is responsible for adding itself to the proper hooks.
34
+ *
35
+ * Proper hooks are (probably/likely) `wp_head` and `wp_footer`
36
+ *
37
+ * This function should be scheduled on the front-end (only), usually via the `wp_loaded` hook.
38
+ *
39
+ * @return void
40
+ */
41
+ public static function register() {
42
+ $factory = new RendererFactory();
43
+
44
+ if ( $factory->shouldRender() ) {
45
+ switch ( $factory->getRenderer() ) {
46
+ case 'cloud':
47
+ $cloud_rendere = new CloudRenderer();
48
+ $cloud_rendere->register();
49
+ break;
50
+ case 'modern':
51
+ $modernRendere = new ModernRenderer();
52
+ $modernRendere->register();
53
+ break;
54
+ default:
55
+ $noop_renderer = new NoopRenderer();
56
+ $noop_renderer->register();
57
+ }
58
+ } else {
59
+ $noop_renderer = new NoopRenderer();
60
+ $noop_renderer->register();
61
+ }
62
+ }
63
+ }
src/renderers/classic/wp_foot.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
-
3
- // don't load directly
4
- use cnb\utils\CnbUtils;
5
-
6
- defined( 'ABSPATH' ) || die( '-1' );
7
-
8
- function cnb_footer() {
9
- $cnb_options = get_option('cnb');
10
-
11
- $cnb_tracking_id = (int) $cnb_options['tracking'];
12
- $cnb_conversion_id = (int) $cnb_options['conversions'];
13
- $cnb_tracking_id = ( $cnb_tracking_id >= 0 && $cnb_tracking_id <= 3 ) ? $cnb_tracking_id : 0;
14
- $cnb_conversion_id = ( $cnb_conversion_id >= 0 && $cnb_conversion_id <= 2 ) ? $cnb_conversion_id : 0;
15
- $cnb_hide_icon = isset( $cnb_options['hideIcon'] ) && $cnb_options['hideIcon'] == 1;
16
- $cnb_has_text = ( $cnb_options['text'] == '' ) ? false : true;
17
- $cnb_show_limited = isset( $cnb_options['show'] ) && $cnb_options['show'] != '';
18
- $cnb_show_included = $cnb_options['limit'] == 'include';
19
- $cnb_click_tracking = $cnb_tracking_id > 0;
20
- $cnb_is_full_width = $cnb_options['appearance'] == 'full' || $cnb_options['appearance'] == 'tfull';
21
- $cnb_hide_frontpage = isset( $cnb_options['frontpage'] ) && $cnb_options['frontpage'] == 1;
22
- $cnb_conversion_tracking = $cnb_conversion_id > 0;
23
-
24
- if ( $cnb_show_limited ) {
25
- $cnb_show_ids = explode( ',', str_replace( ' ', '', $cnb_options['show'] ) );
26
- }
27
-
28
- if ( $cnb_click_tracking ) {
29
- $cnb_tracking_code[1] = '_gaq.push(["_trackEvent", "Contact", "Call Now Button", "Phone"]);';
30
- $cnb_tracking_code[2] = 'ga("send", "event", "Contact", "Call Now Button", "Phone");';
31
- $gtag_props = wp_json_encode( array(
32
- 'event_category' => 'contact',
33
- 'event_label' => 'phone',
34
- 'category' => 'Call Now Button',
35
- 'action_type' => 'PHONE',
36
- 'button_type' => 'Single',
37
- 'action_value' => esc_js( $cnb_options['number'] ),
38
- 'action_label' => esc_js( $cnb_options['text'] ),
39
- 'cnb_version' => CNB_VERSION
40
- ) );
41
- $cnb_tracking_code[3] = 'gtag("event", "Call Now Button", ' . $gtag_props . ');';
42
- $cnb_tracking_code = $cnb_tracking_code[ $cnb_tracking_id ];
43
- } else {
44
- $cnb_tracking_code = '';
45
- }
46
-
47
- if ( $cnb_conversion_tracking ) {
48
- $cnb_conversion_code[1] = 'return gtag_report_conversion("tel:' . esc_js( $cnb_options['number'] ) . '");';
49
- $cnb_conversion_code[2] = 'goog_report_conversion("tel:' . esc_js( $cnb_options['number'] ) . '");';
50
- $cnb_conversion_code = $cnb_conversion_code[ $cnb_conversion_id ];
51
- } else {
52
- $cnb_conversion_code = '';
53
- }
54
-
55
- $cnb_onclick_events = $cnb_click_tracking || $cnb_conversion_tracking ? "onclick='" . $cnb_tracking_code . $cnb_conversion_code . "'" : '';
56
-
57
- if ( ! $cnb_has_text && ! $cnb_is_full_width ) {
58
- $cnb_button_text = '<span>Call Now Button</span>';
59
- } elseif ( ! $cnb_has_text && $cnb_is_full_width ) {
60
- $cnb_button_text = '<img alt="Call Now Button" src="data:image/svg+xml;base64,' . (new CnbUtils())->svg( (new CnbUtils())->changeColor( $cnb_options['color'], 'darker' ), $cnb_options['iconcolor'] ) . '" width="40">';
61
- } elseif ( $cnb_hide_icon && $cnb_is_full_width ) {
62
- $cnb_button_text = '<span style="color:' . esc_attr( $cnb_options['iconcolor'] ) . '">' . esc_html( $cnb_options['text'] ) . '</span>';
63
- } elseif ( $cnb_is_full_width ) {
64
- $cnb_button_text = '<img alt="Call Now Button" src="data:image/svg+xml;base64,' . (new CnbUtils())->svg( (new CnbUtils())->changeColor( $cnb_options['color'], 'darker' ), $cnb_options['iconcolor'] ) . '" width="40"><span style="color:' . esc_attr( $cnb_options['iconcolor'] ) . '">' . esc_html( $cnb_options['text'] ) . '</span>';
65
- } else {
66
- $cnb_button_text = '<span>' . str_replace( ' ', '&nbsp;', esc_html( $cnb_options['text'] ) ) . '</span>';
67
- }
68
-
69
- $cnb_call_link = '<a href="tel:' . esc_attr( $cnb_options['number'] ) . '" id="callnowbutton" ' . $cnb_onclick_events . '>' . $cnb_button_text . '</a>';
70
-
71
- if ( is_front_page() ) {
72
- if ( ! $cnb_hide_frontpage ) {
73
- echo $cnb_call_link;
74
- }
75
- } elseif ( $cnb_show_limited ) {
76
- if ( $cnb_show_included ) {
77
- if ( is_single( $cnb_show_ids ) || is_page( $cnb_show_ids ) || get_option( 'page_for_posts' ) == get_queried_object_id() ) {
78
- echo $cnb_call_link;
79
- }
80
- } else {
81
- if ( ! is_single( $cnb_show_ids ) && ! is_page( $cnb_show_ids ) && get_option( 'page_for_posts' ) != get_queried_object_id() ) {
82
- echo $cnb_call_link;
83
- }
84
- }
85
- } else {
86
- echo $cnb_call_link;
87
- }
88
- }
89
-
90
- add_action( 'wp_footer', 'cnb_footer' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/renderers/classic/wp_head.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
-
3
- // don't load directly
4
- use cnb\utils\CnbUtils;
5
-
6
- defined( 'ABSPATH' ) || die( '-1' );
7
-
8
- function cnb_head() {
9
- $cnb_options = get_option('cnb');
10
- $cnb_has_text = ( $cnb_options['text'] == '' ) ? false : true;
11
- $cnb_button_css = "\n<!-- Call Now Button " . CNB_VERSION . " by Jerry Rietveld (callnowbutton.com) [renderer:classic]-->\n";
12
-
13
- $ButtonExtra = "";
14
- // OLD BUTTON DESIGN
15
- if ( $cnb_options['appearance'] == 'full' || $cnb_options['appearance'] == 'middle' || $cnb_has_text ) {
16
- $cnb_button_appearance = "width:100%;left:0;";
17
- $ButtonExtra = "body {padding-bottom:60px;}";
18
- } elseif ( $cnb_options['appearance'] == 'left' ) {
19
- $cnb_button_appearance = "width:100px;left:0;border-bottom-right-radius:40px; border-top-right-radius:40px;";
20
- } else {
21
- $cnb_button_appearance = "width:100px;right:0;border-bottom-left-radius:40px; border-top-left-radius:40px;";
22
- }
23
-
24
- $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; " .
25
- $cnb_button_appearance .
26
- " height:80px; position:fixed; bottom:-20px; border-top:2px solid " .
27
- (new CnbUtils())->changeColor( esc_html( $cnb_options['color'] ), 'lighter' ) .
28
- "; background:url(data:image/svg+xml;base64," .
29
- (new CnbUtils())->svg( (new CnbUtils())->changeColor( esc_html($cnb_options['color']), 'darker' ), $cnb_options['iconcolor']) .
30
- ") center 2px no-repeat " .
31
- esc_html( $cnb_options['color'] ) .
32
- "; text-decoration:none; box-shadow:0 0 5px #888; z-index:" .
33
- (new CnbUtils())->zindex( $cnb_options['z-index'] ) .
34
- ";background-size:58px 58px}" .
35
- $ButtonExtra .
36
- "}</style>\n";
37
-
38
- echo $cnb_button_css;
39
- }
40
-
41
- add_action( 'wp_head', 'cnb_head' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/renderers/cloud/class-cloudrenderer.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cnb\renderer;
4
+
5
+ use cnb\admin\api\CnbAppRemote;
6
+
7
+ // don't load directly
8
+ defined( 'ABSPATH' ) || die( '-1' );
9
+
10
+ class CloudRenderer extends Renderer {
11
+
12
+ /**
13
+ * Get the configured user/domain ID for the client JS file.
14
+ *
15
+ * @return string|int returns 0 if no ID is found, otherise the configured ID.
16
+ */
17
+ function getId() {
18
+ $cnb_options = get_option( 'cnb' );
19
+ return isset( $cnb_options['cloud_use_id'] ) ? $cnb_options['cloud_use_id'] : 0;
20
+ }
21
+
22
+ /**
23
+ * Create the URL for the user based on the user ID. Adds a cache busting query parameter
24
+ * if the transient base is configured.
25
+ *
26
+ * @param $id {string} user/domain ID
27
+ *
28
+ * @return string URL
29
+ */
30
+ function getUrl($id) {
31
+ $url = CnbAppRemote::cnb_get_user_base() . '/' . $id . '.js';
32
+ $qs = CnbAppRemote::cnb__get_transient_base();
33
+ if ($qs) {
34
+ $url = add_query_arg( array(
35
+ 'dbver' => $qs,
36
+ ), $url );
37
+ }
38
+ return $url;
39
+ }
40
+
41
+ /**
42
+ * Prints a comment indicating cloud usage and which ID is used
43
+ *
44
+ * @param $id string|int
45
+ *
46
+ * @return void
47
+ */
48
+ function renderComment($id) {
49
+ echo sprintf( '<!-- Call Now Button %1$s (https://callnowbutton.com) [renderer:cloud, id:%2$s]-->%3$s',
50
+ esc_attr( CNB_VERSION ),
51
+ esc_attr( $id ),
52
+ "\n"
53
+ );
54
+ }
55
+
56
+ /**
57
+ *
58
+ * Prints the script tag required to include the CallNowButton on this site.
59
+ *
60
+ * If the id is empty, no script tag will be printed.
61
+ *
62
+ * @param $id string|int
63
+ *
64
+ * @return void
65
+ */
66
+ function renderJs($id) {
67
+ if ( $id ) {
68
+ $url = $this->getUrl($id);
69
+ // We echo this ourselves instead of via "wp_enqueue_script",
70
+ // since we want/seed the async feature, which is unsupported by "wp_enqueue_script"
71
+ // phpcs:ignore WordPress.WP
72
+ echo sprintf( '<script data-cnb-version="%1$s" type="text/javascript" async="async" src="%2$s"></script>%3$s',
73
+ esc_attr( CNB_VERSION ),
74
+ esc_url( $url ),
75
+ "\n"
76
+ );
77
+ }
78
+ }
79
+
80
+ public function render() {
81
+ $id = $this->getId();
82
+ $this->renderComment($id);
83
+ $this->renderJs($id);
84
+ }
85
+
86
+ public function register() {
87
+ add_action( 'wp_head', array( $this, 'render' ) );
88
+ }
89
+ }
src/renderers/cloud/wp_foot.php DELETED
@@ -1,4 +0,0 @@
1
- <?php
2
-
3
- // don't load directly
4
- defined( 'ABSPATH' ) || die( '-1' );
 
 
 
 
src/renderers/cloud/wp_head.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
-
3
- // don't load directly
4
- defined( 'ABSPATH' ) || die( '-1' );
5
-
6
- use cnb\admin\api\CnbAppRemote;
7
-
8
- function cnb_head() {
9
- $cnb_options = get_option('cnb');
10
- $id = isset( $cnb_options['cloud_use_id'] ) ? $cnb_options['cloud_use_id'] : 0;
11
- $cnb_button_js = "\n<!-- Call Now Button " . CNB_VERSION . " by Jerry Rietveld (callnowbutton.com) [renderer:cloud, id:" . esc_attr( $id ) . "]-->\n";
12
- if ( $id ) {
13
- $cnb_button_js .= '<script data-cnb-version="' . CNB_VERSION . '" type="text/javascript" async="async" src="' . CnbAppRemote::cnb_get_user_base() . '/' . esc_attr( $id ) . '.js"></script>';
14
- }
15
- echo $cnb_button_js;
16
- }
17
-
18
- add_action( 'wp_head', 'cnb_head' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/renderers/modern/class-modernrenderer.php ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cnb\renderer;
4
+
5
+ use cnb\utils\CnbUtils;
6
+
7
+ // don't load directly
8
+ defined( 'ABSPATH' ) || die( '-1' );
9
+
10
+ class ModernRenderer extends Renderer {
11
+
12
+ /**
13
+ * Enqueues the style required for the modern renderer
14
+ *
15
+ * @return void
16
+ */
17
+ private function enqueue_frontend_style() {
18
+ wp_register_style(
19
+ CNB_SLUG . '-modern-style',
20
+ plugins_url( CNB_SLUG . '/resources/style/modern.css' ),
21
+ array(),
22
+ CNB_VERSION
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Note this function escapes both inputs
28
+ *
29
+ * @param $icon
30
+ *
31
+ * @return string
32
+ */
33
+ private function svg( $icon ) {
34
+ $svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M27.01355,23.48859l-1.753,1.75305a5.001,5.001,0,0,1-5.19928,1.18243c-1.97193-.69372-4.87335-2.36438-8.43848-5.9295S6.387,14.028,5.6933,12.05615A5.00078,5.00078,0,0,1,6.87573,6.85687L8.62878,5.10376a1,1,0,0,1,1.41431.00012l2.828,2.8288A1,1,0,0,1,12.871,9.3468L11.0647,11.153a1.0038,1.0038,0,0,0-.0821,1.32171,40.74278,40.74278,0,0,0,4.07624,4.58374,40.74143,40.74143,0,0,0,4.58374,4.07623,1.00379,1.00379,0,0,0,1.32171-.08209l1.80622-1.80627a1,1,0,0,1,1.41412-.00012l2.8288,2.828A1.00007,1.00007,0,0,1,27.01355,23.48859Z" fill="' . esc_attr( $icon ) . '"/></svg>';
35
+
36
+ return base64_encode( $svg );
37
+ }
38
+
39
+ private function render_comment() {
40
+ echo sprintf( '<!-- Call Now Button %1$s (https://callnowbutton.com) [renderer:modern]-->%2$s',
41
+ esc_attr( CNB_VERSION ),
42
+ "\n" );
43
+ }
44
+
45
+ public function cnb_footer() {
46
+ $this->render_comment();
47
+
48
+ if ($this->should_render()) {
49
+ // phpcs:ignore WordPress.Security
50
+ echo $this->get_button_link();
51
+ }
52
+ }
53
+
54
+ /**
55
+ * @return bool return true if the button should be rendered, false otherwise
56
+ */
57
+ function should_render($x=false) {
58
+ $cnb_options = get_option( 'cnb' );
59
+
60
+ // if we cannot even find this option, we skip the header completely
61
+ if (!is_array($cnb_options)) {
62
+ return false;
63
+ }
64
+
65
+ $cnb_hide_frontpage = isset( $cnb_options['frontpage'] ) && $cnb_options['frontpage'] == 1;
66
+ $cnb_show_limited = isset( $cnb_options['show'] ) && $cnb_options['show'] != '';
67
+ $cnb_show_included = isset($cnb_options['limit']) ? $cnb_options['limit'] === 'include' : true;
68
+
69
+ $is_page_for_posts = get_option( 'page_for_posts' ) == get_queried_object_id() && get_option( 'page_for_posts' ) > 0 && get_queried_object_id() > 0;
70
+
71
+ if ( $cnb_show_limited ) {
72
+ $cnb_show_ids = explode( ',', str_replace( ' ', '', $cnb_options['show'] ) );
73
+ }
74
+
75
+ if ( is_front_page() ) {
76
+ if ( ! $cnb_hide_frontpage ) {
77
+ return 1;
78
+ }
79
+ } elseif ( $cnb_show_limited ) {
80
+ // Is the current page the "posts overview" page
81
+ if ( $cnb_show_included ) {
82
+ if ( is_single( $cnb_show_ids ) || is_page( $cnb_show_ids ) || $is_page_for_posts ) {
83
+ return 2;
84
+ }
85
+ } else {
86
+ if ( ! is_single( $cnb_show_ids ) && ! is_page( $cnb_show_ids ) && ! $is_page_for_posts ) {
87
+ return 3;
88
+ }
89
+ }
90
+ } else {
91
+ return 4;
92
+ }
93
+ return false;
94
+ }
95
+ /**
96
+ * Returns the <a.. > element that makes up the Modern Call Now Button.
97
+ *
98
+ * Note that all values are pre-escaped, so it is safe to echo without escaping.
99
+ *
100
+ * @return string|null null in case there is no Button to output
101
+ */
102
+ function get_button_link() {
103
+ $cnb_options = get_option( 'cnb' );
104
+
105
+ // if we cannot even find this option, we skip the header completely
106
+ if (!is_array($cnb_options)) {
107
+ return null;
108
+ }
109
+
110
+ $cnb_utils = new CnbUtils();
111
+
112
+ $cnb_tracking_id = isset($cnb_options['tracking']) ? (int) $cnb_options['tracking'] : 0;
113
+ $cnb_conversion_id = isset($cnb_options['conversions']) ? (int) $cnb_options['conversions'] : 0;
114
+ $cnb_tracking_id = ( $cnb_tracking_id >= 0 && $cnb_tracking_id <= 3 ) ? $cnb_tracking_id : 0;
115
+ $cnb_conversion_id = ( $cnb_conversion_id >= 0 && $cnb_conversion_id <= 2 ) ? $cnb_conversion_id : 0;
116
+ $cnb_click_tracking = $cnb_tracking_id > 0;
117
+ $cnb_conversion_tracking = $cnb_conversion_id > 0;
118
+ $cnb_number = isset( $cnb_options['number'] ) ? $cnb_options['number'] : null;
119
+ $cnb_zoom = isset( $cnb_options['zoom'] ) ? $cnb_options['zoom'] : 1;
120
+ $cnb_zindex = isset( $cnb_options['z-index'] ) ? $cnb_options['z-index'] : 10;
121
+ $cnb_zindex_val = $cnb_utils->zindex( $cnb_zindex );
122
+
123
+ $cnb_classnames = $this->get_class_names();
124
+
125
+ // These all return pre-escaped results
126
+ $cnb_button_background = $this->get_background_css();
127
+ $tracking_code = $this->get_google_tracking_code( $cnb_click_tracking, $cnb_tracking_id );
128
+ $conversion_code = $this->get_google_conversion_code( $cnb_conversion_tracking, $cnb_conversion_id );
129
+ $cnb_button_text = $this->create_button_text();
130
+
131
+ $cnb_call_link = '<a aria-label="Call Now Button"';
132
+ $cnb_call_link .= ' href="tel:' . esc_attr( $cnb_number ) . '"';
133
+ $cnb_call_link .= ' id="callnowbutton"';
134
+ $cnb_call_link .= ' class="' . esc_attr( $cnb_classnames ) . '"';
135
+
136
+ $cnb_call_link .= ' style="';
137
+ $cnb_call_link .= 'transform: scale(' . esc_attr( $cnb_zoom ) . ');';
138
+ $cnb_call_link .= 'z-index:' . esc_attr( $cnb_zindex_val ) . ';';
139
+ $cnb_call_link .= $cnb_button_background;
140
+ $cnb_call_link .= '"';
141
+
142
+ $cnb_call_link .= $cnb_click_tracking || $cnb_conversion_tracking ? " onclick='" . $tracking_code . $conversion_code . "'" : '';
143
+ $cnb_call_link .= '>';
144
+ $cnb_call_link .= $cnb_button_text;
145
+ $cnb_call_link .= '</a>';
146
+
147
+ return $cnb_call_link;
148
+ }
149
+
150
+ public function cnb_head() {
151
+ $cnb_options = get_option( 'cnb' );
152
+
153
+ // if we cannot even find this option, we skip the header completely
154
+ if (!is_array($cnb_options) || !key_exists('appearance', $cnb_options)) {
155
+ return;
156
+ }
157
+
158
+ $appearance = $cnb_options['appearance'];
159
+ if ( 'full' === $appearance || 'tfull' === $appearance ) {
160
+ switch ( $appearance ) {
161
+ case 'tfull':
162
+ echo '<style>body {padding-top:60px;}</style>';
163
+ break;
164
+ case 'full':
165
+ default:
166
+ echo '<style>body {padding-bottom:60px;}</style>';
167
+ break;
168
+ }
169
+ }
170
+
171
+ wp_enqueue_style( CNB_SLUG . '-modern-style' );
172
+ }
173
+
174
+ function register() {
175
+ $this->enqueue_frontend_style();
176
+
177
+ // We add priority 7 to ensure that we are loaded before wp_head renders the CSS (which is at priority >= 8)
178
+ add_action( 'wp_head', array( $this, 'cnb_head', ), 7 );
179
+
180
+ add_action( 'wp_footer', array( $this, 'cnb_footer' ) );
181
+ }
182
+
183
+ /**
184
+ * Decide on the background settings
185
+ *
186
+ * Get (pre escaped) CSS for the background
187
+ *
188
+ * @return string
189
+ */
190
+ private function get_background_css() {
191
+ $cnb_options = get_option( 'cnb' );
192
+ if ( 'full' === $cnb_options['appearance'] || 'tfull' === $cnb_options['appearance'] ) {
193
+ return sprintf( 'background:%1$s;',
194
+ esc_attr( $cnb_options['color'] )
195
+ );
196
+ } else {
197
+ $svg = $this->svg(
198
+ $cnb_options['iconcolor'] );
199
+
200
+ return
201
+ sprintf( 'background:url(data:image/svg+xml;base64,%1$s) center/35px 35px no-repeat %2$s;',
202
+ esc_attr( $svg ),
203
+ esc_attr( $cnb_options['color'] )
204
+ );
205
+ }
206
+ }
207
+
208
+ /**
209
+ * @param $cnb_click_tracking
210
+ * @param $cnb_tracking_id
211
+ *
212
+ * @return string
213
+ */
214
+ private function get_google_tracking_code( $cnb_click_tracking, $cnb_tracking_id ) {
215
+ $cnb_options = get_option( 'cnb' );
216
+
217
+ if ( $cnb_click_tracking ) {
218
+ switch ( $cnb_tracking_id ) {
219
+ case 1:
220
+ return '_gaq.push(["_trackEvent", "Contact", "Call Now Button", "Phone"]);';
221
+ case 2:
222
+ return 'ga("send", "event", "Contact", "Call Now Button", "Phone");';
223
+ case 3:
224
+ $action_value = isset($cnb_options['number']) ? $cnb_options['number'] : null;
225
+ $action_label = isset($cnb_options['text']) ? $cnb_options['text'] : null;
226
+ $gtag_props = wp_json_encode( array(
227
+ 'event_category' => 'contact',
228
+ 'event_label' => 'phone',
229
+ 'category' => 'Call Now Button',
230
+ 'action_type' => 'PHONE',
231
+ 'button_type' => 'Single',
232
+ 'action_value' => $action_value,
233
+ 'action_label' => $action_label,
234
+ 'cnb_version' => CNB_VERSION
235
+ ) );
236
+
237
+ return 'gtag("event", "Call Now Button", ' . $gtag_props . ');';
238
+ }
239
+ }
240
+
241
+ return '';
242
+ }
243
+
244
+ private function get_google_conversion_code( $cnb_conversion_tracking, $cnb_conversion_id ) {
245
+ $cnb_options = get_option( 'cnb' );
246
+
247
+ if ( $cnb_conversion_tracking ) {
248
+ switch ( $cnb_conversion_id ) {
249
+ case 1:
250
+ return 'return gtag_report_conversion("tel:' . esc_js( $cnb_options['number'] ) . '");';
251
+ case 2:
252
+ return 'goog_report_conversion("tel:' . esc_js( $cnb_options['number'] ) . '");';
253
+ }
254
+ }
255
+
256
+ return '';
257
+ }
258
+
259
+ private function create_button_text() {
260
+ $cnb_options = get_option( 'cnb' );
261
+
262
+ $cnb_has_text = $cnb_options['text'] !== '';
263
+ $cnb_is_full_width = $cnb_options['appearance'] == 'full' || $cnb_options['appearance'] == 'tfull';
264
+ $cnb_hide_icon = isset( $cnb_options['hideIcon'] ) && $cnb_options['hideIcon'] == 1;
265
+
266
+ // Full Width options
267
+ if ( $cnb_is_full_width ) {
268
+ $svg = $this->svg( $cnb_options['iconcolor'] );
269
+
270
+ $result = '';
271
+ // Without text, return just the icon via img tag
272
+ if ( ! $cnb_hide_icon ) {
273
+ $result .= sprintf( '<img alt="Call Now Button" src="data:image/svg+xml;base64,%1$s" width="40">',
274
+ esc_attr( $svg ) );
275
+ }
276
+
277
+ // Without icon, return just the text without icon
278
+ if ( $cnb_has_text ) {
279
+ $result .= sprintf( '<span style="color:%1$s">%2$s</span>',
280
+ esc_attr( $cnb_options['iconcolor'] ),
281
+ esc_html( $cnb_options['text'] )
282
+ );
283
+ }
284
+
285
+ return $result;
286
+ }
287
+
288
+ // Single options
289
+ if ( ! $cnb_has_text ) {
290
+ return '<span>Call Now Button</span>';
291
+ }
292
+
293
+ return sprintf( '<span>%1$s</span>',
294
+ esc_html( $cnb_options['text'] )
295
+ );
296
+ }
297
+
298
+ private function get_class_names() {
299
+ $cnb_options = get_option( 'cnb' );
300
+ $cnb_classnames = 'call-now-button';
301
+
302
+ // Button has text?
303
+ if ( $cnb_options['text'] !== '' ) {
304
+ $cnb_classnames .= ' cnb-text';
305
+ }
306
+
307
+ // Button type & position
308
+ if ( $cnb_options['appearance'] === 'full' ) {
309
+ $cnb_classnames .= ' cnb-full cnb-full-bottom';
310
+ } elseif ( $cnb_options['appearance'] === 'tfull' ) {
311
+ $cnb_classnames .= ' cnb-full cnb-full-top';
312
+ } else {
313
+ $cnb_classnames .= ' cnb-single cnb-' . $cnb_options['appearance'];
314
+ }
315
+
316
+ return $cnb_classnames;
317
+ }
318
+ }
src/renderers/modern/wp_foot.php DELETED
@@ -1,2 +0,0 @@
1
- <?php
2
- require_once dirname( __FILE__ ) . '/../classic/wp_foot.php';
 
 
src/renderers/modern/wp_head.php DELETED
@@ -1,64 +0,0 @@
1
- <?php
2
-
3
- use cnb\utils\CnbUtils;
4
-
5
- function cnb_head() {
6
- $cnb_options = get_option('cnb');
7
- $cnb_has_text = ( $cnb_options['text'] == '' ) ? false : true;
8
- $cnb_is_full_width = $cnb_options['appearance'] == "full" || $cnb_options['appearance'] == "tfull";
9
- $cnb_button_css = "\n<!-- Call Now Button " . CNB_VERSION . " by Jerry Rietveld (callnowbutton.com) [renderer:modern]-->\n";
10
-
11
- $ButtonExtra = "";
12
- // NEW BUTTON DESIGN
13
- $cnb_button_shape = "width:55px; height:55px; border-radius:50%; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);transform: scale(" . esc_html( $cnb_options['zoom'] ) . ");";
14
- $cnb_button_positions = array(
15
- 'middle' => 'bottom:15px; left:50%; margin-left:-28px;',
16
- 'left' => 'bottom:15px; left:20px;',
17
- 'right' => 'bottom:15px; right:20px;',
18
- 'mleft' => 'top:50%; margin-top:-28px; left:20px;',
19
- 'mright' => 'top:50%; margin-top:-28px; right:20px;',
20
- 'tleft' => 'top:15px; left:20px;',
21
- 'tmiddle' => 'top:15px; left:50%; margin-left:-28px;',
22
- 'tright' => 'top:15px; right:20px;',
23
- );
24
-
25
- if ( $cnb_options['appearance'] == 'full' || $cnb_options['appearance'] == 'tfull' ) {
26
- $cnb_top_or_bottom = ( $cnb_options['appearance'] ) == 'full' ? "bottom" : "top";
27
-
28
- $cnb_button_appearance = "width:100%;left:0;" . $cnb_top_or_bottom . ":0;height:60px;";
29
-
30
- $ButtonExtra = "body {padding-" . $cnb_top_or_bottom . ":60px;}#callnowbutton img {transform: scale(" . esc_html( $cnb_options['zoom'] ) . ");}";
31
- if ( $cnb_has_text ) {
32
- $cnb_button_appearance .= "text-align:center;color:#fff; font-weight:600; font-size:120%; overflow: hidden;";
33
- }
34
- } else {
35
- $cnb_button_appearance = $cnb_button_shape . $cnb_button_positions[ $cnb_options['appearance'] ];
36
- }
37
-
38
- $cnb_label_side = ltrim( ltrim( $cnb_options['appearance'], "m" ), "t" );
39
-
40
- if ( $cnb_has_text && ( $cnb_options['appearance'] == 'middle' || $cnb_options['appearance'] == 'tmiddle' ) ) { // don't show the label in this situation
41
- $circularButtonTextCSS = "#callnowbutton span{display: none;";
42
- } elseif ( $cnb_has_text && ! $cnb_is_full_width ) {
43
- $circularButtonTextCSS = "\n#callnowbutton span {-moz-osx-font-smoothing: grayscale; -webkit-user-select: none; -ms-user-select: none; user-select: none; display: block; width: auto; background-color: rgba(70,70,70,.9); position: absolute; " . $cnb_label_side . ": 68px; border-radius: 2px; font-family: Helvetica,Arial,sans-serif; padding: 6px 8px; font-size: 13px; font-weight:700; color: #ececec; top: 15px; box-shadow: 0 1px 2px rgba(0,0,0,.15); word-break: keep-all; line-height: 1em; text-overflow: ellipsis; vertical-align: middle; }";
44
- } elseif ( ! $cnb_is_full_width ) {
45
- $circularButtonTextCSS = "#callnowbutton span{display:none;}";
46
- } else {
47
- $circularButtonTextCSS = "";
48
- }
49
-
50
- $cnb_button_css = $cnb_button_css . '<style data-cnb-version="' . CNB_VERSION . '">';
51
- $cnb_button_css .= "#callnowbutton {display:none;} @media screen and (max-width:650px){#callnowbutton {display:block; position:fixed; text-decoration:none; z-index:" . (new CnbUtils())->zindex( $cnb_options['z-index'] ) . ";";
52
- $cnb_button_css .= $cnb_button_appearance;
53
- if ( $cnb_is_full_width ) {
54
- $cnb_button_css .= "background:" . esc_html( $cnb_options['color'] ) . ";display: flex; justify-content: center; align-items: center;text-shadow: 0 1px 0px rgba(0, 0, 0, 0.18);";
55
- } else {
56
- $cnb_button_css .= "background:url(data:image/svg+xml;base64," . (new CnbUtils())->svg( (new CnbUtils())->changeColor( $cnb_options['color'], 'darker' ), $cnb_options['iconcolor'] ) . ") center/35px 35px no-repeat " . esc_html( $cnb_options['color'] ) . ";";
57
- }
58
- $cnb_button_css .= "}" . $ButtonExtra . "}" . $circularButtonTextCSS;
59
- $cnb_button_css .= "</style>\n";
60
-
61
- echo $cnb_button_css;
62
- }
63
-
64
- add_action( 'wp_head', 'cnb_head' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/renderers/noop/class-nooprenderer.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cnb\renderer;
4
+
5
+ /**
6
+ * The Noop Renderer only outputs a comment that the plugin is used, but does nothing useful.
7
+ */
8
+ class NoopRenderer extends Renderer {
9
+
10
+ /**
11
+ * Outputs a comment with the current version of the Plugin
12
+ *
13
+ * @return void
14
+ */
15
+ public function render() {
16
+ echo sprintf( '<!-- Call Now Button %1$s (https://callnowbutton.com) [renderer:noop]-->%2$s',
17
+ esc_attr( CNB_VERSION ),
18
+ "\n"
19
+ );
20
+ }
21
+
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ function register() {
26
+ add_action( 'wp_head', array( $this, 'render' ) );
27
+ }
28
+ }
src/renderers/{classic → noop}/index.php RENAMED
File without changes
src/renderers/render.php DELETED
@@ -1,34 +0,0 @@
1
- <?php
2
-
3
- // don't load directly
4
- use cnb\utils\CnbUtils;
5
-
6
- defined( 'ABSPATH' ) || die( '-1' );
7
-
8
- /**
9
- * Find the proper renderer and load it. The renderer is responsible for adding itself to the proper hooks.
10
- *
11
- * Proper hooks are (probably/likely) `wp_head` and `wp_footer`
12
- *
13
- * This function should be scheduled on the front-end (only), usually via the `wp_loaded` hook.
14
- *
15
- * @return void
16
- * @global $cnb_options array The Call Now Buttons options array
17
- */
18
- function cnb_render_button() {
19
- $cnb_options = get_option('cnb');
20
-
21
- // If we're in the "wp_loaded" hook, we don't NEED is_admin(), but it's good to have as a safety check
22
- if ( ! is_admin() && (new CnbUtils())->isButtonActive( $cnb_options ) ) {
23
- $cnb_has_text = ( $cnb_options['text'] == '' ) ? false : true;
24
- $cnb_is_classic = $cnb_options['classic'] == 1 && ! $cnb_has_text;
25
-
26
- $renderer = (new CnbUtils())->is_use_cloud( $cnb_options ) ? 'cloud' : ( $cnb_is_classic ? 'classic' : 'modern' );
27
-
28
- require_once dirname( __FILE__ ) . "/$renderer/wp_head.php";
29
- require_once dirname( __FILE__ ) . "/$renderer/wp_foot.php";
30
- }
31
- }
32
-
33
- // This queues the front-end to be rendered (`wp_loaded` should only fire on the front-end facing site
34
- add_action( 'wp_loaded', 'cnb_render_button' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/utils/CnbAdminFunctions.php CHANGED
@@ -5,96 +5,31 @@ namespace cnb\utils;
5
  // don't load directly
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
8
- use cnb\CnbHeaderNotices;
9
- use cnb\notices\CnbAdminNotices;
10
-
11
  class CnbAdminFunctions {
12
- private function get_active_tab_name() {
13
- // using filter_var instead of filter_input, so we can do some "just in time" rewriting of the tab variable if needed
14
- return isset( $_GET['tab'] ) ? filter_var( $_GET['tab'], FILTER_SANITIZE_STRING ) : 'basic_options';
 
 
 
 
 
 
15
  }
16
 
 
 
 
 
 
 
 
17
  function is_active_tab( $tab_name ) {
18
  $active_tab = $this->get_active_tab_name();
19
 
20
  return $active_tab === $tab_name ? 'nav-tab-active' : '';
21
  }
22
 
23
- function get_changelog_version( $cnb_options ) {
24
- if ( ! $cnb_options ) {
25
- return CNB_VERSION;
26
- }
27
-
28
- if ( ! key_exists( 'changelog_version', $cnb_options ) ) {
29
- // Get 1 version behind, so new users always get the latest
30
- $changelog = $this->cnb_get_changelog();
31
- $keys = array_keys( $changelog );
32
-
33
- return $keys[1];
34
- }
35
-
36
- return $cnb_options['changelog_version'];
37
- }
38
-
39
- function has_changelog() {
40
- // These is a message...
41
- $header_notices = new CnbHeaderNotices();
42
- $changelog_message = $header_notices->upgrade_notice();
43
-
44
- // ... and the notice has not been dismissed yet
45
- $dismiss_name = CnbAdminNotices::get_instance()->get_dismiss_option_name( $header_notices->cnb_get_upgrade_notice_dismiss_name() );
46
- $dismissed = CnbAdminNotices::get_instance()->is_dismissed( $dismiss_name );
47
-
48
- return $changelog_message && ! $dismissed;
49
- }
50
-
51
- function cnb_get_changelog() {
52
- return array(
53
- '1.0.8' => array(
54
- 'WhatsApp chat modal (Premium)',
55
- 'Multiple buttons on a single page (Premium)',
56
- 'Icon selection (Premium)',
57
- 'Drag and drop action sorting (Premium)',
58
- 'Time selector in the preview (Premium)',
59
- 'Button animations (Premium)',
60
- 'Set link target (Premium)',
61
- 'Display setting shown in button overview (Premium)',
62
- ),
63
- '1.0.6' => array(
64
- '💬 SMS/Text support in Premium',
65
- '⏱️ More intuitive button scheduler in Premium',
66
- ),
67
- '1.0.4' => array(
68
- 'Live button preview for Premium',
69
- 'Easy premium activation via email',
70
- 'Switch between tabs while editing your button',
71
- ),
72
- '1.0.0' => '🎉Introducing Call Now Button Premium!🎉',
73
- '0.5.0' => 'Better button creation flow, UI improvements, small fixes',
74
- '0.4.7' => 'Small UI improvements',
75
- '0.4.2' => 'Button styling adjustments, security improvements',
76
- '0.4.0' => array(
77
- 'Text bubbles for standard buttons',
78
- 'Set the icon color',
79
- 'Google Ads conversion tracking',
80
- 'Tabbed admin interface',
81
- '6 additional button locations, small button design changes',
82
- 'Added support articles for (nearly) all settings',
83
- 'Control visibility on front page',
84
- 'Plus a bunch of smaller fixes. Enjoy!'
85
- ),
86
- '0.3.6' => 'Small validation fixes and zoom now controls icon size in full width buttons.',
87
- '0.3.5' => 'Small JS fix',
88
- '0.3.4' => 'Option to resize your button and change where it sits in the stack order (z-index).',
89
- '0.3.3' => 'Some small improvements.',
90
- '0.3.2' => 'Option to hide icon in text button, small bug fixes.',
91
- '0.3.1' => 'You can now add text to your button and it\'s possible to switch between including and excluding specific pages.',
92
- '0.3.0' => 'Option to add text to your button.',
93
- '0.2.1' => 'Some small fixes',
94
- '0.2.0' => 'The Call Now Button has a new look!'
95
- );
96
- }
97
-
98
  /**
99
  * Return an array of all ButtonTypes
100
  *
@@ -122,11 +57,14 @@ class CnbAdminFunctions {
122
  return array(
123
  'PHONE' => 'Phone',
124
  'EMAIL' => 'Email',
125
- 'ANCHOR' => 'Anchor',
126
  'LINK' => 'Link',
127
  'MAP' => 'Google Maps',
128
  'WHATSAPP' => 'WhatsApp',
129
  'SMS' => 'SMS/Text',
 
 
 
130
  );
131
  }
132
 
@@ -161,7 +99,7 @@ class CnbAdminFunctions {
161
  // Default everything is NOT selected, then we enable only those days that are passed in via $original
162
  $result = array( false, false, false, false, false, false, false );
163
  foreach ( $result as $day_of_week_index => $day_of_week ) {
164
- $day_of_week_is_enabled = isset( $original[ $day_of_week_index ] ) && ( $original[ $day_of_week_index ] === "true" || $original[ $day_of_week_index ] === true );
165
  $result[ $day_of_week_index ] = $day_of_week_is_enabled;
166
  }
167
 
@@ -173,79 +111,78 @@ class CnbAdminFunctions {
173
  * <p>The CTA block is optional and displays only when there's a link provided or $cta_button_text = 'none'.</p>
174
  * <p>Defaut CTA text is "Let's go". Default <code>$icon</code> is flag (value should be a dashicon name)</p>
175
  *
176
- * <p><strong>NOTE: all values are presumed to be already escaped!</strong></p>
177
  *
178
- * @param $color
179
- * @param $headline
180
- * @param $body
181
- * @param $icon
182
- * @param $cta_pretext
183
- * @param $cta_button_text
184
- * @param $cta_button_link
185
  * @param $cta_footer_notice
186
  *
187
- * @return null It <code>echo</code>s html output of the promobox
188
  */
189
  function cnb_promobox( $color, $headline, $body, $icon = 'flag', $cta_pretext = null, $cta_button_text = 'Let\'s go', $cta_button_link = null, $cta_footer_notice = null ) {
190
- $output = '
191
  <div id="cnb_upgrade_box" class="cnb-promobox">
192
- <div class="cnb-promobox-header cnb-promobox-header-' . $color . '">
193
- <span class="dashicons dashicons-' . $icon . '"></span>
194
  <h2 class="hndle">' .
195
- $headline
196
- . '</h2>
197
  </div>
198
  <div class="inside">
199
  <div class="cnb-promobox-copy">
200
  <div class="cnb_promobox_item">' .
201
- $body
202
- . '</div>
 
203
  <div class="clear"></div>';
204
  if ( ! is_null( $cta_button_link ) || $cta_button_text == 'none' ) {
205
- $output .= '
206
  <div class="cnb-promobox-action">
207
  <div class="cnb-promobox-action-left">' .
208
- $cta_pretext
209
- . '</div>';
 
210
  if ( $cta_button_text != 'none' && $cta_button_link != 'disabled' ) {
211
- $output .= '
212
  <div class="cnb-promobox-action-right">
213
- <a class="button button-primary button-large" href="' . $cta_button_link . '">' . $cta_button_text . '</a>
214
  </div>';
215
  } elseif ( $cta_button_link == 'disabled' ) {
216
- $output .= '
217
  <div class="cnb-promobox-action-right">
218
- <button class="button button-primary button-large" disabled>' . $cta_button_text . '</a>
219
  </div>';
220
  }
221
- $output .= '
222
  <div class="clear"></div>';
223
  if ( ! is_null( $cta_footer_notice ) ) {
224
- $output .= '<div class="nonessential" style="padding-top: 5px;">' . $cta_footer_notice . '</div>';
225
  }
226
- $output .= '
227
  </div>
228
  ';
229
  }
230
- $output .= '
231
  </div>
232
  </div>
233
  </div>
234
  ';
235
- echo $output;
236
-
237
- return null;
238
  }
239
 
240
  /**
 
241
  * Returns the url for the Upgrade to cloud page
242
  *
243
  * @return string upgrade page url
244
  */
245
  function cnb_legacy_upgrade_page() {
246
- $url = admin_url( 'admin.php' );
247
- $new_link = add_query_arg( 'page', 'call-now-button-upgrade', $url );
248
 
249
- return esc_url_raw( $new_link );
250
  }
251
- }
5
  // don't load directly
6
  defined( 'ABSPATH' ) || die( '-1' );
7
 
 
 
 
8
  class CnbAdminFunctions {
9
+ /**
10
+ * Get the active tab name (?tab=<name>)
11
+ *
12
+ * @return string
13
+ */
14
+ function get_active_tab_name() {
15
+ $cnb_utils = new CnbUtils();
16
+
17
+ return $cnb_utils->get_query_val( 'tab', 'basic_options' );
18
  }
19
 
20
+ /**
21
+ * Returns the CSS class used for active tabs
22
+ *
23
+ * @param $tab_name string name of tab to check
24
+ *
25
+ * @return string
26
+ */
27
  function is_active_tab( $tab_name ) {
28
  $active_tab = $this->get_active_tab_name();
29
 
30
  return $active_tab === $tab_name ? 'nav-tab-active' : '';
31
  }
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  /**
34
  * Return an array of all ButtonTypes
35
  *
57
  return array(
58
  'PHONE' => 'Phone',
59
  'EMAIL' => 'Email',
60
+ 'ANCHOR' => 'Anchor (smooth scroll)',
61
  'LINK' => 'Link',
62
  'MAP' => 'Google Maps',
63
  'WHATSAPP' => 'WhatsApp',
64
  'SMS' => 'SMS/Text',
65
+ 'FACEBOOK' => 'Facebook Messenger',
66
+ 'SIGNAL' => 'Signal',
67
+ 'TELEGRAM' => 'Telegram',
68
  );
69
  }
70
 
99
  // Default everything is NOT selected, then we enable only those days that are passed in via $original
100
  $result = array( false, false, false, false, false, false, false );
101
  foreach ( $result as $day_of_week_index => $day_of_week ) {
102
+ $day_of_week_is_enabled = isset( $original[ $day_of_week_index ] ) && ( $original[ $day_of_week_index ] === 'true' || $original[ $day_of_week_index ] === true );
103
  $result[ $day_of_week_index ] = $day_of_week_is_enabled;
104
  }
105
 
111
  * <p>The CTA block is optional and displays only when there's a link provided or $cta_button_text = 'none'.</p>
112
  * <p>Defaut CTA text is "Let's go". Default <code>$icon</code> is flag (value should be a dashicon name)</p>
113
  *
114
+ * <p><strong>NOTE: $body and $cta_pretext are NOT escaped and are assumed to be pre-escaped (or contain no User input)</strong></p>
115
  *
116
+ * @param $color string
117
+ * @param $headline string
118
+ * @param $body string Assumed to be pre-escaped HTML, so this will not be (re)escaped
119
+ * @param $icon string
120
+ * @param $cta_pretext string Assumed to be pre-escaped HTML, so this will not be (re)escaped
121
+ * @param $cta_button_text string
122
+ * @param $cta_button_link string URL
123
  * @param $cta_footer_notice
124
  *
125
+ * @return void It <code>echo</code>s html output of the promobox
126
  */
127
  function cnb_promobox( $color, $headline, $body, $icon = 'flag', $cta_pretext = null, $cta_button_text = 'Let\'s go', $cta_button_link = null, $cta_footer_notice = null ) {
128
+ echo '
129
  <div id="cnb_upgrade_box" class="cnb-promobox">
130
+ <div class="cnb-promobox-header cnb-promobox-header-' . esc_attr( $color ) . '">
131
+ <span class="dashicons dashicons-' . esc_attr( $icon ) . '"></span>
132
  <h2 class="hndle">' .
133
+ esc_html( $headline )
134
+ . '</h2>
135
  </div>
136
  <div class="inside">
137
  <div class="cnb-promobox-copy">
138
  <div class="cnb_promobox_item">' .
139
+ // phpcs:ignore WordPress.Security
140
+ $body
141
+ . '</div>
142
  <div class="clear"></div>';
143
  if ( ! is_null( $cta_button_link ) || $cta_button_text == 'none' ) {
144
+ echo '
145
  <div class="cnb-promobox-action">
146
  <div class="cnb-promobox-action-left">' .
147
+ // phpcs:ignore WordPress.Security
148
+ $cta_pretext
149
+ . '</div>';
150
  if ( $cta_button_text != 'none' && $cta_button_link != 'disabled' ) {
151
+ echo '
152
  <div class="cnb-promobox-action-right">
153
+ <a class="button button-primary button-large" href="' . esc_url( $cta_button_link ) . '">' . esc_html( $cta_button_text ) . '</a>
154
  </div>';
155
  } elseif ( $cta_button_link == 'disabled' ) {
156
+ echo '
157
  <div class="cnb-promobox-action-right">
158
+ <button class="button button-primary button-large" disabled>' . esc_html( $cta_button_text ) . '</a>
159
  </div>';
160
  }
161
+ echo '
162
  <div class="clear"></div>';
163
  if ( ! is_null( $cta_footer_notice ) ) {
164
+ echo '<div class="nonessential" style="padding-top: 5px;">' . esc_html( $cta_footer_notice ) . '</div>';
165
  }
166
+ echo '
167
  </div>
168
  ';
169
  }
170
+ echo '
171
  </div>
172
  </div>
173
  </div>
174
  ';
 
 
 
175
  }
176
 
177
  /**
178
+ *
179
  * Returns the url for the Upgrade to cloud page
180
  *
181
  * @return string upgrade page url
182
  */
183
  function cnb_legacy_upgrade_page() {
184
+ $url = admin_url( 'admin.php' );
 
185
 
186
+ return add_query_arg( 'page', 'call-now-button-upgrade', $url );
187
  }
188
+ }
src/utils/CnbUtils.php CHANGED
@@ -54,49 +54,6 @@ class CnbUtils {
54
  update_option( 'cnb', $updated_options );
55
  }
56
 
57
- /**
58
- * Color functions to calculate borders
59
- *
60
- * @param $color string hex color (#abcdef)
61
- * @param $direction string "lighter" (for 45 shades lighter or "darker" -30 otherwise)
62
- *
63
- * @return string
64
- */
65
- function changeColor( $color, $direction ) {
66
- preg_match( '/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i', $color, $parts );
67
- if ( ! isset( $direction ) || $direction == "lighter" ) {
68
- $change = 45;
69
- } else {
70
- $change = - 30;
71
- }
72
- for ( $i = 1; $i <= 3; $i ++ ) {
73
- $parts[ $i ] = hexdec( $parts[ $i ] );
74
- $parts[ $i ] = round( $parts[ $i ] + $change );
75
- if ( $parts[ $i ] > 255 ) {
76
- $parts[ $i ] = 255;
77
- } elseif ( $parts[ $i ] < 0 ) {
78
- $parts[ $i ] = 0;
79
- }
80
- $parts[ $i ] = dechex( $parts[ $i ] );
81
- }
82
-
83
- return '#' . str_pad( $parts[1], 2, "0", STR_PAD_LEFT ) . str_pad( $parts[2], 2, "0", STR_PAD_LEFT ) . str_pad( $parts[3], 2, "0", STR_PAD_LEFT );
84
- }
85
-
86
- /**
87
- * Note this function escapes both inputs
88
- * @param $color
89
- * @param $icon
90
- *
91
- * @return string
92
- */
93
- function svg( $color, $icon ) {
94
- $phone = '<path d="M7.104 14.032l15.586 1.984c0 0-0.019 0.5 0 0.953c0.029 0.756-0.26 1.534-0.809 2.1 l-4.74 4.742c2.361 3.3 16.5 17.4 19.8 19.8l16.813 1.141c0 0 0 0.4 0 1.1 c-0.002 0.479-0.176 0.953-0.549 1.327l-6.504 6.505c0 0-11.261 0.988-25.925-13.674C6.117 25.3 7.1 14 7.1 14" fill="' . esc_attr( $color ) . '"/><path d="M7.104 13.032l6.504-6.505c0.896-0.895 2.334-0.678 3.1 0.35l5.563 7.8 c0.738 1 0.5 2.531-0.36 3.426l-4.74 4.742c2.361 3.3 5.3 6.9 9.1 10.699c3.842 3.8 7.4 6.7 10.7 9.1 l4.74-4.742c0.897-0.895 2.471-1.026 3.498-0.289l7.646 5.455c1.025 0.7 1.3 2.2 0.4 3.105l-6.504 6.5 c0 0-11.262 0.988-25.925-13.674C6.117 24.3 7.1 13 7.1 13" fill="' . esc_attr( $icon ) . '"/>';
95
- $svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 60 60">' . $phone . '</svg>';
96
-
97
- return base64_encode( $svg );
98
- }
99
-
100
  /**
101
  * Returns true if the `active` flag is set and is enabled
102
  *
@@ -124,16 +81,16 @@ class CnbUtils {
124
  return isset( $cnb_options['cloud_enabled'] ) && $cnb_options['cloud_enabled'] == 1 ? 1 : 0;
125
  }
126
 
127
- /**
128
- * Check if the Cloud ID (user or domain) is set
129
- *
130
- * @param $cnb_options array
131
- *
132
- * @return int|string int 0 if no ID is found, otherwise the string UUID is returned.
133
- */
134
- private function isCloudIdSet( $cnb_options ) {
135
- return isset( $cnb_options['cloud_use_id'] ) && ! empty( $cnb_options['cloud_use_id'] ) ? $cnb_options['cloud_use_id'] : 0;
136
- }
137
 
138
  /**
139
  * Convert an "order" integer into a proper zIndex (10 to 2147483647, for example)
@@ -144,8 +101,11 @@ class CnbUtils {
144
  */
145
  function zindex( $value ) {
146
  $zindexMap = $this->getZindexMap();
147
-
148
- return $zindexMap[ $value ];
 
 
 
149
  }
150
 
151
  private function getZindexMap() {
@@ -206,27 +166,37 @@ class CnbUtils {
206
  return 'chat';
207
  case 'WHATSAPP':
208
  return 'whatsapp';
 
 
 
 
 
 
209
  case 'PHONE':
210
  default:
211
  return 'call';
212
  }
213
  }
214
 
215
- function cnb_utm_params( $element, $page, $echo = true ) {
216
- $output = "?utm_source=wp-plugin";
217
- $output .= "&utm_medium=referral";
218
- $output .= "&utm_campaign=" . $element;
219
- $output .= "&utm_term=" . $page;
220
- if ( $echo ) {
221
- echo $output;
222
- }
 
 
 
 
223
 
224
  return $output;
225
  }
226
 
227
  function cnb_array_column( $array, $column_key, $index_key = null ) {
228
  if ( version_compare( PHP_VERSION, '7.0.0', '>=' ) ) {
229
- // phpcs:ignore
230
  return array_column( $array, $column_key, $index_key );
231
  } else {
232
  // Convert objects to array, since PHP < 7 cannot deal with objects as the first argument
@@ -238,7 +208,7 @@ class CnbUtils {
238
  return array_column_ext( $array_arr, $column_key, $index_key );
239
  }
240
 
241
- // phpcs:ignore
242
  return array_column( $array_arr, $column_key, $index_key );
243
  }
244
  }
@@ -246,9 +216,9 @@ class CnbUtils {
246
  function cnb_timestamp_to_string( $timestamp ) {
247
  $timestamp_parsed = strtotime( $timestamp );
248
  if ( $timestamp instanceof stdClass ) {
249
- return date( "r", $timestamp->seconds );
250
  } else if ( $timestamp_parsed ) {
251
- return date( "r", $timestamp_parsed );
252
  }
253
 
254
  return $timestamp;
@@ -269,16 +239,14 @@ class CnbUtils {
269
 
270
  function get_cnb_domain_upgrade( $cnb_cloud_domain ) {
271
  if ( $cnb_cloud_domain !== null && ! ( $cnb_cloud_domain instanceof WP_Error ) ) {
272
- $url = admin_url( 'admin.php' );
273
- $upgrade_link =
274
- add_query_arg( array(
275
- 'page' => 'call-now-button-domains',
276
- 'action' => 'upgrade',
277
- 'id' => $cnb_cloud_domain->id
278
- ),
279
- $url );
280
-
281
- return esc_url( $upgrade_link );
282
  }
283
 
284
  return null;
@@ -286,7 +254,7 @@ class CnbUtils {
286
 
287
  function is_use_cloud( $cnb_options ) {
288
  $cloud_enabled = $this->isCloudActive( $cnb_options );
289
- $cloud_use_id = $this->isCloudIdSet($cnb_options);
290
 
291
  return $cloud_enabled && $cloud_use_id !== 0;
292
  }
@@ -306,4 +274,40 @@ class CnbUtils {
306
 
307
  return $is_utc_exactly || ( ! ( $plus_variants_domain || $utc_variants_domain ) && $has_slash );
308
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  }
54
  update_option( 'cnb', $updated_options );
55
  }
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  /**
58
  * Returns true if the `active` flag is set and is enabled
59
  *
81
  return isset( $cnb_options['cloud_enabled'] ) && $cnb_options['cloud_enabled'] == 1 ? 1 : 0;
82
  }
83
 
84
+ /**
85
+ * Check if the Cloud ID (user or domain) is set
86
+ *
87
+ * @param $cnb_options array
88
+ *
89
+ * @return int|string int 0 if no ID is found, otherwise the string UUID is returned.
90
+ */
91
+ private function isCloudIdSet( $cnb_options ) {
92
+ return isset( $cnb_options['cloud_use_id'] ) && ! empty( $cnb_options['cloud_use_id'] ) ? $cnb_options['cloud_use_id'] : 0;
93
+ }
94
 
95
  /**
96
  * Convert an "order" integer into a proper zIndex (10 to 2147483647, for example)
101
  */
102
  function zindex( $value ) {
103
  $zindexMap = $this->getZindexMap();
104
+ $default = 10;
105
+ if (array_key_exists($value, $zindexMap)) {
106
+ return $zindexMap[ $value ];
107
+ }
108
+ return $zindexMap[$default];
109
  }
110
 
111
  private function getZindexMap() {
166
  return 'chat';
167
  case 'WHATSAPP':
168
  return 'whatsapp';
169
+ case 'FACEBOOK':
170
+ return 'facebook_messenger';
171
+ case 'SIGNAL':
172
+ return 'signal';
173
+ case 'TELEGRAM':
174
+ return 'telegram';
175
  case 'PHONE':
176
  default:
177
  return 'call';
178
  }
179
  }
180
 
181
+ /**
182
+ *
183
+ * @param $element
184
+ * @param $page
185
+ *
186
+ * @return string
187
+ */
188
+ function cnb_utm_params( $element, $page ) {
189
+ $output = '?utm_source=wp-plugin_' . CNB_VERSION;
190
+ $output .= '&utm_medium=referral';
191
+ $output .= '&utm_campaign=' . $element;
192
+ $output .= '&utm_term=' . $page;
193
 
194
  return $output;
195
  }
196
 
197
  function cnb_array_column( $array, $column_key, $index_key = null ) {
198
  if ( version_compare( PHP_VERSION, '7.0.0', '>=' ) ) {
199
+ // phpcs:ignore PHPCompatibility.FunctionUse
200
  return array_column( $array, $column_key, $index_key );
201
  } else {
202
  // Convert objects to array, since PHP < 7 cannot deal with objects as the first argument
208
  return array_column_ext( $array_arr, $column_key, $index_key );
209
  }
210
 
211
+ // phpcs:ignore PHPCompatibility.FunctionUse
212
  return array_column( $array_arr, $column_key, $index_key );
213
  }
214
  }
216
  function cnb_timestamp_to_string( $timestamp ) {
217
  $timestamp_parsed = strtotime( $timestamp );
218
  if ( $timestamp instanceof stdClass ) {
219
+ return date( 'r', $timestamp->seconds );
220
  } else if ( $timestamp_parsed ) {
221
+ return date( 'r', $timestamp_parsed );
222
  }
223
 
224
  return $timestamp;
239
 
240
  function get_cnb_domain_upgrade( $cnb_cloud_domain ) {
241
  if ( $cnb_cloud_domain !== null && ! ( $cnb_cloud_domain instanceof WP_Error ) ) {
242
+ $url = admin_url( 'admin.php' );
243
+
244
+ return add_query_arg( array(
245
+ 'page' => 'call-now-button-domains',
246
+ 'action' => 'upgrade',
247
+ 'id' => $cnb_cloud_domain->id
248
+ ),
249
+ $url );
 
 
250
  }
251
 
252
  return null;
254
 
255
  function is_use_cloud( $cnb_options ) {
256
  $cloud_enabled = $this->isCloudActive( $cnb_options );
257
+ $cloud_use_id = $this->isCloudIdSet( $cnb_options );
258
 
259
  return $cloud_enabled && $cloud_use_id !== 0;
260
  }
274
 
275
  return $is_utc_exactly || ( ! ( $plus_variants_domain || $utc_variants_domain ) && $has_slash );
276
  }
277
+
278
+ /**
279
+ * Similar to WP_Query get_query_val, but for admin pages (since get_query_val does not work outside The Loop).
280
+ *
281
+ * @param $key string The query parameter to get
282
+ * @param $default string
283
+ *
284
+ * @return string sanitized value of the $_GET parameter
285
+ */
286
+ function get_query_val( $key, $default = '' ) {
287
+ // phpcs:ignore WordPress.Security
288
+ if ( key_exists( $key, $_GET ) && ! empty( $_GET[ $key ] ) ) {
289
+ // phpcs:ignore WordPress.Security
290
+ return sanitize_text_field( wp_unslash( $_GET[ $key ] ) );
291
+ }
292
+
293
+ return $default;
294
+ }
295
+
296
+ /**
297
+ * Similar to WP_Query get_query_val, but for admin pages (since get_query_val does not work outside The Loop).
298
+ *
299
+ * @param $key string The POST parameter to get
300
+ * @param $default string
301
+ *
302
+ * @return string sanitized value of the $_GET parameter
303
+ */
304
+ function get_post_val( $key, $default = '' ) {
305
+ // phpcs:ignore WordPress.Security
306
+ if ( key_exists( $key, $_POST ) && ! empty( $_POST[ $key ] ) ) {
307
+ // phpcs:ignore WordPress.Security
308
+ return sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
309
+ }
310
+
311
+ return $default;
312
+ }
313
  }
src/utils/cnb-backwards-compatible.php CHANGED
@@ -36,20 +36,20 @@ if ( ! function_exists( 'boolval' ) ) {
36
  }
37
 
38
  /**
39
- * For Wordpress < 4.0
40
  */
41
  if ( ! function_exists( 'wp_generate_uuid4' ) ) {
42
  function wp_generate_uuid4() {
43
  return sprintf(
44
  '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
45
- mt_rand( 0, 0xffff ),
46
- mt_rand( 0, 0xffff ),
47
- mt_rand( 0, 0xffff ),
48
- mt_rand( 0, 0x0fff ) | 0x4000,
49
- mt_rand( 0, 0x3fff ) | 0x8000,
50
- mt_rand( 0, 0xffff ),
51
- mt_rand( 0, 0xffff ),
52
- mt_rand( 0, 0xffff )
53
  );
54
  }
55
  }
36
  }
37
 
38
  /**
39
+ * For WordPress < 4.0
40
  */
41
  if ( ! function_exists( 'wp_generate_uuid4' ) ) {
42
  function wp_generate_uuid4() {
43
  return sprintf(
44
  '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
45
+ wp_rand( 0, 0xffff ),
46
+ wp_rand( 0, 0xffff ),
47
+ wp_rand( 0, 0xffff ),
48
+ wp_rand( 0, 0x0fff ) | 0x4000,
49
+ wp_rand( 0, 0x3fff ) | 0x8000,
50
+ wp_rand( 0, 0xffff ),
51
+ wp_rand( 0, 0xffff ),
52
+ wp_rand( 0, 0xffff )
53
  );
54
  }
55
  }