Passed
Push — master ( 0deb8f...f54565 )
by Goffy
04:13
created

CachedClient::request()   B

Complexity

Conditions 10
Paths 42

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 24
nc 42
nop 1
dl 0
loc 46
rs 7.6666
c 0
b 0
f 0

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
namespace XoopsModules\Wggithub\Github\Http;
4
5
use XoopsModules\Wggithub\Github;
6
use XoopsModules\Wggithub\Github\Storages;
7
8
9
/**
10
 * Caching for HTTP clients.
11
 *
12
 * @author  Miloslav Hůla (https://github.com/milo)
13
 */
14
class CachedClient extends Github\Sanity implements IClient
15
{
16
	/** @var Storages\ICache|NULL */
17
	private $cache;
18
19
	/** @var IClient */
20
	private $client;
21
22
	/** @var bool */
23
	private $forbidRecheck;
24
25
	/** @var callable|NULL */
26
	private $onResponse;
27
28
29
	/**
30
	 * @param Storages\ICache
31
	 * @param IClient
32
	 * @param bool  forbid checking Github for new data; more or less development purpose only
0 ignored issues
show
Bug introduced by
The type XoopsModules\Wggithub\Github\Http\forbid was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
	 */
34
	public function __construct(Storages\ICache $cache, IClient $client = NULL, $forbidRecheck = FALSE)
35
	{
36
		$this->cache = $cache;
37
		$this->client = $client ?: Github\Helpers::createDefaultClient();
38
		$this->forbidRecheck = (bool) $forbidRecheck;
39
	}
40
41
42
	/**
43
	 * @return IClient
44
	 */
45
	public function getInnerClient()
46
	{
47
		return $this->client;
48
	}
49
50
51
	/**
52
	 * @return Response
53
	 *
54
	 * @throws BadResponseException
55
	 */
56
	public function request(Request $request)
57
	{
58
		$request = clone $request;
59
60
		$cacheKey = implode('.', [
61
			$request->getMethod(),
62
			$request->getUrl(),
63
64
			/** @todo This should depend on Vary: header */
65
			$request->getHeader('Accept'),
66
			$request->getHeader('Accept-Encoding'),
67
			$request->getHeader('Authorization')
68
		]);
69
70
		if ($cached = $this->cache->load($cacheKey)) {
0 ignored issues
show
Bug introduced by
The method load() does not exist on null. ( Ignorable by Annotation )

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

70
		if ($cached = $this->cache->/** @scrutinizer ignore-call */ load($cacheKey)) {

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...
71
			if ($this->forbidRecheck) {
72
				$cached = clone $cached;
73
				$this->onResponse && call_user_func($this->onResponse, $cached);
74
				return $cached;
75
			}
76
77
			/** @var $cached Response */
78
			if ($cached->hasHeader('Last-Modified')) {
79
				$request->addHeader('If-Modified-Since', $cached->getHeader('Last-Modified'));
80
			}
81
			if ($cached->hasHeader('ETag')) {
82
				$request->addHeader('If-None-Match', $cached->getHeader('ETag'));
83
			}
84
		}
85
86
		$response = $this->client->request($request);
87
88
		if ($this->isCacheable($response)) {
89
			$this->cache->save($cacheKey, clone $response);
90
		}
91
92
		if (isset($cached) && $response->getCode() === Response::S304_NOT_MODIFIED) {
93
			$cached = clone $cached;
94
95
			/** @todo Should be responses somehow combined into one? */
96
			$response = $cached->setPrevious($response);
97
		}
98
99
		$this->onResponse && call_user_func($this->onResponse, $response);
100
101
		return $response;
102
	}
103
104
105
	/**
106
	 * @param  callable|NULL function(Request $request)
0 ignored issues
show
Bug introduced by
The type XoopsModules\Wggithub\Github\Http\function was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
107
	 * @return self
108
	 */
109
	public function onRequest($callback)
110
	{
111
		$this->client->onRequest($callback);
112
		return $this;
113
	}
114
115
116
	/**
117
	 * @param  callable|NULL function(Response $response)
118
	 * @return self
119
	 */
120
	public function onResponse($callback)
121
	{
122
		$this->client->onResponse(NULL);
123
		$this->onResponse = $callback;
124
		return $this;
125
	}
126
127
128
	/**
129
	 * @return bool
130
	 */
131
	protected function isCacheable(Response $response)
132
	{
133
		/** @todo Do it properly. Vary:, Pragma:, TTL...  */
134
		if (!$response->isCode(200)) {
135
			return FALSE;
136
		} elseif (preg_match('#max-age=0|must-revalidate#i', $response->getHeader('Cache-Control', ''))) {
137
			return FALSE;
138
		}
139
140
		return $response->hasHeader('ETag') || $response->hasHeader('Last-Modified');
141
	}
142
143
}
144