Reputation: 85
I am trying to set this up without using a block visibility plugin and it works for the user but internally I would like to have better control by using my own cache tags.
My problem is I can't seem to find the right combination of where to inject a cache tag into a block so as to be able to invalidate it later. I've tried various block hooks and so far the kernel.request and the kernel.finish_request events. The later comes after the hooks and still invalidates the cache (when I do it generically, i.e. not using my own cache tags) so that's good start.
The overall goal is to be able to alternate which block the user sees on subsequent page views on the same page. So, say the home page, on the first view might show block A and the next view block B, the 3rd block C and then back to block A and so on.
With the cache off (i.e in development mode) it works fine. Also invalidating the cache without reference to my own tags with normal caching on works fine as well. But, I would like to do this using my own cache tags.
The choice of which block to show is determined in the hook_block_access() hook so I have to have the setup ready before this event.
I'm open to a different approach to using block hooks if that's not a good idea so alternate ideas are welcome. However, if it's just that I need to tweak something and it will work, even better.
The reason I am using hook_block_view_alter() and not an earlier hook is because before that I have noticed that the block ID may not be there yet (or maybe I missed something and if so please correct me) in the earlier hooks and I need the block ID.
Below is what I have so far.
// In the .module file...
/**
* Implements hook_block_view_alter().
*/
function my_module_block_view_alter(array &$build, BlockPluginInterface $block) {
// 3rd hook to get called in the block hooks
if (array_key_exists('#id', $build) ) {
$ci = MyController::getInfo($build['#id']);
if ($ci['CanControl'] !== []) {
$controlId = &$ci['CanControl']['id'];
$build['#cache']['tags'][] = $controlId;
$build['#cache']['tags'][] = "$controlId:$build[#id]");
}
}
}
// In an event subscriber module off the kernel.FinishRequest event.
class BlockCacheManager implements EventSubscriberInterface {
// EVENT SUBSCRIBER STUFF THEN...
public function kernelFinishRequest(Event $event) {
// Ignore AJAX calls
if (!Drupal::request()->isXmlHttpRequest()) {
// CODE THAT GETS THE RELEVANT BLOCK IDs THEN...
$blocks = Block::loadMultiple($blockIds);
$tags = [];
foreach ($blocks as $block) {
$bTags = $block->getCacheTagsToInvalidate(); // My tags are not here
$bTags2 = $block->getCacheTags(); // nor here
$tags = array_merge($tags, $block->getCacheTagsToInvalidate());
}
// What I would like to to do is below but my tags don't show up with
// $block->getCacheTags() or $block->getCacheTagsToInvalidate() as
// indicated above.
foreach ($blockIds as $blockId) {
$cacheTags[] = "$controlId:$build[#id]";
}
}
}
}
Upvotes: 0
Views: 722
Reputation: 85
I found this article on drupal.org that suggests that the ability to change the cache in that hook has been removed.
The article talks specifically about context cache and not tags but I suspect it's going to be the same result so I'm abandoning trying to do this unless someone shows that it is possible.
Upvotes: 0