PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / trunk
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster vtrunk
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / block-editor / helper.php

helper.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster trunk, at includes/block-editor/helper.php

572 lines 16.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Sellkit\Blocks;
3
4 defined( 'ABSPATH' ) || die();
5
6 /**
7 * Sellkit Blocks Endpoint.
8 *
9 * @since 2.3.0
10 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
11 */
12 class Sellkit_Blocks_Endpoint {
13 /**
14 * Class instance.
15 *
16 * @since 2.3.0
17 * @var Sellkit_Blocks_Endpoint
18 */
19 private static $instance = null;
20
21 /**
22 * Get a class instance.
23 *
24 * @since 2.3.0
25 *
26 * @return Sellkit_Blocks_Endpoint Class
27 */
28 public static function get_instance() {
29 if ( is_null( self::$instance ) ) {
30 self::$instance = new self();
31 }
32
33 return self::$instance;
34 }
35
36 /**
37 * Class constructor.
38 *
39 * @since 2.3.0
40 */
41 private function __construct() {
42 add_action( 'rest_api_init', [ $this, 'register_crm_endpoint' ] );
43 }
44
45 /**
46 * Check if user has admin permission.
47 *
48 * @since 2.3.0
49 * @return bool
50 */
51 public function admin_permission_callback() {
52 return current_user_can( 'administrator' );
53 }
54
55 /**
56 * Fetch data from a given API endpoint.
57 *
58 * @since 2.3.0
59 * @param string $url The API endpoint URL.
60 * @param array $headers The request headers.
61 * @return array|WP_Error
62 */
63 private function fetch_api_data( $url, $headers = [] ) {
64 $response = wp_remote_get( $url, [
65 'timeout' => 100,
66 'sslverify' => false,
67 'headers' => $headers,
68 ] );
69
70 if ( is_wp_error( $response ) ) {
71 return new \WP_Error(
72 'http_request_failed',
73 esc_html__( 'HTTP request failed', 'sellkit' ),
74 [
75 'status' => 500,
76 'details' => $response->get_error_message()
77 ]
78 );
79 }
80
81 $body = wp_remote_retrieve_body( $response );
82 $data = json_decode( $body, true );
83
84 if ( json_last_error() !== JSON_ERROR_NONE ) {
85 return new \WP_Error(
86 'json_error',
87 esc_html__( 'Error parsing JSON response', 'sellkit' ),
88 [
89 'status' => 500,
90 'details' => json_last_error_msg()
91 ]
92 );
93 }
94
95 return $data;
96 }
97
98 /**
99 * Fetch ActiveCampaign lists, tags, and fields.
100 *
101 * @since 2.3.0
102 * @return WP_REST_Response|WP_Error
103 */
104 public function fetch_active_campaign_data() {
105 $key = sellkit_get_option( 'activecampaign_api_key', '' );
106 $url = sellkit_get_option( 'activecampaign_api_url', '' );
107
108 if ( ! $key || ! $url ) {
109 return new \WP_Error( 'missing_params', esc_html__( 'API key or URL is missing', 'sellkit' ), [ 'status' => 400 ] );
110 }
111
112 $headers = [
113 'Api-Token' => $key,
114 'Accept' => 'application/json',
115 'Content-Type' => 'application/json',
116 ];
117
118 $responses = [
119 'lists' => $this->fetch_api_data( "$url/api/3/lists", $headers ),
120 'tags' => $this->fetch_api_data( "$url/api/3/tags", $headers ),
121 'fields' => $this->fetch_api_data( "$url/api/3/fields", $headers ),
122 ];
123
124 if ( is_wp_error( $responses['lists'] ) || is_wp_error( $responses['tags'] ) || is_wp_error( $responses['fields'] ) ) {
125 return new \WP_Error( 'api_request_failed', esc_html__( 'Failed to fetch data from ActiveCampaign API', 'sellkit' ), [ 'status' => 500 ] );
126 }
127
128 $responses['fields']['fields'] = [
129 'email' => esc_html__( 'Email', 'sellkit' ),
130 'firstName' => esc_html__( 'First Name', 'sellkit' ),
131 'lastName' => esc_html__( 'Last Name', 'sellkit' ),
132 'phone' => esc_html__( 'Phone', 'sellkit' ),
133 ];
134
135 return rest_ensure_response( $responses );
136 }
137
138 /**
139 * Fetch ConvertKit data (forms, tags, and custom fields).
140 *
141 * @since 2.3.0
142 * @return WP_REST_Response|WP_Error
143 */
144 public function fetch_convertkit_data() {
145 $api_key = sellkit_get_option( 'convertkit_api_key', '' );
146
147 if ( ! $api_key ) {
148 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
149 }
150
151 $url = 'https://api.convertkit.com/v3/';
152 $responses = [
153 'forms' => $this->fetch_api_data( "$url/forms?api_key=$api_key" ),
154 'tags' => $this->fetch_api_data( "$url/tags?api_key=$api_key" ),
155 'fields' => $this->fetch_api_data( "$url/custom_fields?api_key=$api_key" ),
156 ];
157
158 if ( is_wp_error( $responses['forms'] ) || is_wp_error( $responses['tags'] ) || is_wp_error( $responses['fields'] ) ) {
159 return new \WP_Error( 'api_request_failed', esc_html__( 'Failed to fetch data from ConvertKit API', 'sellkit' ), [ 'status' => 500 ] );
160 }
161
162 $custom_fields = [
163 'email' => esc_html__( 'Email', 'sellkit' ),
164 'first_name' => esc_html__( 'First Name', 'sellkit' ),
165 ];
166
167 if ( isset( $responses['fields']['custom_fields'] ) && is_array( $responses['fields']['custom_fields'] ) ) {
168 $responses['fields']['custom_fields'] = array_merge( $responses['fields']['custom_fields'], $custom_fields );
169 } else {
170 $responses['fields']['custom_fields'] = $custom_fields;
171 }
172
173 return rest_ensure_response( $responses );
174 }
175
176 /**
177 * Fetch Drip accounts.
178 *
179 * @since 2.3.0
180 * @return WP_REST_Response|WP_Error
181 */
182 public function fetch_drip_accounts() {
183 $api_key = sellkit_get_option( 'drip_api_key', '' );
184
185 if ( ! $api_key ) {
186 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
187 }
188
189 $url = 'https://api.getdrip.com/v2/accounts';
190 $headers = [
191 'Authorization' => 'Basic ' . base64_encode( $api_key ),
192 'Content-Type' => 'application/vnd.api+json',
193 'User-Agent' => 'sellkit',
194 ];
195
196 $data = $this->fetch_api_data( $url, $headers );
197
198 if ( is_wp_error( $data ) ) {
199 return $data;
200 }
201
202 $accounts = array_map( function( $account ) {
203 return [
204 'id' => $account['id'],
205 'name' => $account['name'],
206 ];
207 }, $data['accounts'] );
208
209 return rest_ensure_response( $accounts );
210 }
211
212 /**
213 * Fetch Drip tags and custom fields for a specific account.
214 *
215 * @since 2.3.0
216 * @param WP_REST_Request $request The REST API request object.
217 * @return WP_REST_Response|WP_Error
218 */
219 public function fetch_drip_tags_fields( $request ) {
220 $api_key = sellkit_get_option( 'drip_api_key', '' );
221 $account_id = $request->get_param( 'account_id' );
222
223 if ( ! $api_key ) {
224 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
225 }
226
227 if ( ! $account_id ) {
228 return new \WP_Error( 'missing_params', esc_html__( 'Account ID is missing', 'sellkit' ), [ 'status' => 400 ] );
229 }
230
231 $url = "https://api.getdrip.com/v2/$account_id";
232 $headers = [
233 'Authorization' => 'Basic ' . base64_encode( $api_key ),
234 'Content-Type' => 'application/vnd.api+json',
235 'User-Agent' => 'sellkit',
236 ];
237
238 $tags = $this->fetch_api_data( "$url/tags", $headers );
239 $fields = $this->fetch_api_data( "$url/custom_field_identifiers", $headers );
240
241 if ( is_wp_error( $tags ) || is_wp_error( $fields ) ) {
242 return new \WP_Error( 'api_request_failed', __( 'Failed to fetch data from Drip API', 'sellkit' ), [ 'status' => 500 ] );
243 }
244
245 $custom_fields = [
246 'email' => esc_html__( 'Email', 'sellkit' ),
247 'first_name' => esc_html__( 'First Name', 'sellkit' ),
248 'last_name' => esc_html__( 'Last Name', 'sellkit' ),
249 'address1' => esc_html__( 'Address 1', 'sellkit' ),
250 'address2' => esc_html__( 'Address 2', 'sellkit' ),
251 'city' => esc_html__( 'City', 'sellkit' ),
252 'state' => esc_html__( 'State', 'sellkit' ),
253 'country' => esc_html__( 'Country', 'sellkit' ),
254 'zip' => esc_html__( 'Zip', 'sellkit' ),
255 'phone' => esc_html__( 'Phone', 'sellkit' ),
256 'sms_number' => esc_html__( 'SMS Number', 'sellkit' ),
257 'sms_consent' => esc_html__( 'SMS Consent', 'sellkit' ),
258 'time_zone' => esc_html__( 'Timezone', 'sellkit' ),
259 ];
260
261 if ( isset( $fields['custom_field_definitions'] ) && is_array( $fields['custom_field_definitions'] ) ) {
262 $fields['custom_field_definitions'] = array_merge( $fields['custom_field_definitions'], $custom_fields );
263 } else {
264 $fields['custom_field_definitions'] = $custom_fields;
265 }
266
267 return rest_ensure_response([
268 'tags' => $tags['tags'] ?? [],
269 'fields' => $fields['custom_field_definitions'] ?? [],
270 ]);
271 }
272
273 /**
274 * Fetch GetResponse data (campaigns, tags, and custom fields).
275 *
276 * @since 2.3.0
277 * @return WP_REST_Response|WP_Error
278 */
279 public function fetch_getresponse_data() {
280 $api_key = sellkit_get_option( 'getresponse_api_key', '' );
281
282 if ( ! $api_key ) {
283 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
284 }
285
286 $url = 'https://api.getresponse.com/v3';
287 $headers = [
288 'X-Auth-Token' => 'api-key ' . $api_key,
289 'Content-Type' => 'application/json',
290 'User-Agent' => 'sellkit',
291 ];
292
293 $responses = [
294 'campaigns' => $this->fetch_api_data( "$url/campaigns", $headers ),
295 'tags' => $this->fetch_api_data( "$url/tags", $headers ),
296 'fields' => $this->fetch_api_data( "$url/custom-fields", $headers ),
297 ];
298
299 if ( is_wp_error( $responses['campaigns'] ) || is_wp_error( $responses['tags'] ) || is_wp_error( $responses['fields'] ) ) {
300 return new \WP_Error( 'api_request_failed', esc_html__( 'Failed to fetch data from GetResponse API', 'sellkit' ), [ 'status' => 500 ] );
301 }
302
303 $custom_fields = [
304 'email' => esc_html__( 'Email', 'sellkit' ),
305 'name' => esc_html__( 'Name', 'sellkit' ),
306 ];
307
308 foreach ( $responses['fields'] as $field ) {
309 if ( is_array( $field ) && isset( $field['customFieldId'] ) ) {
310 $custom_fields[ $field['customFieldId'] ] = $field['name'];
311 }
312 }
313
314 $responses['fields'] = $custom_fields;
315
316 return rest_ensure_response( $responses );
317 }
318
319 /**
320 * Fetch Mailchimp audiences.
321 *
322 * @since 2.3.0
323 * @return WP_REST_Response|WP_Error
324 */
325 public function fetch_mailchimp_audiences() {
326 $api_key = sellkit_get_option( 'mailchimp_api_key', '' );
327
328 if ( ! $api_key ) {
329 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
330 }
331
332 $parts = explode( '-', $api_key );
333
334 if ( 2 !== count( $parts ) ) {
335 return new \WP_Error( 'invalid_api_key', esc_html__( 'Invalid API key format', 'sellkit' ), [ 'status' => 400 ] );
336 }
337
338 $api = [
339 'token' => $parts[0],
340 'server' => $parts[1],
341 ];
342
343 $url = "https://{$api['server']}.api.mailchimp.com/3.0/lists?count=999";
344 $headers = [
345 'Authorization' => 'Basic ' . base64_encode( 'user:' . $api['token'] ),
346 'Content-Type' => 'application/json',
347 'User-Agent' => 'sellkit',
348 ];
349
350 $data = $this->fetch_api_data( $url, $headers );
351
352 if ( is_wp_error( $data ) ) {
353 return $data;
354 }
355
356 $lists = [];
357
358 if ( ! empty( $data['lists'] ) ) {
359 foreach ( $data['lists'] as $list ) {
360 $lists[ $list['id'] ] = [
361 'name' => $list['name'],
362 'value' => $list['id'],
363 ];
364 }
365 }
366
367 return rest_ensure_response( [ 'lists' => $lists ] );
368 }
369
370 /**
371 * Fetch Mailchimp data (tags, fields, groups, and double opt-in settings based on audience).
372 *
373 * @since 2.3.0
374 * @param WP_REST_Request $request The REST API request object.
375 * @return WP_REST_Response|WP_Error
376 * @SuppressWarnings(PHPMD.NPathComplexity)
377 */
378 public function fetch_mailchimp_data( $request ) {
379 $api_key = sellkit_get_option( 'mailchimp_api_key', '' );
380 $audience_id = $request->get_param( 'audience_id' );
381
382 if ( ! $api_key || ! $audience_id ) {
383 return new \WP_Error( 'missing_params', esc_html__( 'API key or Audience ID is missing', 'sellkit' ), [ 'status' => 400 ] );
384 }
385
386 $parts = explode( '-', $api_key );
387
388 if ( 2 !== count( $parts ) ) {
389 return new \WP_Error( 'invalid_api_key', esc_html__( 'Invalid API key format', 'sellkit' ), [ 'status' => 400 ] );
390 }
391
392 $api = [
393 'token' => $parts[0],
394 'server' => $parts[1],
395 ];
396
397 $url_base = "https://{$api['server']}.api.mailchimp.com/3.0/lists/$audience_id";
398 $headers = [
399 'Authorization' => 'Basic ' . base64_encode( 'user:' . $api['token'] ),
400 'Content-Type' => 'application/json',
401 'User-Agent' => 'sellkit',
402 ];
403
404 $tags = $this->fetch_api_data( "$url_base/tag-search", $headers );
405 $fields = $this->fetch_api_data( "$url_base/merge-fields", $headers );
406 $groups = $this->fetch_api_data( "$url_base/interest-categories?count=99", $headers );
407
408 if ( is_wp_error( $tags ) || is_wp_error( $fields ) || is_wp_error( $groups ) ) {
409 return new \WP_Error( 'api_request_failed', esc_html__( 'Failed to fetch data from Mailchimp API', 'sellkit' ), [ 'status' => 500 ] );
410 }
411
412 $custom_fields = [
413 'email' => esc_html__( 'Email', 'sellkit' ),
414 'full_name' => esc_html__( 'Full Name', 'sellkit' ),
415 ];
416
417 foreach ( $fields['merge_fields'] as $field ) {
418 if ( is_array( $field ) ) {
419 $custom_fields[ $field['tag'] ] = $field['name'];
420 }
421 }
422
423 $responses = [
424 'tags' => $tags['tags'] ?? [],
425 'fields' => $custom_fields,
426 'groups' => [],
427 ];
428
429 if ( ! empty( $groups['categories'] ) ) {
430 foreach ( $groups['categories'] as $category ) {
431 $category_data = $this->fetch_api_data( "$url_base/interest-categories/{$category['id']}/interests?count=999", $headers );
432 if ( ! is_wp_error( $category_data ) && ! empty( $category_data['interests'] ) ) {
433 foreach ( $category_data['interests'] as $interest ) {
434 $responses['groups'][ $interest['id'] ] = "{$category['title']}: {$interest['name']}";
435 }
436 }
437 }
438 }
439
440 return rest_ensure_response( $responses );
441 }
442
443 /**
444 * Fetch MailerLite groups.
445 *
446 * @since 2.3.0
447 * @return WP_REST_Response|WP_Error
448 */
449 public function fetch_mailerlite_data() {
450 $key = sellkit_get_option( 'mailerlite_api_key', '' );
451
452 if ( ! $key ) {
453 return new \WP_Error( 'missing_params', esc_html__( 'API key is missing', 'sellkit' ), [ 'status' => 400 ] );
454 }
455
456 $url_base = 'https://api.mailerlite.com/api/v2';
457 $headers = [
458 'X-MailerLite-ApiKey' => $key,
459 'Accept' => 'application/json',
460 'Content-Type' => 'application/json',
461 ];
462
463 $groups = $this->fetch_api_data( "$url_base/groups", $headers );
464 $fields = $this->fetch_api_data( "$url_base/fields", $headers );
465
466 if ( is_wp_error( $groups ) || is_wp_error( $fields ) ) {
467 return new \WP_Error( 'api_request_failed', esc_html__( 'Failed to fetch data from MailerLite API', 'sellkit' ), [ 'status' => 500 ] );
468 }
469
470 $custom_fields = [
471 'email' => esc_html__( 'Email', 'sellkit' ),
472 'name' => esc_html__( 'Name', 'sellkit' ),
473 ];
474
475 foreach ( $fields as $field ) {
476 if ( is_array( $field ) && ! array_key_exists( $field['key'], $custom_fields ) ) {
477 $custom_fields[ $field['key'] ] = $field['title'];
478 }
479 }
480
481 return rest_ensure_response( [
482 'groups' => $groups,
483 'fields' => $custom_fields,
484 ] );
485 }
486
487 /**
488 * Register CRM endpoint.
489 *
490 * @since 2.3.0
491 */
492 public function register_crm_endpoint() {
493 $routes = [
494 [
495 'namespace' => 'sellkit/v1',
496 'route' => '/activecampaign',
497 'method' => 'GET',
498 'callback' => [ $this, 'fetch_active_campaign_data' ],
499 ],
500 [
501 'namespace' => 'sellkit/v1',
502 'route' => '/convertkit',
503 'method' => 'GET',
504 'callback' => [ $this, 'fetch_convertkit_data' ],
505 ],
506 [
507 'namespace' => 'sellkit/v1',
508 'route' => '/getResponse',
509 'method' => 'GET',
510 'callback' => [ $this, 'fetch_getresponse_data' ],
511 ],
512 [
513 'namespace' => 'sellkit/v1',
514 'route' => '/mailchimp/audiences',
515 'method' => 'GET',
516 'callback' => [ $this, 'fetch_mailchimp_audiences' ],
517 ],
518 [
519 'namespace' => 'sellkit/v1',
520 'route' => '/mailchimp/data',
521 'method' => 'GET',
522 'callback' => [ $this, 'fetch_mailchimp_data' ],
523 'args' => [
524 'audience_id' => [
525 'required' => true,
526 'validate_callback' => function( $param ) {
527 return is_string( $param );
528 }
529 ]
530 ]
531 ],
532 [
533 'namespace' => 'sellkit/v1',
534 'route' => '/drip/accounts',
535 'method' => 'GET',
536 'callback' => [ $this, 'fetch_drip_accounts' ],
537 ],
538 [
539 'namespace' => 'sellkit/v1',
540 'route' => '/drip/tags-fields',
541 'method' => 'GET',
542 'callback' => [ $this, 'fetch_drip_tags_fields' ],
543 'args' => [
544 'account_id' => [
545 'required' => true,
546 'validate_callback' => function( $param ) {
547 return is_string( $param );
548 }
549 ]
550 ]
551 ],
552 [
553 'namespace' => 'sellkit/v1',
554 'route' => '/mailerlite-data',
555 'method' => 'GET',
556 'callback' => [ $this, 'fetch_mailerlite_data' ],
557 ],
558 ];
559
560 foreach ( $routes as $route ) {
561 register_rest_route( $route['namespace'], $route['route'], [
562 'methods' => $route['method'],
563 'callback' => $route['callback'],
564 'permission_callback' => [ $this, 'admin_permission_callback' ],
565 'args' => isset( $route['args'] ) ? $route['args'] : [],
566 ] );
567 }
568 }
569 }
570
571 Sellkit_Blocks_Endpoint::get_instance();
572