PluginProbe
Texty – SMS Notification for WordPress, WooCommerce, Dokan and more / 2.0.0
Texty – SMS Notification for WordPress, WooCommerce, Dokan and more v2.0.0
2.0.2 trunk 0.2 1.0 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 2.0.0 2.0.1
texty / includes / Notifications / WC / Base.php

Base.php in Texty – SMS Notification for WordPress, WooCommerce, Dokan and more 2.0.0, at includes/Notifications/WC/Base.php

225 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Texty\Notifications\WC;
4
5 use Texty\Notifications\Notification;
6 use WC_Order_Item_Product;
7
8 class Base extends Notification {
9
10 /**
11 * @var object
12 */
13 protected $order;
14
15 /**
16 * Set the user ID
17 *
18 * @param mixed $order
19 *
20 * @return self
21 */
22 public function set_order( $order ) {
23 $this->order = $order;
24
25 return $this;
26 }
27
28 /**
29 * Return the message
30 *
31 * @return string
32 */
33 public function get_message() {
34 $message = parent::get_message_raw();
35
36 if ( ! $this->order ) {
37 return $message;
38 }
39
40 foreach ( $this->replacement_keys() as $search => $method ) {
41 $value = method_exists( $this->order, $method ) ? $this->order->$method() : '';
42
43 // WC accessors like `get_date_paid()` return null on unpaid orders
44 // and `WC_DateTime` objects on paid ones — normalize both to a
45 // string before any string handling. PHP 8.1 deprecates passing
46 // null to str_replace's $replace argument.
47 if ( null === $value ) {
48 $value = '';
49 } elseif ( ! is_scalar( $value ) ) {
50 $value = (string) $value;
51 }
52
53 if ( 'order_total' === $search ) {
54 $value = wp_strip_all_tags( html_entity_decode( (string) $value ) );
55 }
56
57 if ( 'items' === $search ) {
58 $value = $this->get_items();
59 }
60
61 $message = str_replace( '{' . $search . '}', (string) $value, $message );
62 }
63
64 $message = $this->replace_global_keys( $message );
65
66 return $message;
67 }
68
69 /**
70 * Get product items from the order
71 *
72 * @return string
73 */
74 protected function get_items() {
75 $products = [];
76
77 foreach ( $this->order->get_items() as $item ) {
78 if ( ! $item instanceof WC_Order_Item_Product ) {
79 continue;
80 }
81
82 $product = $item->get_product();
83
84 // A product may have been deleted after the order was placed —
85 // `get_product()` then returns false. Fall back to the line-item
86 // name stored on the order so building the message doesn't fatal.
87 $name = $product ? $product->get_name() : $item->get_name();
88
89 $products[] = sprintf( '%s x %d', $name, $item->get_quantity() );
90 }
91
92 $names = implode( "\n", $products );
93
94 return $names;
95 }
96
97 /**
98 * Return recipients
99 *
100 * @return array
101 */
102 public function get_recipients() {
103 return $this->get_numbers_by_roles();
104 }
105
106 /**
107 * Get replacement keys
108 *
109 * @return array
110 */
111 public function replacement_keys() {
112 return [
113 'order_id' => 'get_id',
114 'items' => 'products',
115 'date' => 'get_date_paid',
116 'status' => 'get_status',
117 'payment_method' => 'get_payment_method_title',
118 'shipping_method' => 'get_shipping_method',
119 'transaction_id' => 'get_transaction_id',
120 'billing_name' => 'get_formatted_billing_full_name',
121 'billing_email' => 'get_billing_email',
122 'order_total' => 'get_formatted_order_total',
123 'shipping_total' => 'get_shipping_total',
124 'tax_total' => 'get_total_tax',
125 'discount' => 'get_discount_total',
126 ];
127 }
128
129 public function send(): bool {
130 if ( ! $this->enabled() ) {
131 return false;
132 }
133
134 $meta_key = '_texty_' . $this->get_id();
135 $has_sent = $this->order->get_meta( $meta_key, true );
136
137 // if we've already sent the message, don't send again
138 if ( $has_sent ) {
139 return false;
140 }
141
142 // mark as sent
143 $this->order->add_meta_data( $meta_key, 1 );
144 $this->order->save_meta_data();
145
146 if ( 'user' === $this->get_type() ) {
147 $number = $this->order->get_billing_phone();
148
149 $recipients = $number ? [ $number ] : [];
150 } else {
151 $recipients = $this->get_recipients();
152 }
153
154 /**
155 * Filter the recipients for a notification.
156 *
157 * @param array $recipients The recipient phone numbers
158 * @param Notification $notification The notification instance
159 */
160 $recipients = apply_filters( 'texty_notification_recipients', $recipients, $this );
161
162 // Drop nulls / empty strings — a stale `texty_phone` meta value or a
163 // third-party filter can leave them in the array and crash the
164 // gateway send (which expects a string).
165 $recipients = is_array( $recipients ) ? array_values( array_filter( $recipients ) ) : [];
166
167 if ( ! $recipients ) {
168 return false;
169 }
170
171 $content = $this->get_message();
172
173 /**
174 * Filter the notification message content.
175 *
176 * @param string $content The message content
177 * @param Notification $notification The notification instance
178 */
179 $content = apply_filters( 'texty_notification_message', $content, $this );
180
181 /**
182 * Filter the message for a specific notification type.
183 *
184 * @param string $content The message content
185 * @param Notification $notification The notification instance
186 */
187 $content = apply_filters( 'texty_notification_message_' . $this->get_id(), $content, $this );
188
189 /**
190 * Fires before the notification send loop.
191 *
192 * @param Notification $notification The notification instance
193 * @param array $recipients The recipient phone numbers
194 * @param string $content The message content
195 */
196 do_action( 'texty_before_notification', $this, $recipients, $content );
197
198 $gateway = texty()->gateways();
199
200 // Stash the active notification so the after-send logger can attach
201 // notification_id / notification_group to each SmsStat row without
202 // threading them through the gateway pipeline.
203 texty()->notifications()->set_active( $this );
204
205 try {
206 foreach ( $recipients as $number ) {
207 $gateway->send( $number, $content );
208 }
209 } finally {
210 texty()->notifications()->clear_active();
211 }
212
213 /**
214 * Fires after the notification send loop.
215 *
216 * @param Notification $notification The notification instance
217 * @param array $recipients The recipient phone numbers
218 * @param string $content The message content
219 */
220 do_action( 'texty_after_notification', $this, $recipients, $content );
221
222 return true;
223 }
224 }
225