Skip to content

Commit 995a63f

Browse files
authored
Merge pull request #74 from php-http/phpstan
add phpstan to ci build
2 parents 922409f + 3f0266a commit 995a63f

File tree

6 files changed

+88
-71
lines changed

6 files changed

+88
-71
lines changed

Diff for: .github/workflows/.editorconfig

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*.yml]
2+
indent_size = 2

Diff for: .github/workflows/static.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Static analysis
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
9+
jobs:
10+
phpstan:
11+
name: PHPStan
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v2
17+
18+
- name: PHPStan
19+
uses: docker://oskarstark/phpstan-ga
20+
with:
21+
args: analyze --no-progress

Diff for: .github/workflows/tests.yml

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ name: tests
22

33
on:
44
push:
5+
branches:
6+
- master
57
pull_request:
68

79
jobs:

Diff for: phpstan.neon.dist

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 8
3+
paths:
4+
- src
5+
treatPhpDocTypesAsCertain: false

Diff for: src/Cache/Generator/HeaderCacheKeyGenerator.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ class HeaderCacheKeyGenerator implements CacheKeyGenerator
1414
/**
1515
* The header names we should take into account when creating the cache key.
1616
*
17-
* @var array
17+
* @var string[]
1818
*/
1919
private $headerNames;
2020

2121
/**
22-
* @param $headerNames
22+
* @param string[] $headerNames
2323
*/
2424
public function __construct(array $headerNames)
2525
{

Diff for: src/CachePlugin.php

+56-69
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Http\Client\Common\Plugin\Cache\Listener\CacheListener;
1010
use Http\Message\StreamFactory;
1111
use Http\Promise\FulfilledPromise;
12+
use Http\Promise\Promise;
1213
use Psr\Cache\CacheItemInterface;
1314
use Psr\Cache\CacheItemPoolInterface;
1415
use Psr\Http\Message\RequestInterface;
@@ -39,20 +40,20 @@ final class CachePlugin implements Plugin
3940
private $streamFactory;
4041

4142
/**
42-
* @var array
43+
* @var mixed[]
4344
*/
4445
private $config;
4546

4647
/**
4748
* Cache directives indicating if a response can not be cached.
4849
*
49-
* @var array
50+
* @var string[]
5051
*/
5152
private $noCacheFlags = ['no-cache', 'private', 'no-store'];
5253

5354
/**
5455
* @param StreamFactory|StreamFactoryInterface $streamFactory
55-
* @param array $config {
56+
* @param mixed[] $config {
5657
*
5758
* @var bool $respect_cache_headers Whether to look at the cache directives or ignore them
5859
* @var int $default_ttl (seconds) If we do not respect cache headers or can't calculate a good ttl, use this
@@ -61,9 +62,9 @@ final class CachePlugin implements Plugin
6162
* @var int $cache_lifetime (seconds) To support serving a previous stale response when the server answers 304
6263
* we have to store the cache for a longer time than the server originally says it is valid for.
6364
* We store a cache item for $cache_lifetime + max age of the response.
64-
* @var array $methods list of request methods which can be cached
65-
* @var array $blacklisted_paths list of regex for URLs explicitly not to be cached
66-
* @var array $respect_response_cache_directives list of cache directives this plugin will respect while caching responses
65+
* @var string[] $methods list of request methods which can be cached
66+
* @var string[] $blacklisted_paths list of regex for URLs explicitly not to be cached
67+
* @var string[] $respect_response_cache_directives list of cache directives this plugin will respect while caching responses
6768
* @var CacheKeyGenerator $cache_key_generator an object to generate the cache key. Defaults to a new instance of SimpleGenerator
6869
* @var CacheListener[] $cache_listeners an array of objects to act on the response based on the results of the cache check.
6970
* Defaults to an empty array
@@ -78,7 +79,7 @@ public function __construct(CacheItemPoolInterface $pool, $streamFactory, array
7879
$this->pool = $pool;
7980
$this->streamFactory = $streamFactory;
8081

81-
if (isset($config['respect_cache_headers']) && isset($config['respect_response_cache_directives'])) {
82+
if (\array_key_exists('respect_cache_headers', $config) && \array_key_exists('respect_response_cache_directives', $config)) {
8283
throw new \InvalidArgumentException('You can\'t provide config option "respect_cache_headers" and "respect_response_cache_directives". Use "respect_response_cache_directives" instead.');
8384
}
8485

@@ -96,14 +97,14 @@ public function __construct(CacheItemPoolInterface $pool, $streamFactory, array
9697
* cache responses with `private` cache directive.
9798
*
9899
* @param StreamFactory|StreamFactoryInterface $streamFactory
99-
* @param array $config For all possible config options see the constructor docs
100+
* @param mixed[] $config For all possible config options see the constructor docs
100101
*
101102
* @return CachePlugin
102103
*/
103104
public static function clientCache(CacheItemPoolInterface $pool, $streamFactory, array $config = [])
104105
{
105106
// Allow caching of private requests
106-
if (isset($config['respect_response_cache_directives'])) {
107+
if (\array_key_exists('respect_response_cache_directives', $config)) {
107108
$config['respect_response_cache_directives'][] = 'no-cache';
108109
$config['respect_response_cache_directives'][] = 'max-age';
109110
$config['respect_response_cache_directives'] = array_unique($config['respect_response_cache_directives']);
@@ -119,7 +120,7 @@ public static function clientCache(CacheItemPoolInterface $pool, $streamFactory,
119120
* cache responses with the `private`or `no-cache` directives.
120121
*
121122
* @param StreamFactory|StreamFactoryInterface $streamFactory
122-
* @param array $config For all possible config options see the constructor docs
123+
* @param mixed[] $config For all possible config options see the constructor docs
123124
*
124125
* @return CachePlugin
125126
*/
@@ -128,6 +129,11 @@ public static function serverCache(CacheItemPoolInterface $pool, $streamFactory,
128129
return new self($pool, $streamFactory, $config);
129130
}
130131

132+
/**
133+
* {@inheritdoc}
134+
*
135+
* @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient)
136+
*/
131137
protected function doHandleRequest(RequestInterface $request, callable $next, callable $first)
132138
{
133139
$method = strtoupper($request->getMethod());
@@ -146,22 +152,24 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
146152

147153
if ($cacheItem->isHit()) {
148154
$data = $cacheItem->get();
149-
// The array_key_exists() is to be removed in 2.0.
150-
if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) {
151-
// This item is still valid according to previous cache headers
152-
$response = $this->createResponseFromCacheItem($cacheItem);
153-
$response = $this->handleCacheListeners($request, $response, true, $cacheItem);
154-
155-
return new FulfilledPromise($response);
156-
}
155+
if (is_array($data)) {
156+
// The array_key_exists() is to be removed in 2.0.
157+
if (array_key_exists('expiresAt', $data) && (null === $data['expiresAt'] || time() < $data['expiresAt'])) {
158+
// This item is still valid according to previous cache headers
159+
$response = $this->createResponseFromCacheItem($cacheItem);
160+
$response = $this->handleCacheListeners($request, $response, true, $cacheItem);
161+
162+
return new FulfilledPromise($response);
163+
}
157164

158-
// Add headers to ask the server if this cache is still valid
159-
if ($modifiedSinceValue = $this->getModifiedSinceHeaderValue($cacheItem)) {
160-
$request = $request->withHeader('If-Modified-Since', $modifiedSinceValue);
161-
}
165+
// Add headers to ask the server if this cache is still valid
166+
if ($modifiedSinceValue = $this->getModifiedSinceHeaderValue($cacheItem)) {
167+
$request = $request->withHeader('If-Modified-Since', $modifiedSinceValue);
168+
}
162169

163-
if ($etag = $this->getETag($cacheItem)) {
164-
$request = $request->withHeader('If-None-Match', $etag);
170+
if ($etag = $this->getETag($cacheItem)) {
171+
$request = $request->withHeader('If-None-Match', $etag);
172+
}
165173
}
166174
}
167175

@@ -207,22 +215,20 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
207215
$this->pool->save($cacheItem);
208216
}
209217

210-
return $this->handleCacheListeners($request, $response, false, isset($cacheItem) ? $cacheItem : null);
218+
return $this->handleCacheListeners($request, $response, false, $cacheItem);
211219
});
212220
}
213221

214222
/**
215223
* Calculate the timestamp when this cache item should be dropped from the cache. The lowest value that can be
216224
* returned is $maxAge.
217225
*
218-
* @param int|null $maxAge
219-
*
220226
* @return int|null Unix system time passed to the PSR-6 cache
221227
*/
222-
private function calculateCacheItemExpiresAfter($maxAge)
228+
private function calculateCacheItemExpiresAfter(?int $maxAge): ?int
223229
{
224230
if (null === $this->config['cache_lifetime'] && null === $maxAge) {
225-
return;
231+
return null;
226232
}
227233

228234
return $this->config['cache_lifetime'] + $maxAge;
@@ -232,14 +238,12 @@ private function calculateCacheItemExpiresAfter($maxAge)
232238
* Calculate the timestamp when a response expires. After that timestamp, we need to send a
233239
* If-Modified-Since / If-None-Match request to validate the response.
234240
*
235-
* @param int|null $maxAge
236-
*
237241
* @return int|null Unix system time. A null value means that the response expires when the cache item expires
238242
*/
239-
private function calculateResponseExpiresAt($maxAge)
243+
private function calculateResponseExpiresAt(?int $maxAge): ?int
240244
{
241245
if (null === $maxAge) {
242-
return;
246+
return null;
243247
}
244248

245249
return time() + $maxAge;
@@ -268,10 +272,8 @@ protected function isCacheable(ResponseInterface $response)
268272

269273
/**
270274
* Verify that we can cache this request.
271-
*
272-
* @return bool
273275
*/
274-
private function isCacheableRequest(RequestInterface $request)
276+
private function isCacheableRequest(RequestInterface $request): bool
275277
{
276278
$uri = $request->getUri()->__toString();
277279
foreach ($this->config['blacklisted_paths'] as $regex) {
@@ -290,7 +292,7 @@ private function isCacheableRequest(RequestInterface $request)
290292
*
291293
* @return bool|string The value of the directive, true if directive without value, false if directive not present
292294
*/
293-
private function getCacheControlDirective(ResponseInterface $response, $name)
295+
private function getCacheControlDirective(ResponseInterface $response, string $name)
294296
{
295297
$headers = $response->getHeader('Cache-Control');
296298
foreach ($headers as $header) {
@@ -307,22 +309,19 @@ private function getCacheControlDirective(ResponseInterface $response, $name)
307309
return false;
308310
}
309311

310-
/**
311-
* @return string
312-
*/
313-
private function createCacheKey(RequestInterface $request)
312+
private function createCacheKey(RequestInterface $request): string
314313
{
315314
$key = $this->config['cache_key_generator']->generate($request);
316315

317316
return hash($this->config['hash_algo'], $key);
318317
}
319318

320319
/**
321-
* Get a ttl in seconds. It could return null if we do not respect cache headers and got no defaultTtl.
320+
* Get a ttl in seconds.
322321
*
323-
* @return int|null
322+
* Returns null if we do not respect cache headers and got no defaultTtl.
324323
*/
325-
private function getMaxAge(ResponseInterface $response)
324+
private function getMaxAge(ResponseInterface $response): ?int
326325
{
327326
if (!in_array('max-age', $this->config['respect_response_cache_directives'], true)) {
328327
return $this->config['default_ttl'];
@@ -333,7 +332,7 @@ private function getMaxAge(ResponseInterface $response)
333332
if (!is_bool($maxAge)) {
334333
$ageHeaders = $response->getHeader('Age');
335334
foreach ($ageHeaders as $age) {
336-
return $maxAge - ((int) $age);
335+
return ((int) $maxAge) - ((int) $age);
337336
}
338337

339338
return (int) $maxAge;
@@ -351,7 +350,7 @@ private function getMaxAge(ResponseInterface $response)
351350
/**
352351
* Configure an options resolver.
353352
*/
354-
private function configureOptions(OptionsResolver $resolver)
353+
private function configureOptions(OptionsResolver $resolver): void
355354
{
356355
$resolver->setDefaults([
357356
'cache_lifetime' => 86400 * 30, // 30 days
@@ -398,10 +397,7 @@ private function configureOptions(OptionsResolver $resolver)
398397
});
399398
}
400399

401-
/**
402-
* @return ResponseInterface
403-
*/
404-
private function createResponseFromCacheItem(CacheItemInterface $cacheItem)
400+
private function createResponseFromCacheItem(CacheItemInterface $cacheItem): ResponseInterface
405401
{
406402
$data = $cacheItem->get();
407403

@@ -415,22 +411,18 @@ private function createResponseFromCacheItem(CacheItemInterface $cacheItem)
415411
throw new RewindStreamException('Cannot rewind stream.', 0, $e);
416412
}
417413

418-
$response = $response->withBody($stream);
419-
420-
return $response;
414+
return $response->withBody($stream);
421415
}
422416

423417
/**
424-
* Get the value of the "If-Modified-Since" header.
425-
*
426-
* @return string|null
418+
* Get the value for the "If-Modified-Since" header.
427419
*/
428-
private function getModifiedSinceHeaderValue(CacheItemInterface $cacheItem)
420+
private function getModifiedSinceHeaderValue(CacheItemInterface $cacheItem): ?string
429421
{
430422
$data = $cacheItem->get();
431423
// The isset() is to be removed in 2.0.
432424
if (!isset($data['createdAt'])) {
433-
return;
425+
return null;
434426
}
435427

436428
$modified = new \DateTime('@'.$data['createdAt']);
@@ -441,33 +433,28 @@ private function getModifiedSinceHeaderValue(CacheItemInterface $cacheItem)
441433

442434
/**
443435
* Get the ETag from the cached response.
444-
*
445-
* @return string|null
446436
*/
447-
private function getETag(CacheItemInterface $cacheItem)
437+
private function getETag(CacheItemInterface $cacheItem): ?string
448438
{
449439
$data = $cacheItem->get();
450440
// The isset() is to be removed in 2.0.
451441
if (!isset($data['etag'])) {
452-
return;
442+
return null;
453443
}
454444

455445
foreach ($data['etag'] as $etag) {
456446
if (!empty($etag)) {
457447
return $etag;
458448
}
459449
}
450+
451+
return null;
460452
}
461453

462454
/**
463-
* Call the cache listeners, if they are set.
464-
*
465-
* @param bool $cacheHit
466-
* @param CacheItemInterface|null $cacheItem
467-
*
468-
* @return ResponseInterface
455+
* Call the registered cache listeners.
469456
*/
470-
private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, $cacheHit, $cacheItem)
457+
private function handleCacheListeners(RequestInterface $request, ResponseInterface $response, bool $cacheHit, ?CacheItemInterface $cacheItem): ResponseInterface
471458
{
472459
foreach ($this->config['cache_listeners'] as $cacheListener) {
473460
$response = $cacheListener->onCacheResponse($request, $response, $cacheHit, $cacheItem);

0 commit comments

Comments
 (0)