Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.50% covered (warning)
87.50%
28 / 32
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Integration_Dispatcher
87.50% covered (warning)
87.50%
28 / 32
33.33% covered (danger)
33.33%
1 / 3
14.38
0.00% covered (danger)
0.00%
0 / 1
 init
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dispatch
92.00% covered (success)
92.00%
23 / 25
0.00% covered (danger)
0.00%
0 / 1
8.03
 get_form_from_fields
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
5.93
1<?php
2/**
3 * Hands new form responses to the integrations that asked for them.
4 *
5 * @package automattic/jetpack-forms
6 */
7
8namespace Automattic\Jetpack\Forms\Integrations;
9
10use Automattic\Jetpack\Forms\ContactForm\Contact_Form;
11use Automattic\Jetpack\Forms\ContactForm\Feedback;
12
13/**
14 * Calls the `on_submission` callback of every available integration a form has enabled.
15 *
16 * Integrations could hook `grunion_after_feedback_post_inserted` themselves — Form_Webhooks
17 * does. Going through the registry instead means one integration is declared in one place, and
18 * that the settings lookup, the spam check and the enabled check happen once, consistently,
19 * rather than being re-implemented (and re-got-wrong) by each integration.
20 */
21class Integration_Dispatcher {
22
23    /**
24     * Start listening for new responses.
25     *
26     * @return void
27     */
28    public static function init() {
29        add_action( 'grunion_after_feedback_post_inserted', array( __CLASS__, 'dispatch' ), 10, 4 );
30    }
31
32    /**
33     * Notify integrations of a new response.
34     *
35     * @param int   $post_id      Feedback post ID.
36     * @param array $fields       Contact_Form_Field instances for the submission.
37     * @param bool  $is_spam      Whether Akismet flagged the submission as spam.
38     * @param array $entry_values Extra values recorded with the submission.
39     * @return void
40     */
41    public static function dispatch( $post_id, $fields, $is_spam, $entry_values ) {
42        // Spam is never handed on. An integration that wants spam can hook
43        // grunion_after_feedback_post_inserted directly and decide for itself.
44        if ( $is_spam ) {
45            return;
46        }
47
48        $form = self::get_form_from_fields( $fields );
49
50        if ( ! $form ) {
51            return;
52        }
53
54        Built_In_Integrations::register();
55
56        $feedback = Feedback::get( $post_id );
57
58        if ( ! $feedback ) {
59            return;
60        }
61
62        foreach ( Integration_Registry::available() as $slug => $args ) {
63            if ( empty( $args['on_submission'] ) || ! is_callable( $args['on_submission'] ) ) {
64                continue;
65            }
66
67            $settings = Integration_Settings::get( $slug, $form->attributes );
68
69            if ( empty( $settings['enabled'] ) ) {
70                continue;
71            }
72
73            /**
74             * A single associative argument, so that later additions do not change the
75             * signature every registered callback has to match.
76             */
77            call_user_func(
78                $args['on_submission'],
79                array(
80                    'settings'     => $settings,
81                    'post_id'      => $post_id,
82                    'form'         => $form,
83                    'feedback'     => $feedback,
84                    'entry_values' => $entry_values,
85                )
86            );
87        }
88    }
89
90    /**
91     * Find the form a submission belongs to.
92     *
93     * The form is not passed to the hook, but every field holds a reference to it.
94     *
95     * @param array $fields Contact_Form_Field instances.
96     * @return Contact_Form|null
97     */
98    private static function get_form_from_fields( $fields ) {
99        if ( ! is_array( $fields ) ) {
100            return null;
101        }
102
103        foreach ( $fields as $field ) {
104            if ( ! empty( $field->form ) && $field->form instanceof Contact_Form ) {
105                return $field->form;
106            }
107        }
108
109        return null;
110    }
111}