Smarty - {htxt} blocks should not be evaluated unless needed
authorTim Otten <totten@civicrm.org>
Thu, 23 Feb 2023 22:03:13 +0000 (14:03 -0800)
committerTim Otten <totten@civicrm.org>
Fri, 24 Feb 2023 01:44:02 +0000 (17:44 -0800)
CRM/Core/Smarty.php
CRM/Core/Smarty/plugins/prefilter.htxtFilter.php [new file with mode: 0644]

index 41a70205753a3f4f84c1f962142351a77e0d2919..09991fb2751e2ab78341d02f91137b676c23d3a1 100644 (file)
@@ -144,6 +144,7 @@ class CRM_Core_Smarty extends Smarty {
       $this->default_modifiers[] = 'escape:"htmlall"';
     }
     $this->load_filter('pre', 'resetExtScope');
+    $this->load_filter('pre', 'htxtFilter');
 
     $this->assign('crmPermissions', new CRM_Core_Smarty_Permissions());
 
diff --git a/CRM/Core/Smarty/plugins/prefilter.htxtFilter.php b/CRM/Core/Smarty/plugins/prefilter.htxtFilter.php
new file mode 100644 (file)
index 0000000..1a2a56a
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * The content of an "{htxt}" block should not be evaluated unless
+ * the active request is relevant. Otherwise, it will try to
+ * evaluate unassigned variables.
+ *
+ * @param string $tpl_source
+ * @param $smarty
+ * @return string
+ */
+function smarty_prefilter_htxtFilter($tpl_source, &$smarty) {
+  if (strpos($tpl_source, '{htxt') === FALSE) {
+    return $tpl_source;
+  }
+
+  $htxts = 0;
+  $_htxts = 0;
+
+  $result = preg_replace_callback_array([
+    '/\{htxt id=([\'\"][^\'\"]+[\'\"])/' => function ($m) use (&$htxts) {
+      $htxts++;
+      return sprintf('{if $id == %s}%s', $m[1], $m[0]);
+    },
+    ';\{/htxt\};' => function($m) use (&$_htxts) {
+      $_htxts++;
+      return '{/htxt}{/if}';
+    },
+  ], $tpl_source);
+
+  if ($htxts !== $_htxts) {
+    throw new \RuntimeException(sprintf('Invalid {htxt} tag. Wrapped %d opening-tags and %d closing-tags.', $htxts, $_htxts));
+  }
+
+  return $result;
+}