Completed
Push — V6 ( 198742...8f6ce3 )
by Georges
02:35
created

Driver::driverClear()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 2
eloc 8
nc 2
nop 0
1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> http://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
15
namespace phpFastCache\Drivers\Cassandra;
16
17
use phpFastCache\Core\Pool\DriverBaseTrait;
18
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
19
use phpFastCache\Entities\driverStatistic;
20
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
21
use phpFastCache\Exceptions\phpFastCacheDriverException;
22
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
23
use Psr\Cache\CacheItemInterface;
24
use Cassandra;
25
use Cassandra\Session as CassandraSession;
26
27
/**
28
 * Class Driver
29
 * @package phpFastCache\Drivers
30
 * @property CassandraSession $instance Instance of driver service
31
 */
32
class Driver implements ExtendedCacheItemPoolInterface
33
{
34
    const CASSANDRA_KEY_SPACE = 'phpfastcache';
35
    const CASSANDRA_TABLE = 'cacheItems';
36
37
    use DriverBaseTrait;
38
39
    /**
40
     * Driver constructor.
41
     * @param array $config
42
     * @throws phpFastCacheDriverException
43
     */
44 View Code Duplication
    public function __construct(array $config = [])
45
    {
46
        $this->setup($config);
47
48
        if (!$this->driverCheck()) {
49
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
50
        } else {
51
            $this->driverConnect();
52
        }
53
    }
54
55
    /**
56
     * @return bool
57
     */
58
    public function driverCheck()
59
    {
60
        return extension_loaded('Cassandra') && class_exists('Cassandra');
61
    }
62
63
    /**
64
     * @param \Psr\Cache\CacheItemInterface $item
65
     * @return mixed
66
     * @throws phpFastCacheInvalidArgumentException
67
     */
68
    protected function driverWrite(CacheItemInterface $item)
69
    {
70
        /**
71
         * Check for Cross-Driver type confusion
72
         */
73
        if ($item instanceof Item) {
74
            $cacheData = $this->encode($this->driverPreWrap($item));
75
            $options = new Cassandra\ExecutionOptions([
76
              'arguments' => [
77
                  'cache_uuid' => new Cassandra\Uuid(),
78
                  'cache_id' => $item->getKey(),
79
                  'cache_data' => $cacheData,
80
                  'cache_creation_date' => new Cassandra\Timestamp((new \DateTime())->getTimestamp()),
81
                  'cache_expiration_date' => new Cassandra\Timestamp($item->getExpirationDate()->getTimestamp()),
82
                  'cache_length' => strlen($cacheData)
83
                ],
84
              'consistency' => Cassandra::CONSISTENCY_ALL,
85
              'serial_consistency' => Cassandra::CONSISTENCY_SERIAL
86
            ]);
87
88
            $query = sprintf('INSERT INTO %s.%s
89
                    (
90
                      cache_uuid, 
91
                      cache_id, 
92
                      cache_data, 
93
                      cache_creation_date, 
94
                      cache_expiration_date,
95
                      cache_length
96
                    )
97
                  VALUES (:cache_uuid, :cache_id, :cache_data, :cache_creation_date, :cache_expiration_date, :cache_length);
98
            ', self::CASSANDRA_KEY_SPACE, self::CASSANDRA_TABLE);
99
100
            $result = $this->instance->execute(new Cassandra\SimpleStatement($query), $options);
101
            /**
102
             * There's no real way atm
103
             * to know if the item has
104
             * been really upserted
105
             */
106
            return $result instanceof Cassandra\Rows;
1 ignored issue
show
Bug introduced by
The class Cassandra\Rows does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
107
        } else {
108
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
109
        }
110
    }
111
112
    /**
113
     * @param \Psr\Cache\CacheItemInterface $item
114
     * @return mixed
115
     */
116
    protected function driverRead(CacheItemInterface $item)
117
    {
118
        try {
119
            $options = new Cassandra\ExecutionOptions([
120
              'arguments' => ['cache_id' => $item->getKey()],
121
              'page_size' => 1
122
            ]);
123
            $query = sprintf(
124
              'SELECT cache_data FROM %s.%s WHERE cache_id = :cache_id;',
125
              self::CASSANDRA_KEY_SPACE,
126
              self::CASSANDRA_TABLE
127
            );
128
            $results = $this->instance->execute(new Cassandra\SimpleStatement($query), $options);
129
130
            if($results instanceof Cassandra\Rows && $results->count() === 1){
1 ignored issue
show
Bug introduced by
The class Cassandra\Rows does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
131
                return $this->decode($results->first()['cache_data']);
132
            }else{
133
                return null;
134
            }
135
        } catch (Cassandra\Exception $e) {
1 ignored issue
show
Bug introduced by
The class Cassandra\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
136
            return null;
137
        }
138
    }
139
140
    /**
141
     * @param \Psr\Cache\CacheItemInterface $item
142
     * @return bool
143
     * @throws phpFastCacheInvalidArgumentException
144
     */
145
    protected function driverDelete(CacheItemInterface $item)
146
    {
147
        /**
148
         * Check for Cross-Driver type confusion
149
         */
150
        if ($item instanceof Item) {
151
            try {
152
                $options = new Cassandra\ExecutionOptions([
153
                  'arguments' => [
154
                    'cache_id' => $item->getKey(),
155
                  ],
156
                ]);
157
                $result = $this->instance->execute(new Cassandra\SimpleStatement(sprintf(
158
                  'DELETE FROM %s.%s WHERE cache_id = :cache_id;',
159
                  self::CASSANDRA_KEY_SPACE,
160
                  self::CASSANDRA_TABLE
161
                )), $options);
162
163
                /**
164
                 * There's no real way atm
165
                 * to know if the item has
166
                 * been really deleted
167
                 */
168
                return $result instanceof Cassandra\Rows;
1 ignored issue
show
Bug introduced by
The class Cassandra\Rows does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
169
            } catch (Cassandra\Exception $e) {
1 ignored issue
show
Bug introduced by
The class Cassandra\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
170
                return false;
171
            }
172
        } else {
173
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
174
        }
175
    }
176
177
    /**
178
     * @return bool
179
     */
180
    protected function driverClear()
181
    {
182
        try {
183
            $result = $this->instance->execute(new Cassandra\SimpleStatement(sprintf(
184
              'TRUNCATE %s.%s;',
185
              self::CASSANDRA_KEY_SPACE, self::CASSANDRA_TABLE
186
            )));
187
            /**
188
             * There's no real way atm
189
             * to know if the item has
190
             * been really deleted
191
             */
192
            return $result instanceof Cassandra\Rows;
1 ignored issue
show
Bug introduced by
The class Cassandra\Rows does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
193
        } catch (Cassandra\Exception $e) {
1 ignored issue
show
Bug introduced by
The class Cassandra\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
194
            return false;
195
        }
196
    }
197
198
    /**
199
     * @return bool
200
     */
201
    protected function driverConnect()
202
    {
203
        if ($this->instance instanceof CassandraSession) {
1 ignored issue
show
Bug introduced by
The class Cassandra\Session does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
204
            throw new \LogicException('Already connected to Couchbase server');
205
        } else {
206
            $host = isset($this->config[ 'host' ]) ? $this->config[ 'host' ] : '127.0.0.1';
207
            $port = isset($this->config[ 'port' ]) ? $this->config[ 'port' ] : 9042;
208
            $timeout = isset($this->config[ 'timeout' ]) ? $this->config[ 'timeout' ] : 2;
209
            $password = isset($this->config[ 'password' ]) ? $this->config[ 'password' ] : '';
210
            $username = isset($this->config[ 'username' ]) ? $this->config[ 'username' ] : '';
211
212
            $clusterBuilder = Cassandra::cluster()
213
              ->withContactPoints($host)
214
              ->withPort($port);
215
216
            if(!empty($this->config['ssl']['enabled'])){
217
                if(!empty($this->config['ssl']['verify'])){
218
                    $sslBuilder = Cassandra::ssl()->withVerifyFlags(Cassandra::VERIFY_PEER_CERT);
219
                }else{
220
                    $sslBuilder = Cassandra::ssl()->withVerifyFlags(Cassandra::VERIFY_NONE);
221
                }
222
223
                $clusterBuilder->withSSL($sslBuilder->build());
224
            }
225
226
            $clusterBuilder->withConnectTimeout($timeout);
227
228
            if($username){
229
                $clusterBuilder->withCredentials($username, $password);
230
            }
231
232
            $this->instance = $clusterBuilder->build()->connect();
233
234
            /**
235
             * In case of emergency:
236
             * $this->instance->execute(
237
             *      new Cassandra\SimpleStatement(sprintf("DROP KEYSPACE %s;", self::CASSANDRA_KEY_SPACE))
238
             * );
239
             */
240
241
            $this->instance->execute(new Cassandra\SimpleStatement(sprintf(
242
              "CREATE KEYSPACE IF NOT EXISTS %s WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };",
243
              self::CASSANDRA_KEY_SPACE
244
            )));
245
            $this->instance->execute(new Cassandra\SimpleStatement(sprintf('USE %s;', self::CASSANDRA_KEY_SPACE)));
246
            $this->instance->execute(new Cassandra\SimpleStatement(sprintf('
247
                CREATE TABLE IF NOT EXISTS %s (
248
                    cache_uuid uuid,
249
                    cache_id varchar,
250
                    cache_data text,
251
                    cache_creation_date timestamp,
252
                    cache_expiration_date timestamp,
253
                    cache_length int,
254
                    PRIMARY KEY (cache_id)
255
                );', self::CASSANDRA_TABLE
256
            )));
257
        }
258
259
        return true;
260
    }
261
262
    /********************
263
     *
264
     * PSR-6 Extended Methods
265
     *
266
     *******************/
267
268
    /**
269
     * @return string
270
     */
271
    public static function getHelp()
272
    {
273
        return <<<HELP
274
<p>
275
To install the php Cassandra extension via Pecl:
276
<code>sudo pecl install cassandra</code>
277
More information on: https://github.com/datastax/php-driver
278
Please not that this repository only provide php stubs and C/C++ sources, it does NOT provide php client.
279
</p>
280
HELP;
281
    }
282
283
    /**
284
     * @return driverStatistic
285
     */
286
    public function getStats()
287
    {
288
        $result = $this->instance->execute(new Cassandra\SimpleStatement(sprintf(
289
          'SELECT SUM(cache_length) as cache_size FROM %s.%s',
290
          self::CASSANDRA_KEY_SPACE,
291
          self::CASSANDRA_TABLE
292
        )));
293
294
        return (new driverStatistic())
295
          ->setSize($result->first()[ 'cache_size' ])
296
          ->setRawData([])
297
          ->setData(implode(', ', array_keys($this->itemInstances)))
298
          ->setInfo('The cache size represents only the cache data itself without counting data structures associated to the cache entries.');
299
    }
300
}