Completed
Push — master ( 061197...d9e6ea )
by Andreas
02:16
created

CreditCard::setProperties()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 5
crap 2
1
<?php
2
3
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5
/*
6
 * This file is part of the Larium CreditCard package.
7
 *
8
 * (c) Andreas Kollaros <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Larium\CreditCard;
15
16
/**
17
 * CreditCard class acts as value object.
18
 *
19
 * @author  Andreas Kollaros <[email protected]>
20
 */
21
final class CreditCard
22
{
23
    const VISA               = 'visa';
24
    const MASTER             = 'master';
25
    const DISCOVER           = 'discover';
26
    const AMEX               = 'american_express';
27
    const DINERS_CLUB        = 'diners_club';
28
    const JCB                = 'jcb';
29
    const SWITCH_BRAND       = 'switch';
30
    const SOLO               = 'solo';
31
    const DANKORT            = 'dankort';
32
    const MAESTRO            = 'maestro';
33
    const FORBRUGSFORENINGEN = 'forbrugsforeningen';
34
    const LASER              = 'laser';
35
    const UNIONPAY           = 'unionpay';
36
37
    /**
38
     * Card holder name.
39
     * Should be in upper case.
40
     *
41
     * @var string
42
     */
43
    private $holderName;
44
45
    /**
46
     * Expire date of card as value object
47
     *
48
     * @var ExpiryDate
49
     */
50
    private $expiryDate;
51
52
    /**
53
     * The brand of card.
54
     *
55
     * @var mixed|false
56
     */
57
    private $brand;
58
59
    /**
60
     * The number of card.
61
     *
62
     * @var string
63
     */
64
    private $number;
65
66
    /**
67
     * The verification value of card (cvv).
68
     * 3 or 4 digits.
69
     *
70
     * @var integer
71
     */
72
    private $cvv;
73
74
    /**
75
     * Whether card is require verification value to be present.
76
     *
77
     * @var boolean
78
     */
79
    private $requireCvv = true;
80
81
    /**
82
     * Token stored from a real credit card and can be used for purchases.
83
     *
84
     * @var Token
85
     */
86
    private $token;
87
88 24
    public function __construct(array $options = array())
89
    {
90
        $default = array(
91 24
            'holderName' => null,
92 24
            'month'      => 1,
93 24
            'year'       => 1970,
94 24
            'brand'      => '',
95 24
            'number'     => null,
96 24
            'cvv'        => null,
97 24
            'requireCvv' => true,
98
            'token'      => null
99 24
        );
100
101 24
        $options = array_intersect_key($options, $default);
102 24
        $options = array_replace($default, $options);
103
104 24
        $month = $options['month'];
105 24
        $year  = $options['year'];
106 24
        $brand = $options['brand'];
107 24
        $token = $options['token'];
108
109 24
        unset($options['month'], $options['year'], $options['brand'], $options['token']);
110
111 24
        $this->setProperties($month, $year, $brand, $token, $options);
112 24
    }
113
114 24
    private function setProperties($month, $year, $brand, $token, $options)
115
    {
116 24
        foreach ($options as $prop => $value) {
117 24
            $this->$prop = $value;
118 24
        }
119
120 24
        $this->expiryDate = new ExpiryDate($month, $year);
121
122 24
        $this->detectBrand($brand);
123
124 24
        $this->token($token);
125 24
    }
126
127 24
    private function token($token)
128
    {
129 24
        if (null === $token) {
130 20
            return;
131
        }
132
133 4
        if ($token instanceof Token) {
134 1
            $this->token = $token;
135
136 1
            return;
137
        }
138
139 3
        $this->token = new Token($token);
140 3
    }
141
142
    /**
143
     * @param string $brand
144
     * @return void
145
     */
146 24
    private function detectBrand($brand = '')
147
    {
148 24
        $detector = new CreditCardDetector();
149
150 24
        if (false === $this->brand = $detector->detect($this->number)) {
151 9
            $this->brand = $brand;
152 9
        };
153 24
    }
154
155
    /**
156
     * @param string $prop
157
     * @param mixed $value
158
     * @return CreditCard
159
     */
160 4
    private function with($prop, $value)
161
    {
162 4
        $card = clone $this;
163
164 4
        $card->$prop = $value;
165
166 4
        return $card;
167
    }
168
169
    /**
170
     * Gets the number of card.
171
     *
172
     * @return string
173
     */
174 17
    public function getNumber()
175
    {
176 17
        return $this->number;
177
    }
178
179
    /**
180
     * Sets card number.
181
     *
182
     * @param  string $number
183
     * @return CreditCard
184
     */
185 2
    public function withNumber($number)
186
    {
187 2
        $card = $this->with('number', $number);
188 2
        $card->detectBrand();
189 2
        $card->token = null;
190
191 2
        return $card;
192
    }
193
194
    /**
195
     * Gets card holder name.
196
     *
197
     * @return string
198
     */
199 16
    public function getHolderName()
200
    {
201 16
        return $this->holderName;
202
    }
203
204
    /**
205
     * Sets card holder name.
206
     *
207
     * @param  string $holderName
208
     * @return CreditCard
209
     */
210 1
    public function withHolderName($holderName)
211
    {
212 1
        $holderName = strtoupper($holderName);
213 1
        return $this->with('holderName', $holderName);
214
    }
215
216
    /**
217
     * Gets expiry date card.
218
     *
219
     * @return ExpiryDate
220
     */
221 16
    public function getExpiryDate()
222
    {
223 16
        return $this->expiryDate;
224
    }
225
226
    /**
227
     * Sets expiry month of card.
228
     *
229
     * @param  ExpiryDate $expiryDate
230
     * @return CreditCard
231
     */
232 1
    public function withExpiryDate(ExpiryDate $expiryDate)
233
    {
234 1
        return $this->with('expiryDate', $expiryDate);
235
    }
236
237
    /**
238
     * Gets the brand of card.
239
     *
240
     * @return string
241
     */
242 15
    public function getBrand()
243
    {
244 15
        return $this->brand;
245
    }
246
247
    /**
248
     * Sets the brand of card.
249
     *
250
     * @param  string $brand
251
     * @return CreditCard
252
     */
253 1
    public function withBrand($brand)
254
    {
255 1
        return $this->with('brand', $brand);
256
    }
257
258
    /**
259
     * Gets card verification value (cvv).
260
     *
261
     * @return integer
262
     */
263 14
    public function getCvv()
264
    {
265 14
        return $this->cvv;
266
    }
267
268
    /**
269
     * Sets card verification value.
270
     *
271
     * @param  integer $cvv
272
     * @return CreditCard
273
     */
274 1
    public function withCvv($cvv)
275
    {
276 1
        return $this->with('cvv', $cvv);
277
    }
278
279
    /**
280
     * Check if cvv is required for credit card validation.
281
     *
282
     * @return boolean
283
     */
284 14
    public function isRequireCvv()
285
    {
286 14
        return $this->requireCvv;
287
    }
288
289
    /**
290
     * Gets referenece token of a credit card.
291
     *
292
     * @return Token
293
     */
294 6
    public function getToken()
295
    {
296 6
        return $this->token;
297
    }
298
299
    /**
300
     * Sets token value.
301
     *
302
     * @param  Token $token
303
     * @return CreditCard
304
     */
305 2
    public function withToken(Token $token)
306
    {
307 2
        $card = $this->with('token', $token);
308
309 2
        if (null !== $card->number) {
310 1
            $lastDigits = strlen($card->number) <= 4
311 1
                ? $card->number :
312 1
                substr($card->number, -4);
313 1
            $card->number = "XXXX-XXXX-XXXX-" . $lastDigits;
314 1
        }
315
316 2
        $card->cvv = null;
317
318 2
        return $card;
319
    }
320
321
    /**
322
     * Checks whether credit card has stored a Token reference or not.
323
     *
324
     * @return boolean
325
     */
326 2
    public function hasToken()
327
    {
328 2
        return null !== $this->token;
329
    }
330
331 5
    public function __clone()
332
    {
333 5
        if ($this->expiryDate) {
334 5
            $this->expiryDate = clone $this->expiryDate;
335 5
        }
336 5
    }
337
}
338