Completed
Push — master ( a7385b...36e950 )
by Ronan
23s queued 11s
created

Utils::luhn()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 9.1928
c 0
b 0
f 0
cc 5
nc 5
nop 5
1
<?php
2
3
namespace IsoCodes;
4
5
/**
6
 * Utils.
7
 */
8
class Utils
9
{
10
    /**
11
     * @param mixed $input: null or string
0 ignored issues
show
Documentation introduced by
There is no parameter named $input:. Did you maybe mean $input?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
12
     */
13
    public static function unDecorate($input, array $hyphens = []): string
14
    {
15
        $hyphensLength = count($hyphens);
16
        // removing hyphens
17
        for ($i = 0; $i < $hyphensLength; ++$i) {
18
            $input = str_replace($hyphens[$i], '', $input);
19
        }
20
21
        return $input;
22
    }
23
24
    /**
25
     * @param mixed $value: null or string
0 ignored issues
show
Documentation introduced by
There is no parameter named $value:. Did you maybe mean $value?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
26
     * @param $hyphens
27
     */
28
    public static function luhn($value, int $length, int $weight, int $divider, $hyphens): bool
29
    {
30
        $value = self::unDecorate($value, $hyphens);
31
        $digits = substr($value, 0, $length - 1);
32
        $check = substr($value, $length - 1, 1);
33
        $expr = sprintf('/\\d{%d}/i', $length);
34
        if (!preg_match($expr, $value)) {
35
            return false;
36
        }
37
38
        $sum = 0;
39
        for ($i = 0; $i < strlen($digits); ++$i) {
40
            if (0 === $i % 2) {
41
                $add = (int) substr($digits, $i, 1);
42
            } else {
43
                $add = $weight * (int) substr($digits, $i, 1);
44
                if (10 <= $add) { // '18' = 1+8 = 9, etc.
45
                    $strAdd = strval($add);
46
                    $add = intval($strAdd[0]) + intval($strAdd[1]);
47
                }
48
            }
49
            $sum += $add;
50
        }
51
52
        return 0 === ($sum + $check) % $divider;
53
    }
54
55
    /**
56
     * @param mixed $value: null or string
0 ignored issues
show
Documentation introduced by
There is no parameter named $value:. Did you maybe mean $value?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
57
     */
58
    public static function luhnForGTIN($value, int $length, bool $unDecorate = true, array $hyphens = []): bool
59
    {
60
        $value = $unDecorate ? self::unDecorate($value, $hyphens) : $value;
61
        $divider = 10;
62
        $multiplier = 3;
63
64
        if (strlen($value) != $length) {
65
            return false;
66
        }
67
        $expr = sprintf('/\\d{%d}/i', $length);
68
        if (!preg_match($expr, $value)) {
69
            return false;
70
        }
71
        if (0 === (int) $value) {
72
            return false;
73
        }
74
75
        $sum = 0;
76
        // the multiplier get applied differently (even or odd) according the value length
77
        // see https://blog.datafeedwatch.com/hubfs/blog/calculate-14-digit-gtin.png
78
        for ($i = 0; $i < $length; $i += 2) {
79
            if (0 === $length % 2) {
80
                $sum += $multiplier * (int) substr($value, $i, 1);
81
                $sum += (int) substr($value, $i + 1, 1);
82
            } else {
83
                $sum += (int) substr($value, $i, 1);
84
                $sum += $multiplier * (int) substr($value, $i + 1, 1);
85
            }
86
        }
87
88
        return 0 === $sum % $divider;
89
    }
90
91
    public static function luhnWithWeights(string $value, int $length, array $weights, int $divider, $hyphens): bool
92
    {
93
        $value = self::unDecorate($value, $hyphens);
94
        $digits = substr($value, 0, $length - 1);
95
        $check = substr($value, $length - 1, 1);
96
        $expr = sprintf('/\\d{%d}/i', $length);
97
        if (!preg_match($expr, $value)) {
98
            return false;
99
        }
100
101
        $sum = 0;
102
        for ($i = 0; $i < strlen($digits); ++$i) {
103
            if (!is_numeric($digits[$i])) {
104
                return false;
105
            }
106
            $sum += $weights[$i] * intval($digits[$i]);
107
        }
108
109
        $rest = $sum % $divider;
110
111
        if (0 === $rest) {
112
            $check = $divider;
113
        }
114
115
        return intval($check) === $divider - $rest;
116
    }
117
}
118