functions.php ➔ stream_resource()   A
last analyzed

Complexity

Conditions 5
Paths 10

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
nc 10
nop 4
dl 0
loc 23
ccs 15
cts 15
cp 1
crap 5
rs 9.2408
c 0
b 0
f 0
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;
15
16
/*
17
 * Library Functions
18
 *
19
 * @package CSVelte
20
 * @subpackage functions
21
 * @since v0.2.1
22
 */
23
24
use CSVelte\Collection\AbstractCollection;
25
use CSVelte\Collection\Collection;
26
use CSVelte\Contract\Streamable;
27
use CSVelte\IO\IteratorStream;
28
use CSVelte\IO\Stream;
29
use CSVelte\IO\StreamResource;
30
use InvalidArgumentException;
31
32
use Iterator;
33
34
/**
35
 * Stream - streams various types of values and objects.
36
 *
37
 * You can pass a string, or an iterator, or an object with a __toString()
38
 * method to this function and it will find the best possible way to stream the
39
 * data from that object.
40
 *
41
 * @param mixed $obj The item you want to stream
42
 *
43
 * @throws InvalidArgumentException
44
 *
45
 * @return Streamable
46
 *
47
 * @since v0.2.1
48
 */
49
function streamize($obj = '')
50
{
51 27
    if ($obj instanceof Streamable) {
52 1
        return $obj;
53
    }
54
55 27
    if ($obj instanceof StreamResource) {
56 1
        return $obj();
57
    }
58
59 26
    if (is_resource($obj) && get_resource_type($obj) == 'stream') {
60 1
        return new Stream(new StreamResource($obj));
61
    }
62
63 25
    if ($obj instanceof Iterator) {
64 4
        return new IteratorStream($obj);
65
    }
66
67 21
    if (is_object($obj) && method_exists($obj, '__toString')) {
68 2
        $obj = (string) $obj;
69 2
    }
70 21
    if (is_string($obj)) {
71 19
        $stream = Stream::open('php://temp', 'r+');
72 19
        if ($obj !== '') {
73 16
            $res = $stream->getResource();
74 16
            fwrite($res->getHandle(), $obj);
75 16
            fseek($res->getHandle(), 0);
76 16
        }
77
78 19
        return $stream;
79
    }
80
81 2
    throw new InvalidArgumentException(sprintf(
82 2
        'Invalid argument type for %s: %s',
83 2
        __FUNCTION__,
84 2
        gettype($obj)
85 2
    ));
86
}
87
88
/**
89
 * StreamResource factory.
90
 *
91
 * This method is just a shortcut to create a stream resource object using
92
 * a stream URI string.
93
 *
94
 * @param string         $uri     A stream URI
95
 * @param string         $mode    The access mode string
96
 * @param array|resource $context An array or resource with stream context options
97
 * @param bool           $lazy    Whether to lazy-open
98
 *
99
 * @return StreamResource
100
 *
101
 * @since v0.2.1
102
 */
103
function stream_resource(
104
    $uri,
105
    $mode = null,
106
    $context = null,
107
    $lazy = true
108
) {
109 7
    if (is_array($context)) {
110 2
        if (!isset($context['options'])) {
111 1
            $context['options'] = [];
112 1
        }
113 2
        if (!isset($context['params'])) {
114 1
            $context['params'] = [];
115 1
        }
116 2
        $context = stream_context_create($context['options'], $context['params']);
117 2
    }
118 7
    $res = (new StreamResource($uri, $mode, null, true))
119 7
        ->setContextResource($context);
120 7
    if (!$lazy) {
121 1
        $res->connect();
122 1
    }
123
124 7
    return $res;
125
}
126
127
/**
128
 * Stream factory.
129
 *
130
 * This method is just a shortcut to create a stream object using a URI.
131
 *
132
 * @param string         $uri     A stream URI to open
133
 * @param string         $mode    The access mode string
134
 * @param array|resource $context An array or stream context resource of options
135
 * @param bool           $lazy    Whether to lazy-open
136
 *
137
 * @return Stream
138
 *
139
 * @since v0.2.1
140
 */
141
function stream(
142
    $uri,
143
    $mode = null,
144
    $context = null,
145
    $lazy = true
146
) {
147 3
    $res = stream_resource($uri, $mode, $context, $lazy);
148
149 3
    return $res();
150
}
151
152
/**
153
 * "Taste" a stream object.
154
 *
155
 * Pass any class that implements the "Streamable" interface to this function
156
 * to auto-detect "flavor" (formatting attributes).
157
 *
158
 * @param Contract\Streamable Any streamable class to analyze
159
 *
160
 * @return Flavor A flavor representing stream's formatting attributes
161
 *
162
 * @since v0.2.1
163
 */
164
function taste(Streamable $str)
165
{
166 13
    $taster = new Taster($str);
167
168 13
    return $taster();
169
}
170
171
/**
172
 * Does dataset being streamed by $str have a header row?
173
 *
174
 * @param Contract\Streamable $str Stream object
175
 *
176
 * @return bool Whether stream dataset has header
177
 *
178
 * @since v0.2.1
179
 */
180
function taste_has_header(Streamable $str)
181
{
182 5
    $taster = new Taster($str);
183 5
    $flv    = $taster();
184
185 5
    return $taster->lickHeader(
186 5
        $flv->delimiter,
187 5
        $flv->lineTerminator
188 5
    );
189
}
190
191
/**
192
 * Collection factory.
193
 *
194
 * Simply an alias to (new Collection($in)). Allows for a little more concise and
195
 * simpler instantiation of a collection. Also I plan to eventually support
196
 * additional input types that will make this function more flexible and forgiving
197
 * than simply instantiating a Collection object, but for now the two are identical.
198
 *
199
 * @param array|Iterator $in Either an array or an iterator of data
200
 *
201
 * @return AbstractCollection A collection object containing data from $in
202
 *
203
 * @since v0.2.1
204
 * @see AbstractCollection::__construct() (alias)
205
 */
206
function collect($in = null)
207
{
208 66
    return Collection::factory($in);
209
}
210
211
/**
212
 * Invoke a callable and return result.
213
 *
214
 * Pass in a callable followed by whatever arguments you want passed to
215
 * it and this function will invoke it with your arguments and return
216
 * the result.
217
 *
218
 * @param callable $callback The callback function to invoke
219
 * @param array ...$args The args to pass to your callable
220
 *
221
 * @return mixed The result of your invoked callable
222
 *
223
 * @since v0.2.1
224
 */
225
function invoke(callable $callback, ...$args)
226
{
227 1
    return $callback(...$args);
228
}
229
230
/**
231
 * Determine if data is traversable.
232
 *
233
 * Pass in any variable and this function will tell you whether or not it
234
 * is traversable. Basically this just means that it is either an array or an iterator.
235
 * This function was written simply because I was tired of if statements that checked
236
 * whether a variable was an array or a descendant of \Iterator. So I wrote this guy.
237
 *
238
 * @param mixed $input The variable to determine traversability
239
 *
240
 * @return bool True if $input is an array or an Iterator
241
 */
242
function is_traversable($input)
243
{
244 147
    return is_array($input) || $input instanceof Iterator;
245
}
246