Completed
Push — master ( 0c90d1...049fd9 )
by Adrien
9s
created

AbstractReader::isSupportedStreamWrapper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
ccs 5
cts 5
cp 1
cc 2
eloc 5
nc 2
nop 1
crap 2
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
    /**
23
     * Returns whether stream wrappers are supported
24
     *
25
     * @return bool
26
     */
27
    abstract protected function doesSupportStreamWrapper();
28
29
    /**
30
     * Opens the file at the given file path to make it ready to be read
31
     *
32
     * @param  string $filePath Path of the file to be read
33
     * @return void
34
     */
35
    abstract protected function openReader($filePath);
36
37
    /**
38
     * Returns an iterator to iterate over sheets.
39
     *
40
     * @return \Iterator To iterate over sheets
41
     */
42
    abstract public function getConcreteSheetIterator();
43
44
    /**
45
     * Closes the reader. To be used after reading the file.
46
     *
47
     * @return AbstractReader
48
     */
49
    abstract protected function closeReader();
50
51
    /**
52
     * @param $globalFunctionsHelper
53
     * @return AbstractReader
54
     */
55 237
    public function setGlobalFunctionsHelper($globalFunctionsHelper)
56
    {
57 237
        $this->globalFunctionsHelper = $globalFunctionsHelper;
58 237
        return $this;
59
    }
60
61
    /**
62
     * Prepares the reader to read the given file. It also makes sure
63
     * that the file exists and is readable.
64
     *
65
     * @api
66
     * @param  string $filePath Path of the file to be read
67
     * @return void
68
     * @throws \Box\Spout\Common\Exception\IOException If the file at the given path does not exist, is not readable or is corrupted
69
     */
70 234
    public function open($filePath)
71
    {
72 234
        if ($this->isStreamWrapper($filePath) && (!$this->doesSupportStreamWrapper() || !$this->isSupportedStreamWrapper($filePath))) {
73 15
            throw new IOException("Could not open $filePath for reading! Stream wrapper used is not supported for this type of file.");
74
        }
75
76 219
        if (!$this->isPhpStream($filePath)) {
77
            // we skip the checks if the provided file path points to a PHP stream
78 219
            if (!$this->globalFunctionsHelper->file_exists($filePath)) {
79 9
                throw new IOException("Could not open $filePath for reading! File does not exist.");
80 210
            } else if (!$this->globalFunctionsHelper->is_readable($filePath)) {
81 3
                throw new IOException("Could not open $filePath for reading! File is not readable.");
82
            }
83 207
        }
84
85
        try {
86 207
            $fileRealPath = $this->getFileRealPath($filePath);
87 207
            $this->openReader($fileRealPath);
88 192
            $this->isStreamOpened = true;
89 207
        } catch (\Exception $exception) {
90 15
            throw new IOException("Could not open $filePath for reading! ({$exception->getMessage()})");
91
        }
92 192
    }
93
94
    /**
95
     * Returns the real path of the given path.
96
     * If the given path is a valid stream wrapper, returns the path unchanged.
97
     *
98
     * @param string $filePath
99
     * @return string
100
     */
101 207
    protected function getFileRealPath($filePath)
102
    {
103 207
        if ($this->isSupportedStreamWrapper($filePath)) {
104 207
            return $filePath;
105
        }
106
107
        // Need to use realpath to fix "Can't open file" on some Windows setup
108
        return realpath($filePath);
109
    }
110
111
    /**
112
     * Returns the scheme of the custom stream wrapper, if the path indicates a stream wrapper is used.
113
     * For example, php://temp => php, s3://path/to/file => s3...
114
     *
115
     * @param string $filePath Path of the file to be read
116
     * @return string|null The stream wrapper scheme or NULL if not a stream wrapper
117
     */
118 234
    protected function getStreamWrapperScheme($filePath)
119
    {
120 234
        $streamScheme = null;
121 234
        if (preg_match('/^(\w+):\/\//', $filePath, $matches)) {
122 18
            $streamScheme = $matches[1];
123 18
        }
124 234
        return $streamScheme;
125
    }
126
127
    /**
128
     * Checks if the given path is an unsupported stream wrapper
129
     * (like local path, php://temp, mystream://foo/bar...).
130
     *
131
     * @param string $filePath Path of the file to be read
132
     * @return bool Whether the given path is an unsupported stream wrapper
133
     */
134 234
    protected function isStreamWrapper($filePath)
135
    {
136 234
        return ($this->getStreamWrapperScheme($filePath) !== null);
137
    }
138
139
    /**
140
     * Checks if the given path is an supported stream wrapper
141
     * (like php://temp, mystream://foo/bar...).
142
     * If the given path is a local path, returns true.
143
     *
144
     * @param string $filePath Path of the file to be read
145
     * @return bool Whether the given path is an supported stream wrapper
146
     */
147 210
    protected function isSupportedStreamWrapper($filePath)
148
    {
149 210
        $streamScheme = $this->getStreamWrapperScheme($filePath);
150 210
        return ($streamScheme !== null) ?
151 210
            in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) :
152 210
            true;
153
    }
154
155
    /**
156
     * Checks if a path is a PHP stream (like php://output, php://memory, ...)
157
     *
158
     * @param string $filePath Path of the file to be read
159
     * @return bool Whether the given path maps to a PHP stream
160
     */
161 219
    protected function isPhpStream($filePath)
162
    {
163 219
        $streamScheme = $this->getStreamWrapperScheme($filePath);
164 219
        return ($streamScheme === 'php');
165
    }
166
167
    /**
168
     * Returns an iterator to iterate over sheets.
169
     *
170
     * @api
171
     * @return \Iterator To iterate over sheets
172
     * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader
173
     */
174 195
    public function getSheetIterator()
175
    {
176 195
        if (!$this->isStreamOpened) {
177 3
            throw new ReaderNotOpenedException('Reader should be opened first.');
178
        }
179
180 192
        return $this->getConcreteSheetIterator();
181
    }
182
183
    /**
184
     * Closes the reader, preventing any additional reading
185
     *
186
     * @api
187
     * @return void
188
     */
189 180
    public function close()
190
    {
191 180
        if ($this->isStreamOpened) {
192 180
            $this->closeReader();
193
194 180
            $sheetIterator = $this->getConcreteSheetIterator();
195 180
            if ($sheetIterator) {
196 180
                $sheetIterator->end();
197 180
            }
198
199 180
            $this->isStreamOpened = false;
200 180
        }
201 180
    }
202
}
203