Completed
Push — master ( 07f312...c89a6b )
by Ronan
16s queued 14s
created

Imei::validate()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 45
rs 7.9555
c 0
b 0
f 0
cc 8
nc 8
nop 1
1
<?php
2
3
namespace IsoCodes;
4
5
/**
6
 * Class Imei for International Mobile Equipment Identity (IMEI)
7
 * IMEI is a number, usually unique,
8
 * to identify 3GPP and iDEN mobile phones, as well as some satellite phones.
9
 *
10
 * The IMEI (15 decimal digits: 14 digits plus a check digit)
11
 * or IMEISV (16 decimal digits: 14 digits plus two software version digits)
12
 * includes information on the origin, model, and serial number of the device.
13
 *
14
 * As of 2004, the format of the IMEI is AA-BBBBBB-CCCCCC-D,
15
 * although it may not always be displayed this way.
16
 *
17
 * The IMEISV does not have the Luhn check digit
18
 * but instead has two digits for the Software Version Number (SVN), making the format AA-BBBBBB-CCCCCC-EE
19
 *
20
 * @see https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity
21
 */
22
class Imei implements IsoCodeInterface
23
{
24
    const HYPHENS = ['‐', '-', ' ']; // regular dash, authentic hyphen (rare!) and space
25
26
    /**
27
     * @param mixed $imei
28
     *
29
     * @return bool
30
     */
31
    public static function validate($imei)
32
    {
33
        $imei = Utils::unDecorate($imei, self::HYPHENS);
34
        $length = 15; // for EMEI only, IMEISV is +1
35
        $divider = 10;
36
        $weight = 2;
37
        $sum = 0;
38
39
        // IMEISV?
40
        if ($length + 1 === strlen($imei)) {
41
            $expr = sprintf('/\\d{%d}/i', $length + 1);
42
            if (preg_match($expr, $imei)) {
43
                return true;
44
            }
45
46
            return false;
47
        }
48
49
        // IMEI?
50
        $body = substr($imei, 0, $length - 1);
51
        $check = substr($imei, $length - 1, 1);
52
        $expr = sprintf('/\\d{%d}/i', $length);
53
        if (!preg_match($expr, $imei)) {
54
            return false;
55
        }
56
        if (0 === (int) $imei) {
57
            return false;
58
        }
59
60
        for ($i = 0; $i < strlen($body); ++$i) {
61
            if (0 === $i % 2) {
62
                $add = (int) substr($body, $i, 1);
63
                $sum += $add;
64
            } else {
65
                $add = $weight * (int) substr($body, $i, 1);
66
                if (10 <= $add) { // '18' = 1+8 = 9, etc.
67
                    $strAdd = strval($add);
68
                    $add = intval($strAdd[0]) + intval($strAdd[1]);
69
                }
70
                $sum += $add;
71
            }
72
        }
73
74
        return 0 === ($sum + $check) % $divider;
75
    }
76
}
77