1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
<?php // phpcs:ignoreFile
namespace AutomateWoo;
if ( ! defined( 'ABSPATH' ) ) exit;
/** * @class Action_Send_SMS_Twilio */ class Action_Send_SMS_Twilio extends Action {
function load_admin_details() { $this->title = __( 'Send SMS (Twilio)', 'automatewoo' ); $this->group = __( 'SMS', 'automatewoo' ); $this->description = __( 'It is recommended to include an unsubscribe link by using the variable {{ customer.unsubscribe_url }} in the SMS body.', 'automatewoo' );
if ( AW()->options()->bitly_api && AW()->options()->bitly_shorten_sms_links ) { /* translators: %1$s Bitly integration link start, %2$s Bitly integration link end. */ $bitly_text = __( 'Links in the SMS body will be shortened with the %1$sBitly integration%2$s.', 'automatewoo' ); } else { /* translators: %1$s Bitly integration link start, %2$s Bitly integration link end. */ $bitly_text = __( 'To shorten links in the SMS body the %1$sBitly integration%2$s must be enabled.', 'automatewoo' ); }
$this->description .= sprintf( ' ' . $bitly_text, '<a href="' . Admin::page_url( 'settings-bitly' ) . '" target="_blank">', '</a>' ); }
function load_fields() { $sms_recipient = ( new Fields\Text() ) ->set_name( 'sms_recipient' ) ->set_title( __( 'SMS recipients', 'automatewoo' ) ) ->set_description( __( 'Multiple recipient numbers must be separated by commas. When using the {{ customer.phone }} variable the country code will be added automatically, if not already entered by the customer, by referencing the billing country.', 'automatewoo' ) ) ->set_variable_validation() ->set_required();
$sms_body = ( new Fields\Text_Area() ) ->set_name( 'sms_body' ) ->set_title( __( 'SMS body', 'automatewoo' ) ) ->set_rows(4) ->set_variable_validation() ->set_required();
$this->add_field( $sms_recipient ); $this->add_field( $sms_body ); }
/** * @throws \Exception */ function run() { $recipients = Clean::comma_delimited_string( $this->get_option( 'sms_recipient' ) ); $message = $this->get_option( 'sms_body', true );
if ( empty( $message ) ) { throw new \Exception( __( 'Empty message body', 'automatewoo') ); }
$message = $this->process_urls_in_sms( $message );
$valid_recipients_count = 0; foreach ( $recipients as $recipient_string ) { $recipient = $this->workflow->variable_processor()->process_field( $recipient_string ); // Do not send SMS for a variable that resolved to an empty number. if( $recipient ) { $this->send_sms( $recipient, $recipient_string, $message ); $valid_recipients_count++; } } if ( $valid_recipients_count == 0 ) { throw new \Exception( __( 'No valid recipients', 'automatewoo') ); } }
/** * Sends an SMS to one recipient. * * @since 4.3.2 * * @param string $recipient_phone The phone number of the SMS recipient. * @param string $recipient_string Unprocessed recipient string. * @param string $message The body of the SMS */ public function send_sms( $recipient_phone, $recipient_string, $message ) { $twilio = Integrations::get_twilio();
if ( ! $twilio ) { return; }
$is_sms_to_customer = $this->is_recipient_the_primary_customer( $recipient_string );
// check if this SMS is going to the workflow's primary customer if ( $is_sms_to_customer ) { $customer = $this->workflow->data_layer()->get_customer();
// check if the customer is unsubscribed if ( $this->workflow->is_customer_unsubscribed( $customer ) ) { $error = new \WP_Error( 'unsubscribed', __( "The recipient is not opted-in to this workflow.", 'automatewoo' ) ); $this->workflow->log_action_email_error( $error, $this ); return; }
// because the SMS is to the primary customer, use the customer's country to parse the phone number $recipient_phone = Phone_Numbers::parse( $recipient_phone, $customer->get_billing_country() ); } else { $recipient_phone = Phone_Numbers::parse( $recipient_phone ); }
$request = $twilio->send_sms( $recipient_phone, $message );
if ( $request->is_successful() ) { $this->workflow->log_action_note( $this, __( 'SMS successfully sent.', 'automatewoo' ) ); } else { // don't throw exception since the error is only for one recipient $this->workflow->log_action_error( $this, $twilio->get_request_error_message( $request ) ); } }
/** * Determines if a recipient is the primary customer for the workflow. * * Must be used before the $recipient_phone has variables processed. * * @param string $recipient_field * * @return bool */ public function is_recipient_the_primary_customer( $recipient_field ) { if ( ! $recipient_field ) { return false; }
$is_primary_customer = false;
if ( stristr( $recipient_field, 'customer.phone' ) || stristr( $recipient_field, 'order.billing_phone' ) ) { $is_primary_customer = true; }
return apply_filters( 'automatewoo/sms/is_recipient_primary_customer', $is_primary_customer, $this ); }
/** * Process the URLs in an SMS body. * - Maybe converts URLs to trackable URLs * - Maybe shortens URL * * @since 4.3.2 * * @param string $sms * * @return string */ public function process_urls_in_sms( $sms ) { $replacer = new Replace_Helper( $sms, [ $this, 'callback_process_url' ], 'text_urls' ); $processed = $replacer->process(); return $processed; }
/** * Processes a single URL in the SMS body. * * @param string $url * * @return string */ public function callback_process_url( $url ) { $url = html_entity_decode( $url );
// make URL trackable if enabled if ( $this->workflow->is_tracking_enabled() ) { // don't track unsubscribe clicks if ( ! strstr( $url, 'aw-action=unsubscribe' ) ) { $url = $this->workflow->append_ga_tracking_to_url( $url ); $url = esc_url_raw( Tracking::get_click_tracking_url( $this->workflow, $url ) ); } }
// shorten links if enabled if ( AW()->options()->bitly_shorten_sms_links ) { $bitly = Integrations::get_bitly();
if ( $bitly ) { $short_url = $bitly->shorten_url( $url );
// Default to full url if bitly fails for any reason (e.g. exceeded rate limit). // https://github.com/woocommerce/automatewoo/issues/895 if ( $short_url ) { $url = $short_url; } } }
return $url; }
}
|