Completed
Pull Request — master (#10)
by Edgard
15:15
created

Connection::getQueryCacheInfo()   D

Complexity

Conditions 10
Paths 26

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 17
nc 26
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * ActiveRecord for API.
4
 *
5
 * @see      https://github.com/hiqdev/yii2-hiart
6
 * @package   yii2-hiart
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2017, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\hiart;
12
13
use hiqdev\hiart\librariesio\ConnectionInterface;
14
use Throwable;
15
use Yii;
16
use yii\caching\Cache;
17
use yii\caching\Dependency;
18
use yii\httpclient\Client;
19
use yii\httpclient\Request;
20
21
/**
22
 * Abstract connection class.
23
 */
24
class Connection extends Client
25
{
26
    /**
27
     * @var string to be specified in concrete implementation
28
     */
29
    public $queryBuilderClass = QueryBuilder::class;
30
    public $commandClass = Command::class;
31
    public $queryClass = Query::class;
32
    public $activeQueryClass = ActiveQuery::class;
33
    public static $dbname = 'hiart';
34
    public $requestConfig = [
35
        'headers' => [
36
            'User-Agent' => 'HiArt/0.x',
37
        ],
38
    ];
39
40
    /**
41
     * @var bool whether to enable query caching.
42
     * Note that in order to enable query caching, a valid cache component as specified
43
     * by [[queryCache]] must be enabled and [[enableQueryCache]] must be set true.
44
     * Also, only the results of the queries enclosed within [[cache()]] will be cached.
45
     * @see queryCache
46
     * @see cache()
47
     * @see noCache()
48
     */
49
    public $enableQueryCache = true;
50
51
    /**
52
     * @var int the default number of seconds that query results can remain valid in cache.
53
     * Defaults to 3600, meaning 3600 seconds, or one hour. Use 0 to indicate that the cached data will never expire.
54
     * The value of this property will be used when [[cache()]] is called without a cache duration.
55
     * @see enableQueryCache
56
     * @see cache()
57
     */
58
    public $queryCacheDuration = 3600;
59
60
    /**
61
     * @var Cache|string the cache object or the ID of the cache application component
62
     * that is used for query caching
63
     * @see enableQueryCache
64
     */
65
    public $queryCache = 'cache';
66
67
    /**
68
     * @var AbstractQueryBuilder the query builder for this connection
69
     */
70
    protected $_builder;
71
72
    /**
73
     * @var array query cache parameters for the [[cache()]] calls
74
     */
75
    private $_queryCacheInfo = [];
76
77
    /**
78
     * @param null $name
79
     * @return ConnectionInterface|AbstractConnection
80
     */
81
    public static function getDb($name = null, $class = self::class)
82
    {
83
        if ($name) {
84
            return Yii::$app->get($name);
85
        }
86
        if (Yii::$container->hasSingleton($class)) {
87
            return Yii::$container->get($class);
88
        }
89
90
        return Yii::$app->get(static::$dbname);
91
    }
92
93
    /**
94
     * Creates a command for execution.
95
     * @param Request $request the configuration for the Command class
96
     * @return Command the DB command
97
     */
98
    public function createCommand($request)
99
    {
100
        return new $this->commandClass([
101
            'db'      => $this,
102
            'request' => $request,
103
        ]);
104
    }
105
106
    /**
107
     * @return AbstractQueryBuilder the query builder for this connection
108
     */
109
    public function getQueryBuilder()
110
    {
111
        if ($this->_builder === null) {
112
            $this->_builder = new $this->queryBuilderClass($this);
113
        }
114
115
        return $this->_builder;
116
    }
117
118
    /**
119
     * Uses query cache for the queries performed with the callable.
120
     * When query caching is enabled ([[enableQueryCache]] is true and [[queryCache]] refers to a valid cache),
121
     * queries performed within the callable will be cached and their results will be fetched from cache if available.
122
     * For example,.
123
     *
124
     * ```php
125
     * // The customer will be fetched from cache if available.
126
     * // If not, the query will be made against DB and cached for use next time.
127
     * $customer = $db->cache(function (Connection $db) {
128
     *     return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();
129
     * });
130
     * ```
131
     *
132
     * Note that query cache is only meaningful for queries that return results. For queries performed with
133
     * [[Command::execute()]], query cache will not be used.
134
     *
135
     * @param callable $callable a PHP callable that contains DB queries which will make use of query cache.
136
     * The signature of the callable is `function (Connection $db)`.
137
     * @param int $duration the number of seconds that query results can remain valid in the cache. If this is
138
     * not set, the value of [[queryCacheDuration]] will be used instead.
139
     * Use 0 to indicate that the cached data will never expire.
140
     * @param Dependency $dependency the cache dependency associated with the cached query results
141
     * @throws \Exception|\Throwable if there is any exception during query
142
     * @return mixed the return result of the callable
143
     * @see enableQueryCache
144
     * @see queryCache
145
     * @see noCache()
146
     */
147
    public function cache(callable $callable, $duration = null, $dependency = null)
148
    {
149
        $this->_queryCacheInfo[] = [$duration === null ? $this->queryCacheDuration : $duration, $dependency];
150
        try {
151
            $result = call_user_func($callable, $this);
152
            array_pop($this->_queryCacheInfo);
153
            return $result;
154
        } catch (\Exception $e) {
155
            array_pop($this->_queryCacheInfo);
156
            throw $e;
157
        } catch (Throwable $e) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
158
            array_pop($this->_queryCacheInfo);
159
            throw $e;
160
        }
161
    }
162
163
    /**
164
     * Disables query cache temporarily.
165
     * Queries performed within the callable will not use query cache at all. For example,.
166
     *
167
     * ```php
168
     * $db->cache(function (Connection $db) {
169
     *
170
     *     // ... queries that use query cache ...
171
     *
172
     *     return $db->noCache(function (Connection $db) {
173
     *         // this query will not use query cache
174
     *         return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();
175
     *     });
176
     * });
177
     * ```
178
     *
179
     * @param callable $callable a PHP callable that contains DB queries which should not use query cache.
180
     * The signature of the callable is `function (Connection $db)`.
181
     * @throws \Exception|\Throwable if there is any exception during query
182
     * @return mixed the return result of the callable
183
     * @see enableQueryCache
184
     * @see queryCache
185
     * @see cache()
186
     */
187
    public function noCache(callable $callable)
188
    {
189
        $this->_queryCacheInfo[] = false;
190
        try {
191
            $result = call_user_func($callable, $this);
192
            array_pop($this->_queryCacheInfo);
193
            return $result;
194
        } catch (\Exception $e) {
195
            array_pop($this->_queryCacheInfo);
196
            throw $e;
197
        } catch (Throwable $e) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
198
            array_pop($this->_queryCacheInfo);
199
            throw $e;
200
        }
201
    }
202
203
    /**
204
     * Returns the current query cache information.
205
     * This method is used internally by [[Command]].
206
     * @param int $duration the preferred caching duration. If null, it will be ignored.
207
     * @param Dependency $dependency the preferred caching dependency. If null, it will be ignored.
208
     * @return array the current query cache information, or null if query cache is not enabled
209
     * @internal
210
     */
211
    public function getQueryCacheInfo($duration, $dependency)
212
    {
213
        if (!$this->enableQueryCache) {
214
            return null;
215
        }
216
217
        $info = end($this->_queryCacheInfo);
218
        if (is_array($info)) {
219
            if ($duration === null) {
220
                $duration = $info[0];
221
            }
222
            if ($dependency === null) {
223
                $dependency = $info[1];
224
            }
225
        }
226
227
        if ($duration === 0 || $duration > 0) {
228
            if (is_string($this->queryCache) && Yii::$app) {
229
                $cache = Yii::$app->get($this->queryCache, false);
230
            } else {
231
                $cache = $this->queryCache;
232
            }
233
            if ($cache instanceof Cache) {
234
                return [$cache, $duration, $dependency];
235
            }
236
        }
237
238
        return null;
239
    }
240
}
241