From 676747185e30728e032a4cec113150e663d60f06 Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Mon, 9 Dec 2024 10:03:48 -0800 Subject: [PATCH] Use a special Twig env for Template UI elements w/ the CP extension Resolves #16267 --- CHANGELOG-WIP.md | 2 ++ src/fieldlayoutelements/Template.php | 32 +++++++++++++++++++++++++++- src/web/View.php | 15 +++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index be1efd1a08f..de5bb95bb40 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -27,6 +27,7 @@ - The Updates utility now shows an action menu for each plugin, with “Copy plugin handle” and “Copy package name” options. ([#16281](https://github.com/craftcms/cms/discussions/16281)) - The Queue Manager utility now shows jobs’ class names. ([#16228](https://github.com/craftcms/cms/pull/16228)) - Improved the wording of field instance action labels. ([#16261](https://github.com/craftcms/cms/discussions/16261)) +- Templates rendered for “Template” field layout UI elements can now call control panel template functions like `elementChip()` and `elementCard()`. ([#16267](https://github.com/craftcms/cms/issues/16267)) - Improved the error output for nested elements when they can’t be resaved via `resave` commands. - `resave` commands’ `--drafts`, `--provisional-drafts`, and `--revisions` options can now be set to `null`, causing elements to be resaved regardless of whether they’re drafts/provisional drafts/revisions. @@ -58,6 +59,7 @@ - Added `craft\mail\Mailer::$siteId`. - Added `craft\mail\Mailer::$siteOverrides`. - Added `craft\models\MailSettings::$siteOverrides`. +- Added `craft\web\View::setTwig()`. - `craft\elements\NestedElementManager::getIndexHtml()` now supports passing `defaultSort` in the `$config` array. ([#16236](https://github.com/craftcms/cms/discussions/16236)) - `craft\elements\conditions\entries\MatrixFieldConditionRule` is now an alias of `FieldConditionRule`. - `craft\helpers\Cp::elementIndexHtml()` now supports passing `defaultSort` in the `$config` array, when `sources` is `null`. ([#16236](https://github.com/craftcms/cms/discussions/16236)) diff --git a/src/fieldlayoutelements/Template.php b/src/fieldlayoutelements/Template.php index 407f25d18df..37dd320571c 100644 --- a/src/fieldlayoutelements/Template.php +++ b/src/fieldlayoutelements/Template.php @@ -11,6 +11,8 @@ use craft\base\ElementInterface; use craft\helpers\Cp; use craft\helpers\Html; +use craft\web\twig\CpExtension; +use craft\web\twig\Environment; use craft\web\View; use Throwable; @@ -22,6 +24,25 @@ */ class Template extends BaseUiElement { + private static Environment $twig; + + /** + * @return Environment + */ + private static function twig(): Environment + { + if (!isset(self::$twig)) { + $view = Craft::$app->getView(); + $templateMode = $view->getTemplateMode(); + $view->setTemplateMode(View::TEMPLATE_MODE_SITE); + self::$twig = Craft::$app->getView()->createTwig(); + self::$twig->addExtension(new CpExtension()); + $view->setTemplateMode($templateMode); + } + + return self::$twig; + } + /** * @var string The template path */ @@ -102,13 +123,22 @@ public function formHtml(?ElementInterface $element = null, bool $static = false return $this->_error(Craft::t('app', 'No template path has been chosen yet.'), 'warning'); } + $view = Craft::$app->getView(); + $templateMode = $view->getTemplateMode(); + $view->setTemplateMode(View::TEMPLATE_MODE_SITE); + $twig = $view->getTwig(); + $view->setTwig(self::twig()); + try { - $content = trim(Craft::$app->getView()->renderTemplate($this->template, [ + $content = trim($view->renderTemplate($this->template, [ 'element' => $element, 'static' => $static, ], $this->templateMode)); } catch (Throwable $e) { return $this->_error($e->getMessage(), 'error'); + } finally { + $view->setTwig($twig); + $view->setTemplateMode($templateMode); } if ($content === '') { diff --git a/src/web/View.php b/src/web/View.php index 532b7c9ad08..ea516ff45ce 100644 --- a/src/web/View.php +++ b/src/web/View.php @@ -384,6 +384,21 @@ public function getTwig(): Environment : $this->_siteTwig ?? ($this->_siteTwig = $this->createTwig()); } + /** + * Sets the Twig environment for the current template mode. + * + * @param Environment $twig + * @since 5.6.0 + */ + public function setTwig(Environment $twig): void + { + if ($this->_templateMode === self::TEMPLATE_MODE_CP) { + $this->_cpTwig = $twig; + } else { + $this->_siteTwig = $twig; + } + } + /** * Creates a new Twig environment. *