Completed
Push — master ( 9d0a53...ecd7bc )
by Maik
01:48
created

FileInputStream::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * This file is part of the PHP Generics package.
5
 *
6
 * @package Generics
7
 */
8
namespace Generics\Streams;
9
10
use Generics\FileNotFoundException;
11
use Generics\LockException;
12
use Generics\Lockable;
13
14
/**
15
 * This class provides an input stream for files.
16
 *
17
 * @author Maik Greubel <[email protected]>
18
 */
19
class FileInputStream implements InputStream, Lockable
20
{
21
22
    /**
23
     * The file handle
24
     *
25
     * @var resource
26
     */
27
    private $handle;
28
29
    /**
30
     * The absolute file path and name
31
     *
32
     * @var string
33
     */
34
    private $fileName;
35
36
    /**
37
     * Whether the access is locked
38
     *
39
     * @var bool
40
     */
41
    private $locked;
42
43
    /**
44
     * Create a new FileInputStream
45
     *
46
     * @param string $file
47
     *            The absolute (or relative) path to the file to open
48
     * @throws FileNotFoundException
49
     */
50
    public function __construct($file)
51
    {
52
        if (! file_exists($file)) {
53
            throw new FileNotFoundException("File {file} could not be found", array(
54
                'file' => $file
55
            ));
56
        }
57
        
58
        $this->handle = fopen($file, "rb");
59
        
60
        if (! $this->ready()) {
61
            throw new StreamException("Could not open {file} for reading", array(
62
                'file' => $file
63
            ));
64
        }
65
        
66
        $this->fileName = $file;
67
    }
68
69
    /**
70
     * Cleanup (e.g.
71
     * release lock)
72
     */
73
    public function __destruct()
74
    {
75
        try {
76
            if ($this->locked) {
77
                $this->unlock();
78
            }
79
        } catch (\Generics\GenericsException $ex) {
80
            // Do nothing
81
        }
82
    }
83
84
    /**
85
     *
86
     * {@inheritdoc}
87
     * @see \Generics\Streams\Stream::close()
88
     */
89
    public function close()
90
    {
91
        if ($this->handle != null) {
92
            fclose($this->handle);
93
            $this->handle = null;
94
        }
95
    }
96
97
    /**
98
     *
99
     * {@inheritdoc}
100
     * @see \Generics\Streams\Stream::ready()
101
     */
102
    public function ready(): bool
103
    {
104
        return is_resource($this->handle) && ! feof($this->handle);
105
    }
106
107
    /**
108
     *
109
     * {@inheritdoc}
110
     * @see \Generics\Streams\InputStream::read()
111
     */
112
    public function read($length = 1, $offset = null): string
113
    {
114
        if (! $this->ready()) {
115
            throw new StreamException("Stream is not ready!");
116
        }
117
        
118
        if ($offset !== null && intval($offset) > 0) {
119
            if (fseek($this->handle, $offset, SEEK_SET) != 0) {
120
                throw new StreamException("Could not set offset!");
121
            }
122
        }
123
        
124
        return fread($this->handle, $length);
125
    }
126
127
    /**
128
     *
129
     * {@inheritdoc}
130
     * @see \Countable::count()
131
     */
132
    public function count(): int
133
    {
134
        $stat = fstat($this->handle);
135
        return $stat['size'];
136
    }
137
138
    /**
139
     *
140
     * {@inheritdoc}
141
     * @see \Generics\Streams\InputStream::reset()
142
     */
143
    public function reset()
144
    {
145
        fseek($this->handle, 0, SEEK_SET);
146
    }
147
148
    /**
149
     *
150
     * {@inheritdoc}
151
     * @see \Generics\Lockable::lock()
152
     */
153 View Code Duplication
    public function lock()
154
    {
155
        if ($this->locked || flock($this->handle, LOCK_SH) === false) {
156
            throw new LockException("Could not acquire lock");
157
        }
158
        $this->locked = true;
159
    }
160
161
    /**
162
     *
163
     * {@inheritdoc}
164
     * @see \Generics\Lockable::unlock()
165
     */
166 View Code Duplication
    public function unlock()
167
    {
168
        if (! $this->locked || flock($this->handle, LOCK_UN) === false) {
169
            throw new LockException("Could not release lock");
170
        }
171
        $this->locked = false;
172
    }
173
174
    /**
175
     *
176
     * {@inheritdoc}
177
     * @see \Generics\Lockable::isLocked()
178
     */
179
    public function isLocked(): bool
180
    {
181
        return $this->locked;
182
    }
183
184
    /**
185
     * Retrieve the file path and name
186
     *
187
     * @return string
188
     */
189
    public function __toString(): string
190
    {
191
        return realpath($this->fileName);
192
    }
193
194
    /**
195
     *
196
     * {@inheritdoc}
197
     * @see \Generics\Streams\Stream::isOpen()
198
     */
199
    public function isOpen(): bool
200
    {
201
        return is_resource($this->handle);
202
    }
203
}
204