Completed
Push — master ( 74b63b...e0ef9e )
by Marco
03:20
created

lib/Doctrine/Common/Cache/SQLite3Cache.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\Common\Cache;
21
22
use SQLite3;
23
use SQLite3Result;
24
25
/**
26
 * SQLite3 cache provider.
27
 *
28
 * @since  1.4
29
 * @author Jake Bell <[email protected]>
30
 */
31
class SQLite3Cache extends CacheProvider
32
{
33
    /**
34
     * The ID field will store the cache key.
35
     */
36
    const ID_FIELD = 'k';
37
38
    /**
39
     * The data field will store the serialized PHP value.
40
     */
41
    const DATA_FIELD = 'd';
42
43
    /**
44
     * The expiration field will store a date value indicating when the
45
     * cache entry should expire.
46
     */
47
    const EXPIRATION_FIELD = 'e';
48
49
    /**
50
     * @var SQLite3
51
     */
52
    private $sqlite;
53
54
    /**
55
     * @var string
56
     */
57
    private $table;
58
59
    /**
60
     * Constructor.
61
     *
62
     * Calling the constructor will ensure that the database file and table 
63
     * exist and will create both if they don't.
64
     *
65
     * @param SQLite3 $sqlite
66
     * @param string $table
67
     */
68 75
    public function __construct(SQLite3 $sqlite, $table)
69
    {
70 75
        $this->sqlite = $sqlite;
71 75
        $this->table  = (string) $table;
72
73 75
        list($id, $data, $exp) = $this->getFields();
74
75 75
        return $this->sqlite->exec(sprintf(
0 ignored issues
show
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
76 75
            'CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY NOT NULL, %s BLOB, %s INTEGER)',
77 75
            $table,
78 75
            $id,
79 75
            $data,
80
            $exp
81 75
        ));
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 73
    protected function doFetch($id)
88
    {
89 73
        if ($item = $this->findById($id)) {
90 64
            return unserialize($item[self::DATA_FIELD]);
91
        }
92
93 73
        return false;
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 71
    protected function doContains($id)
100
    {
101 71
        return null !== $this->findById($id, false);
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 72
    protected function doSave($id, $data, $lifeTime = 0)
108
    {
109 72
        $statement = $this->sqlite->prepare(sprintf(
110 72
            'INSERT OR REPLACE INTO %s (%s) VALUES (:id, :data, :expire)',
111 72
            $this->table,
112 72
            implode(',', $this->getFields())
113 72
        ));
114
115 72
        $statement->bindValue(':id', $id);
116 72
        $statement->bindValue(':data', serialize($data), SQLITE3_BLOB);
117 72
        $statement->bindValue(':expire', $lifeTime > 0 ? time() + $lifeTime : null);
118
119 72
        return $statement->execute() instanceof SQLite3Result;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 45
    protected function doDelete($id)
126
    {
127 45
        list($idField) = $this->getFields();
128
129 45
        $statement = $this->sqlite->prepare(sprintf(
130 45
            'DELETE FROM %s WHERE %s = :id',
131 45
            $this->table,
132
            $idField
133 45
        ));
134
135 45
        $statement->bindValue(':id', $id);
136
137 45
        return $statement->execute() instanceof SQLite3Result;
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 2
    protected function doFlush()
144
    {
145 2
        return $this->sqlite->exec(sprintf('DELETE FROM %s', $this->table));
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151 1
    protected function doGetStats()
152
    {
153
        // no-op.
154 1
    }
155
156
    /**
157
     * Find a single row by ID.
158
     *
159
     * @param mixed $id
160
     * @param bool $includeData
161
     *
162
     * @return array|null
163
     */
164 73
    private function findById($id, $includeData = true)
165
    {
166 73
        list($idField) = $fields = $this->getFields();
167
168 73
        if (!$includeData) {
169 71
            $key = array_search(static::DATA_FIELD, $fields);
170 71
            unset($fields[$key]);
171 71
        }
172
173 73
        $statement = $this->sqlite->prepare(sprintf(
174 73
            'SELECT %s FROM %s WHERE %s = :id LIMIT 1',
175 73
            implode(',', $fields),
176 73
            $this->table,
177
            $idField
178 73
        ));
179
180 73
        $statement->bindValue(':id', $id, SQLITE3_TEXT);
181
182 73
        $item = $statement->execute()->fetchArray(SQLITE3_ASSOC);
183
184 73
        if ($item === false) {
185 73
            return null;
186
        }
187
188 69
        if ($this->isExpired($item)) {
189 1
            $this->doDelete($id);
190
191 1
            return null;
192
        }
193
194 69
        return $item;
195
    }
196
197
    /**
198
     * Gets an array of the fields in our table.
199
     *
200
     * @return array
201
     */
202 75
    private function getFields()
203
    {
204 75
        return array(static::ID_FIELD, static::DATA_FIELD, static::EXPIRATION_FIELD);
205
    }
206
207
    /**
208
     * Check if the item is expired.
209
     *
210
     * @param array $item
211
     *
212
     * @return bool
213
     */
214 69
    private function isExpired(array $item)
215
    {
216 69
        return isset($item[static::EXPIRATION_FIELD]) &&
217 69
            $item[self::EXPIRATION_FIELD] !== null &&
218 69
            $item[self::EXPIRATION_FIELD] < time();
219
    }
220
}
221