Skip to content

Commit 6b399ae

Browse files
committed
Add slim 4 compatibility
1 parent 4a5be76 commit 6b399ae

5 files changed

Lines changed: 263 additions & 127 deletions

File tree

src/Cache.php

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
<?php
2+
/**
3+
* Slim Framework (https://www.slimframework.com)
4+
*
5+
* @license https://github.com/slimphp/Slim-HttpCache/blob/master/LICENSE.md (MIT License)
6+
*/
7+
28
namespace Slim\HttpCache;
39

4-
use Psr\Http\Message\RequestInterface;
510
use Psr\Http\Message\ResponseInterface;
6-
7-
class Cache
11+
use Psr\Http\Message\ServerRequestInterface;
12+
use Psr\Http\Server\MiddlewareInterface;
13+
use Psr\Http\Server\RequestHandlerInterface;
14+
15+
use function in_array;
16+
use function is_array;
17+
use function is_numeric;
18+
use function preg_split;
19+
use function reset;
20+
use function sprintf;
21+
use function strtotime;
22+
23+
class Cache implements MiddlewareInterface
824
{
925
/**
1026
* Cache-Control type (public or private)
@@ -34,44 +50,45 @@ class Cache
3450
* @param int $maxAge The maximum age of client-side cache
3551
* @param bool $mustRevalidate must-revalidate
3652
*/
37-
public function __construct($type = 'private', $maxAge = 86400, $mustRevalidate = false)
53+
public function __construct(string $type = 'private', int $maxAge = 86400, bool $mustRevalidate = false)
3854
{
3955
$this->type = $type;
4056
$this->maxAge = $maxAge;
4157
$this->mustRevalidate = $mustRevalidate;
4258
}
4359

4460
/**
45-
* Invoke cache middleware
46-
*
47-
* @param RequestInterface $request A PSR7 request object
48-
* @param ResponseInterface $response A PSR7 response object
49-
* @param callable $next The next middleware callable
50-
*
51-
* @return ResponseInterface A PSR7 response object
61+
* {@inheritDoc}
5262
*/
53-
public function __invoke(RequestInterface $request, ResponseInterface $response, callable $next)
63+
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
5464
{
55-
$response = $next($request, $response);
65+
$response = $handler->handle($request);
5666

5767
// Cache-Control header
5868
if (!$response->hasHeader('Cache-Control')) {
5969
if ($this->maxAge === 0) {
60-
$response = $response->withHeader('Cache-Control', sprintf(
61-
'%s, no-cache%s',
62-
$this->type,
63-
$this->mustRevalidate ? ', must-revalidate' : ''
64-
));
70+
$response = $response->withHeader(
71+
'Cache-Control',
72+
sprintf(
73+
'%s, no-cache%s',
74+
$this->type,
75+
$this->mustRevalidate ? ', must-revalidate' : ''
76+
)
77+
);
6578
} else {
66-
$response = $response->withHeader('Cache-Control', sprintf(
67-
'%s, max-age=%s%s',
68-
$this->type,
69-
$this->maxAge,
70-
$this->mustRevalidate ? ', must-revalidate' : ''
71-
));
79+
$response = $response->withHeader(
80+
'Cache-Control',
81+
sprintf(
82+
'%s, max-age=%s%s',
83+
$this->type,
84+
$this->maxAge,
85+
$this->mustRevalidate ? ', must-revalidate' : ''
86+
)
87+
);
7288
}
7389
}
7490

91+
7592
// ETag header and conditional GET check
7693
$etag = $response->getHeader('ETag');
7794
$etag = reset($etag);
@@ -81,7 +98,7 @@ public function __invoke(RequestInterface $request, ResponseInterface $response,
8198

8299
if ($ifNoneMatch) {
83100
$etagList = preg_split('@\s*,\s*@', $ifNoneMatch);
84-
if (in_array($etag, $etagList) || in_array('*', $etagList)) {
101+
if (is_array($etagList) && (in_array($etag, $etagList) || in_array('*', $etagList))) {
85102
return $response->withStatus(304);
86103
}
87104
}
@@ -92,7 +109,7 @@ public function __invoke(RequestInterface $request, ResponseInterface $response,
92109
$lastModified = $response->getHeaderLine('Last-Modified');
93110

94111
if ($lastModified) {
95-
if (!is_integer($lastModified)) {
112+
if (!is_numeric($lastModified)) {
96113
$lastModified = strtotime($lastModified);
97114
}
98115

src/CacheProvider.php

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
11
<?php
2+
/**
3+
* Slim Framework (https://www.slimframework.com)
4+
*
5+
* @license https://github.com/slimphp/Slim-HttpCache/blob/master/LICENSE.md (MIT License)
6+
*/
7+
28
namespace Slim\HttpCache;
39

410
use InvalidArgumentException;
511
use Psr\Http\Message\ResponseInterface;
612

13+
use function gmdate;
14+
use function in_array;
15+
use function is_integer;
16+
use function is_null;
17+
use function strtotime;
18+
use function time;
19+
720
class CacheProvider
821
{
922
/**
1023
* Enable client-side HTTP caching
1124
*
12-
* @param ResponseInterface $response PSR7 response object
13-
* @param string $type Cache-Control type: "private" or "public"
14-
* @param null|int|string $maxAge Maximum cache age (integer timestamp or datetime string)
15-
* @param bool $mustRevalidate add option "must-revalidate" to Cache-Control
25+
* @param ResponseInterface $response PSR7 response object
26+
* @param string $type Cache-Control type: "private" or "public"
27+
* @param null|int|string $maxAge Maximum cache age (integer timestamp or datetime string)
28+
* @param bool $mustRevalidate add option "must-revalidate" to Cache-Control
1629
*
1730
* @return ResponseInterface A new PSR7 response object with `Cache-Control` header
1831
* @throws InvalidArgumentException if the cache-control type is invalid
1932
*/
20-
public function allowCache(ResponseInterface $response, $type = 'private', $maxAge = null, $mustRevalidate = false)
21-
{
33+
public function allowCache(
34+
ResponseInterface $response,
35+
string $type = 'private',
36+
$maxAge = null,
37+
bool $mustRevalidate = false
38+
): ResponseInterface {
2239
if (!in_array($type, ['private', 'public'])) {
2340
throw new InvalidArgumentException('Invalid Cache-Control type. Must be "public" or "private".');
2441
}
2542
$headerValue = $type;
2643
if ($maxAge || is_integer($maxAge)) {
27-
if (!is_integer($maxAge)) {
28-
$maxAge = strtotime($maxAge);
44+
if (!is_integer($maxAge) && !is_null($maxAge)) {
45+
$maxAge = strtotime($maxAge) - time();
2946
}
30-
$headerValue = $headerValue . ', max-age=' . $maxAge;
47+
$headerValue = $headerValue.', max-age='.$maxAge;
3148
}
3249

3350
if ($mustRevalidate) {
34-
$headerValue = $headerValue . ", must-revalidate";
51+
$headerValue = $headerValue.", must-revalidate";
3552
}
3653

3754
return $response->withHeader('Cache-Control', $headerValue);
@@ -40,7 +57,7 @@ public function allowCache(ResponseInterface $response, $type = 'private', $maxA
4057
/**
4158
* Disable client-side HTTP caching
4259
*
43-
* @param ResponseInterface $response PSR7 response object
60+
* @param ResponseInterface $response PSR7 response object
4461
*
4562
* @return ResponseInterface A new PSR7 response object with `Cache-Control` header
4663
*/
@@ -52,8 +69,8 @@ public function denyCache(ResponseInterface $response)
5269
/**
5370
* Add `Expires` header to PSR7 response object
5471
*
55-
* @param ResponseInterface $response A PSR7 response object
56-
* @param int|string $time A UNIX timestamp or a valid `strtotime()` string
72+
* @param ResponseInterface $response A PSR7 response object
73+
* @param int|string $time A UNIX timestamp or a valid `strtotime()` string
5774
*
5875
* @return ResponseInterface A new PSR7 response object with `Expires` header
5976
* @throws InvalidArgumentException if the expiration date cannot be parsed
@@ -73,9 +90,9 @@ public function withExpires(ResponseInterface $response, $time)
7390
/**
7491
* Add `ETag` header to PSR7 response object
7592
*
76-
* @param ResponseInterface $response A PSR7 response object
77-
* @param string $value The ETag value
78-
* @param string $type ETag type: "strong" or "weak"
93+
* @param ResponseInterface $response A PSR7 response object
94+
* @param string $value The ETag value
95+
* @param string $type ETag type: "strong" or "weak"
7996
*
8097
* @return ResponseInterface A new PSR7 response object with `ETag` header
8198
* @throws InvalidArgumentException if the etag type is invalid
@@ -85,9 +102,9 @@ public function withEtag(ResponseInterface $response, $value, $type = 'strong')
85102
if (!in_array($type, ['strong', 'weak'])) {
86103
throw new InvalidArgumentException('Invalid etag type. Must be "strong" or "weak".');
87104
}
88-
$value = '"' . $value . '"';
105+
$value = '"'.$value.'"';
89106
if ($type === 'weak') {
90-
$value = 'W/' . $value;
107+
$value = 'W/'.$value;
91108
}
92109

93110
return $response->withHeader('ETag', $value);
@@ -96,8 +113,8 @@ public function withEtag(ResponseInterface $response, $value, $type = 'strong')
96113
/**
97114
* Add `Last-Modified` header to PSR7 response object
98115
*
99-
* @param ResponseInterface $response A PSR7 response object
100-
* @param int|string $time A UNIX timestamp or a valid `strtotime()` string
116+
* @param ResponseInterface $response A PSR7 response object
117+
* @param int|string $time A UNIX timestamp or a valid `strtotime()` string
101118
*
102119
* @return ResponseInterface A new PSR7 response object with `Last-Modified` header
103120
* @throws InvalidArgumentException if the last modified date cannot be parsed

0 commit comments

Comments
 (0)