Completed
Push — releases/v0.2.1 ( a7ee8f...03c290 )
by Luke
03:04
created

AbstractRow::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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 CSVelte\Collection;
16
use \Iterator;
17
use \Countable;
18
use \ArrayAccess;
19
use CSVelte\Flavor;
20
21
use \OutOfBoundsException;
22
use \InvalidArgumentException;
23
use CSVelte\Exception\ImmutableException;
24
25
use function CSVelte\collect;
26
27
/**
28
 * Table row abstract base class
29
 * Represents a row of tabular data (represented by CSVelte\Table\Data objects)
30
 *
31
 * @package CSVelte
32
 * @subpackage CSVelte\Table
33
 * @since v0.1
34
 * @todo On all of the ArrayAccess methods, the docblocks say that $offset can be
35
 *     either an integer offset or a string index, but that isn't true, they must
36
 *     be an integer offset. Fix docblocks.
37
 */
38
abstract class AbstractRow implements Iterator, Countable, ArrayAccess
39
{
40
    /**
41
     * An collection of fields for this row
42
     * @var Collection
43
     */
44
    protected $fields;
45
46
    /**
47
     * Iterator position
48
     * @var int
49
     */
50
    protected $position;
51
52
    /**
53
     * Class constructor
54
     *
55
     * @param array|Iterator An array (or anything that looks like one) of data (fields)
56
     */
57 58
    public function __construct($fields)
58
    {
59 58
        $this->setFields($fields)
60 57
             ->rewind();
61 57
    }
62
63
    /**
64
     * Set the row fields.
65
     *
66
     * Using either an array or iterator, set the fields for this row.
67
     *
68
     * @param array|Iterator $fields An array or iterator with the row's fields
69
     * @return $this
70
     */
71 58
    protected function setFields($fields)
72
    {
73 58
        if (!is_array($fields)) {
74 3
            if (is_object($fields) && method_exists($fields, 'toArray')) {
75 1
                $fields = $fields->toArray();
76 3
            } elseif ($fields instanceof Iterator) {
77 1
                $fields = iterator_to_array($fields);
78 1
            } else {
79 1
                throw new InvalidArgumentException(__CLASS__ . " requires an array, got: " . gettype($fields));
80
            }
81 2
        }
82 57
        $this->fields = collect(array_values($fields));
83 57
        return $this;
84
    }
85
86
    /**
87
     * Return a string representation of this object
88
     *
89
     * @return string
90
     */
91 1
    public function __toString()
92
    {
93 1
        return $this->join();
94
    }
95
96
    /**
97
     * Join fields together using specified delimiter
98
     *
99
     * @param string The delimiter character
100
     * @return string
101
     */
102 17
    public function join($delimiter = ',')
103
    {
104 17
        return $this->fields->join($delimiter);
105
    }
106
107
    /**
108
     * Convert object to an array
109
     *
110
     * @return array representation of the object
111
     */
112 25
    public function toArray()
113
    {
114 25
        return $this->fields->toArray();
115
    }
116
117
    /** Begin SPL Countable Interface Method **/
118
119
    /**
120
     * Count fields within the row
121
     *
122
     * @return integer The amount of fields
123
     */
124 20
    public function count()
125
    {
126 20
        return count($this->fields);
127
    }
128
129
    /** Begin SPL Iterator Interface Methods **/
130
131
    /**
132
     * Get the current column's data object
133
     *
134
     * @return string
135
     */
136 57
    public function current()
137
    {
138 57
        return $this->fields->getValueAtPosition($this->position);
139
    }
140
141
    /**
142
     * Get the current key (column number or header, if available)
143
     *
144
     * @return string The "current" key
145
     * @todo Figure out if this can return a CSVelte\Table\HeaderData object so long as it
146
     *     has a __toString() method that generated the right key...
147
     */
148 1
    public function key()
149
    {
150
        return $this->position;
151 1
    }
152
153
    /**
154
     * Advance the internal pointer to the next column's data object
155
     * Also returns the next column's data object if there is one
156
     *
157
     * @return CSVelte\Table\Data The "next" column's data
158
     */
159 7
    public function next()
160
    {
161 7
        $this->position++;
162 7
        if ($this->valid()) return $this->current();
163 6
    }
164
165
    /**
166
     * Return the internal pointer to the first column and return that object
167
     *
168
     * @return null|AbstractRow
169
     */
170 57
    public function rewind()
171
    {
172 57
        $this->position = 0;
173 57
        if ($this->valid()) {
174 57
            return $this->current();
175
        }
176
    }
177
178
    /**
179
     * Is the current position within the row's data fields valid?
180
     *
181
     * @return boolean
182
     * @access public
183
     */
184 57
    public function valid()
185
    {
186 57
        return $this->fields->hasPosition($this->position);
187
    }
188
189
    /** Begin SPL ArrayAccess Methods **/
190
191
    /**
192
     * Is there an offset at specified position
193
     *
194
     * @param integer Offset
195
     * @return boolean
196
     */
197 2
    public function offsetExists($offset)
198
    {
199 2
        return $this->fields->hasPosition($offset);
200
    }
201
202
    /**
203
     * Retrieve offset at specified position or by header name
204
     *
205
     * @param integer|string Offset/index
206
     * @return CSVelte\Table\Data
207
     */
208 1
    public function offsetGet($offset)
209
    {
210 1
        return $this->fields->getValueAtPosition($offset);
211
    }
212
213
    /**
214
     * Set offset at specified position
215
     *
216
     * @param integer|string Offset/index
217
     * @param CSVelte\Table\Data
218
     * @return void
219
     * @throws CSVelte\Exception\ImmutableException
220
     */
221 2
    public function offsetSet($offset, $value)
222
    {
223
        // fields are immutable, cannot be set
224 2
        $this->raiseImmutableException();
225
    }
226
227
    /**
228
     * Unset offset at specified position/index
229
     *
230
     * @param integer|string Offset/index
231
     * @return void
232
     * @throws CSVelte\Exception\ImmutableException
233
     * @todo I'm not sure if these objects will stay immutable or not yet...
234
     */
235 1
    public function offsetUnset($offset)
236
    {
237 1
        $this->raiseImmutableException();
238
    }
239
240
    /**
241
     * Raise (throw) immutable exception
242
     *
243
     * @param string Message
244
     * @return void
245
     * @throws CSVelte\Exception\ImmutableException
246
     */
247 3
    protected function raiseImmutableException($msg = null)
248
    {
249
        // fields are immutable, cannot be set
250 3
        throw new ImmutableException($msg ?: 'Cannot change immutable column data');
251
    }
252
}
253