Form   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 47.06%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 184
rs 10
c 0
b 0
f 0
ccs 32
cts 68
cp 0.4706

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B submit() 0 59 8
B prepareRequest() 0 37 6
A prepareResponse() 0 16 5
A getUrl() 0 4 1
A getId() 0 4 1
1
<?php
2
3
namespace Escopecz\MauticFormSubmit\Mautic;
4
5
use Escopecz\MauticFormSubmit\Mautic;
6
use Escopecz\MauticFormSubmit\Mautic\Cookie;
7
use Escopecz\MauticFormSubmit\HttpHeader;
8
9
/**
10
 * Mautic form
11
 */
12
class Form
13
{
14
    /**
15
     * @var Mautic
16
     */
17
    protected $mautic;
18
19
    /**
20
     * Form ID
21
     *
22
     * @var int
23
     */
24
    protected $id;
25
26
    /**
27
     * Constructor
28
     *
29
     * @param Mautic $mautic
30 14
     * @param int    $id
31
     */
32 14
    public function __construct(Mautic $mautic, $id)
33 14
    {
34 14
        $this->mautic = $mautic;
35
        $this->id = $id;
36
    }
37
38
    /**
39
     * Submit the $data array to the Mautic form, using the optional $curlOpts
40
     * array to override curl settings
41
     * Returns array containing info about the request, response and cookie
42
     *
43
     * @param  array  $data
44
     * @param  array  $curlOpts
45
     *
46
     * @return array
47
     */
48
    public function submit(array $data, array $curlOpts = [])
49
    {
50
        $originalCookie = $this->mautic->getCookie()->getSuperGlobalCookie();
51
        $request = $this->prepareRequest($data);
52
53
        $ch = curl_init($request['url']);
54
        curl_setopt($ch, CURLOPT_POST, 1);
55
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request['query']);
56
57
        if (isset($request['header'])) {
58
            curl_setopt($ch, CURLOPT_HTTPHEADER, $request['header']);
59
        }
60
61
        if (isset($request['referer'])) {
62
            curl_setopt($ch, CURLOPT_REFERER, $request['referer']);
63
        }
64
65
        if (isset($request['cookie'])) {
66
            curl_setopt($ch, CURLOPT_COOKIEFILE, $this->mautic->getCookie()->createCookieFile());
67
        }
68
69
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
70
        curl_setopt($ch, CURLOPT_VERBOSE, $this->mautic->getConfig()->getCurlVerbose());
71
        curl_setopt($ch, CURLOPT_HEADER, 1);
72
73
        foreach ($curlOpts as $key => $value) {
74
            curl_setopt($ch, $key, $value);
75
        }
76
77
        $result = curl_exec($ch);
78
        $response = $this->prepareResponse($result);
79
        $response['info'] = curl_getinfo($ch);
80
        curl_close($ch);
81
82
        $contact = $this->mautic->getContact();
83
        $httpHeader = new HttpHeader($response['header']);
84
        $sessionId = $httpHeader->getCookieValue(Cookie::MAUTIC_SESSION_ID);
85
        $deviceId = $httpHeader->getCookieValue(Cookie::MAUTIC_DEVICE_ID);
86
        $contactId = $httpHeader->getCookieValue($sessionId);
87
88
        if ($sessionId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $sessionId of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
89
            $contact->setSessionId($sessionId);
90
        }
91
92
        if ($deviceId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $deviceId of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
93
            $contact->setDeviceId($deviceId);
94
        }
95
96
        if ($contactId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contactId of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
97
            $contact->setId((int)$contactId);
98
        }
99
100 2
        return [
101
            'original_cookie' => $originalCookie,
102 2
            'new_cookie' => $this->mautic->getCookie()->toArray(),
103 2
            'request' => $request,
104
            'response' => $response,
105
        ];
106 2
    }
107
108 2
    /**
109 2
     * Prepares data for CURL request based on provided form data, $_COOKIE and $_SERVER
110
     *
111
     * @param  array $data
112
     *
113
     * @return array
114
     */
115
    public function prepareRequest(array $data)
116
    {
117
        $contact = $this->mautic->getContact();
118
        $request = ['header' => []];
119
120
        $data['formId'] = $this->id;
121
122
        // return has to be part of the form data array so Mautic would accept the submission
123 2
        if (!isset($data['return'])) {
124
            $data['return'] = '';
125 2
        }
126 2
127
        $request['url'] = $this->getUrl();
128
        $request['data'] = ['mauticform' => $data];
129 2
130
        if ($contactId = $contact->getId()) {
131 2
            $request['data']['mtc_id'] = $contactId;
132 2
        }
133
134
        if ($contactIp = $contact->getIp()) {
135
            $request['header'][] = "X-Forwarded-For: $contactIp";
136
            $request['header'][] = "Client-Ip: $contactIp";
137
        }
138
139
        if ($sessionId = $contact->getSessionId()) {
140
            $request['header'][] = "Cookie: mautic_session_id=$sessionId";
141
            $request['header'][] = "Cookie: mautic_device_id=$sessionId";
142
        }
143
144
        if (isset($_SERVER['HTTP_REFERER'])) {
145 2
            $request['referer'] = $_SERVER["HTTP_REFERER"];
146
        }
147 2
148 2
        $request['query'] = http_build_query($request['data']);
149
150 2
        return $request;
151
    }
152
153 2
    /**
154 2
     * Process the result and split into headers and content
155
     *
156
     * @param string|bool $result
157 2
     * @return array
158 2
     */
159
    public function prepareResponse($result)
160 2
    {
161
        $response = ['header' => null, 'content' => null];
162
        $d = "\r\n\r\n"; // Headers and content delimiter
163
164 2
        if (is_string($result) && strpos($result, $d) !== false) {
165
            list($header, $content) = explode($d, $result, 2);
166
            if (stripos($header, '100 Continue') !== false && strpos($content, $d) !== false) {
167
                list($header, $content) = explode($d, $content, 2);
168 2
            }
169
            $response['header'] = $header;
170
            $response['content'] = htmlentities($content);
171
        }
172 2
173
        return $response;
174
    }
175
176 2
    /**
177
     * Builds the form URL
178 2
     *
179
     * @return string
180
     */
181
    public function getUrl()
182
    {
183
        return sprintf('%s/form/submit?formId=%d', $this->mautic->getBaseUrl(), $this->id);
184
    }
185
186 4
    /**
187
     * Returns the Form ID
188 4
     *
189
     * @return int
190
     */
191
    public function getId()
192
    {
193
        return $this->id;
194
    }
195
}
196