Skip to content

Commit

Permalink
Fix the cache tag invalidation (see contao#2551)
Browse files Browse the repository at this point in the history
Description
-----------

| Q                | A
| -----------------| ---
| Fixed issues     | Fixes contao#2137
| Docs PR or issue | -

This is currently a proof of concept that should work for news and events. @Toflar @ausi Can you confirm that my implementation is what you had in mind?

### TODO

* [x] Add a general tag without ID for the top parent record
* [x] Implement cache tagging for the other elements and modules

Commits
-------

b523f61 Fix the cache tag invalidation
64c4cdc CS
4b61ac2 Do not double tag the content elements
5b4a03d Add a tag for the top parent element
996694e Add tagging for the missing modules
601247f Also tag the comments
  • Loading branch information
leofeyer committed Dec 10, 2020
1 parent 137d410 commit 103649e
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 46 deletions.
6 changes: 1 addition & 5 deletions calendar-bundle/src/Resources/contao/classes/Events.php
Expand Up @@ -10,8 +10,6 @@

namespace Contao;

use FOS\HttpCache\ResponseTagger;

/**
* Provide methods to get all events of a certain period from the database.
*
Expand Down Expand Up @@ -283,13 +281,11 @@ protected function addEvent($objEvents, $intStart, $intEnd, $intBegin, $intLimit
}
}

// Tag the response
// Tag the event (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_calendar_events.' . $objEvents->id));
$responseTagger->addTags(array('contao.db.tl_calendar.' . $objEvents->pid));
}

// Store raw data
Expand Down
Expand Up @@ -80,6 +80,13 @@ public function generate()
$this->strLink = $objTarget->getFrontendUrl();
}

// Tag the calendars (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array_map(static function ($id) { return 'contao.db.tl_calendar.' . $id; }, $this->cal_calendar));
}

return parent::generate();
}

Expand Down
17 changes: 7 additions & 10 deletions calendar-bundle/src/Resources/contao/modules/ModuleEventReader.php
Expand Up @@ -13,7 +13,6 @@
use Contao\CoreBundle\Exception\InternalServerErrorException;
use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\CoreBundle\Exception\RedirectResponseException;
use FOS\HttpCache\ResponseTagger;
use Patchwork\Utf8;

/**
Expand Down Expand Up @@ -238,15 +237,6 @@ protected function compile()
$objTemplate->hasDetails = false;
$objTemplate->hasTeaser = false;

// Tag the response
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_calendar_events.' . $objEvent->id));
$responseTagger->addTags(array('contao.db.tl_calendar.' . $objEvent->pid));
}

// Clean the RTE output
if ($objEvent->teaser)
{
Expand Down Expand Up @@ -402,6 +392,13 @@ protected function compile()

$this->Template->event = $objTemplate->parse();

// Tag the event (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_calendar_events.' . $objEvent->id));
}

$bundles = System::getContainer()->getParameter('kernel.bundles');

// HOOK: comments extension required
Expand Down
Expand Up @@ -77,6 +77,13 @@ public function generate()
return $this->getFrontendModule($this->cal_readerModule, $this->strColumn);
}

// Tag the calendars (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array_map(static function ($id) { return 'contao.db.tl_calendar.' . $id; }, $this->cal_calendar));
}

return parent::generate();
}

Expand Down
14 changes: 11 additions & 3 deletions comments-bundle/src/Resources/contao/classes/Comments.php
Expand Up @@ -12,7 +12,6 @@

use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\CoreBundle\OptIn\OptIn;
use FOS\HttpCache\ResponseTagger;

/**
* Class Comments
Expand Down Expand Up @@ -43,10 +42,9 @@ public function addCommentsToTemplate(FrontendTemplate $objTemplate, \stdClass $

$objTemplate->comments = array(); // see #4064

// Tag the response
// Tag the source record (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array(sprintf('contao.comments.%s.%s', $strSource, $intParent)));
}
Expand Down Expand Up @@ -102,6 +100,7 @@ public function addCommentsToTemplate(FrontendTemplate $objTemplate, \stdClass $
if ($objComments !== null && ($total = $objComments->count()) > 0)
{
$count = 0;
$tags = array();
$objPartial = new FrontendTemplate($objConfig->template ?: 'com_default');

while ($objComments->next())
Expand Down Expand Up @@ -134,8 +133,17 @@ public function addCommentsToTemplate(FrontendTemplate $objTemplate, \stdClass $
}

$arrComments[] = $objPartial->parse();
$tags[] = 'contao.db.tl_comments.' . $objComments->id;

++$count;
}

// Tag the comments (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags($tags);
}
}

$objTemplate->comments = $arrComments;
Expand Down
72 changes: 65 additions & 7 deletions core-bundle/src/Resources/contao/classes/DataContainer.php
Expand Up @@ -1278,14 +1278,10 @@ public function invalidateCacheTags()
return;
}

$ns = 'contao.db.';
$tags = array($ns . $this->table, $ns . $this->table . '.' . $this->id);
$tags = array('contao.db.' . $this->table . '.' . $this->id);

if (!empty($this->ptable) && $this->activeRecord && $this->activeRecord->pid > 0)
{
$tags[] = $ns . $this->ptable;
$tags[] = $ns . $this->ptable . '.' . $this->activeRecord->pid;
}
$this->addPtableTags($this->table, $this->id, $tags);
$this->addCtableTags($this->table, $this->id, $tags);

// Trigger the oninvalidate_cache_tags_callback
if (\is_array($GLOBALS['TL_DCA'][$this->table]['config']['oninvalidate_cache_tags_callback']))
Expand All @@ -1312,6 +1308,68 @@ public function invalidateCacheTags()
$cacheManager->invalidateTags($tags);
}

private function addPtableTags($strTable, $intId, &$tags)
{
if (empty($GLOBALS['TL_DCA'][$strTable]['config']['ptable']))
{
$tags[] = 'contao.db.' . $strTable;

return;
}

$ptable = $GLOBALS['TL_DCA'][$strTable]['config']['ptable'];

Controller::loadDataContainer($ptable);

$objPid = $this->Database->prepare('SELECT pid FROM ' . Database::quoteIdentifier($strTable) . ' WHERE id=?')
->execute($intId);

if (!$objPid->numRows)
{
return;
}

$tags[] = 'contao.db.' . $ptable . '.' . $objPid->pid;

$this->addPtableTags($ptable, $objPid->pid, $tags);
}

private function addCtableTags($strTable, $intId, &$tags)
{
if (empty($GLOBALS['TL_DCA'][$strTable]['config']['ctable']))
{
return;
}

foreach ($GLOBALS['TL_DCA'][$strTable]['config']['ctable'] as $ctable)
{
Controller::loadDataContainer($ctable);

if ($GLOBALS['TL_DCA'][$ctable]['config']['dynamicPtable'])
{
$objIds = $this->Database->prepare('SELECT id FROM ' . Database::quoteIdentifier($ctable) . ' WHERE pid=? AND ptable=?')
->execute($intId, $strTable);
}
else
{
$objIds = $this->Database->prepare('SELECT id FROM ' . Database::quoteIdentifier($ctable) . ' WHERE pid=?')
->execute($intId);
}

if (!$objIds->numRows)
{
continue;
}

while ($objIds->next())
{
$tags[] = 'contao.db.' . $ctable . '.' . $objIds->id;

$this->addCtableTags($ctable, $objIds->id, $tags);
}
}
}

/**
* Return the name of the current palette
*
Expand Down
Expand Up @@ -10,7 +10,6 @@

namespace Contao;

use FOS\HttpCache\ResponseTagger;
use Symfony\Component\HttpFoundation\Response;

/**
Expand Down Expand Up @@ -403,10 +402,9 @@ private function setCacheHeaders(Response $response)
$response->setVary(array('Cookie'));
}

// Tag the response with cache tags für the shared cache only
// Tag the page (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_page.' . $objPage->id));
}
Expand Down
4 changes: 1 addition & 3 deletions core-bundle/src/Resources/contao/elements/ContentElement.php
Expand Up @@ -11,7 +11,6 @@
namespace Contao;

use Contao\Model\Collection;
use FOS\HttpCache\ResponseTagger;

/**
* Parent class for content elements.
Expand Down Expand Up @@ -274,10 +273,9 @@ public function generate()
$this->Template->class .= ' ' . implode(' ', $this->objModel->classes);
}

// Tag the response
// Tag the content element (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_content.' . $this->id));
}
Expand Down
5 changes: 1 addition & 4 deletions core-bundle/src/Resources/contao/elements/ContentModule.php
Expand Up @@ -10,8 +10,6 @@

namespace Contao;

use FOS\HttpCache\ResponseTagger;

/**
* Front end content element "module".
*
Expand Down Expand Up @@ -67,10 +65,9 @@ public function generate()
/** @var Module $objModule */
$objModule = new $strClass($objModel, $this->strColumn);

// Tag the response
// Tag the content element (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_content.' . $this->id));
}
Expand Down
4 changes: 1 addition & 3 deletions core-bundle/src/Resources/contao/modules/Module.php
Expand Up @@ -11,7 +11,6 @@
namespace Contao;

use Contao\Model\Collection;
use FOS\HttpCache\ResponseTagger;

/**
* Parent class for front end modules.
Expand Down Expand Up @@ -236,10 +235,9 @@ public function generate()
$this->Template->class .= ' ' . implode(' ', $this->objModel->classes);
}

// Tag the response
// Tag the module (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_module.' . $this->id));
}
Expand Down
5 changes: 1 addition & 4 deletions core-bundle/src/Resources/contao/modules/ModuleArticle.php
Expand Up @@ -10,8 +10,6 @@

namespace Contao;

use FOS\HttpCache\ResponseTagger;

/**
* Provides methodes to handle articles.
*
Expand Down Expand Up @@ -63,10 +61,9 @@ public function generate($blnNoMarkup=false)
$this->type = 'article';
$this->blnNoMarkup = $blnNoMarkup;

// Tag response
// Tag the article (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
/** @var ResponseTagger $responseTagger */
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array('contao.db.tl_article.' . $this->id));
}
Expand Down
17 changes: 17 additions & 0 deletions faq-bundle/src/Resources/contao/modules/ModuleFaqList.php
Expand Up @@ -69,6 +69,13 @@ public function generate()
return $this->getFrontendModule($this->faq_readerModule, $this->strColumn);
}

// Tag the FAQ categories (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags(array_map(static function ($id) { return 'contao.db.tl_faq_category.' . $id; }, $this->faq_categories));
}

return parent::generate();
}

Expand All @@ -86,6 +93,7 @@ protected function compile()
return;
}

$tags = array();
$arrFaq = array_fill_keys($this->faq_categories, array());

// Add FAQs
Expand All @@ -101,6 +109,15 @@ protected function compile()
$arrFaq[$objFaq->pid]['items'][] = $arrTemp;
$arrFaq[$objFaq->pid]['headline'] = $objPid->headline;
$arrFaq[$objFaq->pid]['title'] = $objPid->title;

$tags[] = 'contao.db.tl_faq.' . $objFaq->id;
}

// Tag the FAQs (see #2137)
if (System::getContainer()->has('fos_http_cache.http.symfony_response_tagger'))
{
$responseTagger = System::getContainer()->get('fos_http_cache.http.symfony_response_tagger');
$responseTagger->addTags($tags);
}

$arrFaq = array_values(array_filter($arrFaq));
Expand Down

0 comments on commit 103649e

Please sign in to comment.