Completed
Push — master ( 861886...cceff3 )
by John
10:56
created

Form::prepareRequest()   B

Complexity

Conditions 6
Paths 32

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.3949

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 14
cts 18
cp 0.7778
rs 8.439
c 0
b 0
f 0
cc 6
eloc 18
nc 32
nop 1
crap 6.3949
1
<?php
2
3
namespace Escopecz\MauticFormSubmit\Mautic;
4
5
use Escopecz\MauticFormSubmit\Mautic;
6
7
/**
8
 * Mautic form
9
 */
10
class Form
11
{
12
    /**
13
     * @var Mautic
14
     */
15
    protected $mautic;
16
17
    /**
18
     * Form ID
19
     *
20
     * @var int
21
     */
22
    protected $id;
23
24
    /**
25
     * Constructor
26
     *
27
     * @param Mautic $mautic
28
     * @param int    $id
29
     */
30 14
    public function __construct(Mautic $mautic, $id)
31
    {
32 14
        $this->mautic = $mautic;
33 14
        $this->id = $id;
34 14
    }
35
36
    /**
37
     * Submit the $data array to the Mautic form
38
     * Returns array containing info about the request, response and cookie
39
     *
40
     * @param  array  $data
41
     *
42
     * @return array
43
     */
44
    public function submit(array $data)
45
    {
46
        $originalCookie = $this->mautic->getCookie()->getSuperGlobalCookie();
47
        $response = [];
48
        $request = $this->prepareRequest($data);
49
50
        $ch = curl_init($request['url']);
51
        curl_setopt($ch, CURLOPT_POST, 1);
52
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request['query']);
53
54
        if (isset($request['header'])) {
55
            curl_setopt($ch, CURLOPT_HTTPHEADER, $request['header']);
56
        }
57
58
        if (isset($request['referer'])) {
59
            curl_setopt($ch, CURLOPT_REFERER, $request['referer']);
60
        }
61
62
        if (isset($request['cookie'])) {
63
            curl_setopt($ch, CURLOPT_COOKIEFILE, $this->mautic->getCookie()->createCookieFile());
64
        }
65
66
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
67
        curl_setopt($ch, CURLOPT_VERBOSE, 1);
68
        curl_setopt($ch, CURLOPT_HEADER, 1);
69
        list($header, $content) = explode("\r\n\r\n", curl_exec($ch), 2);
70
        $response['header'] = $header;
71
        $response['content'] = htmlentities($content);
72
        $response['info'] = curl_getinfo($ch);
73
        curl_close($ch);
74
75
        $contact = $this->mautic->getContact();
76
77
        if ($sessionId = $this->getSessionIdFromHeader($response['header'])) {
78
            $contact->setSessionId($sessionId);
79
        }
80
81
        if ($contactId = $this->getContactIdFromHeader($response['header'], $sessionId)) {
82
            $contact->setId($contactId);
83
        }
84
85
        return [
86
            'original_cookie' => $originalCookie,
87
            'new_cookie' => $this->mautic->getCookie()->toArray(),
88
            'request' => $request,
89
            'response' => $response,
90
        ];
91
    }
92
93
    /**
94
     * Finds the session ID hash in the response header
95
     *
96
     * @param  string $headers
97
     *
98
     * @return string|null
99
     */
100 2 View Code Duplication
    public function getSessionIdFromHeader($headers)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
    {
102 2
        if (!$headers) {
103 2
            return null;
104
        }
105
106 2
        preg_match("/mautic_session_id=(.+?);/", $headers, $matches);
107
108 2
        if (isset($matches[1])) {
109 2
            return $matches[1];
110
        }
111
112
        return null;
113
    }
114
115
    /**
116
     * Finds the Mautic Contact ID hash in the response header
117
     *
118
     * @param  string $headers
119
     * @param  string $sessionId
120
     *
121
     * @return int|null
122
     */
123 2 View Code Duplication
    public function getContactIdFromHeader($headers, $sessionId)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
    {
125 2
        if (!$headers || !$sessionId) {
126 2
            return null;
127
        }
128
129 2
        preg_match("/$sessionId=(.+?);/", $headers, $matches);
130
131 2
        if (isset($matches[1])) {
132 2
            return (int) $matches[1];
133
        }
134
135
        return null;
136
    }
137
138
    /**
139
     * Prepares data for CURL request based on provided form data, $_COOKIE and $_SERVER
140
     *
141
     * @param  array $data
142
     *
143
     * @return array
144
     */
145 2
    public function prepareRequest(array $data)
0 ignored issues
show
Coding Style introduced by
prepareRequest uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
146
    {
147 2
        $contact = $this->mautic->getContact();
148 2
        $request = ['header'];
149
150 2
        $data['formId'] = $this->id;
151
152
        // return has to be part of the form data array so Mautic would accept the submission
153 2
        if (!isset($data['return'])) {
154 2
            $data['return'] = '';
155
        }
156
157 2
        $request['url'] = $this->getUrl();
158 2
        $request['data'] = ['mauticform' => $data];
159
160 2
        if ($contactId = $contact->getId()) {
161
            $request['data']['mtc_id'] = $contactId;
162
        }
163
164 2
        if ($contactIp = $contact->getIp()) {
165
            $request['header'][] = "X-Forwarded-For: $contactIp";
166
        }
167
168 2
        if ($sessionId = $contact->getSessionId()) {
169
            $request['header'][] = "Cookie: mautic_session_id=$sessionId";
170
        }
171
172 2
        if (isset($_SERVER['HTTP_REFERER'])) {
173
            $request['referer'] = $_SERVER["HTTP_REFERER"];
174
        }
175
176 2
        $request['query'] = http_build_query($request['data']);
177
178 2
        return $request;
179
    }
180
181
    /**
182
     * Builds the form URL
183
     *
184
     * @return string
185
     */
186 4
    public function getUrl()
187
    {
188 4
        return sprintf('%s/form/submit?formId=%d', $this->mautic->getBaseUrl(), $this->id);
189
    }
190
191
    /**
192
     * Returns the Form ID
193
     *
194
     * @return int
195
     */
196 6
    public function getId()
197
    {
198 6
        return $this->id;
199
    }
200
}
201