Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/markup/view/PHUIRemarkupView.php
<?php | <?php | ||||
/** | /** | ||||
* Simple API for rendering blocks of Remarkup. | * Simple API for rendering blocks of Remarkup. | ||||
* | * | ||||
* Example usage: | * Example usage: | ||||
* | * | ||||
* $fancy_text = new PHUIRemarkupView($viewer, $raw_remarkup); | * $fancy_text = new PHUIRemarkupView($viewer, $raw_remarkup); | ||||
* $view->appendChild($fancy_text); | * $view->appendChild($fancy_text); | ||||
* | * | ||||
*/ | */ | ||||
final class PHUIRemarkupView extends AphrontView { | final class PHUIRemarkupView extends AphrontView { | ||||
private $corpus; | private $corpus; | ||||
private $contextObject; | private $contextObject; | ||||
private $options; | private $options; | ||||
private $oneoff; | |||||
private $generateTableOfContents; | |||||
// TODO: In the long run, rules themselves should define available options. | // TODO: In the long run, rules themselves should define available options. | ||||
// For now, just define constants here so we can more easily replace things | // For now, just define constants here so we can more easily replace things | ||||
// later once this is cleaned up. | // later once this is cleaned up. | ||||
const OPTION_PRESERVE_LINEBREAKS = 'preserve-linebreaks'; | const OPTION_PRESERVE_LINEBREAKS = 'preserve-linebreaks'; | ||||
const OPTION_GENERATE_TOC = 'header.generate-toc'; | |||||
public function __construct(PhabricatorUser $viewer, $corpus) { | public function __construct(PhabricatorUser $viewer, $corpus) { | ||||
$this->setUser($viewer); | $this->setUser($viewer); | ||||
$this->corpus = $corpus; | $this->corpus = $corpus; | ||||
} | } | ||||
public function setContextObject($context_object) { | public function setContextObject($context_object) { | ||||
$this->contextObject = $context_object; | $this->contextObject = $context_object; | ||||
Show All 11 Lines | final class PHUIRemarkupView extends AphrontView { | ||||
public function setRemarkupOptions(array $options) { | public function setRemarkupOptions(array $options) { | ||||
foreach ($options as $key => $value) { | foreach ($options as $key => $value) { | ||||
$this->setRemarkupOption($key, $value); | $this->setRemarkupOption($key, $value); | ||||
} | } | ||||
return $this; | return $this; | ||||
} | } | ||||
public function setGenerateTableOfContents($generate) { | |||||
$this->generateTableOfContents = $generate; | |||||
return $this; | |||||
} | |||||
public function getGenerateTableOfContents() { | |||||
return $this->generateTableOfContents; | |||||
} | |||||
public function getTableOfContents() { | |||||
return $this->oneoff->getTableOfContents(); | |||||
} | |||||
public function render() { | public function render() { | ||||
$viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
$corpus = $this->corpus; | $corpus = $this->corpus; | ||||
$context = $this->getContextObject(); | $context = $this->getContextObject(); | ||||
$options = $this->options; | $options = $this->options; | ||||
$oneoff = id(new PhabricatorMarkupOneOff()) | $oneoff = id(new PhabricatorMarkupOneOff()) | ||||
->setContent($corpus); | ->setContent($corpus) | ||||
->setContentCacheFragment($this->getContentCacheFragment()); | |||||
if ($options) { | if ($options) { | ||||
$oneoff->setEngine($this->getEngine()); | $oneoff->setEngine($this->getEngine()); | ||||
} else { | } else { | ||||
$oneoff->setPreserveLinebreaks(true); | $oneoff->setPreserveLinebreaks(true); | ||||
} | } | ||||
$generate_toc = $this->getGenerateTableOfContents(); | |||||
$oneoff->setGenerateTableOfContents($generate_toc); | |||||
$this->oneoff = $oneoff; | |||||
$content = PhabricatorMarkupEngine::renderOneObject( | $content = PhabricatorMarkupEngine::renderOneObject( | ||||
$oneoff, | $oneoff, | ||||
'default', | 'default', | ||||
$viewer, | $viewer, | ||||
$context); | $context); | ||||
return $content; | return $content; | ||||
} | } | ||||
private function getEngine() { | private function getEngine() { | ||||
$options = $this->options; | $options = $this->options; | ||||
$viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
$viewer_key = $viewer->getCacheFragment(); | $viewer_key = $viewer->getCacheFragment(); | ||||
$engine_key = $this->getEngineCacheFragment(); | |||||
ksort($options); | |||||
$engine_key = serialize($options); | |||||
$engine_key = PhabricatorHash::digestForIndex($engine_key); | |||||
$cache = PhabricatorCaches::getRequestCache(); | $cache = PhabricatorCaches::getRequestCache(); | ||||
$cache_key = "remarkup.engine({$viewer_key}, {$engine_key})"; | $cache_key = "remarkup.engine({$viewer_key}, {$engine_key})"; | ||||
$engine = $cache->getKey($cache_key); | $engine = $cache->getKey($cache_key); | ||||
if (!$engine) { | if (!$engine) { | ||||
$engine = PhabricatorMarkupEngine::newMarkupEngine($options); | $engine = PhabricatorMarkupEngine::newMarkupEngine($options); | ||||
$cache->setKey($cache_key, $engine); | $cache->setKey($cache_key, $engine); | ||||
} | } | ||||
return $engine; | return $engine; | ||||
} | } | ||||
private function getEngineCacheFragment() { | |||||
$options = $this->options; | |||||
ksort($options); | |||||
$engine_key = serialize($options); | |||||
$engine_key = PhabricatorHash::digestForIndex($engine_key); | |||||
return $engine_key; | |||||
} | |||||
private function getContentCacheFragment() { | |||||
$corpus = $this->corpus; | |||||
$content_fragment = PhabricatorHash::digestForIndex($corpus); | |||||
$options_fragment = array( | |||||
'toc' => $this->getGenerateTableOfContents(), | |||||
); | |||||
$options_fragment = serialize($options_fragment); | |||||
$options_fragment = PhabricatorHash::digestForIndex($options_fragment); | |||||
return "remarkup({$content_fragment}, {$options_fragment})"; | |||||
} | |||||
} | } |