Skip to content

Commit e1f4dff

Browse files
authored
Forms: Add backend MailPoet integration (#44439)
1 parent 7498c09 commit e1f4dff

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: added
3+
4+
Forms: Add MailPoet backend integration.

projects/packages/forms/src/contact-form/class-contact-form-plugin.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Automattic\Jetpack\Constants;
1212
use Automattic\Jetpack\Extensions\Contact_Form\Contact_Form_Block;
1313
use Automattic\Jetpack\Forms\Jetpack_Forms;
14+
use Automattic\Jetpack\Forms\Service\MailPoet_Integration;
1415
use Automattic\Jetpack\Forms\Service\Post_To_Url;
1516
use Automattic\Jetpack\Status;
1617
use Automattic\Jetpack\Terms_Of_Service;
@@ -301,6 +302,16 @@ protected function __construct() {
301302
}
302303

303304
self::register_contact_form_blocks();
305+
306+
// Register MailPoet integration hook after the class is loaded.
307+
if ( Jetpack_Forms::is_mailpoet_enabled() ) {
308+
add_action(
309+
'grunion_after_feedback_post_inserted',
310+
array( MailPoet_Integration::class, 'handle_mailpoet_integration' ),
311+
15,
312+
4
313+
);
314+
}
304315
}
305316

306317
/**
@@ -1383,6 +1394,7 @@ public function process_form_submission() {
13831394
if ( ! empty( $form->attributes['salesforceData'] ) || ! empty( $form->attributes['postToUrl'] ) ) {
13841395
Post_To_Url::init();
13851396
}
1397+
13861398
// Process the form
13871399
return $form->process_submission();
13881400
}

projects/packages/forms/src/contact-form/class-contact-form.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ public function __construct( $attributes, $content = null, $set_id = true ) {
179179
'customThankyouMessage' => __( 'Thank you for your submission!', 'jetpack-forms' ), // The message to show when customThankyou is set to 'message'.
180180
'customThankyouRedirect' => '', // The URL to redirect to when customThankyou is set to 'redirect'.
181181
'jetpackCRM' => true, // Whether Jetpack CRM should store the form submission.
182+
'connectMailPoet' => false, // Whether to send contact to MailPoet.
182183
'className' => null,
183184
'postToUrl' => null,
184185
'salesforceData' => null,
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<?php
2+
/**
3+
* MailPoet Integration for Jetpack Contact Forms.
4+
*
5+
* @package automattic/jetpack
6+
*/
7+
8+
namespace Automattic\Jetpack\Forms\Service;
9+
10+
/**
11+
* Class MailPoet_Integration
12+
*
13+
* Handles integration with MailPoet for Jetpack Contact Forms.
14+
*/
15+
class MailPoet_Integration {
16+
/**
17+
* MailPoet API instance
18+
*
19+
* @var mixed
20+
*/
21+
protected static $mailpoet_api = null;
22+
23+
/**
24+
* Get the MailPoet API instance (v1), instantiating if necessary.
25+
*
26+
* @return mixed
27+
*/
28+
protected static function get_api() {
29+
if ( null === self::$mailpoet_api && class_exists( '\MailPoet\API\API' ) ) {
30+
// @phan-suppress-next-line PhanUndeclaredClassMethod
31+
self::$mailpoet_api = \MailPoet\API\API::MP( 'v1' );
32+
}
33+
return self::$mailpoet_api;
34+
}
35+
36+
/**
37+
* Get or create a MailPoet list for Jetpack Forms.
38+
*
39+
* @param mixed $mailpoet_api The MailPoet API instance.
40+
* @param string|null $list_name Optional. The name of the list to get or create. Defaults to 'Jetpack Form Subscribers'.
41+
* @return string|null List ID or null on failure.
42+
*/
43+
protected static function get_or_create_list_id( $mailpoet_api, $list_name = null ) {
44+
$default_list_name = 'Jetpack Form Subscribers';
45+
$default_list_description = 'Subscribers from Jetpack Forms';
46+
$list_name = $list_name ? $list_name : $default_list_name;
47+
$list_description = $list_name === $default_list_name ? $default_list_description : $list_name;
48+
try {
49+
$lists = $mailpoet_api->getLists();
50+
// Look for an existing list with the given name (not deleted)
51+
foreach ( $lists as $list ) {
52+
if ( $list['name'] === $list_name && empty( $list['deleted_at'] ) ) {
53+
return $list['id'];
54+
}
55+
}
56+
// Not found, create it
57+
$new_list = $mailpoet_api->addList(
58+
array(
59+
'name' => $list_name,
60+
'description' => $list_description,
61+
)
62+
);
63+
return $new_list['id'];
64+
} catch ( \Exception $e ) {
65+
return null;
66+
}
67+
}
68+
69+
/**
70+
* Add a subscriber to a MailPoet list.
71+
*
72+
* @param mixed $mailpoet_api The MailPoet API instance.
73+
* @param string $list_id The MailPoet list ID.
74+
* @param array $subscriber_data Associative array with at least 'email', optionally 'first_name', 'last_name'.
75+
* @return array|null Subscriber data on success, or null on failure.
76+
*/
77+
protected static function add_subscriber_to_list( $mailpoet_api, $list_id, $subscriber_data ) {
78+
try {
79+
$subscriber = $mailpoet_api->addSubscriber(
80+
$subscriber_data,
81+
array( $list_id )
82+
);
83+
return $subscriber;
84+
} catch ( \Exception $e ) {
85+
return null;
86+
}
87+
}
88+
89+
/**
90+
* Extract subscriber data (email, first_name, last_name) from form fields.
91+
*
92+
* @param array $fields Collection of Contact_Form_Field instances.
93+
* @return array Associative array with at least 'email', optionally 'first_name', 'last_name'. Empty array if no email found.
94+
*/
95+
protected static function get_subscriber_data_from_fields( $fields ) {
96+
// Try and get the form from any of the fields
97+
$form = null;
98+
foreach ( $fields as $field ) {
99+
if ( ! empty( $field->form ) ) {
100+
$form = $field->form;
101+
break;
102+
}
103+
}
104+
if ( ! $form || ! is_a( $form, 'Automattic\Jetpack\Forms\ContactForm\Contact_Form' ) ) {
105+
return array();
106+
}
107+
108+
$subscriber_data = array();
109+
foreach ( $form->fields as $field ) {
110+
$id = strtolower( str_replace( array( ' ', '_' ), '', $field->get_attribute( 'id' ) ) );
111+
$label = strtolower( str_replace( array( ' ', '_' ), '', $field->get_attribute( 'label' ) ) );
112+
$value = trim( $field->value );
113+
114+
if ( ( $id === 'email' || $label === 'email' ) && ! empty( $value ) ) {
115+
$subscriber_data['email'] = $value;
116+
} elseif ( ( $id === 'firstname' || $label === 'firstname' ) && ! empty( $value ) ) {
117+
$subscriber_data['first_name'] = $value;
118+
} elseif ( ( $id === 'lastname' || $label === 'lastname' ) && ! empty( $value ) ) {
119+
$subscriber_data['last_name'] = $value;
120+
}
121+
}
122+
123+
if ( empty( $subscriber_data['email'] ) ) {
124+
return array();
125+
}
126+
127+
return $subscriber_data;
128+
}
129+
130+
/**
131+
* Handle MailPoet integration after feedback post is inserted.
132+
*
133+
* @param int $post_id The post ID for the feedback CPT.
134+
* @param array $fields Collection of Contact_Form_Field instances.
135+
* @param bool $is_spam Whether the submission is spam.
136+
*/
137+
public static function handle_mailpoet_integration( $post_id, $fields, $is_spam ) {
138+
if ( $is_spam ) {
139+
return;
140+
}
141+
142+
// Try and get the form from any of the fields
143+
$form = null;
144+
foreach ( $fields as $field ) {
145+
if ( ! empty( $field->form ) ) {
146+
$form = $field->form;
147+
break;
148+
}
149+
}
150+
if ( ! $form || ! is_a( $form, 'Automattic\Jetpack\Forms\ContactForm\Contact_Form' ) ) {
151+
return;
152+
}
153+
154+
if ( empty( $form->attributes['connectMailPoet'] ) ) {
155+
return;
156+
}
157+
158+
$mailpoet_api = self::get_api();
159+
if ( ! $mailpoet_api ) {
160+
// MailPoet is not active or not loaded.
161+
return;
162+
}
163+
164+
$list_id = self::get_or_create_list_id( $mailpoet_api );
165+
if ( ! $list_id ) {
166+
// Could not get or create the list; bail out.
167+
return;
168+
}
169+
170+
$subscriber_data = self::get_subscriber_data_from_fields( $fields );
171+
if ( empty( $subscriber_data ) ) {
172+
// Email is required for MailPoet subscribers.
173+
return;
174+
}
175+
176+
self::add_subscriber_to_list( $mailpoet_api, $list_id, $subscriber_data );
177+
}
178+
}

projects/packages/forms/tests/php/contact-form/Contact_Form_Test.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,7 @@ public function test_get_instance_from_jwt_returns_with_all_attribute_data() {
29592959
'hiddenField2' => 'value2',
29602960
), // Hidden fields to include in the form.
29612961
'stepTransition' => 'fade-slide',
2962+
'connectMailPoet' => false,
29622963
);
29632964
// Add a widget ID to the attributes for testing.
29642965
$expected_attributes = $attributes;

0 commit comments

Comments
 (0)