Completed
Pull Request — master (#433)
by Roberto
06:56
created

Parser   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 0
dl 0
loc 85
ccs 0
cts 62
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B read() 0 31 6
B block() 0 27 6
1
<?php
2
3
namespace NFePHP\EFD\Common;
4
5
use \NFePHP\Common\Strings;
6
7
class Parser
8
{
9
10
    public $error = [];
11
    protected $blocks;
12
    protected $info = [];
13
    
14
    /**
15
     * Constructor
16
     * @param string $version
17
     * @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...
18
     */
19
    public function __construct($version = '310')
20
    {
21
        $structurefile = __DIR__ . "/../../storage/structure_EFDICMS_{$version}.txt";
22
        $structure = file_get_contents($structurefile);
23
        $this->blocks = $this->block($structure, true);
24
    }
25
    
26
    /**
27
     * Read EFD content file and return as array
28
     * @param string $contentfile
29
     * @return array
30
     * @throws Exception
31
     */
32
    public function read($contentfile)
33
    {
34
        //cleaning
35
        $contentfile = str_replace('__', '_', $contentfile);
36
        $contentfile = str_replace(['| ', ' |'], '|', $contentfile);
37
        $contentfile = str_replace(['- ', ' -'], '-', $contentfile);
38
        $contentfile = str_replace('\r', '', $contentfile);
39
        $contentfile = strtoupper($contentfile);
40
41
        $datas = $this->block($contentfile);
42
        foreach ($datas as $data) {
43
            foreach ($data as $key => $d) {
44
                $node = $this->blocks[$key];
45
                $vars = [];
46
                if (empty($d)) {
47
                    continue;
48
                }
49
                if (count($node) !== count($d)) {
50
                    $this->error[] = "Erro de conteúdo da chave $key";
51
                }
52
                foreach ($d as $n => $value) {
53
                    $name = $node[$n];
54
                    $value = str_replace(',', '.', Strings::toASCII($value));
55
                    $value = preg_replace("/[^a-zA-Z0-9 @,-_.;:\/]/", "", $value);
56
                    $vars[$name] = trim($value);
57
                }
58
            }
59
            $this->info[] = [$key => $vars];
0 ignored issues
show
Bug introduced by
The variable $key seems to be defined by a foreach iteration on line 43. 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...
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...
60
        }
61
        return $this->info;
62
    }
63
64
    protected function block($fields, $unique = false)
65
    {
66
        $elements = explode("\n", $fields);
67
        $block = [];
68
        foreach ($elements as $element) {
69
            if (empty($element)) {
70
                continue;
71
            }
72
            $arr = explode('|', $element);
73
            $n = count($arr);
74
            $fields = array_slice($arr, 1, $n - 2);
75
            $key = (string) $fields[0];
76
            if (substr($key, 1, 3) === '990' || substr($key, 0, 1) === '9'
77
            ) {
78
                continue;
79
            }
80
            array_splice($fields, 0, 1);
81
            if ($unique) {
82
                $block[$key] = $fields;
83
            } else {
84
                $block[] = [
85
                    $key => $fields
86
                ];
87
            }
88
        }
89
        return $block;
90
    }
91
}
92