Completed
Push — master ( 5e45ac...a1e047 )
by John
04:04
created

Form::getSessionIdFromHeader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 14
Ratio 100 %

Code Coverage

Tests 2
CRAP Score 3.3332

Importance

Changes 0
Metric Value
dl 14
loc 14
rs 9.7998
c 0
b 0
f 0
cc 3
nc 3
nop 1
ccs 2
cts 3
cp 0.6667
crap 3.3332
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
        $response = [];
52
        $request = $this->prepareRequest($data);
53
54
        $ch = curl_init($request['url']);
55
        curl_setopt($ch, CURLOPT_POST, 1);
56
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request['query']);
57
58
        if (isset($request['header'])) {
59
            curl_setopt($ch, CURLOPT_HTTPHEADER, $request['header']);
60
        }
61
62
        if (isset($request['referer'])) {
63
            curl_setopt($ch, CURLOPT_REFERER, $request['referer']);
64
        }
65
66
        if (isset($request['cookie'])) {
67
            curl_setopt($ch, CURLOPT_COOKIEFILE, $this->mautic->getCookie()->createCookieFile());
68
        }
69
70
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
71
        curl_setopt($ch, CURLOPT_VERBOSE, 1);
72
        curl_setopt($ch, CURLOPT_HEADER, 1);
73
74
        foreach ($curlOpts as $key => $value) {
75
            curl_setopt($ch, $key, $value);
76
        }
77
78
        list($header, $content) = explode("\r\n\r\n", curl_exec($ch), 2);
79
        $response['header'] = $header;
80
        $response['content'] = htmlentities($content);
81
        $response['info'] = curl_getinfo($ch);
82
        curl_close($ch);
83
84
        $contact = $this->mautic->getContact();
85
        $httpHeader = new HttpHeader($response['header']);
86
        $sessionId = $httpHeader->getCookieValue(Cookie::MAUTIC_SESSION_ID);
87
        $deviceId = $httpHeader->getCookieValue(Cookie::MAUTIC_DEVICE_ID);
88
        $contactId = $httpHeader->getCookieValue($sessionId);
89
90
        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...
91
            $contact->setSessionId($sessionId);
92
        }
93
94
        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...
95
            $contact->setDeviceId($deviceId);
96
        }
97
98
        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...
99
            $contact->setId($contactId);
100 2
        }
101
102 2
        return [
103 2
            'original_cookie' => $originalCookie,
104
            'new_cookie' => $this->mautic->getCookie()->toArray(),
105
            'request' => $request,
106 2
            'response' => $response,
107
        ];
108 2
    }
109 2
110
    /**
111
     * Prepares data for CURL request based on provided form data, $_COOKIE and $_SERVER
112
     *
113
     * @param  array $data
114
     *
115
     * @return array
116
     */
117
    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...
118
    {
119
        $contact = $this->mautic->getContact();
120
        $request = ['header'];
121
122
        $data['formId'] = $this->id;
123 2
124
        // return has to be part of the form data array so Mautic would accept the submission
125 2
        if (!isset($data['return'])) {
126 2
            $data['return'] = '';
127
        }
128
129 2
        $request['url'] = $this->getUrl();
130
        $request['data'] = ['mauticform' => $data];
131 2
132 2
        if ($contactId = $contact->getId()) {
133
            $request['data']['mtc_id'] = $contactId;
134
        }
135
136
        if ($contactIp = $contact->getIp()) {
137
            $request['header'][] = "X-Forwarded-For: $contactIp";
138
            $request['header'][] = "Client-Ip: $contactIp";
139
        }
140
141
        if ($sessionId = $contact->getSessionId()) {
142
            $request['header'][] = "Cookie: mautic_session_id=$sessionId";
143
            $request['header'][] = "Cookie: mautic_device_id=$sessionId";
144
        }
145 2
146
        if (isset($_SERVER['HTTP_REFERER'])) {
147 2
            $request['referer'] = $_SERVER["HTTP_REFERER"];
148 2
        }
149
150 2
        $request['query'] = http_build_query($request['data']);
151
152
        return $request;
153 2
    }
154 2
155
    /**
156
     * Builds the form URL
157 2
     *
158 2
     * @return string
159
     */
160 2
    public function getUrl()
161
    {
162
        return sprintf('%s/form/submit?formId=%d', $this->mautic->getBaseUrl(), $this->id);
163
    }
164 2
165
    /**
166
     * Returns the Form ID
167
     *
168 2
     * @return int
169
     */
170
    public function getId()
171
    {
172 2
        return $this->id;
173
    }
174
}
175