Luhn   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 73
ccs 28
cts 28
cp 1
rs 10
c 0
b 0
f 0
wmc 12

3 Methods

Rating   Name   Duplication   Size   Complexity  
A validate() 0 18 4
A create() 0 24 6
A validateNumericString() 0 4 2
1
<?php
2
3
/**
4
 * Luhn algorithm.
5
 *
6
 * The Luhn algorithm or Luhn formula, also known as the "modulus 10" or
7
 * "mod 10" algorithm, is a simple checksum formula used to validate a
8
 * variety of identification numbers, such as credit card numbers,
9
 * IMEI numbers, National Provider Identifier numbers in the US, and
10
 * Canadian Social Insurance Numbers. It was created by IBM scientist
11
 * Hans Peter Luhn and described in U.S. Patent No. 2,950,048, filed
12
 * on January 6, 1954, and granted on August 23, 1960.
13
 */
14
15
namespace Selective\Luhn;
16
17
use InvalidArgumentException;
18
19
/**
20
 * Luhn.
21
 */
22
class Luhn
23
{
24
    /**
25
     * Returns the luhn check digit.
26
     *
27
     * @param string $numbers Numbers as string
28
     *
29
     * @return int Checksum digit
30
     */
31 5
    public function create(string $numbers): int
32
    {
33 5
        $this->validateNumericString($numbers);
34
35
        // Add a zero check digit
36 4
        $numbers .= '0';
37 4
        $sum = 0;
38
        // Find the last character
39 4
        $i = strlen($numbers);
40 4
        $odd_length = $i % 2;
41
        // Iterate all digits backwards
42 4
        while ($i-- > 0) {
43
            // Add the current digit
44 4
            $sum += $numbers[$i];
45
            // If the digit is even, add it again. Adjust for digits 10+ by subtracting 9.
46 4
            if ($odd_length === ($i % 2) && $numbers[$i] > 4) {
47 4
                $sum += ((int)$numbers[$i] - 9);
48
            }
49 4
            if ($odd_length === ($i % 2) && $numbers[$i] <= 4) {
50 4
                $sum += $numbers[$i];
51
            }
52
        }
53
54 4
        return (10 - ($sum % 10)) % 10;
55
    }
56
57
    /**
58
     * Check luhn number.
59
     *
60
     * @param string $number The number to validate
61
     *
62
     * @return bool Status
63
     */
64 17
    public function validate(string $number): bool
65
    {
66 17
        $this->validateNumericString($number);
67
68 16
        $sum = 0;
69 16
        $numDigits = strlen($number) - 1;
70 16
        $parity = $numDigits % 2;
71
72 16
        for ($i = $numDigits; $i >= 0; $i--) {
73 16
            $digit = (int)substr($number, $i, 1);
74 16
            if (!$parity == ($i % 2)) {
75 16
                $digit <<= 1;
76
            }
77 16
            $digit = ($digit > 9) ? ($digit - 9) : $digit;
78 16
            $sum += $digit;
79
        }
80
81 16
        return 0 == ($sum % 10);
82
    }
83
84
    /**
85
     * Validate numeric string.
86
     *
87
     * @param string $number The number to validate
88
     *
89
     * @return void
90
     */
91 22
    private function validateNumericString(string $number): void
92
    {
93 22
        if (!preg_match('/^\d+$/', $number)) {
94 2
            throw new InvalidArgumentException(sprintf('An invalid numeric value was given: %s', $number));
95
        }
96
    }
97
}
98