- Affected version
- 2.2.10
When importing a style to overwrite an existing style, the style import service calls
This method then enqueues job
The job finally queries and recompiles all templates
This seems like an insane overhead as only templates that are (or were prior to the import) customized in the style; templates that are customized in a parent or an entirely different tree wouldn't be affected at all.
On one of our installs (that has 7 styles and 4 languages) this causes recompilation of ~ 40.000 templates while the style only has a ~ 10 customized templates.
\XF\Repository\Style::triggerStyleDataRebuild
PHP:
public function importFromXml(\SimpleXMLElement $document)
{
$db = $this->db();
$db->beginTransaction();
$addOnId = (string)$document['addon_id'];
$style = $this->getTargetStyle($document);
$this->importAssets($style, $document->assets, $addOnId);
$this->importPropertyGroups($style, $document->properties, $addOnId);
$this->importProperties($style, $document->properties, $addOnId);
$this->importTemplates($style, $document->templates, $addOnId);
/** @var \XF\Repository\Style $styleRepo */
$styleRepo = $this->repository('XF:Style');
$styleRepo->triggerStyleDataRebuild();
$db->commit();
return $style;
}
This method then enqueues job
\XF\Job\TemplateReuild
PHP:
public function triggerStyleDataRebuild()
{
// this task is a subset of what we're doing so don't bother
\XF::dequeueRunOnce('stylePartialRebuild');
$this->app()->service('XF:Style\Rebuild')->rebuildFullParentList();
$this->app()->jobManager()->enqueueUnique('styleRebuild', 'XF:Atomic', [
'execute' => ['XF:TemplateRebuild', 'XF:StyleAssetRebuild', 'XF:StylePropertyRebuild']
]);
}
The job finally queries and recompiles all templates
PHP:
if ($this->data['skipCore'])
{
$skipCoreSql = "AND (addon_id <> 'XF' OR style_id > 0)";
}
else
{
$skipCoreSql = '';
}
$templateIds = $db->fetchAllColumn($db->limit(
"
SELECT template_id
FROM xf_template
WHERE template_id > ?
{$skipCoreSql}
ORDER BY template_id
", $this->data['batch']
), $this->data['templateId']);
if (!$templateIds)
{
return $this->complete();
}
/** @var \XF\Service\Template\Compile $compileService */
$compileService = $app->service('XF:Template\Compile');
$done = 0;
foreach ($templateIds AS $templateId)
{
$this->data['templateId'] = $templateId;
/** @var \XF\Entity\Template $template */
$template = $em->find('XF:Template', $templateId);
if (!$template)
{
continue;
}
$template->getBehavior('XF:DevOutputWritable')->setOption('write_dev_output', false);
$needsSave = $template->reparseTemplate(true);
if ($needsSave)
{
// this will recompile
$template->save();
}
else
{
$compileService->recompile($template);
This seems like an insane overhead as only templates that are (or were prior to the import) customized in the style; templates that are customized in a parent or an entirely different tree wouldn't be affected at all.
On one of our installs (that has 7 styles and 4 languages) this causes recompilation of ~ 40.000 templates while the style only has a ~ 10 customized templates.