Completed
Push — V6 ( ff865a...1287ab )
by Georges
02:38
created

Driver::driverCheck()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
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\Couchdb;
16
17
use Doctrine\CouchDB\CouchDBClient as CouchdbClient;
18
use Doctrine\CouchDB\CouchDBException;
19
use phpFastCache\Core\Pool\DriverBaseTrait;
20
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
21
use phpFastCache\Entities\DriverStatistic;
22
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
23
use phpFastCache\Exceptions\phpFastCacheDriverException;
24
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
25
use phpFastCache\Exceptions\phpFastCacheLogicException;
26
use Psr\Cache\CacheItemInterface;
27
28
/**
29
 * Class Driver
30
 * @package phpFastCache\Drivers
31
 * @property CouchdbClient $instance Instance of driver service
32
 */
33
class Driver implements ExtendedCacheItemPoolInterface
34
{
35
    use DriverBaseTrait;
36
37
    /**
38
     * Driver constructor.
39
     * @param array $config
40
     * @throws phpFastCacheDriverException
41
     */
42 View Code Duplication
    public function __construct(array $config = [])
43
    {
44
        $this->setup($config);
45
46
        if (!$this->driverCheck()) {
47
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
48
        } else {
49
            $this->driverConnect();
50
        }
51
    }
52
53
    /**
54
     * @return bool
55
     */
56
    public function driverCheck()
57
    {
58
        return class_exists('Doctrine\CouchDB\CouchDBClient');
59
    }
60
61
    /**
62
     * @param \Psr\Cache\CacheItemInterface $item
63
     * @return mixed
64
     * @throws phpFastCacheDriverException
65
     * @throws phpFastCacheInvalidArgumentException
66
     */
67
    protected function driverWrite(CacheItemInterface $item)
68
    {
69
        /**
70
         * Check for Cross-Driver type confusion
71
         */
72
        if ($item instanceof Item) {
73
            try{
74
                $this->instance->putDocument(['data' => $this->encode($this->driverPreWrap($item))], $item->getEncodedKey(), $this->getLatestDocumentRevision($item->getEncodedKey()));
75
            }catch (CouchDBException $e){
1 ignored issue
show
Bug introduced by
The class Doctrine\CouchDB\CouchDBException 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...
76
                throw new phpFastCacheDriverException('Got error while trying to upsert a document: ' . $e->getMessage(), null, $e);
77
            }
78
            return true;
79
        } else {
80
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
81
        }
82
    }
83
84
    /**
85
     * @param \Psr\Cache\CacheItemInterface $item
86
     * @return mixed
87
     * @throws phpFastCacheDriverException
88
     */
89
    protected function driverRead(CacheItemInterface $item)
90
    {
91
        try{
92
            $response = $this->instance->findDocument($item->getEncodedKey());
93
        }catch (CouchDBException $e){
1 ignored issue
show
Bug introduced by
The class Doctrine\CouchDB\CouchDBException 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...
94
            throw new phpFastCacheDriverException('Got error while trying to get a document: ' . $e->getMessage(), null, $e);
95
        }
96
97
        if($response->status === 404 || empty($response->body['data'])){
98
            return null;
99
        }else if($response->status === 200){
100
            return $this->decode($response->body['data']);
101
        }else{
102
            throw new phpFastCacheDriverException('Got unexpected HTTP status: ' . $response->status);
103
        }
104
    }
105
106
    /**
107
     * @param \Psr\Cache\CacheItemInterface $item
108
     * @return bool
109
     * @throws phpFastCacheDriverException
110
     * @throws phpFastCacheInvalidArgumentException
111
     */
112
    protected function driverDelete(CacheItemInterface $item)
113
    {
114
        /**
115
         * Check for Cross-Driver type confusion
116
         */
117
        if ($item instanceof Item) {
118
            try{
119
                $this->instance->deleteDocument($item->getEncodedKey(), $this->getLatestDocumentRevision($item->getEncodedKey()));
120
            }catch (CouchDBException $e){
1 ignored issue
show
Bug introduced by
The class Doctrine\CouchDB\CouchDBException 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...
121
                throw new phpFastCacheDriverException('Got error while trying to delete a document: ' . $e->getMessage(), null, $e);
122
            }
123
            return true;
124
        } else {
125
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
126
        }
127
    }
128
129
    /**
130
     * @return bool
131
     * @throws phpFastCacheDriverException
132
     */
133
    protected function driverClear()
134
    {
135
        try{
136
            $this->instance->deleteDatabase($this->getDatabaseName());
137
            $this->createDatabase();
138
        }catch (CouchDBException $e){
1 ignored issue
show
Bug introduced by
The class Doctrine\CouchDB\CouchDBException 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...
139
            throw new phpFastCacheDriverException('Got error while trying to delete and recreate the database: ' . $e->getMessage(), null, $e);
140
        }
141
142
143
        return true;
144
    }
145
146
    /**
147
     * @return bool
148
     * @throws phpFastCacheLogicException
149
     */
150
    protected function driverConnect()
151
    {
152
        if ($this->instance instanceof CouchdbClient) {
1 ignored issue
show
Bug introduced by
The class Doctrine\CouchDB\CouchDBClient 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...
153
            throw new phpFastCacheLogicException('Already connected to Couchdb server');
154
        } else {
155
            $host = isset($this->config[ 'host' ]) ? $this->config[ 'host' ] : '127.0.0.1';
156
            $ssl = isset($this->config[ 'ssl' ]) ? $this->config[ 'ssl' ] : false;
157
            $port = isset($this->config[ 'port' ]) ? $this->config[ 'port' ] : 5984;
158
            $path = isset($this->config[ 'path' ]) ? $this->config[ 'path' ] : '/';
159
            $username = isset($this->config[ 'username' ]) ? $this->config[ 'username' ] : '';
160
            $password = isset($this->config[ 'password' ]) ? $this->config[ 'password' ] : '';
161
            $timeout = isset($this->config[ 'timeout' ]) ? $this->config[ 'timeout' ] : 10;
162
163
            $url = ($ssl ? 'https://' : 'http://');
164
            if($username)
165
            {
166
                $url .= "{$username}";
167
                if($password)
168
                {
169
                    $url .= ":{$password}";
170
                }
171
                $url .= '@';
172
            }
173
            $url .= $host;
174
            $url .= ":{$port}";
175
            $url .= $path;
176
177
            $this->instance = CouchDBClient::create([
178
              'dbname' => $this->getDatabaseName(),
179
              'url' => $url,
180
              'timeout' => $timeout
181
            ]);
182
183
            $this->createDatabase();
184
        }
185
186
        return true;
187
    }
188
189
    /**
190
     * @return string|null
191
     */
192
    protected function getLatestDocumentRevision($docId)
193
    {
194
        $path = '/' . $this->getDatabaseName() . '/' . urlencode($docId);
195
196
        $response = $this->instance->getHttpClient()->request(
197
          'GET',// At this moment HEAD requests are not working: https://github.com/doctrine/couchdb-client/issues/72
198
          $path,
199
          null,
200
          false
201
        );
202
        if(!empty($response->headers['etag'])){
203
            return trim($response->headers['etag'], " '\"\t\n\r\0\x0B");
204
        }else{
205
            return null;
206
        }
207
    }
208
209
    /**
210
     * @return string
211
     */
212
    protected function getDatabaseName()
213
    {
214
        return isset($this->config[ 'database' ]) ? $this->config[ 'database' ] : 'phpfastcache';
215
    }
216
217
    /**
218
     * @return void
219
     */
220
    protected function createDatabase()
221
    {
222
        if(!in_array($this->instance->getDatabase(), $this->instance->getAllDatabases(), true)){
223
            $this->instance->createDatabase($this->instance->getDatabase());
224
        }
225
    }
226
227
    /********************
228
     *
229
     * PSR-6 Extended Methods
230
     *
231
     *******************/
232
233
    /**
234
     * @return string
235
     */
236
    public function getHelp()
237
    {
238
        return <<<HELP
239
<p>
240
To install the Couchdb HTTP client library via Composer:
241
<code>composer require "doctrine/couchdb" "@dev"</code>
242
</p>
243
HELP;
244
    }
245
246
    /**
247
     * @return DriverStatistic
248
     */
249
    public function getStats()
250
    {
251
        $info = $this->instance->getDatabaseInfo();
252
253
        return (new DriverStatistic())
254
          ->setSize($info['sizes']['active'])
255
          ->setRawData($info)
256
          ->setData(implode(', ', array_keys($this->itemInstances)))
257
          ->setInfo('Couchdb version ' . $this->instance->getVersion() . "\n For more information see RawData.");
258
    }
259
}