Completed
Push — master ( 138c0b...920a1b )
by John
01:56
created

Form   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 192
Duplicated Lines 14.58 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 42.68%

Importance

Changes 0
Metric Value
wmc 22
c 0
b 0
f 0
lcom 1
cbo 2
dl 28
loc 192
ccs 35
cts 82
cp 0.4268
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B submit() 0 49 6
A getSessionIdFromHeader() 14 14 3
A getContactIdFromHeader() 14 14 4
B prepareRequest() 0 35 6
A getUrl() 0 4 1
A getId() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 = (int) $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)
0 ignored issues
show
Coding Style introduced by
submit uses the super-global variable $_COOKIE 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...
45
    {
46
        $originalCookie = $_COOKIE;
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
            $ckfile = tempnam(sys_get_temp_dir(), 'mauticcookie');
64
            curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
65
        }
66
67
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
68
        curl_setopt($ch, CURLOPT_VERBOSE, 1);
69
        curl_setopt($ch, CURLOPT_HEADER, 1);
70
        list($header, $content) = explode("\r\n\r\n", curl_exec($ch), 2);
71
        $response['header'] = $header;
72
        $response['content'] = htmlentities($content);
73
        $response['info'] = curl_getinfo($ch);
74
        curl_close($ch);
75
76
        $contact = $this->mautic->getContact();
77
78
        if ($sessionId = $this->getSessionIdFromHeader($response['header'])) {
79
            $contact->setSessionIdCookie($sessionId);
80
        }
81
82
        if ($contactId = $this->getContactIdFromHeader($response['header'], $sessionId)) {
83
            $contact->setIdCookie($contactId);
84
        }
85
86
        return [
87
            'original_cookie' => $originalCookie,
88
            'new_cookie' => $_COOKIE,
89
            'request' => $request,
90
            'response' => $response,
91
        ];
92
    }
93
94
    /**
95
     * Finds the session ID hash in the response header
96
     *
97
     * @param  string $headers
98
     *
99
     * @return string|null
100
     */
101 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...
102
    {
103 2
        if (!$headers) {
104 2
            return null;
105
        }
106
107 2
        preg_match("/mautic_session_id=(.+?);/", $headers, $matches);
108
109 2
        if (isset($matches[1])) {
110 2
            return $matches[1];
111
        }
112
113
        return null;
114
    }
115
116
    /**
117
     * Finds the Mautic Contact ID hash in the response header
118
     *
119
     * @param  string $headers
120
     * @param  string $sessionId
121
     *
122
     * @return string|null
123
     */
124 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...
125
    {
126 2
        if (!$headers || !$sessionId) {
127 2
            return null;
128
        }
129
130 2
        preg_match("/$sessionId=(.+?);/", $headers, $matches);
131
132 2
        if (isset($matches[1])) {
133 2
            return (int) $matches[1];
134
        }
135
136
        return null;
137
    }
138
139
    /**
140
     * Prepares data for CURL request based on provided form data, $_COOKIE and $_SERVER
141
     *
142
     * @param  array $data
143
     *
144
     * @return array
145
     */
146 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...
147
    {
148 2
        $contact = $this->mautic->getContact();
149 2
        $request = ['header'];
150
151 2
        $data['formId'] = $this->id;
152
153
        // return has to be part of the form data array so Mautic would accept the submission
154 2
        if (!isset($data['return'])) {
155 2
            $data['return'] = '';
156 1
        }
157
158 2
        $request['url'] = $this->getUrl();
159 2
        $request['data'] = ['mauticform' => $data];
160
161 2
        if ($contactId = $contact->getId()) {
162
            $request['data']['mtc_id'] = $contactId;
163
        }
164
165 2
        if ($contactIp = $contact->getIp()) {
166
            $request['header'][] = "X-Forwarded-For: $contactIp";
167
        }
168
169 2
        if ($sessionId = $contact->getMauticSessionIdFromCookie()) {
170
            $request['header'][] = "Cookie: mautic_session_id=$sessionId";
171
        }
172
173 2
        if (isset($_SERVER['HTTP_REFERER'])) {
174
            $request['referer'] = $_SERVER["HTTP_REFERER"];
175
        }
176
177 2
        $request['query'] = http_build_query($request['data']);
178
179 2
        return $request;
180
    }
181
182
    /**
183
     * Builds the form URL
184
     *
185
     * @return string
186
     */
187 4
    public function getUrl()
188
    {
189 4
        return sprintf('%s/form/submit?formId=%d', $this->mautic->getBaseUrl(), $this->id);
190
    }
191
192
    /**
193
     * Returns the Form ID
194
     *
195
     * @return int
196
     */
197 6
    public function getId()
198
    {
199 6
        return $this->id;
200
    }
201
}
202