diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 32161243de..7df620a718 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -125,7 +125,7 @@ return array( 'rsrc/css/phui/phui-box.css' => '7b3a2eed', 'rsrc/css/phui/phui-button.css' => 'c7412aa1', 'rsrc/css/phui/phui-document.css' => 'a5615198', - 'rsrc/css/phui/phui-feed-story.css' => 'e2c9bc83', + 'rsrc/css/phui/phui-feed-story.css' => '55dc7732', 'rsrc/css/phui/phui-fontkit.css' => 'fff25cfa', 'rsrc/css/phui/phui-form-view.css' => 'a2d72756', 'rsrc/css/phui/phui-form.css' => 'b78ec020', @@ -771,7 +771,7 @@ return array( 'phui-calendar-list-css' => 'c1d0ca59', 'phui-calendar-month-css' => 'a92e47d2', 'phui-document-view-css' => 'a5615198', - 'phui-feed-story-css' => 'e2c9bc83', + 'phui-feed-story-css' => '55dc7732', 'phui-font-icon-base-css' => 'eb84f033', 'phui-fontkit-css' => 'fff25cfa', 'phui-form-css' => 'b78ec020', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 66587a7b07..8f5b7d061a 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4376,7 +4376,10 @@ phutil_register_library_map(array( 'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController', 'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFeedSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PhabricatorFeedStory' => 'PhabricatorPolicyInterface', + 'PhabricatorFeedStory' => array( + 'PhabricatorPolicyInterface', + 'PhabricatorMarkupInterface', + ), 'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory', diff --git a/src/applications/feed/story/PhabricatorFeedStory.php b/src/applications/feed/story/PhabricatorFeedStory.php index 4ee8a6372f..04d5b7fd75 100644 --- a/src/applications/feed/story/PhabricatorFeedStory.php +++ b/src/applications/feed/story/PhabricatorFeedStory.php @@ -8,7 +8,10 @@ * @task load Loading Stories * @task policy Policy Implementation */ -abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface { +abstract class PhabricatorFeedStory + implements + PhabricatorPolicyInterface, + PhabricatorMarkupInterface { private $data; private $hasViewed; @@ -19,6 +22,7 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface { private $handles = array(); private $objects = array(); private $projectPHIDs = array(); + private $markupFieldOutput = array(); /* -( Loading Stories )---------------------------------------------------- */ @@ -150,9 +154,46 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface { $stories[$key]->setHandles($story_handles); } + // Load and process story markup blocks. + + $engine = new PhabricatorMarkupEngine(); + $engine->setViewer($viewer); + foreach ($stories as $story) { + foreach ($story->getFieldStoryMarkupFields() as $field) { + $engine->addObject($story, $field); + } + } + + $engine->process(); + + foreach ($stories as $story) { + foreach ($story->getFieldStoryMarkupFields() as $field) { + $story->setMarkupFieldOutput( + $field, + $engine->getOutput($story, $field)); + } + } + return $stories; } + public function setMarkupFieldOutput($field, $output) { + $this->markupFieldOutput[$field] = $output; + return $this; + } + + public function getMarkupFieldOutput($field) { + if (!array_key_exists($field, $this->markupFieldOutput)) { + throw new Exception( + pht( + 'Trying to retrieve markup field key "%s", but this feed story '. + 'did not request it be rendered.', + $field)); + } + + return $this->markupFieldOutput[$field]; + } + public function setHovercard($hover) { $this->hovercard = $hover; return $this; @@ -374,6 +415,10 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface { return $this->projectPHIDs; } + public function getFieldStoryMarkupFields() { + return array(); + } + /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ @@ -425,4 +470,31 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface { return null; } + +/* -( PhabricatorMarkupInterface Implementation )--------------------------- */ + + + public function getMarkupFieldKey($field) { + return 'feed:'.$this->getChronologicalKey().':'.$field; + } + + public function newMarkupEngine($field) { + return PhabricatorMarkupEngine::newMarkupEngine(array()); + } + + public function getMarkupText($field) { + throw new PhutilMethodNotImplementedException(); + } + + public function didMarkupText( + $field, + $output, + PhutilMarkupEngine $engine) { + return $output; + } + + public function shouldUseMarkupCache($field) { + return true; + } + } diff --git a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php index dc820fb6db..0e488b359a 100644 --- a/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php +++ b/src/applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php @@ -34,6 +34,35 @@ class PhabricatorApplicationTransactionFeedStory return $this->getObject($this->getPrimaryTransactionPHID()); } + public function getFieldStoryMarkupFields() { + $xaction_phids = $this->getValue('transactionPHIDs'); + + $fields = array(); + foreach ($xaction_phids as $xaction_phid) { + $xaction = $this->getObject($xaction_phid); + foreach ($xaction->getMarkupFieldsForFeed($this) as $field) { + $fields[] = $field; + } + } + + return $fields; + } + + public function getMarkupText($field) { + $xaction_phids = $this->getValue('transactionPHIDs'); + + foreach ($xaction_phids as $xaction_phid) { + $xaction = $this->getObject($xaction_phid); + foreach ($xaction->getMarkupFieldsForFeed($this) as $xaction_field) { + if ($xaction_field == $field) { + return $xaction->getMarkupTextForFeed($this, $field); + } + } + } + + return null; + } + public function renderView() { $view = $this->newStoryView(); diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index c5cbe2e72f..103d894309 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -788,6 +788,31 @@ abstract class PhabricatorApplicationTransaction return $this->getTitle(); } + public function getMarkupFieldsForFeed(PhabricatorFeedStory $story) { + $fields = array(); + + switch ($this->getTransactionType()) { + case PhabricatorTransactions::TYPE_COMMENT: + $text = $this->getComment()->getContent(); + if (strlen($text)) { + $fields[] = 'comment/'.$this->getID(); + } + break; + } + + return $fields; + } + + public function getMarkupTextForFeed(PhabricatorFeedStory $story, $field) { + switch ($this->getTransactionType()) { + case PhabricatorTransactions::TYPE_COMMENT: + $text = $this->getComment()->getContent(); + return PhabricatorMarkupEngine::summarize($text); + } + + return null; + } + public function getBodyForFeed(PhabricatorFeedStory $story) { $old = $this->getOldValue(); $new = $this->getNewValue(); @@ -797,10 +822,12 @@ abstract class PhabricatorApplicationTransaction switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: $text = $this->getComment()->getContent(); - $body = phutil_escape_html_newlines( - phutil_utf8_shorten($text, 128)); + if (strlen($text)) { + $body = $story->getMarkupFieldOutput('comment/'.$this->getID()); + } break; } + return $body; } diff --git a/src/infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php b/src/infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php index cef6f22b00..d0bf3a69b1 100644 --- a/src/infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php +++ b/src/infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php @@ -8,7 +8,7 @@ final class PhabricatorNavigationRemarkupRule extends PhutilRemarkupRule { public function apply($text) { return preg_replace_callback( - '@{nav\b((?:[^}\\\\]+|\\\\.)+)}$@m', + '@{nav\b((?:[^}\\\\]+|\\\\.)*)}@m', array($this, 'markupNavigation'), $text); } @@ -99,5 +99,4 @@ final class PhabricatorNavigationRemarkupRule extends PhutilRemarkupRule { return $this->getEngine()->storeText($out); } - } diff --git a/webroot/rsrc/css/phui/phui-feed-story.css b/webroot/rsrc/css/phui/phui-feed-story.css index 2749566ee5..f53a2dcbf9 100644 --- a/webroot/rsrc/css/phui/phui-feed-story.css +++ b/webroot/rsrc/css/phui/phui-feed-story.css @@ -28,9 +28,11 @@ } .phui-feed-story-body { - padding: 0 8px 8px; + margin: 0 8px 8px; color: {$darkgreytext}; word-break: break-word; + max-height: 300px; + overflow: hidden; } .phui-feed-story-foot {