Skip to content

Commit 25c2c32

Browse files
committed
Refactor Brevo API integration
- migrate Brevo adapter from legacy v2 API classes to the unified v4 client and typed request objects - add full paginated list/folder fetching with request-scoped memoization - replace legacy contact model usage in admin flows and improve Brevo exception logging
1 parent 1b00ea0 commit 25c2c32

File tree

2 files changed

+333
-73
lines changed

2 files changed

+333
-73
lines changed

includes/class-brevwoo-admin.php

Lines changed: 165 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
* @link https://github.com/AlecRust/brevwoo
88
*/
99

10-
use Brevo\Client\Model\CreateContact;
10+
use Brevo\Exceptions\BrevoApiException;
11+
use Brevo\Exceptions\BrevoException;
1112

1213
/**
1314
* The admin-specific functionality of the plugin.
@@ -42,6 +43,13 @@ class BrevWoo_Admin {
4243
*/
4344
protected $wc_logger;
4445

46+
/**
47+
* Max length for debug API error body snippet.
48+
*
49+
* @var int
50+
*/
51+
private const DEBUG_ERROR_BODY_MAX_LENGTH = 300;
52+
4553
/**
4654
* Initialize the class and set its properties.
4755
*
@@ -327,13 +335,13 @@ public function render_default_lists_input( $val ) {
327335
}
328336

329337
try {
330-
$all_lists_result = $this->api_client->get_lists();
331-
$all_folders_result = $this->api_client->get_folders();
338+
$all_lists = $this->api_client->get_lists();
339+
$all_folders = $this->api_client->get_folders();
332340
$this->render_select_lists_input(
333341
$field_id, // HTML ID and name attribute.
334342
$default_brevo_lists, // Currently selected list IDs.
335-
$all_lists_result->getLists(), // All Brevo lists from API.
336-
$all_folders_result->getFolders(), // All Brevo folders from API.
343+
$all_lists, // All Brevo lists from API.
344+
$all_folders, // All Brevo folders from API.
337345
__( 'Disabled (product-specific lists only)', 'brevwoo' ) // Disabled option label.
338346
);
339347
printf(
@@ -354,6 +362,16 @@ public function render_default_lists_input( $val ) {
354362
'brevwoo'
355363
)
356364
);
365+
} catch ( BrevoApiException $e ) {
366+
printf(
367+
'<p class="description">%s</p>',
368+
esc_html__( 'Could not load lists', 'brevwoo' )
369+
);
370+
} catch ( BrevoException $e ) {
371+
printf(
372+
'<p class="description">%s</p>',
373+
esc_html__( 'Could not load lists', 'brevwoo' )
374+
);
357375
} catch ( Exception $e ) {
358376
printf(
359377
'<p class="description">%s</p>',
@@ -525,8 +543,8 @@ public function render_edit_product_panel( $post ) {
525543
}
526544

527545
try {
528-
$all_lists_result = $this->api_client->get_lists();
529-
$all_folders_result = $this->api_client->get_folders();
546+
$all_lists = $this->api_client->get_lists();
547+
$all_folders = $this->api_client->get_folders();
530548
wp_nonce_field(
531549
'brevwoo_edit_product_nonce_action',
532550
'brevwoo_edit_product_nonce'
@@ -548,13 +566,13 @@ public function render_edit_product_panel( $post ) {
548566
'<label for="brevwoo_product_lists" class="hidden">%s</label>',
549567
esc_html__( 'Product Brevo Lists', 'brevwoo' )
550568
);
551-
$this->render_select_lists_input(
552-
'brevwoo_product_lists', // HTML ID and name attribute.
553-
$product_lists, // Currently selected list IDs.
554-
$all_lists_result->getLists(), // All Brevo lists from API.
555-
$all_folders_result->getFolders(), // All Brevo folders from API.
556-
__( 'Disabled (default lists only)', 'brevwoo' ) // Disabled option label.
557-
);
569+
$this->render_select_lists_input(
570+
'brevwoo_product_lists', // HTML ID and name attribute.
571+
$product_lists, // Currently selected list IDs.
572+
$all_lists, // All Brevo lists from API.
573+
$all_folders, // All Brevo folders from API.
574+
__( 'Disabled (default lists only)', 'brevwoo' ) // Disabled option label.
575+
);
558576
printf(
559577
'<p class="howto">%s</p>',
560578
sprintf(
@@ -567,6 +585,36 @@ public function render_edit_product_panel( $post ) {
567585
'</a>'
568586
)
569587
);
588+
} catch ( BrevoApiException $e ) {
589+
$message =
590+
'<p><strong>' .
591+
esc_html__( 'Error fetching Brevo lists', 'brevwoo' ) .
592+
'</strong></p><p>' .
593+
esc_html( $e->getMessage() ) .
594+
'</p>';
595+
wp_admin_notice(
596+
$message,
597+
array(
598+
'type' => 'error',
599+
'paragraph_wrap' => false,
600+
'additional_classes' => array( 'inline' ),
601+
)
602+
);
603+
} catch ( BrevoException $e ) {
604+
$message =
605+
'<p><strong>' .
606+
esc_html__( 'Error fetching Brevo lists', 'brevwoo' ) .
607+
'</strong></p><p>' .
608+
esc_html( $e->getMessage() ) .
609+
'</p>';
610+
wp_admin_notice(
611+
$message,
612+
array(
613+
'type' => 'error',
614+
'paragraph_wrap' => false,
615+
'additional_classes' => array( 'inline' ),
616+
)
617+
);
570618
} catch ( Exception $e ) {
571619
$message =
572620
'<p><strong>' .
@@ -706,11 +754,11 @@ public function process_wc_order( $order_id ) {
706754
/**
707755
* Render a multiple select dropdown for Brevo lists, grouped by folder.
708756
*
709-
* @param string $field_id The HTML id and name attribute for the input.
710-
* @param array<int> $selected_lists The list IDs to pre-select.
711-
* @param array<object> $all_lists Brevo API lists response.
712-
* @param array<object> $all_folders Brevo API folders response.
713-
* @param string $disabled_label The label for the disabled (default) option.
757+
* @param string $field_id The HTML id and name attribute for the input.
758+
* @param array<int> $selected_lists The list IDs to pre-select.
759+
* @param array<int, array{id:int,name:string,folderId:int}> $all_lists Brevo API lists response.
760+
* @param array<int, array{id:int,name:string}> $all_folders Brevo API folders response.
761+
* @param string $disabled_label The label for the disabled (default) option.
714762
* @return void
715763
*/
716764
private function render_select_lists_input(
@@ -753,14 +801,14 @@ private function render_select_lists_input(
753801
: __( 'No folder', 'brevwoo' );
754802
echo '<optgroup label="' . esc_attr( $folder_name ) . '">';
755803
foreach ( $lists as $list ) {
756-
$selected = in_array( $list['id'], $selected_lists, true )
757-
? ' selected'
758-
: '';
759-
echo '<option value="' .
760-
esc_attr( $list['id'] ) .
761-
'"' .
762-
esc_attr( $selected ) .
763-
'>' .
804+
$selected = in_array( $list['id'], $selected_lists, true )
805+
? ' selected'
806+
: '';
807+
echo '<option value="' .
808+
esc_attr( strval( $list['id'] ) ) .
809+
'"' .
810+
esc_attr( $selected ) .
811+
'>' .
764812
esc_html( '#' . $list['id'] . ' ' . $list['name'] ) .
765813
'</option>';
766814
}
@@ -815,24 +863,18 @@ private function create_brevo_contact( $order, $list_ids ) {
815863
$order_date = $order->get_date_created()->date( 'd-m-Y' );
816864
$order_status = $order->get_status();
817865

818-
// Create the contact object.
819-
$brevo_contact = new CreateContact(
820-
array(
821-
'email' => $email,
822-
'updateEnabled' => true,
823-
'attributes' => array(
866+
try {
867+
$this->api_client->create_contact(
868+
$email,
869+
array(
824870
'FIRSTNAME' => $first_name,
825871
'LASTNAME' => $last_name,
826872
'ORDER_ID' => strval( $order_id ),
827873
'ORDER_PRICE' => $order_total,
828874
'ORDER_DATE' => $order_date,
829875
),
830-
'listIds' => $list_ids,
831-
)
832-
);
833-
834-
try {
835-
$this->api_client->create_contact( $brevo_contact );
876+
$list_ids
877+
);
836878
if ( $debug_logging ) {
837879
$this->log_contact_created(
838880
$email,
@@ -841,6 +883,31 @@ private function create_brevo_contact( $order, $list_ids ) {
841883
$order_status
842884
);
843885
}
886+
} catch ( BrevoApiException $e ) {
887+
$error_message = sprintf(
888+
'Error creating Brevo contact (HTTP %d): %s',
889+
intval( $e->getCode() ),
890+
$e->getMessage()
891+
);
892+
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
893+
error_log( 'BrevWoo: ' . $error_message );
894+
if ( $this->wc_logger ) {
895+
$this->wc_logger->error( $error_message );
896+
if ( $debug_logging ) {
897+
$this->wc_logger->debug(
898+
'Brevo API error body: ' .
899+
$this->format_debug_error_body( $e->getBody() )
900+
);
901+
}
902+
}
903+
} catch ( BrevoException $e ) {
904+
$error_message =
905+
'Error creating Brevo contact: ' . $e->getMessage();
906+
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
907+
error_log( 'BrevWoo: ' . $error_message );
908+
if ( $this->wc_logger ) {
909+
$this->wc_logger->error( $error_message );
910+
}
844911
} catch ( Exception $e ) {
845912
$error_message =
846913
'Error creating Brevo contact: ' . $e->getMessage();
@@ -876,6 +943,34 @@ private function render_brevo_status_notice() {
876943
'additional_classes' => array( 'notice-alt' ),
877944
)
878945
);
946+
} catch ( BrevoApiException $e ) {
947+
$message =
948+
'<p><strong>' .
949+
esc_html__( 'Error connecting to Brevo', 'brevwoo' ) .
950+
'</strong></p><p>' .
951+
esc_html( $e->getMessage() ) .
952+
'</p>';
953+
wp_admin_notice(
954+
$message,
955+
array(
956+
'type' => 'error',
957+
'paragraph_wrap' => false,
958+
)
959+
);
960+
} catch ( BrevoException $e ) {
961+
$message =
962+
'<p><strong>' .
963+
esc_html__( 'Error connecting to Brevo', 'brevwoo' ) .
964+
'</strong></p><p>' .
965+
esc_html( $e->getMessage() ) .
966+
'</p>';
967+
wp_admin_notice(
968+
$message,
969+
array(
970+
'type' => 'error',
971+
'paragraph_wrap' => false,
972+
)
973+
);
879974
} catch ( Exception $e ) {
880975
$message =
881976
'<p><strong>' .
@@ -893,6 +988,37 @@ private function render_brevo_status_notice() {
893988
}
894989
}
895990

991+
/**
992+
* Format an API error response body for concise debug logging.
993+
*
994+
* @param mixed $body Raw API response body from Brevo exception.
995+
* @return string
996+
*/
997+
private function format_debug_error_body( $body ) {
998+
$body_string = '';
999+
1000+
if ( is_string( $body ) ) {
1001+
$body_string = $body;
1002+
} elseif ( is_array( $body ) ) {
1003+
$encoded = wp_json_encode( $body );
1004+
$body_string = is_string( $encoded ) ? $encoded : '';
1005+
} elseif ( is_object( $body ) ) {
1006+
$encoded = wp_json_encode( $body );
1007+
$body_string = is_string( $encoded ) ? $encoded : '';
1008+
}
1009+
1010+
if ( '' === $body_string ) {
1011+
return 'No API response body';
1012+
}
1013+
1014+
$body_string = wp_strip_all_tags( $body_string );
1015+
if ( strlen( $body_string ) > self::DEBUG_ERROR_BODY_MAX_LENGTH ) {
1016+
return substr( $body_string, 0, self::DEBUG_ERROR_BODY_MAX_LENGTH ) . '...';
1017+
}
1018+
1019+
return $body_string;
1020+
}
1021+
8961022
/**
8971023
* Log Brevo contact add to WooCommerce.
8981024
*

0 commit comments

Comments
 (0)