Passed
Push — v9 ( 467cbb...1836cb )
by Georges
03:07 queued 24s
created

Driver::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 *
5
 * This file is part of Phpfastcache.
6
 *
7
 * @license MIT License (MIT)
8
 *
9
 * For full copyright and license information, please see the docs/CREDITS.txt and LICENCE files.
10
 *
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 * @author Contributors  https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phpfastcache\Drivers\Couchbasev3;
18
19
use Couchbase\BaseException as CouchbaseException;
20
use Couchbase\Bucket as CouchbaseBucket;
21
use Couchbase\Cluster;
22
use Couchbase\ClusterOptions;
23
use Couchbase\Collection;
24
use Couchbase\DocumentNotFoundException;
25
use Couchbase\Scope;
26
use Couchbase\UpsertOptions;
27
use DateTimeInterface;
28
use Phpfastcache\Cluster\AggregatablePoolInterface;
29
use Phpfastcache\Config\ConfigurationOption;
30
use Phpfastcache\Core\Item\ExtendedCacheItemInterface;
31
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
32
use Phpfastcache\Core\Pool\TaggableCacheItemPoolTrait;
33
use Phpfastcache\Entities\DriverStatistic;
34
use Phpfastcache\Event\EventManagerInterface;
35
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
36
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
37
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
38
39
/**
40
 * @property Cluster $instance Instance of driver service
41
 * @method Config getConfig()
42
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
43
 */
44
class Driver implements ExtendedCacheItemPoolInterface, AggregatablePoolInterface
45
{
46
    use TaggableCacheItemPoolTrait {
47
        __construct as __baseConstruct;
48
    }
49
50
    protected Scope $scope;
51
52
    protected Collection $collection;
53
54
    protected CouchbaseBucket $bucketInstance;
55
56
    public function __construct(ConfigurationOption $config, $instanceId, EventManagerInterface $em)
57
    {
58
        $this->__baseConstruct($config, $instanceId, $em);
59
    }
60
61
    /**
62
     * @return bool
63
     */
64
    public function driverCheck(): bool
65
    {
66
        return extension_loaded('couchbase');
67
    }
68
69
    /**
70
     * @return bool
71
     * @throws PhpfastcacheDriverCheckException
72
     */
73
    protected function driverConnect(): bool
74
    {
75
        if (!\class_exists(ClusterOptions::class)) {
76
            throw new PhpfastcacheDriverCheckException('You are using the Couchbase PHP SDK 2.x which is no longer supported in Phpfastcache v9');
77
        }
78
79
        $connectionString = "couchbase://{$this->getConfig()->getHost()}:{$this->getConfig()->getPort()}";
80
81
        $options = new ClusterOptions();
82
        $options->credentials($this->getConfig()->getUsername(), $this->getConfig()->getPassword());
83
        $this->instance = new Cluster($connectionString, $options);
0 ignored issues
show
Unused Code introduced by
The call to Couchbase\Cluster::__construct() has too many arguments starting with $options. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
        $this->instance = /** @scrutinizer ignore-call */ new Cluster($connectionString, $options);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
84
85
        $this->setBucket($this->instance->bucket($this->getConfig()->getBucketName()));
0 ignored issues
show
Bug introduced by
The method bucket() does not exist on Couchbase\Cluster. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

85
        $this->setBucket($this->instance->/** @scrutinizer ignore-call */ bucket($this->getConfig()->getBucketName()));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
86
        $this->setScope($this->getBucket()->scope($this->getConfig()->getScopeName()));
0 ignored issues
show
Bug introduced by
The method scope() does not exist on Couchbase\Bucket. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
        $this->setScope($this->getBucket()->/** @scrutinizer ignore-call */ scope($this->getConfig()->getScopeName()));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
87
        $this->setCollection($this->getScope()->collection($this->getConfig()->getCollectionName()));
88
89
        return true;
90
    }
91
92
    /**
93
     * @param ExtendedCacheItemInterface $item
94
     * @return null|array
95
     */
96
    protected function driverRead(ExtendedCacheItemInterface $item): ?array
97
    {
98
        try {
99
            /**
100
             * CouchbaseBucket::get() returns a GetResult interface
101
             */
102
            return $this->decodeDocument((array)$this->getCollection()->get($item->getEncodedKey())->content());
103
        } catch (DocumentNotFoundException) {
104
            return null;
105
        }
106
    }
107
108
    /**
109
     * @param ExtendedCacheItemInterface $item
110
     * @return bool
111
     * @throws PhpfastcacheInvalidArgumentException
112
     * @throws PhpfastcacheLogicException
113
     */
114
    protected function driverWrite(ExtendedCacheItemInterface $item): bool
115
    {
116
        $this->assertCacheItemType($item, Item::class);
117
118
        try {
119
            $this->getCollection()->upsert(
120
                $item->getEncodedKey(),
121
                $this->encodeDocument($this->driverPreWrap($item)),
122
                (new UpsertOptions())->expiry($item->getTtl())
123
            );
124
            return true;
125
        } catch (CouchbaseException) {
126
            return false;
127
        }
128
    }
129
130
    /**
131
     * @param ExtendedCacheItemInterface $item
132
     * @return bool
133
     * @throws PhpfastcacheInvalidArgumentException
134
     */
135
    protected function driverDelete(ExtendedCacheItemInterface $item): bool
136
    {
137
        $this->assertCacheItemType($item, Item::class);
138
139
        try {
140
            $this->getCollection()->remove($item->getEncodedKey());
141
            return true;
142
        } catch (DocumentNotFoundException) {
143
            return true;
144
        } catch (CouchbaseException) {
145
            return false;
146
        }
147
    }
148
149
    /**
150
     * @return bool
151
     */
152
    protected function driverClear(): bool
153
    {
154
        $this->instance->buckets()->flush($this->getConfig()->getBucketName());
0 ignored issues
show
Bug introduced by
The method buckets() does not exist on Couchbase\Cluster. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

154
        $this->instance->/** @scrutinizer ignore-call */ 
155
                         buckets()->flush($this->getConfig()->getBucketName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
155
        return true;
156
    }
157
158
    /**
159
     * @return DriverStatistic
160
     * @throws \Exception
161
     */
162
    public function getStats(): DriverStatistic
163
    {
164
        /**
165
         * Between SDK 2 and 3 we lost a lot of useful information :(
166
         * @see https://docs.couchbase.com/java-sdk/current/project-docs/migrating-sdk-code-to-3.n.html#management-apis
167
         */
168
        $info = $this->getBucket()->diagnostics(\bin2hex(\random_bytes(16)));
0 ignored issues
show
Bug introduced by
The method diagnostics() does not exist on Couchbase\Bucket. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

168
        $info = $this->getBucket()->/** @scrutinizer ignore-call */ diagnostics(\bin2hex(\random_bytes(16)));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
169
170
        return (new DriverStatistic())
171
            ->setSize(0)
172
            ->setRawData($info)
173
            ->setData(implode(', ', array_keys($this->itemInstances)))
174
            ->setInfo($info['sdk'] . "\n For more information see RawData.");
175
    }
176
177
    /**
178
     * @return Collection
179
     */
180
    public function getCollection(): Collection
181
    {
182
        return $this->collection;
183
    }
184
185
    /**
186
     * @param Collection $collection
187
     * @return Driver
188
     */
189
    public function setCollection(Collection $collection): Driver
190
    {
191
        $this->collection = $collection;
192
        return $this;
193
    }
194
195
    /**
196
     * @return Scope
197
     */
198
    public function getScope(): Scope
199
    {
200
        return $this->scope;
201
    }
202
203
    /**
204
     * @param Scope $scope
205
     * @return Driver
206
     */
207
    public function setScope(Scope $scope): Driver
208
    {
209
        $this->scope = $scope;
210
        return $this;
211
    }
212
213
    /**
214
     * @return CouchbaseBucket
215
     */
216
    protected function getBucket(): CouchbaseBucket
217
    {
218
        return $this->bucketInstance;
219
    }
220
221
    /**
222
     * @param CouchbaseBucket $couchbaseBucket
223
     */
224
    protected function setBucket(CouchbaseBucket $couchbaseBucket): void
225
    {
226
        $this->bucketInstance = $couchbaseBucket;
227
    }
228
229
230
    /**
231
     * @param array $data
232
     * @return array
233
     */
234
    protected function encodeDocument(array $data): array
235
    {
236
        $data[ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX] = $this->encode($data[ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX]);
237
        $data[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX] = $data[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX]
238
            ->format(DateTimeInterface::ATOM);
239
240
        if ($this->getConfig()->isItemDetailedDate()) {
241
            $data[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX] = $data[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX]
242
                ->format(\DateTimeInterface::ATOM);
243
244
            $data[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX] = $data[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX]
245
                ->format(\DateTimeInterface::ATOM);
246
        }
247
248
        return $data;
249
    }
250
251
    /**
252
     * @param array $data
253
     * @return array
254
     */
255
    protected function decodeDocument(array $data): array
256
    {
257
        $data[ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX] = $this->decode($data[ExtendedCacheItemPoolInterface::DRIVER_DATA_WRAPPER_INDEX]);
258
        $data[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX] = \DateTime::createFromFormat(
259
            \DateTimeInterface::ATOM,
260
            $data[ExtendedCacheItemPoolInterface::DRIVER_EDATE_WRAPPER_INDEX]
261
        );
262
263
        if ($this->getConfig()->isItemDetailedDate()) {
264
            $data[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX] = \DateTime::createFromFormat(
265
                \DateTimeInterface::ATOM,
266
                $data[ExtendedCacheItemPoolInterface::DRIVER_CDATE_WRAPPER_INDEX]
267
            );
268
269
            $data[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX] = \DateTime::createFromFormat(
270
                \DateTimeInterface::ATOM,
271
                $data[ExtendedCacheItemPoolInterface::DRIVER_MDATE_WRAPPER_INDEX]
272
            );
273
        }
274
275
        return $data;
276
    }
277
}
278