Csv   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 99
ccs 36
cts 36
cp 1
rs 10
c 0
b 0
f 0
wmc 12
lcom 1
cbo 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
B getCask() 0 27 6
A getEstimatedSize() 0 21 3
1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DataFlow\Provider;
5
6
use SlayerBirden\DataFlow\Data\SimpleBag;
7
use SlayerBirden\DataFlow\IdentificationTrait;
8
use SlayerBirden\DataFlow\Provider\Exception\FileDoesNotExist;
9
use SlayerBirden\DataFlow\Provider\Exception\RowInvalid;
10
use SlayerBirden\DataFlow\Provider\Exception\HeaderMissing;
11
use SlayerBirden\DataFlow\ProviderInterface;
12
13
class Csv implements ProviderInterface
14
{
15
    use IdentificationTrait;
16
17
    /**
18
     * @var string
19
     */
20
    private $id;
21
    /**
22
     * @var \SplFileObject
23
     */
24
    private $file;
25
    /**
26
     * @var bool
27
     */
28
    private $headerRow;
29
    /**
30
     * @var array|null
31
     */
32
    private $header;
33
34
    /**
35
     * @param string $id
36
     * @param \SplFileObject $file
37
     * @param bool $headerRow
38
     * @param string[]|null $header
39
     * @throws FileDoesNotExist
40
     * @throws HeaderMissing
41
     */
42 5
    public function __construct(string $id, \SplFileObject $file, bool $headerRow = true, ?array $header = null)
43
    {
44 5
        $this->id = $id;
45 5
        $this->file = $file;
46 5
        if (!$headerRow && empty($header)) {
47 1
            throw new HeaderMissing(
48 1
                sprintf('You did not provide header for the file %s.', $this->file->getFilename())
49
            );
50
        }
51 4
        $this->headerRow = $headerRow;
52 4
        $this->header = $header;
53 4
    }
54
55
    /**
56
     * @inheritdoc
57
     * @throws RowInvalid
58
     */
59 3
    public function getCask(): \Generator
60
    {
61 3
        $this->file->rewind();
62 3
        if ($this->header === null && $this->headerRow) {
63
            // get header from the 1st row only if header is not explicitly provided
64 1
            $this->header = $this->file->current();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->file->current() can also be of type string. However, the property $header is declared as type array|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
65
        }
66 3
        if ($this->headerRow) {
67 3
            $this->file->next();
68
        }
69
70 3
        while ($this->file->valid()) {
71 3
            $row = $this->file->current();
72 3
            if (count($row) !== count($this->header)) {
73 1
                yield new RowInvalid(
74 1
                    sprintf(
75 1
                        'Invalid row %s for header %s. Column count mismatch.',
76 1
                        json_encode($row),
77 1
                        json_encode($this->header)
78
                    )
79
                );
80
            } else {
81 2
                yield new SimpleBag(array_combine($this->header, $row));
82
            }
83 3
            $this->file->next();
84
        }
85 3
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90 1
    public function getEstimatedSize(): int
91
    {
92
        /**
93
         * @see https://stackoverflow.com/a/43075929/927404
94
         */
95
        // attempt to reach max (will reach last line);
96 1
        $prevPos = $this->file->key();
97 1
        $this->file->seek(PHP_INT_MAX);
98 1
        $numberOfLines = $this->file->key();
99 1
        if ($this->file->valid()) {
100
            // this line is not eof
101 1
            $numberOfLines += 1;
102
        }
103 1
        if ($this->headerRow) {
104
            // subtract header row if it's present in the file
105 1
            --$numberOfLines;
106
        }
107
        // return the file to the previous line
108 1
        $this->file->seek($prevPos);
109 1
        return $numberOfLines;
110
    }
111
}
112