Completed
Push — releases/v0.2.2 ( aa5f3f...012d2a )
by Luke
06:02
created

TabularCollection::getColumn()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.0261

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
ccs 6
cts 7
cp 0.8571
crap 3.0261
1
<?php
2
3
/*
4
 * CSVelte: Slender, elegant CSV for PHP
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   {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
19
class TabularCollection extends MultiCollection
20
{
21
    /**
22
     * Tabular Where Search.
23
     *
24
     * Search for values of a certain key that meet a particular search criteria
25
     * using either one of the "Collection\Criteria::" class constants, or its string
26
     * counterpart.
27
     *
28
     * Warning: Only works for tabular collections (2-dimensional data array)
29
     *
30
     * @param string $key The key to compare to $val
31
     * @param mixed|Callable $val Either a value to test against or a callable to
32
     *     run your own custom "where comparison logic"
33
     * @param string $comp The type of comparison operation ot use (such as "=="
34
     *     or "instanceof"). Must be one of the self::* constants' values
35
     *     listed at the top of this class.
36
     * @return TabularCollection A collection of rows that meet the criteria
37
     *     specified by $key, $val, and $comp
38
     */
39 1
    public function where($key, $val, $comp = null)
40
    {
41 1
        $data = [];
42 1
        if ($this->hasColumn($key)) {
43 1
            if (is_callable($val)) {
44
                foreach ($this->data as $ln => $row) {
45
                    if ($val($row[$key], $key)) {
46
                        $data[$ln] = $row;
47
                    }
48
                }
49
            } else {
50 1
                foreach ($this->data as $ln => $row) {
51 1
                    $fieldval = $row[$key];
52 1
                    switch (strtolower($comp)) {
53 1
                        case Criteria::ID:
54
                            $comparison = $fieldval === $val;
55
                            break;
56 1
                        case Criteria::NID:
57
                            $comparison = $fieldval !== $val;
58
                            break;
59 1
                        case Criteria::LT:
60
                            $comparison = $fieldval < $val;
61
                            break;
62 1
                        case Criteria::LTE:
63
                            $comparison = $fieldval <= $val;
64
                            break;
65 1
                        case Criteria::GT:
66
                            $comparison = $fieldval > $val;
67
                            break;
68 1
                        case Criteria::GTE:
69
                            $comparison = $fieldval >= $val;
70
                            break;
71 1
                        case Criteria::LIKE:
72
                            $comparison = strtolower($fieldval) == strtolower($val);
73
                            break;
74 1
                        case Criteria::NLIKE:
75
                            $comparison = strtolower($fieldval) != strtolower($val);
76
                            break;
77 1
                        case Criteria::TOF:
78
                            $comparison = (strtolower(gettype($fieldval)) == strtolower($val));
79
                            break;
80 1
                        case Criteria::NTOF:
81
                            $comparison = (strtolower(gettype($fieldval)) != strtolower($val));
82
                            break;
83 1
                        case Criteria::NEQ:
84
                            $comparison = $fieldval != $val;
85
                            break;
86 1
                        case Criteria::MATCH:
87
                            $match = preg_match($val, $fieldval);
88
                            $comparison = $match === 1;
89
                            break;
90 1
                        case Criteria::NMATCH:
91
                            $match = preg_match($val, $fieldval);
92
                            $comparison = $match === 0;
93
                            break;
94 1
                        case Criteria::EQ:
95 1
                        default:
96 1
                            $comparison = $fieldval == $val;
97 1
                            break;
98 1
                    }
99 1
                    if ($comparison) {
100 1
                        $data[$ln] = $row;
101 1
                    }
102 1
                }
103
            }
104 1
        }
105 1
        return new TabularCollection($data);
106
    }
107
108
    /**
109
     * Magic method call.
110
     *
111
     * @param string $method The name of the method
112
     * @param array  $args   The argument list
113
     *
114
     * @throws BadMethodCallException If no method exists
115
     *
116
     * @return mixed
117
     *
118
     * @todo Add phpdoc comments for dynamic methods
119
     * @todo throw BadMethodCallException
120
     */
121 8
    public function __call($method, $args)
122
    {
123 8
        $argc = count($args);
124 8
        if ($argc == 1 && $this->hasColumn($index = array_pop($args))) {
125 7
            $column = $this->getColumn($index);
126 7
            if (method_exists($column, $method)) {
127 7
                return call_user_func_array([$column, $method], $args);
128
            }
129
        }
130 1
        throw new BadMethodCallException('Method does not exist: ' . __CLASS__ . "::{$method}()");
131
    }
132
133
    /**
134
     * Does this collection have specified column?
135
     *
136
     * @param mixed $column The column index
137
     *
138
     * @return bool
139
     */
140 9
    public function hasColumn($column)
141
    {
142
        try {
143 9
            $this->getColumn($column);
144
145 9
            return true;
146 1
        } catch (OutOfBoundsException $e) {
147 1
            return false;
148
        }
149
    }
150
151
    /**
152
     * Get column as collection.
153
     *
154
     * @param mixed $column The column index
155
     * @param bool  $throw  Throw an exception on failure
156
     *
157
     * @return AbstractCollection|false
158
     */
159 10
    public function getColumn($column, $throw = true)
160
    {
161 10
        $values = array_column($this->data, $column);
162 10
        if (count($values)) {
163 10
            return static::factory($values);
164
        }
165 1
        if ($throw) {
166 1
            throw new OutOfBoundsException(__CLASS__ . ' could not find column: ' . $column);
167
        }
168
169
        return false;
170
    }
171
172
    /**
173
     * Does this collection have a row at specified index?
174
     *
175
     * @param int $offset The column index
176
     *
177
     * @return bool
178
     */
179 1
    public function hasRow($offset)
180
    {
181
        try {
182 1
            $this->getRow($offset);
183
184 1
            return true;
185 1
        } catch (OutOfBoundsException $e) {
186 1
            return false;
187
        }
188
    }
189
190
    /**
191
     * Get row at specified index.
192
     *
193
     * @param int $offset The row offset (starts from 0)
194
     *
195
     * @return AbstractCollection|false
196
     */
197 3
    public function getRow($offset)
198
    {
199 3
        return $this->getValueAtPosition($offset);
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205 1
    public function map(callable $callback)
206
    {
207 1
        $ret = [];
208 1
        foreach ($this->data as $key => $row) {
209 1
            $ret[$key] = $callback(static::factory($row));
210 1
        }
211
212 1
        return static::factory($ret);
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218 21
    public function walk(callable $callback, $extraContext = null)
219
    {
220 21
        foreach ($this as $offset => $row) {
221 21
            $callback(static::factory($row), $offset, $extraContext);
222 21
        }
223
224 21
        return $this;
225
    }
226
227
    /**
228
     * Is input data structure valid?
229
     *
230
     * In order to determine whether a given data structure is valid for a
231
     * particular collection type (tabular, numeric, etc.), we have this method.
232
     *
233
     * @param mixed $data The data structure to check
234
     *
235
     * @return bool True if data structure is tabular
236
     */
237 44
    protected function isConsistentDataStructure($data)
238
    {
239 44
        return static::isTabular($data);
240
    }
241
}
242