Completed
Pull Request — master (#235)
by
unknown
02:55
created

AbstractReader::isStreamWrapper()   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 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
ccs 2
cts 2
cp 1
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Box\Spout\Reader;
4
5
use Box\Spout\Common\Exception\IOException;
6
use Box\Spout\Reader\Exception\ReaderNotOpenedException;
7
8
/**
9
 * Class AbstractReader
10
 *
11
 * @package Box\Spout\Reader
12
 * @abstract
13
 */
14
abstract class AbstractReader implements ReaderInterface
15
{
16
    /** @var bool Indicates whether the stream is currently open */
17
    protected $isStreamOpened = false;
18
19
    /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
20
    protected $globalFunctionsHelper;
21
22
    /** @var \Box\Spout\Reader\ReaderOptions */
23
    protected $readerOptions;
24
25
    /**
26
     * The constructor.
27
     */
28 285
    public function __construct()
29
    {
30 285
        $this->readerOptions = new ReaderOptions();
31 285
    }
32
33
    /**
34
     * Returns whether stream wrappers are supported
35
     *
36
     * @return bool
37
     */
38
    abstract protected function doesSupportStreamWrapper();
39
40
    /**
41
     * Opens the file at the given file path to make it ready to be read
42
     *
43
     * @param  string $filePath Path of the file to be read
44
     * @return void
45
     */
46
    abstract protected function openReader($filePath);
47
48
    /**
49
     * Returns an iterator to iterate over sheets.
50
     *
51
     * @return \Iterator To iterate over sheets
52
     */
53
    abstract public function getConcreteSheetIterator();
54
55
    /**
56
     * Closes the reader. To be used after reading the file.
57
     *
58
     * @return AbstractReader
59
     */
60
    abstract protected function closeReader();
61
62
    /**
63
     * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
64
     * @return AbstractReader
65
     */
66 285
    public function setGlobalFunctionsHelper($globalFunctionsHelper)
67
    {
68 285
        $this->globalFunctionsHelper = $globalFunctionsHelper;
69 285
        return $this;
70
    }
71
72
    /**
73
     * Sets whether date/time values should be returned as PHP objects or be formatted as strings.
74
     *
75
     * @param bool $shouldFormatDates
76
     * @return AbstractReader
77
     */
78 6
    public function setShouldFormatDates($shouldFormatDates)
79
    {
80 6
        $this->readerOptions->setShouldFormatDates($shouldFormatDates);
81 6
        return $this;
82
    }
83
84
    /**
85
     * Sets whether the row iterators should use the original rows' indices as keys.
86
     *
87
     * @param bool $shouldPreserveRowIndices
88
     * @return AbstractReader
89
     */
90 6
    public function setShouldPreserveRowIndices($shouldPreserveRowIndices)
91
    {
92 6
        $this->readerOptions->setShouldPreserveRowIndices($shouldPreserveRowIndices);
93 6
        return $this;
94
    }
95
96
    /**
97
     * Sets whether to skip or return "empty" rows.
98
     *
99
     * @param bool $shouldOmitEmptyRows
100
     * @return AbstractReader
101
     */
102
    public function setShouldOmitEmptyRows($shouldOmitEmptyRows)
103
    {
104
        $this->readerOptions->setShouldOmitEmptyRows($shouldOmitEmptyRows);
0 ignored issues
show
Bug introduced by
The method setShouldOmitEmptyRows() does not seem to exist on object<Box\Spout\Reader\ReaderOptions>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
        return $this;
106
    }
107
108
    /**
109
     * Prepares the reader to read the given file. It also makes sure
110
     * that the file exists and is readable.
111
     *
112
     * @api
113
     * @param  string $filePath Path of the file to be read
114
     * @return void
115
     * @throws \Box\Spout\Common\Exception\IOException If the file at the given path does not exist, is not readable or is corrupted
116
     */
117 282
    public function open($filePath)
118 3
    {
119 282
        if ($this->isStreamWrapper($filePath) && (!$this->doesSupportStreamWrapper() || !$this->isSupportedStreamWrapper($filePath))) {
120 15
            throw new IOException("Could not open $filePath for reading! Stream wrapper used is not supported for this type of file.");
121
        }
122
123 267
        if (!$this->isPhpStream($filePath)) {
124
            // we skip the checks if the provided file path points to a PHP stream
125 267
            if (!$this->globalFunctionsHelper->file_exists($filePath)) {
126 9
                throw new IOException("Could not open $filePath for reading! File does not exist.");
127 258
            } else if (!$this->globalFunctionsHelper->is_readable($filePath)) {
128 3
                throw new IOException("Could not open $filePath for reading! File is not readable.");
129
            }
130 255
        }
131
132
        try {
133 255
            $fileRealPath = $this->getFileRealPath($filePath);
134 255
            $this->openReader($fileRealPath);
135 240
            $this->isStreamOpened = true;
136 255
        } catch (\Exception $exception) {
137 15
            throw new IOException("Could not open $filePath for reading! ({$exception->getMessage()})");
138
        }
139 240
    }
140
141
    /**
142
     * Returns the real path of the given path.
143
     * If the given path is a valid stream wrapper, returns the path unchanged.
144
     *
145
     * @param string $filePath
146
     * @return string
147
     */
148 255
    protected function getFileRealPath($filePath)
149
    {
150 255
        if ($this->isSupportedStreamWrapper($filePath)) {
151 255
            return $filePath;
152
        }
153
154
        // Need to use realpath to fix "Can't open file" on some Windows setup
155
        return realpath($filePath);
156
    }
157
158
    /**
159
     * Returns the scheme of the custom stream wrapper, if the path indicates a stream wrapper is used.
160
     * For example, php://temp => php, s3://path/to/file => s3...
161
     *
162
     * @param string $filePath Path of the file to be read
163
     * @return string|null The stream wrapper scheme or NULL if not a stream wrapper
164
     */
165 282
    protected function getStreamWrapperScheme($filePath)
166
    {
167 282
        $streamScheme = null;
168 282
        if (preg_match('/^(\w+):\/\//', $filePath, $matches)) {
169 18
            $streamScheme = $matches[1];
170 18
        }
171 282
        return $streamScheme;
172
    }
173
174
    /**
175
     * Checks if the given path is an unsupported stream wrapper
176
     * (like local path, php://temp, mystream://foo/bar...).
177
     *
178
     * @param string $filePath Path of the file to be read
179
     * @return bool Whether the given path is an unsupported stream wrapper
180
     */
181 282
    protected function isStreamWrapper($filePath)
182
    {
183 282
        return ($this->getStreamWrapperScheme($filePath) !== null);
184
    }
185
186
    /**
187
     * Checks if the given path is an supported stream wrapper
188
     * (like php://temp, mystream://foo/bar...).
189
     * If the given path is a local path, returns true.
190
     *
191
     * @param string $filePath Path of the file to be read
192
     * @return bool Whether the given path is an supported stream wrapper
193
     */
194 258
    protected function isSupportedStreamWrapper($filePath)
195
    {
196 258
        $streamScheme = $this->getStreamWrapperScheme($filePath);
197 258
        return ($streamScheme !== null) ?
198 258
            in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) :
199 258
            true;
200
    }
201
202
    /**
203
     * Checks if a path is a PHP stream (like php://output, php://memory, ...)
204
     *
205
     * @param string $filePath Path of the file to be read
206
     * @return bool Whether the given path maps to a PHP stream
207
     */
208 267
    protected function isPhpStream($filePath)
209
    {
210 267
        $streamScheme = $this->getStreamWrapperScheme($filePath);
211 267
        return ($streamScheme === 'php');
212
    }
213
214
    /**
215
     * Returns an iterator to iterate over sheets.
216
     *
217
     * @api
218
     * @return \Iterator To iterate over sheets
219
     * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader
220
     */
221 243
    public function getSheetIterator()
222
    {
223 243
        if (!$this->isStreamOpened) {
224 3
            throw new ReaderNotOpenedException('Reader should be opened first.');
225
        }
226
227 240
        return $this->getConcreteSheetIterator();
228
    }
229
230
    /**
231
     * Closes the reader, preventing any additional reading
232
     *
233
     * @api
234
     * @return void
235
     */
236 228
    public function close()
237
    {
238 228
        if ($this->isStreamOpened) {
239 228
            $this->closeReader();
240
241 228
            $sheetIterator = $this->getConcreteSheetIterator();
242 228
            if ($sheetIterator) {
243 228
                $sheetIterator->end();
244 228
            }
245
246 228
            $this->isStreamOpened = false;
247 228
        }
248 228
    }
249
}
250