Passed
Pull Request — master (#6)
by
unknown
02:26
created

CSVParser::chunk()   B

Complexity

Conditions 7
Paths 47

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7.0099

Importance

Changes 0
Metric Value
cc 7
eloc 17
nc 47
nop 2
dl 0
loc 30
ccs 16
cts 17
cp 0.9412
crap 7.0099
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: sergio.rodenas
5
 * Date: 15/5/18
6
 * Time: 18:59
7
 */
8
9
namespace Rodenastyle\StreamParser\Parsers;
10
11
12
use Rodenastyle\StreamParser\Exceptions\IncompleteParseException;
13
use Rodenastyle\StreamParser\Exceptions\StopParseException;
14
use Rodenastyle\StreamParser\StreamParserInterface;
15
use Tightenco\Collect\Support\Collection;
16
17
class CSVParser implements StreamParserInterface
18
{
19
	protected $reader, $source, $headers, $currentLine;
20
21
	public static $delimiters = [",", ";"];
22
23
	public function __construct()
24
	{
25
		Collection::macro('recursive', function () {
26 5
			return $this->map(function ($value) {
0 ignored issues
show
Bug introduced by
The method map() does not exist on Rodenastyle\StreamParser\Parsers\CSVParser. ( Ignorable by Annotation )

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

26
			return $this->/** @scrutinizer ignore-call */ map(function ($value) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
27 5
				if (is_array($value) || is_object($value)) {
28 5
					return (new Collection($value))->recursive();
29
				}
30 5
				return $value;
31 5
			});
32 5
		});
33 5
	}
34
35 5
	public function from(String $source): StreamParserInterface
36
	{
37 5
		$this->source = $source;
38
39 5
		return $this;
40
	}
41
42 5
	public function each(callable $function)
43
	{
44 5
		$this->start();
45
		try {
46 5
			while($this->read()){
47 5
				if($function($this->getCurrentLineAsCollection()) === false) {
48 1
					break;
49
				}
50
			}
51 1
		} catch (StopParseException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
52 5
		} finally {
53 5
			$this->close();
54
		}
55 5
	}
56
57 5
	public function chunk($count, callable $function)
58
	{
59 5
		if($count <= 0) {
60
			return;
61
		}
62
63 5
		$this->start();
64
		try {
65 5
			$chunk = new Collection();
66
67 5
			while($this->read()){
68 5
				$chunk->push($this->getCurrentLineAsCollection());
69
70 5
				if($chunk->count() >= $count) {
71 5
					$stop = $function($chunk) === false;
72
73 5
					$chunk = new Collection();
74
75 5
					if($stop) {
76 1
						break;
77
					}
78
				}
79
			}
80
81 5
			if($chunk->count() > 0) {
82 5
				$function($chunk);
83
			}
84 1
		} catch (StopParseException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
85 5
		} finally {
86 5
			$this->close();
87
		}
88 5
	}
89
90 5
	private function start()
91
	{
92 5
		$this->reader = fopen($this->source, 'r');
93
94 5
		$this->read();
95 5
		$this->headers = new Collection($this->currentLine);
96
97 5
		return $this;
98
	}
99
100 5
	private function close(){
101 5
		if( ! fclose($this->reader)){
102
			throw new IncompleteParseException();
103
		}
104 5
	}
105
106 5
	private function read(): bool{
107 5
		$this->currentLine = (new Collection(fgetcsv($this->reader)))->filter();
108 5
		return $this->currentLine->isNotEmpty();
109
	}
110
111 5
	private function getCurrentLineAsCollection()
112
	{
113 5
		$headers = $this->headers;
114 5
		$values = $this->formatCurrentLineValues($this->currentLine);
115
116 5
		return $headers->intersectByKeys($this->currentLine)->combine($values->recursive());
117
	}
118
119 5
	private function formatCurrentLineValues(Collection $collection){
120 5
		$this->explodeCollectionValues($collection);
121 5
		return $collection;
122
	}
123
124
	private function explodeCollectionValues(Collection $collection){
125
		$collection->transform(function($value){
126 5
			(new Collection(static::$delimiters))->each(function($delimiter) use (&$value){
127 5
				if( ! is_array($value) && strpos($value, $delimiter) !== false){
128 5
					$value = explode($delimiter, $value);
129
				}
130 5
			});
131 5
			if(is_array($value)){
132 5
				return (new Collection($value))->reject(function($value){
133 5
					return empty($value);
134 5
				});
135
			} else {
136 5
				return $value;
137
			}
138 5
		});
139 5
	}
140
}
141