Completed
Push — master ( cb9cb0...a2a2e1 )
by
unknown
43:00 queued 13:11
created

AuthorizeNetCP_Response::__construct()   C

Complexity

Conditions 11
Paths 71

Size

Total Lines 95
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 20.8435
Metric Value
dl 0
loc 95
ccs 34
cts 60
cp 0.5667
rs 5.2653
cc 11
eloc 62
nc 71
nop 4
crap 20.8435

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Easily interact with the Authorize.Net Card Present API.
4
 *
5
 *
6
 * @package    AuthorizeNet
7
 * @subpackage AuthorizeNetCP
8
 * @link       http://www.authorize.net/support/CP_guide.pdf Card Present Guide
9
 */
10
11
 
12
/**
13
 * Builds and sends an AuthorizeNet CP Request.
14
 *
15
 * @package    AuthorizeNet
16
 * @subpackage AuthorizeNetCP
17
 */
18
class AuthorizeNetCP extends AuthorizeNetAIM
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
19
{
20
    
21
    const LIVE_URL = 'https://cardpresent.authorize.net/gateway/transact.dll';
22
    
23
    public $verify_x_fields = false; 
24
    
25
    /**
26
     * Holds all the x_* name/values that will be posted in the request. 
27
     * Default values are provided for best practice fields.
28
     */
29
    protected $_x_post_fields = array(
30
        "cpversion" => "1.0", 
31
        "delim_char" => ",",
32
        "encap_char" => "|",
33
        "market_type" => "2",
34
        "response_format" => "1", // 0 - XML, 1 - NVP
35
        );
36
    
37
    /**
38
     * Device Types (x_device_type)
39
     * 1 = Unknown
40
     * 2 = Unattended Terminal
41
     * 3 = Self Service Terminal
42
     * 4 = Electronic Cash Register
43
     * 5 = Personal Computer- Based Terminal
44
     * 6 = AirPay
45
     * 7 = Wireless POS
46
     * 8 = Website
47
     * 9 = Dial Terminal
48
     * 10 = Virtual Terminal
49
     */
50
    
51
	/**
52
     * Only used if merchant wants to send custom fields.
53
     */
54
    private $_custom_fields = array();
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
55
	
56
    /**
57
     * Strip sentinels and set track1 field.
58
     *
59
     * @param  string $track1data
60
     */
61 1
    public function setTrack1Data($track1data) {
62 1
        if (preg_match('/^%.*\?$/', $track1data)) {
63 1
            $this->track1 = substr($track1data, 1, -1);
0 ignored issues
show
Documentation introduced by
The property track1 does not exist on object<AuthorizeNetCP>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
64
        } else {
65
            $this->track1 = $track1data;    
0 ignored issues
show
Documentation introduced by
The property track1 does not exist on object<AuthorizeNetCP>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
66
        }
67 1
    }
68
    
69
    /**
70
     * Strip sentinels and set track2 field.
71
     *
72
     * @param  string $track2data
73
     */
74 2
    public function setTrack2Data($track2data) {
75 2
        if (preg_match('/^;.*\?$/', $track2data)) {
76
            $this->track2 = substr($track2data, 1, -1);
0 ignored issues
show
Documentation introduced by
The property track2 does not exist on object<AuthorizeNetCP>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
77
        } else {
78 2
            $this->track2 = $track2data;    
0 ignored issues
show
Documentation introduced by
The property track2 does not exist on object<AuthorizeNetCP>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
79
        }
80 2
    }
81
    
82
    /**
83
     *
84
     *
85
     * @param string $response
86
     * 
87
     * @return AuthorizeNetAIM_Response
88
     */
89 5
    protected function _handleResponse($response)
90
    {
91 5
        return new AuthorizeNetCP_Response($response, $this->_x_post_fields['delim_char'], $this->_x_post_fields['encap_char'], $this->_custom_fields);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \AuthorizeNet...$this->_custom_fields); (AuthorizeNetCP_Response) is incompatible with the return type of the parent method AuthorizeNetAIM::_handleResponse of type AuthorizeNetAIM_Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
92
    }
93
    
94
}
95
96
97
/**
98
 * Parses an AuthorizeNet Card Present Response.
99
 *
100
 * @package    AuthorizeNet
101
 * @subpackage AuthorizeNetCP
102
 */
103
class AuthorizeNetCP_Response extends AuthorizeNetResponse
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
104
{
105
    private $_response_array = array(); // An array with the split response.
106
107
    /**
108
     * Constructor. Parses the AuthorizeNet response string.
109
     *
110
     * @param string $response      The response from the AuthNet server.
111
     * @param string $delimiter     The delimiter used (default is ",")
112
     * @param string $encap_char    The encap_char used (default is "|")
113
     * @param array  $custom_fields Any custom fields set in the request.
114
     */
115 5
    public function __construct($response, $delimiter, $encap_char, $custom_fields)
0 ignored issues
show
Unused Code introduced by
The parameter $custom_fields is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
116
    {
117 5
        if ($response) {
118
            
119
            // If it's an XML response
120 5
            if (substr($response, 0, 5) == "<?xml") {
121
                
122
                $this->xml = @simplexml_load_string($response);
0 ignored issues
show
Bug introduced by
The property xml does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
123
                // Set all fields
124
                $this->version              = array_pop(array_slice(explode('"', $response), 1,1));
0 ignored issues
show
Bug introduced by
array_slice(explode('"', $response), 1, 1) cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
Bug introduced by
The property version does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
125
                $this->response_code        = (string)$this->xml->ResponseCode;
126
                
127
                if ($this->response_code == 1) {
128
                    $this->response_reason_code = (string)$this->xml->Messages->Message->Code;
129
                    $this->response_reason_text = (string)$this->xml->Messages->Message->Description;
130
                } else {
131
                    $this->response_reason_code = (string)$this->xml->Errors->Error->ErrorCode;
132
                    $this->response_reason_text = (string)$this->xml->Errors->Error->ErrorText;
133
                }
134
                
135
                $this->authorization_code   = (string)$this->xml->AuthCode;
136
                $this->avs_code             = (string)$this->xml->AVSResultCode;
0 ignored issues
show
Bug introduced by
The property avs_code does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
137
                $this->card_code_response   = (string)$this->xml->CVVResultCode;
138
                $this->transaction_id       = (string)$this->xml->TransID;
139
                $this->md5_hash             = (string)$this->xml->TransHash;
140
                $this->user_ref             = (string)$this->xml->UserRef;
0 ignored issues
show
Bug introduced by
The property user_ref does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
141
                $this->card_num             = (string)$this->xml->AccountNumber;
0 ignored issues
show
Bug introduced by
The property card_num does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
142
                $this->card_type            = (string)$this->xml->AccountType;
143
                $this->test_mode            = (string)$this->xml->TestMode;
0 ignored issues
show
Bug introduced by
The property test_mode does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
144
                $this->ref_trans_id         = (string)$this->xml->RefTransID;
0 ignored issues
show
Bug introduced by
The property ref_trans_id does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
145
                
146
                
147
            } else { // If it's an NVP response
148
                
149
                // Split Array
150 5
                $this->response = $response;
151 5
                if ($encap_char) {
152 5
                    $this->_response_array = explode($encap_char.$delimiter.$encap_char, substr($response, 1, -1));
153
                } else {
154
                    $this->_response_array = explode($delimiter, $response);
155
                }
156
                
157
                /**
158
                 * If AuthorizeNet doesn't return a delimited response.
159
                 */
160 5
                if (count($this->_response_array) < 10) {
161
                    $this->approved = false;
162
                    $this->error = true;
163
                    $this->error_message = "Unrecognized response from AuthorizeNet: $response";
0 ignored issues
show
Bug introduced by
The property error_message does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
164
                    return;
165
                }
166
                
167
                
168
                
169
                // Set all fields
170 5
                $this->version              = $this->_response_array[0];
171 5
                $this->response_code        = $this->_response_array[1];
172 5
                $this->response_reason_code = $this->_response_array[2];
173 5
                $this->response_reason_text = $this->_response_array[3];
174 5
                $this->authorization_code   = $this->_response_array[4];
175 5
                $this->avs_code             = $this->_response_array[5];
176 5
                $this->card_code_response   = $this->_response_array[6];
177 5
                $this->transaction_id       = $this->_response_array[7];
178 5
                $this->md5_hash             = $this->_response_array[8];
179 5
                $this->user_ref             = $this->_response_array[9];
180 5
                $this->card_num             = $this->_response_array[20];
181 5
                $this->card_type            = $this->_response_array[21];
182 5
                $this->split_tender_id      = isset($this->_response_array[22]) ? $this->_response_array[22] : NULL;
183 5
                $this->requested_amount     = isset($this->_response_array[23]) ? $this->_response_array[23] : NULL;
184 5
                $this->approved_amount      = isset($this->_response_array[24]) ? $this->_response_array[24] : NULL;
0 ignored issues
show
Bug introduced by
The property approved_amount does not seem to exist. Did you mean approved?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
185 5
                $this->card_balance         = isset($this->_response_array[25]) ? $this->_response_array[25] : NULL;
0 ignored issues
show
Bug introduced by
The property card_balance does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
186
    
187
    
188
                
189
            }
190 5
            $this->approved = ($this->response_code == self::APPROVED);
191 5
            $this->declined = ($this->response_code == self::DECLINED);
192 5
            $this->error    = ($this->response_code == self::ERROR);
193 5
            $this->held     = ($this->response_code == self::HELD);
194
195
            
196 5
            if ($this->error) {
197 1
                $this->error_message = "AuthorizeNet Error:
198 1
                Response Code: ".$this->response_code."
199 1
                Response Reason Code: ".$this->response_reason_code."
200 1
                Response Reason Text: ".$this->response_reason_text."
201 5
                ";
202
            }
203
            
204
        } else {
205
            $this->approved = false;
206
            $this->error = true;
207
            $this->error_message = "Error connecting to AuthorizeNet";
208
        }
209 5
    }
210
    
211
    /**
212
     * Is the MD5 provided correct?
213
     *
214
     * @param string $api_login_id
215
     * @param string $md5_setting
216
     * @return bool
217
     */
218
    public function isAuthorizeNet($api_login_id = false, $md5_setting = false)
219
    {
220
        $amount = ($this->amount ? $this->amount : '0.00');
221
        $api_login_id = ($api_login_id ? $api_login_id : AUTHORIZENET_API_LOGIN_ID);
222
        $md5_setting = ($md5_setting ? $md5_setting : AUTHORIZENET_MD5_SETTING);
223
        return ($this->md5_hash == strtoupper(md5($md5_setting . $api_login_id . $this->transaction_id . $amount)));
224
    }
225
226
}
227
228