Parser::block()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 0
cts 26
cp 0
rs 9.1928
c 0
b 0
f 0
cc 5
nc 5
nop 2
crap 30
1
<?php
2
3
namespace NFePHP\EFD\Common;
4
5
use ForceUTF8\Encoding;
6
use NFePHP\Common\Strings;
7
8
class Parser
9
{
10
11
    public $error = [];
12
    protected $blocks;
13
    protected $info = [];
14
15
    /**
16
     * Constructor
17
     * @param string $version
18
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
19
     */
20
    public function __construct($version = '310')
21
    {
22
        $structurefile = __DIR__ . "/../../storage/structure_EFDICMS_{$version}.txt";
23
        $structure = file_get_contents($structurefile);
24
        $this->blocks = $this->block($structure, true);
25
    }
26
27
    /**
28
     * Read EFD content file and return as array
29
     * @param string $contentfile
30
     * @return array
31
     * @throws \Exception
32
     */
33
    public function read($contentfile)
34
    {
35
        //cleaning
36
        $contentfile = str_replace('__', '_', $contentfile);
37
        $contentfile = str_replace(['| ', ' |'], '|', $contentfile);
38
        $contentfile = str_replace(['- ', ' -'], '-', $contentfile);
39
        $contentfile = str_replace('\r', '', $contentfile);
40
        $contentfile = strtoupper($contentfile);
41
        $contentfile = Encoding::fixUTF8($contentfile);
42
        $contentfile = Strings::squashCharacters($contentfile);
43
44
        $datas = $this->block($contentfile);
45
        $i = 1;
46
        foreach ($datas as $data) {
47
            foreach ($data as $key => $d) {
48
                $node = $this->blocks[$key];
49
                $vars = [];
50
                if (empty($d)) {
51
                    continue;
52
                }
53
                if (count($node) !== count($d)) {
54
                    $this->error[] = "Erro de conteúdo da chave $key";
55
                }
56
                foreach ($d as $n => $value) {
57
                    $name = $node[$n];
58
                    $value = str_replace(',', '.', $value);
59
                    $value = str_replace(["\r","\t","\n"], "", $value);
60
                    //$value = preg_replace('/(?:\s\s+)/', ' ', $value);
61
                    $value = preg_replace("/[^a-zA-Z0-9 @,-_.;:\/]/", "", $value);
62
                    $vars[$name] = trim($value);
63
                }
64
            }
65
            if (substr($key, 1, 2) === '99') {
0 ignored issues
show
Bug introduced by
The variable $key seems to be defined by a foreach iteration on line 47. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
66
                $i++;
67
                continue;
68
            }
69
            $this->info[$i] = [$key => $vars];
0 ignored issues
show
Bug introduced by
The variable $vars 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...
70
            $i++;
71
        }
72
        return $this->info;
73
    }
74
75
    protected function block($fields, $unique = false)
76
    {
77
        $elements = explode("\n", $fields);
78
        $block = [];
79
        foreach ($elements as $element) {
80
            if (empty($element)) {
81
                continue;
82
            }
83
            $arr = explode('|', $element);
84
            $n = count($arr);
85
            $fields = array_slice($arr, 1, $n - 2);
86
            $key = (string) $fields[0];
87
            if (substr($key, 0, 1) === '9') {
88
                continue;
89
            }
90
            array_splice($fields, 0, 1);
91
            if ($unique) {
92
                $block[$key] = $fields;
93
            } else {
94
                $block[] = [
95
                    $key => $fields
96
                ];
97
            }
98
        }
99
        return $block;
100
    }
101
}
102