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 v0.2.1 |
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; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Library Functions |
18
|
|
|
* |
19
|
|
|
* @package CSVelte |
20
|
|
|
* @subpackage functions |
21
|
|
|
* @since v0.2.1 |
22
|
|
|
*/ |
23
|
|
|
|
24
|
|
|
use \Iterator; |
25
|
|
|
use CSVelte\IO\Stream; |
26
|
|
|
use CSVelte\IO\Resource; |
27
|
|
|
use CSVelte\IO\IteratorStream; |
28
|
|
|
use CSVelte\Contract\Streamable; |
29
|
|
|
|
30
|
|
|
use \InvalidArgumentException; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Stream - streams various types of values and objects. |
34
|
|
|
* |
35
|
|
|
* You can pass a string, or an iterator, or an object with a __toString() |
36
|
|
|
* method to this function and it will find the best possible way to stream the |
37
|
|
|
* data from that object. |
38
|
|
|
* |
39
|
|
|
* @param mixed $obj The item you want to stream |
40
|
|
|
* @return Streamable |
41
|
|
|
* @throws InvalidArgumentException |
42
|
|
|
* @since v0.2.1 |
43
|
|
|
*/ |
44
|
|
|
function streamize($obj = '') |
45
|
|
|
{ |
46
|
27 |
|
if ($obj instanceof Streamable) { |
47
|
1 |
|
return $obj; |
48
|
|
|
} |
49
|
|
|
|
50
|
27 |
|
if ($obj instanceof Resource) { |
51
|
1 |
|
return $obj(); |
52
|
|
|
} |
53
|
|
|
|
54
|
26 |
|
if (is_resource($obj) && get_resource_type($obj) == 'stream') { |
55
|
1 |
|
return new Stream(new Resource($obj)); |
56
|
|
|
} |
57
|
|
|
|
58
|
25 |
|
if ($obj instanceof Iterator) { |
59
|
4 |
|
return new IteratorStream($obj); |
60
|
|
|
} |
61
|
|
|
|
62
|
21 |
|
if (is_object($obj) && method_exists($obj, '__toString')) { |
63
|
2 |
|
$obj = (string) $obj; |
64
|
2 |
|
} |
65
|
21 |
|
if (is_string($obj)) { |
66
|
19 |
|
$stream = Stream::open('php://temp', 'r+'); |
67
|
19 |
|
if ($obj !== '') { |
68
|
16 |
|
$res = $stream->getResource(); |
69
|
16 |
|
fwrite($res->getHandle(), $obj); |
70
|
16 |
|
fseek($res->getHandle(), 0); |
71
|
16 |
|
} |
72
|
19 |
|
return $stream; |
73
|
|
|
} |
74
|
|
|
|
75
|
2 |
|
throw new InvalidArgumentException(sprintf( |
76
|
2 |
|
"Invalid argument type for %s: %s", |
77
|
2 |
|
__FUNCTION__, |
78
|
2 |
|
gettype($obj) |
79
|
2 |
|
)); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Stream resource factory. |
84
|
|
|
* |
85
|
|
|
* This method is just a shortcut to create a stream resource object using |
86
|
|
|
* a stream URI string. |
87
|
|
|
* |
88
|
|
|
* @param string $uri A stream URI |
89
|
|
|
* @param string $mode The access mode string |
90
|
|
|
* @param array|resource $context An array or resource with stream context options |
91
|
|
|
* @param bool $lazy Whether to lazy-open |
92
|
|
|
* @return $this |
93
|
|
|
* @since v0.2.1 |
94
|
|
|
*/ |
95
|
|
|
function stream_resource( |
96
|
|
|
$uri, |
97
|
|
|
$mode = null, |
98
|
|
|
$context = null, |
99
|
|
|
$lazy = true |
100
|
|
|
) { |
101
|
5 |
|
$res = (new Resource($uri, $mode, null, true)) |
102
|
5 |
|
->setContextResource($context); |
|
|
|
|
103
|
5 |
|
if (!$lazy) { |
104
|
1 |
|
$res->connect(); |
105
|
1 |
|
} |
106
|
5 |
|
return $res; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Stream factory. |
111
|
|
|
* |
112
|
|
|
* This method is just a shortcut to create a stream object using a URI. |
113
|
|
|
* |
114
|
|
|
* @param string $uri A stream URI to open |
115
|
|
|
* @param string $mode The access mode string |
116
|
|
|
* @param array|resource $context An array or stream context resource of options |
117
|
|
|
* @param bool $lazy Whether to lazy-open |
118
|
|
|
* @return Stream |
119
|
|
|
* @since v0.2.1 |
120
|
|
|
*/ |
121
|
|
|
function stream( |
122
|
|
|
$uri, |
123
|
|
|
$mode = null, |
124
|
|
|
$context = null, |
125
|
|
|
$lazy = true |
126
|
|
|
) { |
127
|
3 |
|
$res = stream_resource($uri, $mode, $context, $lazy); |
128
|
3 |
|
return $res(); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* "Taste" a stream object. |
133
|
|
|
* |
134
|
|
|
* Pass any class that implements the "Streamable" interface to this function |
135
|
|
|
* to auto-detect "flavor" (formatting attributes). |
136
|
|
|
* |
137
|
|
|
* @param Contract\Streamable Any streamable class to analyze |
138
|
|
|
* @return Flavor A flavor representing stream's formatting attributes |
139
|
|
|
* @since v0.2.1 |
140
|
|
|
*/ |
141
|
|
|
function taste(Streamable $str) |
142
|
|
|
{ |
143
|
13 |
|
$taster = new Taster($str); |
144
|
13 |
|
return $taster(); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Does dataset being streamed by $str have a header row? |
149
|
|
|
* |
150
|
|
|
* @param Contract\Streamable $str Stream object |
151
|
|
|
* @return boolean Whether stream dataset has header |
152
|
|
|
* @since v0.2.1 |
153
|
|
|
*/ |
154
|
|
|
function taste_has_header(Streamable $str) |
155
|
|
|
{ |
156
|
5 |
|
$taster = new Taster($str); |
157
|
5 |
|
$flv = $taster(); |
158
|
5 |
|
return $taster->lickHeader( |
159
|
5 |
|
$flv->delimiter, |
160
|
5 |
|
$flv->lineTerminator |
161
|
5 |
|
); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Collection factory. |
166
|
|
|
* |
167
|
|
|
* Simply an alias to (new Collection($in)). Allows for a little more concise and |
168
|
|
|
* simpler instantiation of a collection. Also I plan to eventually support |
169
|
|
|
* additional input types that will make this function more flexible and forgiving |
170
|
|
|
* than simply instantiating a Collection object, but for now the two are identical. |
171
|
|
|
* |
172
|
|
|
* @param array|Iterator $in Either an array or an iterator of data |
173
|
|
|
* @return Collection A collection object containing data from $in |
174
|
|
|
* @since v0.2.1 |
175
|
|
|
* @see Collection::__construct() (alias) |
176
|
|
|
*/ |
177
|
|
|
function collect($in = null) |
178
|
|
|
{ |
179
|
65 |
|
return new Collection($in); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Invoke a callable and return result. |
184
|
|
|
* |
185
|
|
|
* Pass in a callable followed by whatever arguments you want passed to |
186
|
|
|
* it and this function will invoke it with your arguments and return |
187
|
|
|
* the result. |
188
|
|
|
* |
189
|
|
|
* @param callable $callback The callback function to invoke |
190
|
|
|
* @param array ...$args The args to pass to your callable |
191
|
|
|
* @return mixed The result of your invoked callable |
192
|
|
|
* @since v0.2.1 |
193
|
|
|
*/ |
194
|
|
|
function invoke(Callable $callback, ...$args) |
195
|
|
|
{ |
196
|
|
|
return $callback(...$args); |
197
|
|
|
} |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.