Completed
Branch refactor/142 (8a1d2c)
by Luke
02:46
created

AbstractRow::rewind()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * CSVelte: Slender, elegant CSV for PHP
4
 * Inspired by Python's CSV module and Frictionless Data and the W3C's CSV
5
 * standardization efforts, CSVelte was written in an effort to take all the
6
 * suck out of working with CSV.
7
 *
8
 * @version   v0.2.1
9
 * @copyright Copyright (c) 2016 Luke Visinoni <[email protected]>
10
 * @author    Luke Visinoni <[email protected]>
11
 * @license   https://github.com/deni-zen/csvelte/blob/master/LICENSE The MIT License (MIT)
12
 */
13
namespace CSVelte\Table;
14
15
use \Iterator;
16
use \Countable;
17
use \ArrayAccess;
18
use CSVelte\Flavor;
19
20
use \OutOfBoundsException;
21
use \InvalidArgumentException;
22
use CSVelte\Exception\ImmutableException;
23
24
use function CSVelte\collect;
25
26
/**
27
 * Table row abstract base class
28
 * Represents a row of tabular data (represented by CSVelte\Table\Data objects)
29
 *
30
 * @package CSVelte
31
 * @subpackage CSVelte\Table
32
 * @since v0.1
33
 * @todo On all of the ArrayAccess methods, the docblocks say that $offset can be
34
 *     either an integer offset or a string index, but that isn't true, they must
35
 *     be an integer offset. Fix docblocks.
36
 */
37
abstract class AbstractRow implements Iterator, Countable, ArrayAccess
38
{
39
    /**
40
     * An array of fields for this row
41
     * @var array
42
     */
43
    protected $fields;
44
45
    /**
46
     * Iterator position
47
     * @var int
48
     */
49
    protected $position;
50
51
    /**
52
     * Class constructor
53
     *
54
     * @param array|Iterator An array (or anything that looks like one) of data (fields)
55
     * @access public
56
     */
57 63
    public function __construct($fields)
58
    {
59 63
        $this->setFields($fields)
60 62
             ->rewind();
61 62
    }
62
63 63
    protected function setFields($fields)
64
    {
65 63
        if (!is_array($fields)) {
66 3
            if (is_object($fields) && method_exists($fields, 'toArray')) {
67 1
                $fields = $fields->toArray();
68 3
            } elseif ($fields instanceof Iterator) {
69 1
                $fields = iterator_to_array($fields);
70 1
            } else {
71 1
                throw new InvalidArgumentException(__CLASS__ . " requires an array, got: " . gettype($fields));
72
            }
73 2
        }
74 62
        $this->fields = collect(array_values($fields));
0 ignored issues
show
Documentation Bug introduced by
It seems like \CSVelte\collect(array_values($fields)) of type object<CSVelte\Collection> is incompatible with the declared type array of property $fields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
75 62
        return $this;
76
    }
77
78 1
    public function __toString()
79
    {
80 1
        return $this->join();
81
    }
82
83
    /**
84
     * Join fields together using specified delimiter
85
     *
86
     * @param char The delimiter character
87
     * @return string
88
     * @access public
89
     */
90 17
    public function join($delimiter = ',')
91
    {
92 17
        return $this->fields->join($delimiter);
0 ignored issues
show
Bug introduced by
The method join cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
93
    }
94
95
    /**
96
     * Convert object to an array
97
     *
98
     * @return array representation of the object
99
     * @access public
100
     */
101 28
    public function toArray()
102
    {
103 28
        return $this->fields->toArray();
0 ignored issues
show
Bug introduced by
The method toArray cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
104
    }
105
106
    /** Begin SPL Countable Interface Method **/
107
108
    /**
109
     * Count fields within the row
110
     *
111
     * @return integer The amount of fields
112
     * @access public
113
     */
114 23
    public function count()
115
    {
116 23
        return count($this->fields);
117
    }
118
119
    /** Begin SPL Iterator Interface Methods **/
120
121
    /**
122
     * Get the current column's data object
123
     *
124
     * @return string
125
     * @access public
126
     */
127 61
    public function current()
128
    {
129 61
        return $this->fields->getValueAtPosition($this->position);
0 ignored issues
show
Bug introduced by
The method getValueAtPosition cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
130
    }
131
132
    /**
133
     * Get the current key (column number or header, if available)
134
     *
135
     * @return string The "current" key
136
     * @access public
137
     * @todo Figure out if this can return a CSVelte\Table\HeaderData object so long as it
138
     *     has a __toString() method that generated the right key...
139
     */
140
    public function key()
141
    {
142
        return $this->position;
143
    }
144
145
    /**
146
     * Advance the internal pointer to the next column's data object
147
     * Also returns the next column's data object if there is one
148
     *
149
     * @return CSVelte\Table\Data The "next" column's data
150
     * @access public
151
     */
152 9
    public function next()
153
    {
154 9
        $this->position++;
155 9
        if ($this->valid()) return $this->current();
156 6
    }
157
158
    /**
159
     * Return the internal pointer to the first column and return that object
160
     *
161
     * @return void
162
     * @access public
163
     */
164 62
    public function rewind()
165
    {
166 62
        $this->position = 0;
167 62
        if ($this->valid()) return $this->current();
168 1
    }
169
170
    /**
171
     * Is the current position within the row's data fields valid?
172
     *
173
     * @return boolean
174
     * @access public
175
     */
176 62
    public function valid()
177
    {
178 62
        return $this->fields->hasPosition($this->position);
0 ignored issues
show
Bug introduced by
The method hasPosition cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
179
    }
180
181
    /** Begin SPL ArrayAccess Methods **/
182
183
    /**
184
     * Is there an offset at specified position
185
     *
186
     * @param integer Offset
187
     * @return boolean
188
     * @access public
189
     */
190 2
    public function offsetExists($offset)
191
    {
192 2
        return $this->fields->hasPosition($offset);
0 ignored issues
show
Bug introduced by
The method hasPosition cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
193
    }
194
195
    /**
196
     * Retrieve offset at specified position or by header name
197
     *
198
     * @param integer|string Offset/index
199
     * @return CSVelte\Table\Data
200
     * @access public
201
     */
202 1
    public function offsetGet($offset)
203
    {
204 1
        return $this->fields->getValueAtPosition($offset);
0 ignored issues
show
Bug introduced by
The method getValueAtPosition cannot be called on $this->fields (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
205
    }
206
207
    /**
208
     * Set offset at specified position
209
     *
210
     * @param integer|string Offset/index
211
     * @param CSVelte\Table\Data
212
     * @return void
213
     * @access public
214
     * @throws CSVelte\Exception\ImmutableException
215
     */
216 3
    public function offsetSet($offset, $value)
217
    {
218
        // fields are immutable, cannot be set
219 3
        $this->raiseImmutableException();
220
    }
221
222
    /**
223
     * Unset offset at specified position/index
224
     *
225
     * @param integer|string Offset/index
226
     * @return void
227
     * @access public
228
     * @throws CSVelte\Exception\ImmutableException
229
     * @todo I'm not sure if these objects will stay immutable or not yet...
230
     */
231 2
    public function offsetUnset($offset)
232
    {
233 2
        $this->raiseImmutableException();
234
    }
235
236
    /**
237
     * Raise (throw) immutable exception
238
     *
239
     * @param string Message
240
     * @return void
241
     * @access protected
242
     * @throws CSVelte\Exception\ImmutableException
243
     */
244 4
    protected function raiseImmutableException($msg = null)
245
    {
246
        // fields are immutable, cannot be set
247 4
        throw new ImmutableException($msg ?: 'Cannot change immutable column data');
248
    }
249
}
250