PluginProbe
WANotifier for Forms and Actions / 3.1.1
WANotifier for Forms and Actions v3.1.1
3.1.1 3.1.0 3.0.4 2.7.10 2.7.11 2.7.12 2.7.13 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 3.0.0 3.0.1 3.0.2 3.0.3 trunk 0.1.0 0.1.1 1.0.0 1.0.1 1.0.2 All 67 releases
← All changes | includes/classes/class-notifier-notification-triggers.php +510 -154 1.0.23.1.1 View file →
@@ -1,5 +1,9 @@
1 1 <?php
2 +if ( ! defined( 'ABSPATH' ) ) {
3 + exit;
4 +}
5 +
2 6 /**
3 7 * Notification Triggers class
4 8 *
5 9 * @package Wa_Notifier
@@ -9,30 +13,78 @@
9 13 /**
10 14 * Init.
11 15 */
12 16 public static function init() {
13 - add_action( 'plugins_loaded', array( __CLASS__ , 'setup_triggers_action_hooks' ), 100 );
17 + add_filter( 'init', array( __CLASS__ , 'register_cpt') );
18 + add_action( 'admin_menu', array( __CLASS__ , 'setup_admin_page') );
19 + add_action( 'init', array( __CLASS__ , 'setup_triggers_action_hooks' ));
20 + add_action( 'wp_ajax_notifier_change_trigger_status', array(__CLASS__, 'notifier_change_trigger_status'));
21 + add_action( 'wp_ajax_notifier_fetch_trigger_fields', array(__CLASS__, 'notifier_fetch_trigger_fields'));
14 22 }
15 23
16 24 /**
25 + * Register custom post type.
26 + *
27 + * Always registered so existing v2 trigger posts remain accessible for
28 + * migration queries and backward-compat firing. The admin UI is hidden.
29 + */
30 + public static function register_cpt () {
31 + notifier_register_post_type('wa_notifier_trigger', 'Trigger', 'Triggers');
32 + }
33 +
34 + /**
35 + * Add page to admin menu.
36 + *
37 + * Hidden after migration is complete — users no longer need the CPT UI.
38 + */
39 + public static function setup_admin_page () {
40 + // v3: Trigger CPT menu items are always hidden.
41 + // The CPT is still registered (register_cpt) so posts exist and fire,
42 + // but users manage everything through the React Integrations UI.
43 + return;
44 + }
45 +
46 + /**
17 47 * Setup triggers action hooks
18 48 */
19 49 public static function setup_triggers_action_hooks() {
20 - $main_triggers = self::get_notification_triggers();
21 - foreach ($main_triggers as $key => $triggers) {
22 - foreach ($triggers as $trigger) {
23 - $hook = isset($trigger['action']['hook']) ? $trigger['action']['hook'] : '';
24 - $callback = isset($trigger['action']['callback']) ? $trigger['action']['callback'] : '';
25 - $priority = isset($trigger['action']['priority']) ? $trigger['action']['priority'] : 10;
26 - $args_num = isset($trigger['action']['args_num']) ? $trigger['action']['args_num'] : 1;
27 - if ('' == $hook || '' == $callback) {
28 - continue;
50 + // Legacy path: register hooks for CPT-enabled triggers.
51 + $triggers_to_register = self::get_enabled_notification_triggers();
52 +
53 + // v3 path: also register hooks for any trigger whose integration is connected,
54 + // regardless of whether a legacy CPT trigger exists.
55 + if ( class_exists( 'Notifier_Connection' ) ) {
56 + $all_triggers = self::get_notification_triggers();
57 + foreach ( $all_triggers as $group => $group_triggers ) {
58 + foreach ( $group_triggers as $trigger ) {
59 + $trigger_id = isset( $trigger['id'] ) ? $trigger['id'] : '';
60 + $base = self::get_trigger_id_without_site_key( $trigger_id );
61 + $slug = self::get_integration_slug_for_trigger( $base );
62 + if ( $slug && Notifier_Connection::is_connected( $slug ) ) {
63 + $triggers_to_register[] = $trigger;
64 + }
29 65 }
30 - if(self::is_trigger_enabled($trigger['id'])){
31 - add_action($hook, $callback, $priority, $args_num);
32 - }
33 66 }
34 67 }
68 +
69 + // De-duplicate by trigger ID to avoid registering the same hook twice.
70 + $registered = array();
71 + foreach ( $triggers_to_register as $trigger ) {
72 + $trigger_id = isset( $trigger['id'] ) ? $trigger['id'] : '';
73 + $hook = isset( $trigger['action']['hook'] ) ? $trigger['action']['hook'] : '';
74 + $callback = isset( $trigger['action']['callback'] ) ? $trigger['action']['callback'] : '';
75 + $priority = isset( $trigger['action']['priority'] ) ? $trigger['action']['priority'] : 10;
76 + $args_num = isset( $trigger['action']['args_num'] ) ? $trigger['action']['args_num'] : 1;
77 + if ( '' === $hook || '' === $callback ) {
78 + continue;
79 + }
80 + $key = $trigger_id ?: ( $hook . '|' . ( is_string( $callback ) ? $callback : '' ) );
81 + if ( isset( $registered[ $key ] ) ) {
82 + continue;
83 + }
84 + $registered[ $key ] = true;
85 + add_action( $hook, $callback, $priority, $args_num );
86 + }
35 87 }
36 88
37 89 /**
38 90 * Get notification triggers
@@ -38,214 +90,518 @@
38 90 * Get notification triggers
39 91 */
40 92 public static function get_notification_triggers() {
41 93 $triggers = array();
42 - $triggers['WordPress'] = array (
43 - array(
44 - 'id' => 'new_post',
45 - 'label' => 'New post is published',
46 - 'description' => 'Trigger notification when a new blog post is published.',
47 - 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( array('Post') ),
48 - 'recipient_fields' => array(),
94 + $args = array(
95 + 'public' => true,
96 + );
97 +
98 + $post_types = get_post_types( $args, 'objects');
99 +
100 + $triggers = array ();
101 + unset($post_types['attachment']);
102 +
103 + foreach($post_types as $post){
104 + $post_slug = $post->name;
105 + $triggers['WordPress'][] = array(
106 + 'id' => 'new_'.$post->name,
107 + 'label' => 'New '.$post->labels->singular_name.' is published',
108 + 'description' => 'Trigger notification when a new '.$post->name.' is published.',
109 + 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( Notifier_Notification_Merge_Tags::get_post_merge_tag_types( $post->labels->singular_name ) ),
110 + 'recipient_fields' => Notifier_Notification_Merge_Tags::get_recipient_fields( Notifier_Notification_Merge_Tags::get_post_recipient_types( $post->labels->singular_name ) ),
49 111 'action' => array (
50 - 'hook' => 'transition_post_status',
112 + 'hook' => 'publish_'.$post->name,
51 113 'args_num' => 3,
52 - 'callback' => function ( $new_status, $old_status, $post ) {
53 - if ('post' !== get_post_type($post)) {
54 - return;
55 - }
56 -
57 - if ( 'publish' === $new_status && 'publish' !== $old_status ) {
114 + 'callback' => function ( $post_id, $post, $old_status ) use ($post_slug) {
115 + if ( 'publish' !== $old_status ) {
58 116 $args = array (
59 - 'object_type' => 'post',
117 + 'object_type' => $post_slug,
60 118 'object_id' => $post->ID
61 119 );
62 - $merge_tags = Notifier_Notification_Merge_Tags::get_merge_tags( array('Post') );
63 - self::send_trigger_request('new_post', $args, $merge_tags);
120 + self::send_trigger_request('new_'.$post_slug, $args);
64 121 }
65 122 }
66 - )
67 - ),
68 - array(
69 - 'id' => 'new_comment',
70 - 'label' => 'New comment is added',
71 - 'description' => 'Trigger notification when a new comment is added.',
72 - 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( array('Comment') ),
73 - 'recipient_fields' => array(),
74 - 'action' => array (
75 - 'hook' => 'comment_post',
76 - 'args_num' => 3,
77 - 'callback' => function ( $comment_id, $comment_approved, $commentdata ) {
78 - if ( 'spam' != $comment_approved) {
79 - $args = array (
80 - 'object_type' => 'comment',
81 - 'object_id' => $comment_id
82 - );
83 - $merge_tags = Notifier_Notification_Merge_Tags::get_merge_tags( array('Comment') );
84 - self::send_trigger_request('new_comment', $args, $merge_tags);
85 - }
86 - }
87 - )
88 - ),
89 - array(
90 - 'id' => 'new_user',
91 - 'label' => 'New user is registered',
92 - 'description' => 'Trigger notification when a new user is created.',
93 - 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( array('User') ),
94 - 'recipient_fields' => array(),
95 - 'action' => array (
96 - 'hook' => 'user_register',
97 - 'callback' => function ( $user_id ) {
123 + ),
124 + );
125 + }
126 +
127 + $triggers['WordPress'][] = array(
128 + 'id' => 'new_comment',
129 + 'label' => 'New Comment is added',
130 + 'description' => 'Trigger notification when a new comment is added.',
131 + 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( Notifier_Notification_Merge_Tags::get_comment_merge_tag_types() ),
132 + 'recipient_fields' => array(),
133 + 'action' => array (
134 + 'hook' => 'comment_post',
135 + 'args_num' => 3,
136 + 'callback' => function ( $comment_id, $comment_approved, $commentdata ) {
137 + if ( 'spam' != $comment_approved) {
98 138 $args = array (
99 - 'object_type' => 'user',
100 - 'object_id' => $user_id
139 + 'object_type' => 'comment',
140 + 'object_id' => $comment_id
101 141 );
102 - $merge_tags = Notifier_Notification_Merge_Tags::get_merge_tags( array('User') );
103 - self::send_trigger_request('new_user', $args, $merge_tags);
142 + self::send_trigger_request('new_comment', $args);
104 143 }
105 - )
144 + }
106 145 )
107 146 );
108 - return apply_filters('notifier_notification_triggers', $triggers);
147 +
148 + $triggers['WordPress'][] = array(
149 + 'id' => 'new_user',
150 + 'label' => 'New User is registered',
151 + 'description' => 'Trigger notification when a new user is created.',
152 + 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( Notifier_Notification_Merge_Tags::get_user_merge_tag_types() ),
153 + 'recipient_fields' => Notifier_Notification_Merge_Tags::get_recipient_fields( Notifier_Notification_Merge_Tags::get_user_recipient_types() ),
154 + 'action' => array (
155 + 'hook' => 'user_register',
156 + 'callback' => function ( $user_id ) {
157 + $args = array (
158 + 'object_type' => 'user',
159 + 'object_id' => $user_id
160 + );
161 + self::send_trigger_request('new_user', $args);
162 + },
163 + 'priority' => 999
164 + )
165 + );
166 +
167 + $triggers['WordPress'][] = array(
168 + 'id' => 'new_attachment',
169 + 'label' => 'New Media is uploded',
170 + 'description' => 'Trigger notification when a new attachement is uploded.',
171 + 'merge_tags' => Notifier_Notification_Merge_Tags::get_merge_tags( Notifier_Notification_Merge_Tags::get_attachment_merge_tag_types() ),
172 + 'recipient_fields' => Notifier_Notification_Merge_Tags::get_recipient_fields( Notifier_Notification_Merge_Tags::get_attachment_recipient_types() ),
173 + 'action' => array (
174 + 'hook' => 'add_attachment',
175 + 'callback' => function ( $attachement_id ) {
176 + $args = array (
177 + 'object_type' => 'attachment',
178 + 'object_id' => $attachement_id
179 + );
180 + self::send_trigger_request('new_attachment', $args);
181 + }
182 + )
183 + );
184 +
185 + $triggers = apply_filters('notifier_notification_triggers', $triggers);
186 +
187 + // Add site key to trigger IDs
188 + $site_key = self::get_notification_trigger_site_key();
189 +
190 + foreach ($triggers as $trigs_key => $trigs) {
191 + foreach($trigs as $trig_key => $trig){
192 + $triggers[$trigs_key][$trig_key]['id'] = $site_key . $trig['id'];
193 + }
194 + }
195 +
196 + return $triggers;
109 197 }
110 198
111 199 /**
112 - * Get notification triggers for dropdown
200 + * Get notification trigger site key
113 201 */
114 - public static function get_notification_triggers_dropdown() {
202 + public static function get_notification_trigger_site_key(){
203 + $site_key = get_option(NOTIFIER_PREFIX . 'site_key');
204 + if(!$site_key){
205 + $site_key = notifier_generate_random_key(5);
206 + update_option(NOTIFIER_PREFIX . 'site_key', $site_key, true);
207 + }
208 + $site_key = 'wp_' . $site_key . '_';
209 + return $site_key;
210 + }
211 +
212 + /**
213 + * Get notification trigger
214 + */
215 + public static function get_notification_trigger($trigger) {
216 + $trigger = self::get_trigger_id_with_site_key($trigger);
217 + $found_trigger = array();
115 218 $main_triggers = self::get_notification_triggers();
116 - $dropdown_triggers = array('' => 'Select a trigger');
117 219 foreach ($main_triggers as $key => $triggers) {
118 - $dropdown_triggers[$key] = wp_list_pluck($triggers, 'label', 'id');
220 + foreach($triggers as $the_trigger){
221 + if($the_trigger['id'] == $trigger){
222 + $found_trigger = $the_trigger;
223 + break 2;
224 + }
225 + }
119 226 }
120 - return $dropdown_triggers;
227 + return $found_trigger;
121 228 }
122 229
123 230 /**
124 - * Check whether current trigger is enabled
231 + * Get enabled notification triggers
125 232 */
126 - public static function is_trigger_enabled($trigger) {
127 - $enabled_triggers = get_option('notifier_enabled_triggers');
233 + public static function get_enabled_notification_triggers() {
234 + $enabled_triggers = array();
235 + $enabled_post_ids = get_posts( array (
236 + 'post_type' => 'wa_notifier_trigger',
237 + 'post_status' => 'publish',
238 + 'numberposts' => -1,
239 + 'fields' => 'ids',
240 + 'meta_query' => array(
241 + array(
242 + 'key' => NOTIFIER_PREFIX . 'trigger_enabled',
243 + 'value' => 'yes',
244 + 'compare' => '='
245 + )
246 + )
247 + ) );
128 248
129 - if(empty($enabled_triggers)){
130 - return false;
249 + if(!empty($enabled_post_ids)){
250 + foreach($enabled_post_ids as $enabled_post_id){
251 + $trigger_name = get_post_meta($enabled_post_id, NOTIFIER_PREFIX . 'trigger', true);
252 + $enabled_triggers[] = self::get_notification_trigger($trigger_name);
253 + }
131 254 }
132 255
133 - if(in_array($trigger, $enabled_triggers)){
134 - return true;
256 + return $enabled_triggers;
257 + }
258 +
259 + /**
260 + * Check whether current trigger is in use
261 + */
262 + public static function is_trigger_in_use($trigger, $excluded_ids = array()) {
263 + $in_use = false;
264 + $in_use_post_id = get_posts( array (
265 + 'post_type' => 'wa_notifier_trigger',
266 + 'post_status' => 'publish',
267 + 'numberposts' => -1,
268 + 'fields' => 'ids',
269 + 'meta_query' => array(
270 + array(
271 + 'key' => NOTIFIER_PREFIX . 'trigger',
272 + 'value' => $trigger,
273 + 'compare' => '='
274 + )
275 + ),
276 + 'post__not_in' => $excluded_ids
277 + ) );
278 +
279 + if(!empty($in_use_post_id)){
280 + $in_use = $in_use_post_id[0];
135 281 }
136 282
137 - return false;
283 + return $in_use;
138 284 }
139 285
140 286 /**
141 - * Send triggered notifications
287 + * Send triggered notifications.
288 + *
289 + * Runs both paths simultaneously during migration:
290 + * - v3 path: dispatches via Action Scheduler when the integration is connected.
291 + * - Legacy path: fires via old API key until migration is complete.
292 + *
293 + * @param string $trigger Trigger ID (with site key prefix).
294 + * @param array $context_args Context arguments passed to payload builders.
142 295 */
143 - public static function send_trigger_request($trigger, $context_args, $merge_tags, $recipient_fields = array()) {
144 - if(empty($context_args) || empty($merge_tags)){
296 + public static function send_trigger_request( $trigger, $context_args ) {
297 + if ( empty( $context_args ) ) {
145 298 return false;
146 299 }
147 300
148 - $data = array();
149 - $recipient_data = array();
301 + $slug = self::get_integration_slug_for_trigger( $trigger );
150 302
151 - foreach($merge_tags as $group_name => $group_tags){
152 - foreach($group_tags as $tag){
153 - $data[$tag['id']] = Notifier_Notification_Merge_Tags::get_trigger_merge_tag_value($tag['id'], $context_args);
154 - }
303 + error_log( sprintf( 'Notifier [send_trigger_request] trigger=%s slug=%s', $trigger, $slug ) );
304 +
305 + // If the Woo plugin is active it owns all WooCommerce triggers — skip them here
306 + // so they are not double-fired. The Woo plugin registers its own action hooks.
307 + if ( 'woocommerce' === $slug && class_exists( 'WANOWC_Notification_Triggers' ) ) {
308 + error_log( 'Notifier [send_trigger_request] skipped — handed off to Woo plugin' );
309 + return false;
155 310 }
156 311
157 - foreach($recipient_fields as $recipient_field){
158 - foreach($recipient_field as $field){
159 - $recipient_data[$field['id']] = self::get_trigger_recipient_field_value($field['id'], $context_args);
160 - }
312 + // v3 path: dispatch via Action Scheduler to SaaS integration endpoint.
313 + // Payload is built inside the async job to keep the main request fast.
314 + $is_connected = $slug && class_exists( 'Notifier_Connection' ) && Notifier_Connection::is_connected( $slug );
315 + error_log( sprintf( 'Notifier [send_trigger_request] is_connected=%s', $is_connected ? 'yes' : 'no' ) );
316 + if ( $is_connected ) {
317 + Notifier_Connection::dispatch_trigger( $slug, self::get_trigger_id_without_site_key( $trigger ), $context_args );
161 318 }
162 319
163 - $params = array(
164 - 'action' => 'fire_notification',
165 - 'site_url' => site_url(),
166 - 'source' => 'wp',
167 - 'trigger' => $trigger,
168 - 'merge_tags_data' => $data,
169 - 'recipient_fields' => $recipient_data
170 - );
320 + // Legacy path: fire via old API key until migration is complete.
321 + $migration_complete = class_exists( 'Notifier_Migration' ) && Notifier_Migration::is_migration_complete();
322 + error_log( sprintf( 'Notifier [send_trigger_request] migration_complete=%s', $migration_complete ? 'yes' : 'no' ) );
323 + if ( ! $migration_complete ) {
324 + self::send_legacy_trigger_request( $trigger, $context_args );
325 + }
326 + }
171 327
172 - $response = Notifier::send_api_request( $params, 'POST' );
328 + /**
329 + * Fire a trigger via the legacy /api/v1/fire_notification endpoint.
330 + * Used during the transition period before migration is complete.
331 + *
332 + * @param string $trigger Trigger ID (with site key prefix).
333 + * @param array $context_args Context arguments.
334 + */
335 + private static function send_legacy_trigger_request( $trigger, $context_args ) {
336 + $api_key = trim( get_option( 'notifier_api_key', '' ) );
337 + if ( empty( $api_key ) ) {
338 + error_log( 'Notifier [send_legacy_trigger_request] skipped — no API key' );
339 + return;
340 + }
173 341
174 - if($response->error){
175 - error_log($response->message);
342 + // Send trigger in v2 format (wp_{key}_{slug}) so Phase 1 SaaS can rewrite and match notifications.
343 + $trigger = self::get_trigger_id_with_site_key( $trigger );
344 +
345 + error_log( sprintf( 'Notifier [send_legacy_trigger_request] trigger=%s', $trigger ) );
346 +
347 + // Look up the v2 CPT post for this trigger to get the user-selected fields.
348 + // This mirrors exactly what v2 sent — only the fields the user configured.
349 + $cpt_post = get_posts( array(
350 + 'post_type' => 'wa_notifier_trigger',
351 + 'post_status' => 'publish',
352 + 'numberposts' => 1,
353 + 'fields' => 'ids',
354 + 'meta_query' => array(
355 + array(
356 + 'key' => NOTIFIER_PREFIX . 'trigger',
357 + 'value' => $trigger,
358 + ),
359 + ),
360 + ) );
361 +
362 + // If no CPT post exists for this trigger, the user never configured it in v2 — don't send.
363 + if ( empty( $cpt_post ) ) {
364 + error_log( sprintf( 'Notifier [send_legacy_trigger_request] skipped — no CPT post for trigger=%s', $trigger ) );
365 + return;
176 366 }
177 367
368 + $post_id = $cpt_post[0];
369 + $enabled_merge_tags = get_post_meta( $post_id, NOTIFIER_PREFIX . 'data_fields', true );
370 + $enabled_recipient_fields = get_post_meta( $post_id, NOTIFIER_PREFIX . 'recipient_fields', true );
371 + $enabled_merge_tags = is_array( $enabled_merge_tags ) ? $enabled_merge_tags : array();
372 + $enabled_recipient_fields = is_array( $enabled_recipient_fields ) ? $enabled_recipient_fields : array();
373 +
374 + // Resolve only the selected field values.
375 + $merge_tags_data = array();
376 + $recipient_fields = array();
377 + foreach ( $enabled_merge_tags as $tag_id ) {
378 + $merge_tags_data[ $tag_id ] = Notifier_Notification_Merge_Tags::get_trigger_merge_tag_value( $tag_id, $context_args );
379 + }
380 + foreach ( $enabled_recipient_fields as $field_id ) {
381 + $recipient_fields[ $field_id ] = Notifier_Notification_Merge_Tags::get_trigger_merge_tag_value( $field_id, $context_args );
382 + }
383 +
384 + error_log( sprintf( 'Notifier [send_legacy_trigger_request] recipient_fields before=%s', wp_json_encode( $recipient_fields ) ) );
385 + foreach ( $recipient_fields as $key => $value ) {
386 + $recipient_fields[ $key ] = notifier_maybe_add_default_country_code( notifier_sanitize_phone_number( (string) $value ) );
387 + }
388 + error_log( sprintf( 'Notifier [send_legacy_trigger_request] recipient_fields after=%s', wp_json_encode( $recipient_fields ) ) );
389 +
390 + $body = wp_json_encode( array(
391 + 'source' => 'wp',
392 + 'trigger' => $trigger,
393 + 'merge_tags_data' => $merge_tags_data,
394 + 'recipient_fields' => $recipient_fields,
395 + 'site_url' => site_url(),
396 + ) );
397 +
398 + error_log( 'Notifier: ' . $body );
399 +
400 + $url = untrailingslashit( NOTIFIER_APP_BASE_URL ) . '/' . NOTIFIER_APP_API_PATH . '/fire_notification?key=' . rawurlencode( $api_key );
401 +
402 + wp_remote_post( $url, array(
403 + 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ),
404 + 'body' => $body,
405 + 'timeout' => 30,
406 + 'sslverify' => true,
407 + ) );
178 408 }
179 409
180 - /*
181 - * Get recipient fields
410 + /**
411 + * Determine the integration slug for a given trigger ID.
412 + *
413 + * @param string $trigger Trigger ID (with or without site key prefix).
414 + * @return string|null Integration slug or null if not determinable.
182 415 */
183 - public static function get_recipient_fields($types = array()){
184 - $recipient_fields = array();
185 - $recipient_fields = apply_filters('notifier_notification_recipient_fields', $recipient_fields);
416 + public static function get_integration_slug_for_trigger( $trigger ) {
417 + $base = self::get_trigger_id_without_site_key( $trigger );
186 418
187 - $final_recipient_fields = array();
419 + // woocommerce_cart_abandonment_recovery falls through to the woocommerce_ prefix check below.
420 + if ( strpos( $base, 'woo_' ) === 0 || strpos( $base, 'woocommerce_' ) === 0 ) {
421 + return 'woocommerce';
422 + }
423 + if ( strpos( $base, 'gravityforms_' ) === 0 ) {
424 + return 'gravityforms';
425 + }
426 + if ( strpos( $base, 'cf7_' ) === 0 ) {
427 + return 'cf7';
428 + }
429 + if ( strpos( $base, 'wpf_' ) === 0 || strpos( $base, 'wpforms_' ) === 0 ) {
430 + return 'wpforms';
431 + }
432 + if ( strpos( $base, 'ninjaforms_' ) === 0 ) {
433 + return 'ninjaforms';
434 + }
435 + if ( strpos( $base, 'formidableforms_' ) === 0 || strpos( $base, 'formidable_' ) === 0 ) {
436 + return 'formidable';
437 + }
438 + if ( strpos( $base, 'fluentforms_' ) === 0 ) {
439 + return 'fluentforms';
440 + }
441 + if ( strpos( $base, 'forminator_' ) === 0 ) {
442 + return 'forminator';
443 + }
444 + if ( strpos( $base, 'sureforms_' ) === 0 ) {
445 + return 'sureforms';
446 + }
447 + if ( strpos( $base, 'wsform_' ) === 0 ) {
448 + return 'wsform';
449 + }
450 + // WordPress core triggers (new_post, new_user, new_comment, new_attachment, etc.)
451 + if ( in_array( $base, array( 'new_comment', 'new_user', 'new_attachment' ), true )
452 + || strpos( $base, 'new_' ) === 0 ) {
453 + return 'wordpress';
454 + }
188 455
189 - if (empty($types)) {
190 - $final_recipient_fields = $recipient_fields;
191 - } else {
192 - foreach ($types as $type) {
193 - $final_recipient_fields[$type] = $recipient_fields[$type];
194 - }
456 + return null;
457 + }
458 +
459 + /**
460 + * Enable / disable trigger
461 + */
462 + public static function notifier_change_trigger_status(){
463 + // Security check: Verify user has manage_options capability
464 + if ( ! current_user_can( 'manage_options' ) ) {
465 + wp_send_json_error( array(
466 + 'message' => 'You do not have permission to perform this action.'
467 + ) );
195 468 }
196 469
197 - return $recipient_fields;
470 + // Verify nonce for additional security
471 + if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_change_trigger_status' ) ) {
472 + wp_send_json_error( array(
473 + 'message' => 'Security check failed.'
474 + ) );
475 + }
476 +
477 + $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
478 + $enabled = isset($_POST['enabled']) ? sanitize_text_field($_POST['enabled']) : 'no';
479 +
480 + if('wa_notifier_trigger' != get_post_type($post_id)){
481 + wp_send_json( array(
482 + 'error' => true,
483 + 'message' => 'Invalid post type.'
484 + ) );
485 + }
486 +
487 + update_post_meta( $post_id, NOTIFIER_PREFIX . 'trigger_enabled' , $enabled);
488 + wp_send_json( array(
489 + 'error' => false,
490 + 'message' => 'Updated'
491 + ) );
198 492 }
199 493
200 - /*
201 - * Get trigger recipient fields
494 + /**
495 + * Fetch trigger fields for a speicific trigger
202 496 */
203 - public static function get_trigger_recipient_fields($trigger){
204 - $recipient_fields = array();
205 - $main_triggers = self::get_notification_triggers();
206 - foreach ($main_triggers as $key => $triggers) {
207 - foreach ($triggers as $t) {
208 - if ( $trigger == $t['id'] ) {
209 - $recipient_fields = $t['recipient_fields'];
210 - break 2;
497 + public static function notifier_fetch_trigger_fields(){
498 + // Security check: Verify user has manage_options capability
499 + if ( ! current_user_can( 'manage_options' ) ) {
500 + wp_send_json_error( array(
501 + 'message' => 'You do not have permission to perform this action.'
502 + ) );
503 + }
504 +
505 + // Verify nonce for additional security
506 + if ( ! wp_verify_nonce( $_POST['_wpnonce'] ?? '', 'notifier_fetch_trigger_fields' ) ) {
507 + wp_send_json_error( array(
508 + 'message' => 'Security check failed.'
509 + ) );
510 + }
511 +
512 + $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
513 + $trigger = isset($_POST['trigger']) ? sanitize_text_field($_POST['trigger']) : '';
514 +
515 + $data_fields = get_post_meta( $post_id, NOTIFIER_PREFIX . 'data_fields', true);
516 + $recipient_fields = get_post_meta( $post_id, NOTIFIER_PREFIX . 'recipient_fields', true);
517 +
518 + // Backward compatibility for Woo recipient fields not starting with woo_order_
519 + if(!empty($recipient_fields)){
520 + if ( strpos($trigger, 'woo_order') !== false){
521 + foreach($recipient_fields as $key => $recipient_field){
522 + if (in_array($recipient_field, array('billing_phone', 'shipping_phone'))){
523 + $recipient_fields[$key] = 'woo_order_' . $recipient_field;
524 + }
211 525 }
212 526 }
213 527 }
214 528
215 - $final_fields = array();
529 + $merge_tags = Notifier_Notification_Merge_Tags::get_trigger_merge_tags($trigger);
530 + $recipient_tags = Notifier_Notification_Merge_Tags::get_trigger_recipient_fields($trigger);
216 531
217 - foreach ($recipient_fields as $field_key => $recipient_fields_list) {
218 - foreach($recipient_fields_list as $field) {
219 - $final_fields[$field_key][$field['id']] = $field['label'];
220 - }
532 + ob_start();
533 + echo '<div class="trigger-fields-wrap"><div class="d-flex justify-content-between"><label class="form-label w-auto">Data fields</label><div class="small"><a href="#" class="notifier-select-all-checkboxes">select all</a> / <a href="#" class="notifier-unselect-all-checkboxes">unselect all</a></div></div>';
534 +
535 + notifier_wp_select( array(
536 + 'id' => NOTIFIER_PREFIX . 'data_fields',
537 + 'name' => NOTIFIER_PREFIX . 'data_fields[]',
538 + 'value' => $data_fields,
539 + 'label' => '',
540 + 'description' => '',
541 + 'placeholder' => 'Start typing here...',
542 + 'options' => $merge_tags,
543 + 'show_wrapper' => false,
544 + 'custom_attributes' => array('multiple' => 'multiple')
545 + ) );
546 +
547 + echo '<span class="description">Select the data fields that will be sent to WANotifier.com when the trigger happens. These fields will be available to map with message template variables like <code>{{1}}</code>, <code>{{2}}</code> etc when you <a href="https://app.wanotifier.com/notifications/add/" target="_blank">create a Notification</a>.</span></div>';
548 +
549 + if(!empty($recipient_tags)){
550 + echo '<div class="trigger-fields-wrap"><div class="d-flex justify-content-between"><label class="form-label w-auto">Recipient fields</label><div class="small"><a href="#" class="notifier-select-all-checkboxes">select all</a> / <a href="#" class="notifier-unselect-all-checkboxes">unselect all</a></div></div>';
551 +
552 + notifier_wp_select( array(
553 + 'id' => NOTIFIER_PREFIX . 'recipient_fields',
554 + 'name' => NOTIFIER_PREFIX . 'recipient_fields[]',
555 + 'value' => $recipient_fields,
556 + 'label' => '',
557 + 'description' => '',
558 + 'placeholder' => 'Start typing here...',
559 + 'options' => $recipient_tags,
560 + 'show_wrapper' => false,
561 + 'custom_attributes' => array('multiple' => 'multiple')
562 + ) );
563 +
564 + echo '<span class="description">Select the recipient fields that will be sent to WANotifier.com when this trigger happens. These fields will be available under <b>Recipients</b> section when you create a Notification. Note that the selected recipient fields <b>must return a phone number</b> with a country code (e.g. +919876543210) or the message wll not be sent.</span></div>';
221 565 }
222 566
223 - return $final_fields;
567 + $html = ob_get_clean();
568 +
569 + wp_send_json( array(
570 + 'status' => 'success',
571 + 'html' => $html
572 + ) );
224 573 }
225 574
226 575 /**
227 - * Get recipient_field value
576 + * Get post trigger ID
228 577 */
229 - public static function get_trigger_recipient_field_value($recipient_field, $context_args) {
230 - $value = '';
231 - $main_triggers = self::get_notification_triggers();
232 - foreach ($main_triggers as $key => $triggers) {
233 - foreach ($triggers as $t) {
234 - $recipient_fields = (!empty($t['recipient_fields'])) ? $t['recipient_fields'] : array();
235 - if(empty($recipient_fields)){
236 - continue;
237 - }
238 - foreach($recipient_fields as $fields){
239 - foreach($fields as $field){
240 - if ( isset($field['id']) && $recipient_field == $field['id'] ) {
241 - $value = $field['value']($context_args);
242 - break 2;
243 - }
244 - }
245 - }
246 - }
578 + public static function get_post_trigger_id($post_id){
579 + $site_key = self::get_notification_trigger_site_key();
580 + $selected_trigger = get_post_meta( $post_id, NOTIFIER_PREFIX . 'trigger', true);
581 + if($selected_trigger && strpos($selected_trigger, $site_key) === false ){
582 + $selected_trigger = $site_key . $selected_trigger;
247 583 }
248 - return $value;
584 + return $selected_trigger;
585 + }
586 +
587 + /**
588 + * Get trigger ID with site key
589 + */
590 + public static function get_trigger_id_with_site_key($trigger_id){
591 + $site_key = self::get_notification_trigger_site_key();
592 + if( strpos($trigger_id, $site_key) === false ){
593 + $trigger_id = $site_key . $trigger_id;
594 + }
595 + return $trigger_id;
596 + }
597 +
598 + /**
599 + * Get trigger ID without site key
600 + */
601 + public static function get_trigger_id_without_site_key($trigger_id){
602 + $site_key = self::get_notification_trigger_site_key();
603 + $trigger_id = str_replace($site_key, '', $trigger_id);
604 + return $trigger_id;
249 605 }
250 606
251 607 }