1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* CSVelte: Slender, elegant CSV for PHP |
4
|
|
|
* |
5
|
|
|
* Inspired by Python's CSV module and Frictionless Data and the W3C's CSV |
6
|
|
|
* standardization efforts, CSVelte was written in an effort to take all the |
7
|
|
|
* suck out of working with CSV. |
8
|
|
|
* |
9
|
|
|
* @version v${CSVELTE_DEV_VERSION} |
10
|
|
|
* @copyright Copyright (c) 2016 Luke Visinoni <[email protected]> |
11
|
|
|
* @author Luke Visinoni <[email protected]> |
12
|
|
|
* @license https://github.com/deni-zen/csvelte/blob/master/LICENSE The MIT License (MIT) |
13
|
|
|
*/ |
14
|
|
|
namespace CSVelte\Collection; |
15
|
|
|
|
16
|
|
|
use BadMethodCallException; |
17
|
|
|
use OutOfBoundsException; |
18
|
|
|
use function CSVelte\is_traversable; |
19
|
|
|
use function CSVelte\collect; |
20
|
|
|
|
21
|
|
|
class TabularCollection extends MultiCollection |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* Is input data structure valid? |
25
|
|
|
* |
26
|
|
|
* In order to determine whether a given data structure is valid for a |
27
|
|
|
* particular collection type (tabular, numeric, etc.), we have this method. |
28
|
|
|
* |
29
|
|
|
* @param mixed $data The data structure to check |
30
|
|
|
* @return boolean True if data structure is tabular |
31
|
|
|
*/ |
32
|
40 |
|
protected function isConsistentDataStructure($data) |
33
|
|
|
{ |
34
|
40 |
|
return static::isTabular($data); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Does this collection have specified column? |
39
|
|
|
* |
40
|
|
|
* @param mixed $column The column index |
41
|
|
|
* @return bool |
42
|
|
|
*/ |
43
|
8 |
|
public function hasColumn($column) |
44
|
|
|
{ |
45
|
|
|
try { |
46
|
8 |
|
$this->getColumn($column); |
47
|
8 |
|
return true; |
48
|
1 |
|
} catch (OutOfBoundsException $e) { |
49
|
1 |
|
return false; |
50
|
|
|
} |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Get column as collection |
55
|
|
|
* |
56
|
|
|
* @param mixed $column The column index |
57
|
|
|
* @param bool $throw Throw an exception on failure |
58
|
|
|
* @return AbstractCollection|false |
59
|
|
|
*/ |
60
|
9 |
|
public function getColumn($column, $throw = true) |
61
|
|
|
{ |
62
|
9 |
|
$values = array_column($this->data, $column); |
63
|
9 |
|
if (count($values)) { |
64
|
9 |
|
return static::factory($values); |
65
|
|
|
} |
66
|
1 |
|
if ($throw) { |
67
|
1 |
|
throw new OutOfBoundsException(__CLASS__ . " could not find column: " . $column); |
68
|
|
|
} |
69
|
|
|
return false; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Does this collection have a row at specified index? |
74
|
|
|
* |
75
|
|
|
* @param int $offset The column index |
76
|
|
|
* @return bool |
77
|
|
|
*/ |
78
|
|
|
public function hasRow($offset) |
79
|
|
|
{ |
80
|
|
|
try { |
81
|
|
|
$this->getRow($offset); |
82
|
|
|
return true; |
83
|
|
|
} catch (OutOfBoundsException $e) { |
84
|
|
|
return false; |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Get row at specified index. |
90
|
|
|
* |
91
|
|
|
* @param int $offset The row offset (starts from 0) |
92
|
|
|
* |
93
|
|
|
* @return AbstractCollection|false |
94
|
|
|
*/ |
95
|
|
|
public function getRow($offset) |
96
|
|
|
{ |
97
|
|
|
return $this->getValueAtPosition($offset); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @inheritdoc |
102
|
|
|
*/ |
103
|
1 |
|
public function map(callable $callback) |
104
|
|
|
{ |
105
|
1 |
|
$ret = []; |
106
|
1 |
|
foreach ($this->data as $key => $row) { |
107
|
1 |
|
$ret[$key] = $callback(static::factory($row)); |
108
|
1 |
|
} |
109
|
1 |
|
return static::factory($ret); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @inheritdoc |
114
|
|
|
*/ |
115
|
21 |
|
public function walk(callable $callback, $extraContext = null) |
116
|
|
|
{ |
117
|
21 |
|
foreach ($this as $offset => $row) { |
118
|
21 |
|
$callback(static::factory($row), $offset, $extraContext); |
119
|
21 |
|
} |
120
|
21 |
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
// public function average($column) |
|
|
|
|
124
|
|
|
// { |
125
|
|
|
// $coll = $this->getColumnAsCollection($column); |
126
|
|
|
// return $coll->sum() / $coll->count(); |
127
|
|
|
// } |
128
|
|
|
// |
129
|
|
|
// public function mode($column) |
130
|
|
|
// { |
131
|
|
|
// return $this->getColumnAsCollection($column)->mode(); |
132
|
|
|
// } |
133
|
|
|
// |
134
|
|
|
// public function sum($column) |
135
|
|
|
// { |
136
|
|
|
// return $this->getColumnAsCollection($column)->sum(); |
137
|
|
|
// } |
138
|
|
|
// |
139
|
|
|
// public function median($column) |
140
|
|
|
// { |
141
|
|
|
// return $this->getColumnAsCollection($column)->median(); |
142
|
|
|
// } |
143
|
|
|
// |
144
|
|
|
// protected function getColumnAsCollection($column) |
145
|
|
|
// { |
146
|
|
|
// return static::factory(array_column($this->data, $column)); |
147
|
|
|
// } |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Magic method call |
151
|
|
|
* |
152
|
|
|
* @param string $method The name of the method |
153
|
|
|
* @param array $args The argument list |
154
|
|
|
* |
155
|
|
|
* @throws BadMethodCallException If no method exists |
156
|
|
|
* |
157
|
|
|
* @return mixed |
158
|
|
|
* |
159
|
|
|
* @todo Add phpdoc comments for dynamic methods |
160
|
|
|
* @todo throw BadMethodCallException |
161
|
|
|
*/ |
162
|
8 |
|
public function __call($method, $args) |
163
|
|
|
{ |
164
|
8 |
|
$argc = count($args); |
165
|
8 |
|
if ($argc == 1 && $this->hasColumn($index = array_pop($args))) { |
166
|
7 |
|
$column = $this->getColumn($index); |
167
|
7 |
|
if (method_exists($column, $method)) { |
168
|
7 |
|
return call_user_func_array([$column, $method], $args); |
169
|
|
|
} |
170
|
|
|
} |
171
|
1 |
|
throw new BadMethodCallException("Method does not exist: " . __CLASS__ . "::{$method}()"); |
172
|
|
|
} |
173
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.