diff --git a/public_html/wp-content/plugins/camptix-webhook/addons/webhook.php b/public_html/wp-content/plugins/camptix-webhook/addons/webhook.php new file mode 100644 index 000000000..c644c14ae --- /dev/null +++ b/public_html/wp-content/plugins/camptix-webhook/addons/webhook.php @@ -0,0 +1,222 @@ +caps['manage_options'] ) ) { + add_filter( 'camptix_setup_sections', array( $this, 'setup_sections' ) ); + add_action( 'camptix_menu_setup_controls', array( $this, 'setup_controls' ), 10, 1 ); + add_filter( 'camptix_validate_options', array( $this, 'validate_options' ), 10, 2 ); + + // Add js for testing webhook. + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + } + + add_action( 'save_post_tix_attendee', array( $this, 'trigger_webhook_async' ), 10, 2 ); + add_action( 'camptix_webhook_trigger', array( $this, 'trigger_webhook' ) ); + } + + /** + * Add a new section to the Setup screen. + */ + public function setup_sections( $sections ) { + $sections['webhook-ui'] = esc_html__( 'Webhook', 'wordcamporg' ); + + return $sections; + } + + /** + * Add some controls to our Setup section. + */ + public function setup_controls( $section ) { + global $camptix; + + if ( 'webhook-ui' != $section ) { + return; + } + + add_settings_section( 'general', esc_html__( 'Attendees Webhook', 'wordcamporg' ), array( $this, 'setup_controls_section' ), 'camptix_options' ); + + // Fields. + $camptix->add_settings_field_helper( 'webhook-enabled', esc_html__( 'Enabled', 'wordcamporg' ), 'field_yesno', 'general' ); + $camptix->add_settings_field_helper( 'webhook-url', esc_html__( 'Webhook URL', 'wordcamporg' ), 'field_text', 'general', esc_html__( 'Webhook URL including protocol such as https://', 'wordcamporg' ) ); + + add_action( 'camptix_setup_buttons', array( $this, 'setup_buttons_test_webhook' ) ); + } + + /** + * Runs whenever the CampTix option is updated. + */ + public function validate_options( $output, $input ) { + if ( isset( $input['webhook-enabled'] ) ) { + $output['webhook-enabled'] = (bool) $input['webhook-enabled']; + } + + if ( ! empty( $input['webhook-url'] ) ) { + $output['webhook-url'] = sanitize_url( $input['webhook-url'] ); + } + + return $output; + } + + /** + * Setup section description. + */ + public function setup_controls_section() { + ?> +
+ ++ ' . esc_html__( 'Test Webhook', 'wordcamporg' ) . ''; + + echo wp_kses_post( $button ); + } + + /** + * Trigger webhook asynchronously. + * Use cron to trigger webhook 5 seconds after attendee is updated. + * So this process won't block the main process. And prevents multiple triggers. + * + * @param int $post_id Attendee ID. + * @param WP_Post $post Attendee Post Object. + * @return void + */ + public function trigger_webhook_async( $post_id, $post ) { + // Trigger webhook asynchronously. + if ( ! wp_next_scheduled( 'camptix_webhook_trigger', array( $post_id ) ) ) { + wp_schedule_single_event( time() + 5, 'camptix_webhook_trigger', array( $post_id ) ); + } + } + + /** + * Trigger webhook when attendee is updated. + * + * @param int $post_id Attendee ID. + * @return void + */ + public function trigger_webhook( $post_id ) { + /** @var CampTix_Plugin $camptix */ + global $camptix; + + $camptix_options = $camptix->get_options(); + + $is_enabled = isset( $camptix_options['webhook-enabled'] ) ? $camptix_options['webhook-enabled'] : false; + $webhook_url = isset( $camptix_options['webhook-url'] ) ? $camptix_options['webhook-url'] : ''; + + if ( ! $is_enabled ) { + return; + } + + if ( empty( $webhook_url ) ) { + return; + } + + $post = get_post( $post_id ); + + if ( 'tix_attendee' !== $post->post_type ) { + return; + } + + $triggered_number = absint( get_post_meta( $post_id, 'tix_webhook_triggered_number', true ) ); + + // Get attendee data. + $attendee_data = array( + 'timestamp' => time(), + 'status' => $post->post_status, + 'is_new_entry' => 0 === $triggered_number, + 'tix_email' => get_post_meta( $post_id, 'tix_email', true ), + 'tix_first_name' => get_post_meta( $post_id, 'tix_first_name', true ), + 'tix_last_name' => get_post_meta( $post_id, 'tix_last_name', true ), + 'tix_ticket_id' => get_post_meta( $post_id, 'tix_ticket_id', true ), + 'tix_coupon' => get_post_meta( $post_id, 'tix_coupon', true ), + ); + + $attendee_data = apply_filters( 'camptix_webhook_attendee_data', $attendee_data, $post_id ); + + // Prepare webhook data. + $response = wp_remote_post( + $webhook_url, + array( + 'body' => wp_json_encode( $attendee_data ), + 'headers' => array( + 'Content-Type' => 'application/json', + ), + ) + ); + + update_post_meta( $post_id, 'tix_webhook_triggered_number', $triggered_number + 1 ); + + // Log the response. + if ( is_wp_error( $response ) ) { + $this->log( sprintf( 'Webhook failed: %s', $response->get_error_message() ), $post_id, $response ); + } + + $this->log( 'Webhook triggered', $post_id, $response ); + } + + /** + * Enqueue scripts for admin. + * + * @param mixed $hook Current page hook. + * @return void + */ + public function admin_enqueue_scripts( $hook ) { + if ( 'tix_ticket_page_camptix_options' !== $hook ) { + return; + } + + wp_enqueue_script( + 'camptix-webhook-admin', + plugin_dir_url( Webhook\BASE_FILE ) . 'js/camptix-webhook-admin.js', + array(), + '1.0', + array( + 'strategy' => 'async', + 'footer' => true, + ) + ); + } + + /** + * Write a log entry to CampTix. + */ + public function log( $message, $post_id = 0, $data = null ) { + global $camptix; + $camptix->log( $message, $post_id, $data, 'webhook' ); + } + + /** + * Register self as a CampTix addon. + */ + public static function register_addon() { + camptix_register_addon( __CLASS__ ); + } +} diff --git a/public_html/wp-content/plugins/camptix-webhook/camptix-webhook.php b/public_html/wp-content/plugins/camptix-webhook/camptix-webhook.php new file mode 100644 index 000000000..577ca0571 --- /dev/null +++ b/public_html/wp-content/plugins/camptix-webhook/camptix-webhook.php @@ -0,0 +1,43 @@ + setup page. + */ +function test_webhook_action() { + + if ( ! isset( $_GET['test_webhook'] ) || '1' !== $_GET['test_webhook'] ) { + return; + } + + /** @var CampTix_Plugin $camptix */ + global $camptix; + + $camptix_options = $camptix->get_options(); + + $webhook_url = isset( $camptix_options['webhook-url'] ) ? $camptix_options['webhook-url'] : ''; + + // Get attendee data. + $attendee_data = array( + 'timestamp' => time(), + 'status' => 'publish', + 'is_new_entry' => true, + 'tix_email' => 'camptix-webhook-test@wordcamp.org', + 'tix_first_name' => 'Camptix Webhook', + 'tix_last_name' => 'Test', + 'tix_ticket_id' => '0000', + 'tix_coupon' => 'Coupon_XXX', + ); + + // Post ID: -1 will invalid when getting post object. We use this to indicate that this is a test webhook. + $attendee_data = apply_filters( 'camptix_webhook_attendee_data', $attendee_data, -1 ); + + // Prepare webhook data. + $response = wp_remote_post( + $webhook_url, + array( + 'body' => wp_json_encode( $attendee_data ), + 'headers' => array( + 'Content-Type' => 'application/json', + ), + ) + ); + + if ( is_wp_error( $response ) ) { + add_settings_error( + 'camptix-webhook', + 'error', + __( 'Webhook test failed: ', 'wordcamporg' ) . $response->get_error_message(), + 'error' + ); + return; + } + + add_settings_error( + 'camptix-webhook', + 'success', + __( 'Webhook test success', 'wordcamporg' ), + 'success' + ); +} + +/** + * Add attendees admin flag to attendee data. + * + * @param array $attendee_data Array of attendee data. + * @param int $post_id Post ID. + * @return array + */ +function add_attendees_admin_flag( $attendee_data, $post_id ): array { + // Post ID: -1 will invalid when getting post object. We use this to indicate that this is a test webhook. + if ( -1 === $post_id ) { + $admin_flag = array( 'volunteer', 'speaker', 'organiser' ); + $attendee_data['tix_admin_flag'] = $admin_flag[ array_rand( $admin_flag ) ]; + + return $attendee_data; + } + + // Admin flag meta could be more than 1. + $attendee_data['tix_admin_flag'] = get_post_meta( $post_id, 'camptix-admin-flag', false ); + + return $attendee_data; +} + +/** + * Add attendees meta to attendee data. + * + * @param array $attendee_data Array of attendee data. + * @param int $post_id Post ID. + * @return array + */ +function add_attendees_meta( $attendee_data, $post_id ): array { + $allowed_meta = array( + 'tix_accommodations', + 'tix_allergy', + 'tix_coupon', + 'tix_first_time_attending_wp_event', + ); + + // Post ID: -1 will invalid when getting post object. We use this to indicate that this is a test webhook. + if ( -1 === $post_id ) { + $attendee_data['tix_accommodations'] = 'yes'; + $attendee_data['tix_allergy'] = 'no'; + $attendee_data['tix_coupon'] = 'test'; + $attendee_data['tix_first_time_attending_wp_event'] = 'test'; + + return $attendee_data; + } + + foreach ( $allowed_meta as $meta_key ) { + $attendee_data[ $meta_key ] = get_post_meta( $post_id, $meta_key, true ); + } + + return $attendee_data; +} + +/** + * Add attendees questions answered to attendee data. + * + * @param array $attendee_data Array of attendee data. + * @param int $post_id Post ID. + * @return array + */ +function add_attendees_questions_answered( $attendee_data, $post_id ): array { + // Post ID: -1 will invalid when getting post object. We use this to indicate that this is a test webhook. + if ( -1 === $post_id ) { + $attendee_data['answered'] = 'N/A'; + + return $attendee_data; + } + + global $camptix; + $ticket_id = intval( get_post_meta( $post_id, 'tix_ticket_id', true ) ); + $questions = $camptix->get_sorted_questions( $ticket_id ); + $answers = get_post_meta( $post_id, 'tix_questions', true ); + + $rows = array(); + foreach ( $questions as $question ) { + if ( isset( $answers[ $question->ID ] ) ) { + $answer = $answers[ $question->ID ]; + if ( is_array( $answer ) ) { + $answer = implode( ', ', $answer ); + } + $rows[] = array( $question->post_title, $answer ); + } + } + + $attendee_data['answered'] = $rows; + + return $attendee_data; +} diff --git a/public_html/wp-content/plugins/camptix-webhook/js/camptix-webhook-admin.js b/public_html/wp-content/plugins/camptix-webhook/js/camptix-webhook-admin.js new file mode 100644 index 000000000..470827adb --- /dev/null +++ b/public_html/wp-content/plugins/camptix-webhook/js/camptix-webhook-admin.js @@ -0,0 +1,30 @@ +/** + * Add event listener to test button. + */ +function addEventHandler() { + const testWebhookButton = document.getElementById( 'camptix-webhook-test-url' ); + + if ( ! testWebhookButton ) { + return; + } + + testWebhookButton.addEventListener( 'click', function ( event ) { + event.preventDefault(); + + try { + // Get current url. + const url = new URL( window.location.href ); + + // Add search param test_webhook to url. + url.searchParams.append( 'test_webhook', '1' ); + + // Redirect to new url. + window.location = url.href; + } catch ( error ) { + // Do nothing. + } + } ); +} + +// Run event listener when window load. +window.addEventListener( 'load', addEventHandler );