diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php index e9716f0868..413d3dc856 100644 --- a/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php +++ b/src/applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php @@ -37,11 +37,25 @@ final class PhabricatorDashboardTextPanelType PhabricatorDashboardPanelRenderingEngine $engine) { $text = $panel->getProperty('text', ''); + $oneoff = id(new PhabricatorMarkupOneOff())->setContent($text); + $field = 'default'; - $text_content = PhabricatorMarkupEngine::renderOneObject( - id(new PhabricatorMarkupOneOff())->setContent($text), - 'default', - $viewer); + // NOTE: We're taking extra steps here to prevent creation of a text panel + // which embeds itself using `{Wnnn}`, recursing indefinitely. + + $parent_key = PhabricatorDashboardRemarkupRule::KEY_PARENT_PANEL_PHIDS; + $parent_phids = $engine->getParentPanelPHIDs(); + $parent_phids[] = $panel->getPHID(); + + $markup_engine = id(new PhabricatorMarkupEngine()) + ->setViewer($viewer) + ->setContextObject($panel) + ->setAuxiliaryConfig($parent_key, $parent_phids); + + $text_content = $markup_engine + ->addObject($oneoff, $field) + ->process() + ->getOutput($oneoff, $field); return id(new PHUIPropertyListView()) ->addTextContent($text_content); diff --git a/src/applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php b/src/applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php index 9870795f25..6b0a48dc01 100644 --- a/src/applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php +++ b/src/applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php @@ -3,6 +3,8 @@ final class PhabricatorDashboardRemarkupRule extends PhabricatorObjectRemarkupRule { + const KEY_PARENT_PANEL_PHIDS = 'dashboard.parentPanelPHIDs'; + protected function getObjectNamePrefix() { return 'W'; } @@ -21,12 +23,16 @@ final class PhabricatorDashboardRemarkupRule PhabricatorObjectHandle $handle, $options) { - $viewer = $this->getEngine()->getConfig('viewer'); + $engine = $this->getEngine(); + $viewer = $engine->getConfig('viewer'); + + $parent_key = self::KEY_PARENT_PANEL_PHIDS; + $parent_phids = $engine->getConfig($parent_key, array()); return id(new PhabricatorDashboardPanelRenderingEngine()) ->setViewer($viewer) ->setPanel($object) - ->setParentPanelPHIDs(array()) + ->setParentPanelPHIDs($parent_phids) ->renderPanel(); } diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php index 933a21b163..c6babe99e0 100644 --- a/src/infrastructure/markup/PhabricatorMarkupEngine.php +++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php @@ -44,6 +44,7 @@ final class PhabricatorMarkupEngine extends Phobject { private $contextObject; private $version = 15; private $engineCaches = array(); + private $auxiliaryConfig = array(); /* -( Markup Pipeline )---------------------------------------------------- */ @@ -122,6 +123,10 @@ final class PhabricatorMarkupEngine extends Phobject { $engines[$key] = $info['object']->newMarkupEngine($info['field']); $engines[$key]->setConfig('viewer', $this->viewer); $engines[$key]->setConfig('contextObject', $this->contextObject); + + foreach ($this->auxiliaryConfig as $aux_key => $aux_value) { + $engines[$key]->setConfig($aux_key, $aux_value); + } } // Load or build the preprocessor caches. @@ -310,6 +315,12 @@ final class PhabricatorMarkupEngine extends Phobject { return $this; } + public function setAuxiliaryConfig($key, $value) { + // TODO: This is gross and should be removed. Avoid use. + $this->auxiliaryConfig[$key] = $value; + return $this; + } + /* -( Engine Construction )------------------------------------------------ */