Skip to content

Commit 5a8c64a

Browse files
committed
addTags on TagHandler
1 parent ea6748c commit 5a8c64a

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

src/CacheInvalidator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public function addSubscriber(EventSubscriberInterface $subscriber)
160160
*/
161161
public function setTagsHeader($tagsHeader)
162162
{
163-
if ($this->tagHandler && $this->tagsHeader !== $tagsHeader) {
163+
if ($this->tagHandler && $this->tagHandler->getTagsHeader() !== $tagsHeader) {
164164
$this->tagHandler = new TagHandler($this, $tagsHeader);
165165
}
166166

@@ -176,7 +176,7 @@ public function setTagsHeader($tagsHeader)
176176
*/
177177
public function getTagsHeader()
178178
{
179-
return $this->tagsHeader;
179+
return $this->tagHandler ? $this->tagHandler->getTagsHeader() : $this->tagsHeader;
180180
}
181181

182182
/**

src/Handler/TagHandler.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class TagHandler
3232
*/
3333
private $tagsHeader;
3434

35+
/**
36+
* @var array
37+
*/
38+
private $tags = array();
39+
3540
/**
3641
* Constructor
3742
*
@@ -49,6 +54,29 @@ public function __construct(CacheInvalidator $invalidator, $tagsHeader = 'X-Cach
4954
$this->tagsHeader = $tagsHeader;
5055
}
5156

57+
/**
58+
* Add tags to be sent.
59+
*
60+
* This must be called before any response is sent to the client.
61+
*
62+
* @param array $tags List of tags to add.
63+
*/
64+
public function addTags(array $tags)
65+
{
66+
$this->tags = array_merge($this->tags, $tags);
67+
}
68+
69+
/**
70+
* Set tags on the response.
71+
*
72+
* This must be called before any response is sent to the client.
73+
* Make sure this is called after all addTags calls and only once.
74+
*/
75+
public function flushTags()
76+
{
77+
header(sprintf('%s: %s', $this->getTagsHeader(), $this->formatTagsString($this->tags)));
78+
}
79+
5280
/**
5381
* Invalidate cache entries that contain any of the specified tags in their
5482
* tag header.
@@ -59,10 +87,48 @@ public function __construct(CacheInvalidator $invalidator, $tagsHeader = 'X-Cach
5987
*/
6088
public function invalidateTags(array $tags)
6189
{
62-
$tagExpression = sprintf('(%s)(,.+)?$', implode('|', array_map('preg_quote', $tags)));
90+
$tagExpression = sprintf('(%s)(,.+)?$', implode('|', array_map('preg_quote', $this->escapeTags($tags))));
6391
$headers = array($this->tagsHeader => $tagExpression);
6492
$this->invalidator->invalidate($headers);
6593

6694
return $this;
6795
}
96+
97+
/**
98+
* Get the HTTP header name that will hold cache tags
99+
*
100+
* @return string
101+
*/
102+
public function getTagsHeader()
103+
{
104+
return $this->tagsHeader;
105+
}
106+
107+
/**
108+
* Format the tags string.
109+
*
110+
* @param array $tags Non-empty list of tags to output
111+
*
112+
* @return string
113+
*/
114+
protected function formatTagsString(array $tags)
115+
{
116+
return implode(',', $this->escapeTags(array_unique($tags)));
117+
}
118+
119+
/**
120+
* Make sure that the tags are valid.
121+
*
122+
* @param array $tags The tags to escape.
123+
*
124+
* @return array Sane tags.
125+
*/
126+
protected function escapeTags(array $tags)
127+
{
128+
array_walk($tags, function (&$tag) {
129+
$tag = str_replace(array(',', "\n"), array('_', '_'), $tag);
130+
});
131+
132+
return $tags;
133+
}
68134
}

tests/Unit/Handler/TagHandlerTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ public function testInvalidateTagsCustomHeader()
4848
$tagHandler->invalidateTags(array('post-1'));
4949
}
5050

51+
public function testEscapingTags()
52+
{
53+
$cacheInvalidator = \Mockery::mock('FOS\HttpCache\CacheInvalidator')
54+
->shouldReceive('invalidate')
55+
->with(array('X-Cache-Tags' => '(post_test)(,.+)?$'))
56+
->once()
57+
->shouldReceive('supports')
58+
->with(CacheInvalidator::INVALIDATE)
59+
->once()
60+
->andReturn(true)
61+
->getMock();
62+
63+
$tagHandler = new TagHandler($cacheInvalidator);
64+
$tagHandler->invalidateTags(array('post,test'));
65+
}
66+
5167
/**
5268
* @expectedException \FOS\HttpCache\Exception\UnsupportedProxyOperationException
5369
*/
@@ -62,4 +78,22 @@ public function testInvalidateUnsupported()
6278

6379
new TagHandler($cacheInvalidator);
6480
}
81+
82+
/**
83+
* @runInSeparateProcess
84+
*/
85+
public function testTagResponse()
86+
{
87+
$cacheInvalidator = \Mockery::mock('FOS\HttpCache\CacheInvalidator')
88+
->shouldReceive('supports')
89+
->with(CacheInvalidator::INVALIDATE)
90+
->once()
91+
->andReturn(true)
92+
->getMock();
93+
94+
$tagHandler = new TagHandler($cacheInvalidator);
95+
$tagHandler->addTags(array('post-1', 'test,post'));
96+
$tagHandler->flushTags();
97+
// it seems on cli we can not investigate the headers_list
98+
}
6599
}

0 commit comments

Comments
 (0)