Skip to content

Commit cc9db91

Browse files
committed
fetchAssoc internal code improved
1 parent a20b9eb commit cc9db91

File tree

2 files changed

+81
-60
lines changed

2 files changed

+81
-60
lines changed

Diff for: src/Reader.php

+78-57
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function query(callable $callable = null)
7373
*/
7474
public function each(callable $callable)
7575
{
76-
$index = 0;
76+
$index = 0;
7777
$iterator = $this->query();
7878
$iterator->rewind();
7979
while ($iterator->valid() && true === $callable($iterator->current(), $iterator->key(), $iterator)) {
@@ -84,6 +84,38 @@ public function each(callable $callable)
8484
return $index;
8585
}
8686

87+
/**
88+
* Return a single column from the CSV data
89+
*
90+
* The callable function will be applied to each value to be return
91+
*
92+
* @param int $column_index field Index
93+
* @param callable $callable a callable function
94+
*
95+
* @throws \InvalidArgumentException If the column index is not a positive integer or 0
96+
*
97+
* @return array
98+
*/
99+
public function fetchColumn($column_index = 0, callable $callable = null)
100+
{
101+
if (false === filter_var($column_index, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
102+
throw new InvalidArgumentException(
103+
'the column index must be a positive integer or 0'
104+
);
105+
}
106+
107+
$iterator = $this->query($callable);
108+
$iterator = new MapIterator($iterator, function ($row) use ($column_index) {
109+
if (! array_key_exists($column_index, $row)) {
110+
return null;
111+
}
112+
113+
return $row[$column_index];
114+
});
115+
116+
return iterator_to_array($iterator, false);
117+
}
118+
87119
/**
88120
* Return a single row from the CSV
89121
*
@@ -123,22 +155,18 @@ public function fetchAll(callable $callable = null)
123155
* The rows are presented as associated arrays
124156
* The callable function will be applied to each Iterator item
125157
*
126-
* @param array|int $keys the name for each key member OR the row Index to be
127-
* used as the associated named keys
128-
* @param callable $callable a callable function
158+
* @param array|int $offset_or_keys the name for each key member OR the row Index to be
159+
* used as the associated named keys
160+
* @param callable $callable a callable function
129161
*
130-
* @throws \InvalidArgumentException If the submitted keys are not integer or string
162+
* @throws \InvalidArgumentException If the submitted keys are invalid
131163
*
132164
* @return array
133165
*/
134-
public function fetchAssoc($keys = 0, callable $callable = null)
166+
public function fetchAssoc($offset_or_keys = 0, callable $callable = null)
135167
{
136-
$keys = $this->formatAssocKeys($keys);
137-
if (! $this->isValidAssocKeys($keys)) {
138-
throw new InvalidArgumentException(
139-
'Use a flat non empty array with unique string values'
140-
);
141-
}
168+
$keys = $this->getAssocKeys($offset_or_keys);
169+
142170
$iterator = $this->query($callable);
143171
$iterator = new MapIterator($iterator, function ($row) use ($keys) {
144172
return static::combineArray($keys, $row);
@@ -149,29 +177,54 @@ public function fetchAssoc($keys = 0, callable $callable = null)
149177

150178
/**
151179
* Select the array to be used as key for the fetchAssoc method
152-
* @param array|int $keys the assoc key OR the row Index to be used
153-
* as the key index
180+
* @param array|int $offset_or_keys the assoc key OR the row Index to be used
181+
* as the key index
154182
*
155-
* @throws \InvalidArgumentException If the row index is invalid
183+
* @throws \InvalidArgumentException If the row index and/or the resulting array is invalid
156184
*
157185
* @return array
158186
*/
159-
protected function formatAssocKeys($keys)
187+
protected function getAssocKeys($offset_or_keys)
160188
{
161-
if (is_array($keys)) {
162-
return $keys;
163-
} elseif (false === filter_var($keys, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
164-
throw new InvalidArgumentException('the column index must be a positive integer or 0');
189+
$res = $offset_or_keys;
190+
if (! is_array($res)) {
191+
$res = $this->getRow($offset_or_keys);
192+
$this->addFilter(function ($row, $rowIndex) use ($offset_or_keys) {
193+
return is_array($row) && $rowIndex != $offset_or_keys;
194+
});
195+
}
196+
if (! $this->isValidAssocKeys($res)) {
197+
throw new InvalidArgumentException(
198+
'Use a flat non empty array with unique string values'
199+
);
165200
}
166201

167-
$this->addFilter(function ($row, $rowIndex) use ($keys) {
168-
return is_array($row) && $rowIndex != $keys;
169-
});
202+
return $res;
203+
}
170204

171-
$iterator = new LimitIterator($this->getIterator(), $keys, 1);
205+
/**
206+
* Return a single row from the CSV without filtering
207+
*
208+
* @param int $offset
209+
*
210+
* @throws \InvalidArgumentException If the $offset is not valid or the row does not exist
211+
*
212+
* @return array
213+
*/
214+
protected function getRow($offset)
215+
{
216+
if (false === filter_var($offset, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
217+
throw new InvalidArgumentException('the row index must be a positive integer or 0');
218+
}
219+
220+
$iterator = new LimitIterator($this->getIterator(), $offset, 1);
172221
$iterator->rewind();
222+
$res = $iterator->current();
223+
if (is_null($res)) {
224+
throw new InvalidArgumentException('the specified row does not exist');
225+
}
173226

174-
return (array) $iterator->current();
227+
return $res;
175228
}
176229

177230
/**
@@ -213,36 +266,4 @@ protected static function combineArray(array $keys, array $value)
213266

214267
return array_combine($keys, $value);
215268
}
216-
217-
/**
218-
* Return a single column from the CSV data
219-
*
220-
* The callable function will be applied to each value to be return
221-
*
222-
* @param int $column_index field Index
223-
* @param callable $callable a callable function
224-
*
225-
* @throws \InvalidArgumentException If the column index is not a positive integer or 0
226-
*
227-
* @return array
228-
*/
229-
public function fetchColumn($column_index = 0, callable $callable = null)
230-
{
231-
if (false === filter_var($column_index, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
232-
throw new InvalidArgumentException(
233-
'the column index must be a positive integer or 0'
234-
);
235-
}
236-
237-
$iterator = $this->query($callable);
238-
$iterator = new MapIterator($iterator, function ($row) use ($column_index) {
239-
if (! array_key_exists($column_index, $row)) {
240-
return null;
241-
}
242-
243-
return $row[$column_index];
244-
});
245-
246-
return iterator_to_array($iterator, false);
247-
}
248269
}

Diff for: test/ReaderTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public function testFetchAssocKeyFailure()
200200

201201
/**
202202
* @expectedException \InvalidArgumentException
203-
* @expectedExceptionMessage the column index must be a positive integer or 0
203+
* @expectedExceptionMessage the row index must be a positive integer or 0
204204
*/
205205
public function testFetchAssocWithInvalidKey()
206206
{
@@ -222,9 +222,9 @@ public function testFetchAssocWithInvalidKey()
222222

223223
/**
224224
* @expectedException \InvalidArgumentException
225-
* @expectedExceptionMessage Use a flat non empty array with unique string values
225+
* @expectedExceptionMessage the specified row does not exist
226226
*/
227-
public function testFetchAssocWithEmptyArr()
227+
public function testFetchAssocWithInvalidOffset()
228228
{
229229
$arr = [
230230
['A', 'B', 'C'],

0 commit comments

Comments
 (0)