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

Driver::getCollection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
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\Mongodb;
16
17
use LogicException;
18
use MongoBinData;
19
use MongoClient as MongodbClient;
20
use MongoConnectionException;
21
use MongoCursorException;
22
use MongoDate;
23
use phpFastCache\Core\Pool\DriverBaseTrait;
24
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
25
use phpFastCache\Entities\driverStatistic;
26
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
27
use phpFastCache\Exceptions\phpFastCacheDriverException;
28
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
29
use Psr\Cache\CacheItemInterface;
30
31
/**
32
 * Class Driver
33
 * @package phpFastCache\Drivers
34
 */
35
class Driver implements ExtendedCacheItemPoolInterface
36
{
37
    use DriverBaseTrait;
38
    
39
    /**
40
     * @var MongodbClient
41
     */
42
    public $instance;
43
44
    /**
45
     * Driver constructor.
46
     * @param array $config
47
     * @throws phpFastCacheDriverException
48
     */
49 View Code Duplication
    public function __construct(array $config = [])
50
    {
51
        $this->setup($config);
52
53
        if (!$this->driverCheck()) {
54
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
55
        } else {
56
            $this->driverConnect();
57
        }
58
    }
59
60
    /**
61
     * @return bool
62
     */
63
    public function driverCheck()
64
    {
65
        if(class_exists('MongoDB\Driver\Manager')){
66
            trigger_error('PhpFastCache currently only support the pecl Mongo extension.<br />
67
            The Support for the MongoDB extension will be added coming soon.', E_USER_ERROR);
68
        }
69
70
        return extension_loaded('Mongodb') && class_exists('MongoClient');
71
    }
72
73
    /**
74
     * @param \Psr\Cache\CacheItemInterface $item
75
     * @return mixed
76
     * @throws phpFastCacheInvalidArgumentException
77
     */
78
    protected function driverWrite(CacheItemInterface $item)
79
    {
80
        /**
81
         * Check for Cross-Driver type confusion
82
         */
83
        if ($item instanceof Item) {
84
            try {
85
                $result = (array) $this->getCollection()->update(
86
                  ['_id' => $item->getKey()],
87
                  [
88
                    '$set' => [
89
                      self::DRIVER_EDATE_WRAPPER_INDEX => ($item->getTtl() > 0 ? new MongoDate(time() + $item->getTtl()) : new MongoDate(time())),
90
                      self::DRIVER_DATA_WRAPPER_INDEX => new MongoBinData($this->encode($item->get()), MongoBinData::BYTE_ARRAY),
91
                      self::DRIVER_TAGS_WRAPPER_INDEX => new MongoBinData($this->encode($item->getTags()), MongoBinData::BYTE_ARRAY),
92
                    ],
93
                  ],
94
                  ['upsert' => true, 'multiple' => false]
95
                );
96
            } catch (MongoCursorException $e) {
97
                return false;
98
            }
99
100
            return isset($result[ 'ok' ]) ? $result[ 'ok' ] == 1 : true;
101
        } else {
102
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
103
        }
104
    }
105
106
    /**
107
     * @param \Psr\Cache\CacheItemInterface $item
108
     * @return mixed
109
     */
110
    protected function driverRead(CacheItemInterface $item)
111
    {
112
        $document = $this->getCollection()
113
          ->findOne(['_id' => $item->getKey()],
114
            [self::DRIVER_DATA_WRAPPER_INDEX, self::DRIVER_EDATE_WRAPPER_INDEX, self::DRIVER_TAGS_WRAPPER_INDEX  /*'d', 'e'*/]);
115
116
        if ($document) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
117
            return [
118
              self::DRIVER_DATA_WRAPPER_INDEX => $this->decode($document[ self::DRIVER_DATA_WRAPPER_INDEX ]->bin),
119
              self::DRIVER_EDATE_WRAPPER_INDEX => (new \DateTime())->setTimestamp($document[ self::DRIVER_EDATE_WRAPPER_INDEX ]->sec),
120
              self::DRIVER_TAGS_WRAPPER_INDEX => $this->decode($document[ self::DRIVER_TAGS_WRAPPER_INDEX ]->bin),
121
            ];
122
        } else {
123
            return null;
124
        }
125
    }
126
127
    /**
128
     * @param \Psr\Cache\CacheItemInterface $item
129
     * @return bool
130
     * @throws phpFastCacheInvalidArgumentException
131
     */
132
    protected function driverDelete(CacheItemInterface $item)
133
    {
134
        /**
135
         * Check for Cross-Driver type confusion
136
         */
137
        if ($item instanceof Item) {
138
            $deletionResult = (array) $this->getCollection()->remove(['_id' => $item->getKey()], ["w" => 1]);
139
140
            return (int) $deletionResult[ 'ok' ] === 1 && !$deletionResult[ 'err' ];
141
        } else {
142
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
143
        }
144
    }
145
146
    /**
147
     * @return bool
148
     */
149
    protected function driverClear()
150
    {
151
        return (bool) $this->getCollection()->drop()['ok'];
152
    }
153
154
    /**
155
     * @return bool
156
     * @throws MongoConnectionException
157
     * @throws LogicException
158
     */
159
    protected function driverConnect()
160
    {
161
        if ($this->instance instanceof MongodbClient) {
162
            throw new LogicException('Already connected to Mongodb server');
163
        } else {
164
            $host = isset($this->config[ 'host' ]) ? $this->config[ 'host' ] : '127.0.0.1';
165
            $port = isset($this->config[ 'port' ]) ? $this->config[ 'port' ] : '27017';
166
            $timeout = isset($this->config[ 'timeout' ]) ? $this->config[ 'timeout' ] : 3;
167
            $password = isset($this->config[ 'password' ]) ? $this->config[ 'password' ] : '';
168
            $username = isset($this->config[ 'username' ]) ? $this->config[ 'username' ] : '';
169
170
171
            /**
172
             * @todo make an url builder
173
             */
174
            $this->instance = $this->instance ?: (new MongodbClient('mongodb://' .
175
              ($username ?: '') .
176
              ($password ? ":{$password}" : '') .
177
              ($username ? '@' : '') . "{$host}" .
178
              ($port != '27017' ? ":{$port}" : ''), ['connectTimeoutMS' => $timeout * 1000]))->phpFastCache;
179
            // $this->instance->Cache->createIndex([self::DRIVER_TIME_WRAPPER_INDEX => 1], ['expireAfterSeconds' => 0]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
180
        }
181
    }
182
183
184
    /**
185
     * @return \MongoCollection
186
     */
187
    protected function getCollection()
188
    {
189
        return $this->instance->Cache;
190
    }
191
192
    /********************
193
     *
194
     * PSR-6 Extended Methods
195
     *
196
     *******************/
197
198
    /**
199
     * @return string
200
     */
201
    public static function getHelp()
202
    {
203
        return <<<HELP
204
<p>
205
This driver rely on php's Mongo (http://php.net/manual/fr/class.mongo.php) extension, not php's MongoDb (http://php.net/manual/fr/class.mongodb.php) extension.
206
</p>
207
HELP;
208
    }
209
210
    /**
211
     * @return driverStatistic
212
     */
213
    public function getStats()
214
    {
215
        $serverStatus = $this->getCollection()->db->command([
216
          'serverStatus' => 1,
217
          'recordStats' => 0,
218
          'repl' => 0,
219
          'metrics' => 0,
220
        ]);
221
222
        $collStats = $this->getCollection()->db->command([
223
          'collStats' => 'Cache',
224
          'verbose' => true,
225
        ]);
226
227
        $stats = (new driverStatistic())
228
          ->setInfo('MongoDB version ' . $serverStatus[ 'version' ] . ', Uptime (in days): ' . round($serverStatus[ 'uptime' ] / 86400, 1) . "\n For more information see RawData.")
229
          ->setSize((int) @$collStats[ 'size' ])
230
          ->setData(implode(', ', array_keys($this->itemInstances)))
231
          ->setRawData([
232
            'serverStatus' => $serverStatus,
233
            'collStats' => $collStats,
234
          ]);
235
236
        return $stats;
237
    }
238
}