Completed
Pull Request — master (#309)
by ignace nyamagana
03:02
created

RFC4180Iterator::__construct()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 2
nop 1
dl 0
loc 12
ccs 8
cts 8
cp 1
crap 4
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Csv (https://csv.thephpleague.com).
5
 *
6
 * @author  Ignace Nyamagana Butera <[email protected]>
7
 * @license https://github.com/thephpleague/csv/blob/master/LICENSE (MIT License)
8
 * @version 9.1.5
9
 * @link    https://github.com/thephpleague/csv
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
declare(strict_types=1);
16
17
namespace League\Csv;
18
19
use IteratorAggregate;
20
use SplFileObject;
21
use TypeError;
22
use function get_class;
23
use function gettype;
24
use function is_object;
25
use function sprintf;
26
use function substr;
27
28
/**
29
 * A RFC4180 Compliant Parser in Pure PHP.
30
 *
31
 * @see https://php.net/manual/en/function.fgetcsv.php
32
 * @see https://php.net/manual/en/function.fgetc.php
33
 * @see https://tools.ietf.org/html/rfc4180
34
 * @see http://edoceo.com/utilitas/csv-file-format
35
 *
36
 * @package League.csv
37
 * @since   9.2.0
38
 * @author  Ignace Nyamagana Butera <[email protected]>
39
 * @internal used internally to produce RFC4180 compliant records
40
 */
41
final class RFC4180Iterator implements IteratorAggregate
42
{
43
    /**
44
     * The CSV document.
45
     *
46
     * @var SplFileObject|Stream
47
     */
48
    private $document;
49
50
    /**
51
     * New instance.
52
     *
53
     * @param SplFileObject|Stream $document
54
     */
55 9
    public function __construct($document)
56
    {
57 9
        if (!$document instanceof Stream && !$document instanceof SplFileObject) {
58 3
            throw new TypeError(sprintf(
59 3
                'Expected a %s or an SplFileObject object, % given',
60 3
                Stream::class,
61 3
                is_object($document) ? get_class($document) : gettype($document)
62
            ));
63
        }
64
65 6
        $this->document = $document;
66 6
    }
67
68
    /**
69
     * @inheritdoc
70
     *
71
     * Converts the stream into a CSV record iterator
72
     */
73 12
    public function getIterator()
74
    {
75
        //initialisation
76 12
        $record = [];
77 12
        $buffer = '';
78 12
        $previous_char = '';
79 12
        $enclosed_field = false;
80 12
        list($delimiter, $enclosure, ) = $this->document->getCsvControl();
81 12
        $this->document->rewind();
82
83
        //let's walk through the stream a char by char
84 12
        while (false !== ($char = $this->document->fgetc())) {
85
            switch ($char) {
86 12
                case $enclosure:
87 12
                    if (false === $enclosed_field) {
88
                        //the enclosure is at the start of the record
89
                        //this is an enclosed field
90 12
                        if ('' === $buffer) {
91 12
                            $enclosed_field = true;
92 12
                            break;
93
                        }
94
                        //invalid CSV content let's deal with it like fgetcsv
95
                        //we add the character to the buffer and we move on
96 6
                        $previous_char = $char;
97 6
                        $buffer .= $char;
98 6
                        break;
99
                    }
100
                    //double quoted enclosure let's skip the character and move on
101 12
                    if ($previous_char === $enclosure) {
102 6
                        $previous_char = '';
103 6
                        break;
104
                    }
105 12
                    $previous_char = $char;
106 12
                    $buffer .= $char;
107 12
                    break;
108 12
                case $delimiter:
109 12
                    if ($enclosed_field) {
110
                        //the delimiter is enclosed let's add it to the buffer and move on
111 12
                        if ($previous_char !== $enclosure) {
112 6
                            $buffer .= $char;
113 6
                            break;
114
                        }
115
                        //strip the enclosure character present at the
116
                        //end of the buffer; this is the end of en enclosed field
117 12
                        $buffer = substr($buffer, 0, -1);
118
                    }
119
120
                    //the buffer is the field content we add it to the record
121 12
                    $record[] = $buffer;
122
123
                    //reset field parameters
124 12
                    $buffer = '';
125 12
                    $previous_char = '';
126 12
                    $enclosed_field = false;
127 12
                    break;
128 12
                case "\n":
129 12
                case "\r":
130 12
                    if ($enclosed_field) {
131
                        //the line break is enclosed let's add it to the buffer and move on
132 12
                        if ($previous_char !== $enclosure) {
133 6
                            $previous_char = $char;
134 6
                            $buffer .= $char;
135 6
                            break;
136
                        }
137
                        //strip the enclosure character present at the
138
                        //end of the buffer; this is the end of a record
139 6
                        $buffer = substr($buffer, 0, -1);
140
                    }
141
142
                    //adding field content to the record
143 12
                    $record[] = $buffer;
144
                    //reset field parameters
145 12
                    $buffer = '';
146 12
                    $enclosed_field = false;
147 12
                    $previous_char = '';
148
149
                    //yield the record
150 12
                    yield $record;
151
152
                    //reset record
153 12
                    $record = [];
154 12
                    break;
155
                default:
156 12
                    $buffer .= $char;
157 12
                    break;
158
            }
159
        }
160 12
        $record[] = $buffer;
161 12
        $buffer = '';
0 ignored issues
show
Unused Code introduced by
$buffer is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
162 12
        $enclosed_field = false;
0 ignored issues
show
Unused Code introduced by
$enclosed_field is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
163 12
        $previous_char = '';
0 ignored issues
show
Unused Code introduced by
$previous_char is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
164
165 12
        yield $record;
166 12
    }
167
}
168