Completed
Pull Request — 5.x (#16)
by Lars
05:10
created

Swift_KeyCache_DiskKeyCache::clearAll()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4
Metric Value
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.2
cc 4
eloc 7
nc 5
nop 1
crap 4
1
<?php
2
3
/*
4
 * This file is part of SwiftMailer.
5
 * (c) 2004-2009 Chris Corbyn
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
/**
12
 * A KeyCache which streams to and from disk.
13
 *
14
 * @author Chris Corbyn
15
 */
16
class Swift_KeyCache_DiskKeyCache implements Swift_KeyCache
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
17
{
18
    /** Signal to place pointer at start of file */
19
    const POSITION_START = 0;
20
21
    /** Signal to place pointer at end of file */
22
    const POSITION_END = 1;
23
24
    /** Signal to leave pointer in whatever position it currently is */
25
    const POSITION_CURRENT = 2;
26
27
    /**
28
     * An InputStream for cloning.
29
     *
30
     * @var Swift_KeyCache_KeyCacheInputStream
31
     */
32
    private $_stream;
33
34
    /**
35
     * A path to write to.
36
     *
37
     * @var string
38
     */
39
    private $_path;
40
41
    /**
42
     * Stored keys.
43
     *
44
     * @var array
45
     */
46
    private $_keys = array();
47
48
    /**
49
     * Will be true if magic_quotes_runtime is turned on.
50
     *
51
     * @var bool
52
     */
53
    private $_quotes = false;
54
55
    /**
56
     * Create a new DiskKeyCache with the given $stream for cloning to make
57
     * InputByteStreams, and the given $path to save to.
58
     *
59
     * @param Swift_KeyCache_KeyCacheInputStream $stream
60
     * @param string                             $path   to save to
61
     */
62 14
    public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path)
63
    {
64 14
        $this->_stream = $stream;
65 14
        $this->_path = $path;
66
67 14
        if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) {
68
            $this->_quotes = true;
69
        }
70 14
    }
71
72
    /**
73
     * Set a string into the cache under $itemKey for the namespace $nsKey.
74
     *
75
     * @see MODE_WRITE, MODE_APPEND
76
     *
77
     * @param string $nsKey
78
     * @param string $itemKey
79
     * @param string $string
80
     * @param int    $mode
81
     *
82
     * @throws Swift_IoException
83
     * @throws Swift_SwiftException
84
     */
85 66
    public function setString($nsKey, $itemKey, $string, $mode)
86
    {
87 66
        $this->_prepareCache($nsKey);
88
89 View Code Duplication
        switch ($mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
90 66
            case self::MODE_WRITE:
91 50
                $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
92 50
                break;
93 20
            case self::MODE_APPEND:
94 20
                $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
95 20
                break;
96
            default:
97
                throw new Swift_SwiftException(
98
                    'Invalid mode [' . $mode . '] used to set nsKey=' .
99
                    $nsKey . ', itemKey=' . $itemKey
100
                    );
101
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
102
        }
103
104 66
        fwrite($fp, $string);
105 66
        $this->_freeHandle($nsKey, $itemKey);
106 66
    }
107
108
    /**
109
     * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
110
     *
111
     * @see MODE_WRITE, MODE_APPEND
112
     *
113
     * @param string                 $nsKey
114
     * @param string                 $itemKey
115
     * @param Swift_OutputByteStream $os
116
     * @param int                    $mode
117
     *
118
     * @throws Swift_IoException
119
     */
120 3
    public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode)
121
    {
122 3
        $this->_prepareCache($nsKey);
123 View Code Duplication
        switch ($mode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124 3
            case self::MODE_WRITE:
125 1
                $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
126 1
                break;
127 2
            case self::MODE_APPEND:
128 2
                $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
129 2
                break;
130
            default:
131
                throw new Swift_SwiftException(
132
                    'Invalid mode [' . $mode . '] used to set nsKey=' .
133
                    $nsKey . ', itemKey=' . $itemKey
134
                    );
135
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
136
        }
137
138 3
        while (false !== $bytes = $os->read(8192)) {
139 3
            fwrite($fp, $bytes);
140
        }
141
142 3
        $this->_freeHandle($nsKey, $itemKey);
143 3
    }
144
145
    /**
146
     * Provides a ByteStream which when written to, writes data to $itemKey.
147
     *
148
     * NOTE: The stream will always write in append mode.
149
     *
150
     * @param string                $nsKey
151
     * @param string                $itemKey
152
     * @param Swift_InputByteStream $writeThrough
153
     *
154
     * @return Swift_InputByteStream
155
     */
156 18 View Code Duplication
    public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
    {
158 18
        $is = clone $this->_stream;
159
160 18
        $is->setKeyCache($this);
161 18
        $is->setNsKey($nsKey);
162 18
        $is->setItemKey($itemKey);
163
164 18
        if (isset($writeThrough)) {
165
            $is->setWriteThroughStream($writeThrough);
166
        }
167
168 18
        return $is;
169
    }
170
171
    /**
172
     * Get data back out of the cache as a string.
173
     *
174
     * @param string $nsKey
175
     * @param string $itemKey
176
     *
177
     * @throws Swift_IoException
178
     *
179
     * @return string
180
     */
181 11
    public function getString($nsKey, $itemKey)
182
    {
183 11
        $this->_prepareCache($nsKey);
184 11 View Code Duplication
        if ($this->hasKey($nsKey, $itemKey)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185 11
            $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
186 11
            if ($this->_quotes) {
187
                ini_set('magic_quotes_runtime', 0);
188
            }
189
190 11
            $str = '';
191 11
            while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
192 11
                $str .= $bytes;
193
            }
194
195 11
            if ($this->_quotes) {
196
                ini_set('magic_quotes_runtime', 1);
197
            }
198
199 11
            $this->_freeHandle($nsKey, $itemKey);
200
201 11
            return $str;
202
        }
203
    }
204
205
    /**
206
     * Get data back out of the cache as a ByteStream.
207
     *
208
     * @param string                $nsKey
209
     * @param string                $itemKey
210
     * @param Swift_InputByteStream $is      to write the data to
211
     */
212 4
    public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
213
    {
214 4 View Code Duplication
        if ($this->hasKey($nsKey, $itemKey)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
215 4
            $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
216
217 4
            if ($this->_quotes) {
218
                ini_set('magic_quotes_runtime', 0);
219
            }
220
221 4
            while (!feof($fp) && false !== $bytes = fread($fp, 8192)) {
222 4
                $is->write($bytes);
223
            }
224
225 4
            if ($this->_quotes) {
226
                ini_set('magic_quotes_runtime', 1);
227
            }
228
229 4
            $this->_freeHandle($nsKey, $itemKey);
230
        }
231 4
    }
232
233
    /**
234
     * Check if the given $itemKey exists in the namespace $nsKey.
235
     *
236
     * @param string $nsKey
237
     * @param string $itemKey
238
     *
239
     * @return bool
240
     */
241 139
    public function hasKey($nsKey, $itemKey)
242
    {
243 139
        return is_file($this->_path . '/' . $nsKey . '/' . $itemKey);
244
    }
245
246
    /**
247
     * Clear data for $itemKey in the namespace $nsKey if it exists.
248
     *
249
     * @param string $nsKey
250
     * @param string $itemKey
251
     */
252 128
    public function clearKey($nsKey, $itemKey)
253
    {
254 128
        if ($this->hasKey($nsKey, $itemKey)) {
255 57
            $this->_freeHandle($nsKey, $itemKey);
256 57
            unlink($this->_path . '/' . $nsKey . '/' . $itemKey);
257
        }
258 128
    }
259
260
    /**
261
     * Clear all data in the namespace $nsKey if it exists.
262
     *
263
     * @param string $nsKey
264
     */
265 125
    public function clearAll($nsKey)
266
    {
267 125
        if (array_key_exists($nsKey, $this->_keys)) {
268 55
            foreach ($this->_keys[$nsKey] as $itemKey => $null) {
269 55
                $this->clearKey($nsKey, $itemKey);
270
            }
271
272 55
            if (is_dir($this->_path . '/' . $nsKey)) {
273 55
                rmdir($this->_path . '/' . $nsKey);
274
            }
275
276 55
            unset($this->_keys[$nsKey]);
277
        }
278 125
    }
279
280
    /**
281
     * Initialize the namespace of $nsKey if needed.
282
     *
283
     * @param string $nsKey
284
     */
285 68
    private function _prepareCache($nsKey)
286
    {
287 68
        $cacheDir = $this->_path . '/' . $nsKey;
288 68
        if (!is_dir($cacheDir)) {
289 68
            if (!mkdir($cacheDir)) {
290
                throw new Swift_IoException('Failed to create cache directory ' . $cacheDir);
291
            }
292 68
            $this->_keys[$nsKey] = array();
293
        }
294 68
    }
295
296
    /**
297
     * Get a file handle on the cache item.
298
     *
299
     * @param string $nsKey
300
     * @param string $itemKey
301
     * @param int    $position
302
     *
303
     * @return resource
304
     */
305 68
    private function _getHandle($nsKey, $itemKey, $position)
306
    {
307 68
        if (!isset($this->_keys[$nsKey][$itemKey])) {
308 68
            $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b';
309 68
            $fp = fopen($this->_path . '/' . $nsKey . '/' . $itemKey, $openMode);
310 68
            $this->_keys[$nsKey][$itemKey] = $fp;
311
        }
312
313 68
        if (self::POSITION_START == $position) {
314 57
            fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET);
315 68
        } elseif (self::POSITION_END == $position) {
316 21
            fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END);
317
        }
318
319 68
        return $this->_keys[$nsKey][$itemKey];
320
    }
321
322
    /**
323
     * @param string $nsKey
324
     * @param string $itemKey
325
     */
326 68
    private function _freeHandle($nsKey, $itemKey)
327
    {
328 68
        $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_CURRENT);
329 68
        fclose($fp);
330 68
        $this->_keys[$nsKey][$itemKey] = null;
331 68
    }
332
333
    /**
334
     * Destructor.
335
     */
336
    public function __destruct()
337
    {
338
        foreach ($this->_keys as $nsKey => $null) {
339
            $this->clearAll($nsKey);
340
        }
341
    }
342
}
343