Swift_KeyCache_DiskKeyCache::setString()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 16

Duplication

Lines 14
Ratio 63.64 %

Code Coverage

Tests 11
CRAP Score 3.3955

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 3
nop 4
dl 14
loc 22
rs 9.2
c 0
b 0
f 0
ccs 11
cts 17
cp 0.6471
crap 3.3955
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 78
    public function setString($nsKey, $itemKey, $string, $mode)
86
    {
87 78
        $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 78
            case self::MODE_WRITE:
91 62
                $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
92 62
                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 78
        fwrite($fp, $string);
105 78
        $this->_freeHandle($nsKey, $itemKey);
106 78
    }
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 3
        }
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 11
            }
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 4
            }
224
225 4
            if ($this->_quotes) {
226
                ini_set('magic_quotes_runtime', 1);
227
            }
228
229 4
            $this->_freeHandle($nsKey, $itemKey);
230 4
        }
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 175
    public function hasKey($nsKey, $itemKey)
242
    {
243 175
        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 164
    public function clearKey($nsKey, $itemKey)
253
    {
254 164
        if ($this->hasKey($nsKey, $itemKey)) {
255 69
            $this->_freeHandle($nsKey, $itemKey);
256 69
            unlink($this->_path . '/' . $nsKey . '/' . $itemKey);
257 69
        }
258 164
    }
259
260
    /**
261
     * Clear all data in the namespace $nsKey if it exists.
262
     *
263
     * @param string $nsKey
264
     */
265 161
    public function clearAll($nsKey)
266
    {
267 161
        if (isset($this->_keys[$nsKey])) {
268 67
            foreach ($this->_keys[$nsKey] as $itemKey => $null) {
269 67
                $this->clearKey($nsKey, $itemKey);
270 67
            }
271
272 67
            if (is_dir($this->_path . '/' . $nsKey)) {
273 67
                rmdir($this->_path . '/' . $nsKey);
274 67
            }
275
276 67
            unset($this->_keys[$nsKey]);
277 67
        }
278 161
    }
279
280
    /**
281
     * Initialize the namespace of $nsKey if needed.
282
     *
283
     * @param string $nsKey
284
     */
285 80
    private function _prepareCache($nsKey)
286
    {
287 80
        $cacheDir = $this->_path . '/' . $nsKey;
288 80
        if (!is_dir($cacheDir)) {
289 80
            if (!mkdir($cacheDir)) {
290
                throw new Swift_IoException('Failed to create cache directory ' . $cacheDir);
291
            }
292 80
            $this->_keys[$nsKey] = array();
293 80
        }
294 80
    }
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 80
    private function _getHandle($nsKey, $itemKey, $position)
306
    {
307 80
        $position = (int)$position;
308
309 80
        if (!isset($this->_keys[$nsKey][$itemKey])) {
310 80
            $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b';
311 80
            $fp = fopen($this->_path . '/' . $nsKey . '/' . $itemKey, $openMode);
312 80
            $this->_keys[$nsKey][$itemKey] = $fp;
313 80
        }
314
315 80
        if (self::POSITION_START === $position) {
316 69
            fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET);
317 80
        } elseif (self::POSITION_END === $position) {
318 21
            fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END);
319 21
        }
320
321 80
        return $this->_keys[$nsKey][$itemKey];
322
    }
323
324
    /**
325
     * @param string $nsKey
326
     * @param string $itemKey
327
     */
328 80
    private function _freeHandle($nsKey, $itemKey)
329
    {
330 80
        $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_CURRENT);
331 80
        fclose($fp);
332 80
        $this->_keys[$nsKey][$itemKey] = null;
333 80
    }
334
335
    /**
336
     * Destructor.
337
     */
338
    public function __destruct()
339
    {
340
        foreach ($this->_keys as $nsKey => $null) {
341
            $this->clearAll($nsKey);
342
        }
343
    }
344
}
345