PluginProbe
Texty – SMS Notification for WordPress, WooCommerce, Dokan and more / 2.0.1
Texty – SMS Notification for WordPress, WooCommerce, Dokan and more v2.0.1
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 / Dispatcher.php

Dispatcher.php in Texty – SMS Notification for WordPress, WooCommerce, Dokan and more 2.0.1, at includes/Dispatcher.php

189 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Texty;
4
5 use Texty\Integrations\Dokan;
6 use Texty\Integrations\WooCommerce;
7 use Texty\Models\SmsStat;
8 use WeDevs\WPKit\DataLayer\DataLayerFactory;
9 use Texty\Gateways\GatewayInterface;
10
11 /**
12 * Dispatcher Class
13 */
14 class Dispatcher {
15
16 /**
17 * Initialize
18 */
19 public function __construct() {
20
21 // WordPress Events
22 add_action( 'user_register', [ $this, 'user_register' ] );
23 add_action( 'comment_post', [ $this, 'new_comment' ] );
24
25 // SMS Logging via gateway hooks
26 add_action( 'texty_after_send_sms', [ $this, 'log_sms' ], 10, 4 );
27
28 // Load integrations
29 $this->register_integrations();
30 }
31
32 /**
33 * Register integrations via hook for extensibility.
34 *
35 * @return void
36 */
37 private function register_integrations() {
38 /**
39 * Fires to allow registration of custom integrations.
40 *
41 * Default handler loads WooCommerce and Dokan integrations
42 * when their respective plugins are active.
43 */
44 do_action( 'texty_register_integrations' );
45
46 // Load built-in integrations conditionally
47 if ( class_exists( 'WooCommerce' ) ) {
48 new WooCommerce();
49 }
50
51 if ( class_exists( 'WeDevs_Dokan' ) ) {
52 new Dokan();
53 }
54 }
55
56 /**
57 * Send message upon user registration
58 *
59 * @param int $user_id
60 *
61 * @return void
62 */
63 public function user_register( $user_id ) {
64 $class = texty()->notifications()->get( 'registration' );
65 $notifier = new $class();
66
67 $notifier->set_user( $user_id );
68 $notifier->send();
69 }
70
71 /**
72 * Send message upon a new comment
73 *
74 * @param int $comment_id
75 *
76 * @return void
77 */
78 public function new_comment( $comment_id ) {
79 $class = texty()->notifications()->get( 'comment' );
80 $notifier = new $class();
81
82 $notifier->set_comment( $comment_id );
83 $notifier->send();
84 }
85
86 /**
87 * Log SMS message to database via gateway hook
88 *
89 * Uses DataLayer for type-safe, cached, and hookable SMS logging.
90 *
91 * @param mixed $result The send result (bool, array, or WP_Error)
92 * @param string $to Recipient phone number
93 * @param string $message The message body
94 * @param GatewayInterface|false $gateway The gateway instance or false
95 *
96 * @return void
97 */
98 public function log_sms( $result, $to, $message, $gateway ) {
99 $store = DataLayerFactory::make_store( SmsStat::class );
100
101 if ( null === $store ) {
102 return;
103 }
104
105 $gateway_name = $gateway ? $gateway->name() : texty()->settings()->gateway();
106
107 // Determine status based on result
108 $status = is_wp_error( $result ) ? 'failed' : 'sent';
109
110 // Extract reference_id from gateway response
111 $reference_id = $this->extract_reference_id( $result );
112 if ( null === $reference_id ) {
113 $reference_id = '';
114 }
115
116 // Pull notification context off the registry — set by
117 // `Notification::send()` around its `$gateway->send()` loop.
118 $notification = texty()->notifications()->get_active();
119 $notification_id = $notification ? (string) $notification->get_id() : '';
120 $notification_group = $notification ? (string) $notification->get_group() : '';
121
122 // Create and save SMS record using DataLayer.
123 // `set_receiver` is typed `string`; coerce defensively so a failed
124 // send with a null/missing recipient still logs instead of fatalling.
125 $sms = new SmsStat();
126 $sms->set_props(
127 [
128 'receiver' => is_string( $to ) ? $to : '',
129 'gateway' => $gateway_name ? $gateway_name : '',
130 'status' => $status,
131 'notification_id' => $notification_id,
132 'notification_group' => $notification_group,
133 'message' => is_string( $message ) ? $message : '',
134 'response' => $this->encode_response( $result ),
135 'reference_id' => is_scalar( $reference_id ) ? (string) $reference_id : '',
136 'created_at' => current_time( 'mysql' ),
137 'updated_at' => current_time( 'mysql' ),
138 ]
139 );
140
141 $store->create( $sms );
142 }
143
144 /**
145 * Normalize the gateway result into a JSON-friendly payload for the
146 * `response` column. WP_Error gets unpacked into code/message/data so
147 * the failure is human-readable; arrays/objects are passed through;
148 * scalars are JSON-encoded as-is.
149 *
150 * @param mixed $result The send result (bool, array, or WP_Error).
151 *
152 * @return array|string|null
153 */
154 private function encode_response( $result ) {
155 if ( is_wp_error( $result ) ) {
156 return [
157 'code' => $result->get_error_code(),
158 'message' => $result->get_error_message(),
159 'data' => $result->get_error_data(),
160 ];
161 }
162
163 return $result;
164 }
165
166 private function extract_reference_id( $result ) {
167 if ( ! is_array( $result ) ) {
168 return null;
169 }
170
171 $id_keys = [ 'sid', 'message-id', 'message_uuid', 'apiMsgId', 'reference_id' ];
172
173 foreach ( $id_keys as $key ) {
174 if ( ! empty( $result[ $key ] ) ) {
175 $value = $result[ $key ];
176
177 // Plivo wraps message_uuid in an array — flatten to the first id.
178 if ( is_array( $value ) ) {
179 $value = reset( $value );
180 }
181
182 return $value;
183 }
184 }
185
186 return null;
187 }
188 }
189