Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OpenSpout\Reader;
6
 
7
use OpenSpout\Common\Exception\IOException;
8
use OpenSpout\Reader\Exception\ReaderException;
9
use OpenSpout\Reader\Exception\ReaderNotOpenedException;
10
 
11
/**
12
 * @template T of SheetIteratorInterface
13
 *
14
 * @implements ReaderInterface<T>
15
 */
16
abstract class AbstractReader implements ReaderInterface
17
{
18
    /** @var bool Indicates whether the stream is currently open */
19
    private bool $isStreamOpened = false;
20
 
21
    /**
22
     * Prepares the reader to read the given file. It also makes sure
23
     * that the file exists and is readable.
24
     *
25
     * @param string $filePath Path of the file to be read
26
     *
27
     * @throws IOException If the file at the given path does not exist, is not readable or is corrupted
28
     */
29
    public function open(string $filePath): void
30
    {
31
        if ($this->isStreamWrapper($filePath) && (!$this->doesSupportStreamWrapper() || !$this->isSupportedStreamWrapper($filePath))) {
32
            throw new IOException("Could not open {$filePath} for reading! Stream wrapper used is not supported for this type of file.");
33
        }
34
 
35
        if (!$this->isPhpStream($filePath)) {
36
            // we skip the checks if the provided file path points to a PHP stream
37
            if (!file_exists($filePath)) {
38
                throw new IOException("Could not open {$filePath} for reading! File does not exist.");
39
            }
40
            if (!is_readable($filePath)) {
41
                throw new IOException("Could not open {$filePath} for reading! File is not readable.");
42
            }
43
        }
44
 
45
        try {
46
            $fileRealPath = $this->getFileRealPath($filePath);
47
            $this->openReader($fileRealPath);
48
            $this->isStreamOpened = true;
49
        } catch (ReaderException $exception) {
50
            throw new IOException(
51
                "Could not open {$filePath} for reading!",
52
                0,
53
                $exception
54
            );
55
        }
56
    }
57
 
58
    /**
59
     * Closes the reader, preventing any additional reading.
60
     */
61
    final public function close(): void
62
    {
63
        if ($this->isStreamOpened) {
64
            $this->closeReader();
65
 
66
            $this->isStreamOpened = false;
67
        }
68
    }
69
 
70
    /**
71
     * Returns whether stream wrappers are supported.
72
     */
73
    abstract protected function doesSupportStreamWrapper(): bool;
74
 
75
    /**
76
     * Opens the file at the given file path to make it ready to be read.
77
     *
78
     * @param string $filePath Path of the file to be read
79
     */
80
    abstract protected function openReader(string $filePath): void;
81
 
82
    /**
83
     * Closes the reader. To be used after reading the file.
84
     */
85
    abstract protected function closeReader(): void;
86
 
87
    final protected function ensureStreamOpened(): void
88
    {
89
        if (!$this->isStreamOpened) {
90
            throw new ReaderNotOpenedException('Reader should be opened first.');
91
        }
92
    }
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
    private function getFileRealPath(string $filePath): string
99
    {
100
        if ($this->isSupportedStreamWrapper($filePath)) {
101
            return $filePath;
102
        }
103
 
104
        // Need to use realpath to fix "Can't open file" on some Windows setup
105
        $realpath = realpath($filePath);
106
        \assert(false !== $realpath);
107
 
108
        return $realpath;
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
     *
117
     * @return null|string The stream wrapper scheme or NULL if not a stream wrapper
118
     */
119
    private function getStreamWrapperScheme(string $filePath): ?string
120
    {
121
        $streamScheme = null;
122
        if (1 === preg_match('/^(\w+):\/\//', $filePath, $matches)) {
123
            $streamScheme = $matches[1];
124
        }
125
 
126
        return $streamScheme;
127
    }
128
 
129
    /**
130
     * Checks if the given path is an unsupported stream wrapper
131
     * (like local path, php://temp, mystream://foo/bar...).
132
     *
133
     * @param string $filePath Path of the file to be read
134
     *
135
     * @return bool Whether the given path is an unsupported stream wrapper
136
     */
137
    private function isStreamWrapper(string $filePath): bool
138
    {
139
        return null !== $this->getStreamWrapperScheme($filePath);
140
    }
141
 
142
    /**
143
     * Checks if the given path is an supported stream wrapper
144
     * (like php://temp, mystream://foo/bar...).
145
     * If the given path is a local path, returns true.
146
     *
147
     * @param string $filePath Path of the file to be read
148
     *
149
     * @return bool Whether the given path is an supported stream wrapper
150
     */
151
    private function isSupportedStreamWrapper(string $filePath): bool
152
    {
153
        $streamScheme = $this->getStreamWrapperScheme($filePath);
154
 
155
        return null === $streamScheme || \in_array($streamScheme, stream_get_wrappers(), true);
156
    }
157
 
158
    /**
159
     * Checks if a path is a PHP stream (like php://output, php://memory, ...).
160
     *
161
     * @param string $filePath Path of the file to be read
162
     *
163
     * @return bool Whether the given path maps to a PHP stream
164
     */
165
    private function isPhpStream(string $filePath): bool
166
    {
167
        $streamScheme = $this->getStreamWrapperScheme($filePath);
168
 
169
        return 'php' === $streamScheme;
170
    }
171
}