Passed
Push — master ( eeace4...fe6676 )
by Roberto
03:31 queued 01:44
created

Keys::cNFIsValid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 3
cp 0
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
namespace NFePHP\Common;
4
5
/**
6
 * Class to create and validate the identification keys of electronic documents
7
 * from SPED
8
 * NT 2018.001 Emitente com CPF e IE
9
 * @category   NFePHP
10
 * @package    NFePHP\Common\Keys
11
 * @copyright  Copyright (c) 2008-2018
12
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
13
 * @author     Roberto L. Machado <linux dot rlm at gmail dot com>
14
 * @link       http://github.com/nfephp-org/sped-common for the canonical source repository
15
 */
16
17
class Keys
18
{
19
    /**
20
     * Build 44 digits keys to NFe, NFCe, CTe and MDFe
21
     * @param string $cUF UF number
22
     * @param string $ano year
23
     * @param string $mes month
24
     * @param string $cnpj or CPF
25
     * @param string $mod model of document 55, 65, 57 etc
26
     * @param string $serie
27
     * @param string $numero document number
28
     * @param string $tpEmis emission type
29
     * @param string $codigo random number or document number
30
     * @return string
31
     */
32 2
    public static function build(
33
        $cUF,
34
        $ano,
35
        $mes,
36
        $cnpj,
37
        $mod,
38
        $serie,
39
        $numero,
40
        $tpEmis,
41
        $codigo = null
42
    ) {
43 2
        if (empty($codigo)) {
44
            $codigo = self::random();
45
        }
46
        //if a cpf with 11 digits is passed then complete with leading zeros
47
        //up to the 14 digits
48 2
        if (strlen($cnpj) < 14) {
49 1
            $cnpj = str_pad($cnpj, 14, '0', STR_PAD_LEFT);
50
        }
51 2
        $format = "%02d%02d%02d%s%02d%03d%09d%01d%08d";
52 2
        $key = sprintf(
53
            $format,
54
            $cUF,
55
            $ano,
56
            $mes,
57
            $cnpj,
58
            $mod,
59
            $serie,
60
            $numero,
61
            $tpEmis,
62
            $codigo
63
        );
64 2
        return $key . self::verifyingDigit($key);
65
    }
66
    
67
    /**
68
     * Verifies that the key provided is valid
69
     * @param string $key
70
     * @return boolean
71
     */
72 2
    public static function isValid($key)
73
    {
74 2
        if (strlen($key) != 44) {
75
            return false;
76
        }
77 2
        $cDV = substr($key, -1);
78 2
        $calcDV = self::verifyingDigit(substr($key, 0, 43));
79 2
        if ($cDV === $calcDV) {
80 1
            return true;
81
        }
82 1
        return false;
83
    }
84
    
85
    /**
86
     * This method calculates verifying digit
87
     * @param string $key
88
     * @return string
89
     */
90 6
    public static function verifyingDigit($key)
91
    {
92 6
        if (strlen($key) != 43) {
93 1
            return '';
94
        }
95 5
        $multipliers = [2, 3, 4, 5, 6, 7, 8, 9];
96 5
        $iCount = 42;
97 5
        $weightedSum = 0;
98 5
        while ($iCount >= 0) {
99 5
            for ($mCount = 0; $mCount < 8 && $iCount >= 0; $mCount++) {
100 5
                $weightedSum += (substr($key, $iCount, 1) * $multipliers[$mCount]);
101 5
                $iCount--;
102
            }
103
        }
104 5
        $vdigit = 11 - ($weightedSum % 11);
105 5
        if ($vdigit > 9) {
106 3
            $vdigit = 0;
107
        }
108 5
        return (string) $vdigit;
109
    }
110
    
111
    /**
112
     * Generate and return a 8 digits random number
113
     * for cNF tag
114
     * @param string|null $nnf
115
     * @return string
116
     */
117
    public static function random($nnf = null)
118
    {
119
        $loop = true;
120
        while ($loop) {
121
            $cnf = str_pad(mt_rand(0, 99999999), 8, '0', STR_PAD_LEFT);
122
            $loop = !self::cNFIsValid($cnf);
123
            if (!empty($nnf)) {
124
                if (intval($cnf) === intval($nnf)) {
125
                    $loop = true;
126
                }
127
            }
128
        }
129
        return $cnf;
0 ignored issues
show
Bug introduced by
The variable $cnf does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
130
    }
131
    
132
    /**
133
     * Verify if cNF number is valid NT2019.001
134
     * @param string $cnf
135
     */
136
    public static function cNFIsValid($cnf)
137
    {
138
        $defs = [
139
            '00000000', '11111111', '22222222', '33333333', '44444444',
140
            '55555555', '66666666', '77777777', '88888888', '99999999',
141
            '12345678', '23456789', '34567890', '45678901', '56789012',
142
            '67890123', '78901234', '89012345', '90123456', '01234567'
143
        ];
144
        return !in_array($cnf, $defs);
145
    }
146
}
147