Passed
Branch etl-core (c0e492)
by Jean Paul
01:52
created

CsvExtractor::getEnclosure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Coco\SourceWatcher\Core\Extractors;
4
5
use Coco\SourceWatcher\Core\Extractor;
6
use Coco\SourceWatcher\Core\Row;
7
8
use Exception;
9
10
class CsvExtractor extends Extractor
11
{
12
    private array $columns;
13
    private string $delimiter;
14
    private string $enclosure;
15
16
    public function __construct ()
17
    {
18
        $this->columns = array();
19
        $this->delimiter = ",";
20
        $this->enclosure = "\"";
21
    }
22
23
    /**
24
     * @return array
25
     */
26
    public function getColumns () : array
27
    {
28
        return $this->columns;
29
    }
30
31
    /**
32
     * @param array $columns
33
     */
34
    public function setColumns ( array $columns ) : void
35
    {
36
        $this->columns = $columns;
37
    }
38
39
    /**
40
     * @return string
41
     */
42
    public function getDelimiter () : string
43
    {
44
        return $this->delimiter;
45
    }
46
47
    /**
48
     * @param string $delimiter
49
     */
50
    public function setDelimiter ( string $delimiter ) : void
51
    {
52
        $this->delimiter = $delimiter;
53
    }
54
55
    /**
56
     * @return string
57
     */
58
    public function getEnclosure () : string
59
    {
60
        return $this->enclosure;
61
    }
62
63
    /**
64
     * @param string $enclosure
65
     */
66
    public function setEnclosure ( string $enclosure ) : void
67
    {
68
        $this->enclosure = $enclosure;
69
    }
70
71
    public function extract () : array
72
    {
73
        if ( $this->input == null ) {
74
            throw new Exception( "An input must be provided." );
75
        }
76
77
        $result = array();
78
79
        $fileHandler = fopen( $this->input, "r" );
80
81
        $columns = $this->generateColumns( $fileHandler );
82
83
        while ( $currentFileLine = fgets( $fileHandler ) ) {
0 ignored issues
show
Bug introduced by
It seems like $fileHandler can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

83
        while ( $currentFileLine = fgets( /** @scrutinizer ignore-type */ $fileHandler ) ) {
Loading history...
84
            $currentRowArray = $this->generateRow( $currentFileLine, $columns );
85
86
            array_push( $result, new Row( $currentRowArray ) );
87
        }
88
89
        fclose( $fileHandler );
0 ignored issues
show
Bug introduced by
It seems like $fileHandler can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

89
        fclose( /** @scrutinizer ignore-type */ $fileHandler );
Loading history...
90
91
        return $result;
92
    }
93
94
    private function generateColumns ( $fileHandler ) : array
95
    {
96
        // The goal will be to represent the keys in format [key1 -> 1, key2 -> 2, ... keyN -> N]
97
        $columnsArrayFlipped = array_flip( str_getcsv( fgets( $fileHandler ), $this->delimiter, $this->enclosure ) );
98
99
        foreach ( $columnsArrayFlipped as $key => $index ) {
100
            $columnsArrayFlipped[$key] = $index + 1;
101
        }
102
103
        // If no columns have been defined, make the columns attribute equal to the ones with format [key1 -> 1, key2 -> 2, ... keyN -> n]
104
        if ( empty( $this->columns ) ) {
105
            return $columnsArrayFlipped;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $columnsArrayFlipped could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
106
        }
107
108
        // If the keys of the columns attribute equal to an array in format [0, 1, ... N] then they need to be reformatted as an intersection of the ones found and the ones requested.
109
        if ( array_keys( $this->columns ) === range( 0, count( $this->columns ) - 1 ) ) {
110
            return array_intersect_key( $columnsArrayFlipped, array_flip( $this->columns ) );
111
        }
112
113
        $result = array();
114
115
        foreach ( $this->columns as $key => $value ) {
116
            $result[$value] = $columnsArrayFlipped[$key];
117
        }
118
119
        return $result;
120
    }
121
122
    private function generateRow ( string $rowString, array $columns ) : array
123
    {
124
        $resultRow = array();
125
126
        $rowArray = str_getcsv( $rowString, $this->delimiter, $this->enclosure );
127
128
        foreach ( $columns as $column => $index ) {
129
            $resultRow[$column] = $rowArray[$index - 1];
130
        }
131
132
        return $resultRow;
133
    }
134
}
135