diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index a69d7a4032..6ee3882191 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1152,7 +1152,6 @@ phutil_register_library_map(array( 'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', - 'PhameBlogDetailView' => 'applications/phame/view/PhameBlogDetailView.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php', @@ -2286,7 +2285,6 @@ phutil_register_library_map(array( 2 => 'PhabricatorMarkupInterface', ), 'PhameBlogDeleteController' => 'PhameController', - 'PhameBlogDetailView' => 'AphrontView', 'PhameBlogEditController' => 'PhameController', 'PhameBlogListController' => 'PhameController', 'PhameBlogLiveController' => 'PhameController', diff --git a/src/applications/phame/controller/post/PhamePostPreviewController.php b/src/applications/phame/controller/post/PhamePostPreviewController.php index 8964c5a441..b69e0778e1 100644 --- a/src/applications/phame/controller/post/PhamePostPreviewController.php +++ b/src/applications/phame/controller/post/PhamePostPreviewController.php @@ -39,6 +39,8 @@ extends PhameController { PhamePost::MARKUP_FIELD_BODY, $user); + $content = '
'.$content.'
'; + return id(new AphrontAjaxResponse())->setContent($content); } } diff --git a/src/applications/phame/skins/PhameBasicBlogSkin.php b/src/applications/phame/skins/PhameBasicBlogSkin.php index 8c1a7109d9..b177420488 100644 --- a/src/applications/phame/skins/PhameBasicBlogSkin.php +++ b/src/applications/phame/skins/PhameBasicBlogSkin.php @@ -69,12 +69,17 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { } protected function renderPostList(array $posts) { + $summaries = array(); + foreach ($posts as $post) { + $summaries[] = $post->renderWithSummary(); + } + $list = phutil_render_tag( 'div', array( 'class' => 'phame-post-list', ), - id(new AphrontNullView())->appendChild($posts)->render()); + id(new AphrontNullView())->appendChild($summaries)->render()); $pager = $this->renderOlderPageLink().$this->renderNewerPageLink(); if ($pager) { @@ -224,6 +229,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $phids = array(); foreach ($posts as $post) { $engine->addObject($post, PhamePost::MARKUP_FIELD_BODY); + $engine->addObject($post, PhamePost::MARKUP_FIELD_SUMMARY); $phids[] = $post->getBloggerPHID(); } @@ -240,6 +246,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { ->setSkin($this) ->setPost($post) ->setBody($engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY)) + ->setSummary($engine->getOutput($post, PhamePost::MARKUP_FIELD_SUMMARY)) ->setAuthor($handles[$post->getBloggerPHID()]); $post->makeEphemeral(); diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php index c9143141d2..7a707789a3 100644 --- a/src/applications/phame/storage/PhamePost.php +++ b/src/applications/phame/storage/PhamePost.php @@ -23,6 +23,7 @@ final class PhamePost extends PhameDAO implements PhabricatorPolicyInterface, PhabricatorMarkupInterface { const MARKUP_FIELD_BODY = 'markup:body'; + const MARKUP_FIELD_SUMMARY = 'markup:summary'; const VISIBILITY_DRAFT = 0; const VISIBILITY_PUBLISHED = 1; @@ -193,10 +194,14 @@ final class PhamePost extends PhameDAO public function getMarkupText($field) { - return $this->getBody(); + switch ($field) { + case self::MARKUP_FIELD_BODY: + return $this->getBody(); + case self::MARKUP_FIELD_SUMMARY: + return PhabricatorMarkupEngine::summarize($this->getBody()); + } } - public function didMarkupText( $field, $output, diff --git a/src/applications/phame/view/PhameBlogDetailView.php b/src/applications/phame/view/PhameBlogDetailView.php deleted file mode 100644 index 330ff8b0e1..0000000000 --- a/src/applications/phame/view/PhameBlogDetailView.php +++ /dev/null @@ -1,100 +0,0 @@ -user = $user; - return $this; - } - private function getUser() { - return $this->user; - } - - public function setBloggers(array $bloggers) { - assert_instances_of($bloggers, 'PhabricatorObjectHandle'); - $this->bloggers = $bloggers; - return $this; - } - private function getBloggers() { - return $this->bloggers; - } - - public function setBlog(PhameBlog $blog) { - $this->blog = $blog; - return $this; - } - private function getBlog() { - return $this->blog; - } - - public function render() { - require_celerity_resource('phabricator-remarkup-css'); - - $user = $this->getUser(); - $blog = $this->getBlog(); - $bloggers = $this->getBloggers(); - $name = phutil_escape_html($blog->getName()); - $description = phutil_escape_html($blog->getDescription()); - - $detail = phutil_render_tag( - 'div', - array( - 'class' => 'blog-detail' - ), - phutil_render_tag( - 'div', - array( - 'class' => 'header', - ), - phutil_render_tag( - 'h1', - array(), - $name - ) - ). - phutil_render_tag( - 'div', - array( - 'class' => 'description' - ), - $description - ) - ); - - return $detail; - } - - private function getBloggersHTML(array $bloggers) { - assert_instances_of($bloggers, 'PhabricatorObjectHandle'); - - $arr = array(); - foreach ($bloggers as $blogger) { - $arr[] = ''.phutil_escape_html($blogger->getName()).''; - } - - return implode(' · ', $arr); - } -} diff --git a/src/applications/phame/view/PhamePostView.php b/src/applications/phame/view/PhamePostView.php index 235dd822de..b39af0d038 100644 --- a/src/applications/phame/view/PhamePostView.php +++ b/src/applications/phame/view/PhamePostView.php @@ -26,6 +26,8 @@ final class PhamePostView extends AphrontView { private $viewer; private $body; private $skin; + private $summary; + public function setSkin(PhameBlogSkin $skin) { $this->skin = $skin; @@ -72,6 +74,15 @@ final class PhamePostView extends AphrontView { return $this->body; } + public function setSummary($summary) { + $this->summary = $summary; + return $this; + } + + public function getSummary() { + return $this->summary; + } + public function renderTitle() { $href = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle()); return phutil_render_tag( @@ -111,6 +122,15 @@ final class PhamePostView extends AphrontView { $this->getBody()); } + public function renderSummary() { + return phutil_render_tag( + 'div', + array( + 'class' => 'phame-post-body', + ), + $this->getSummary()); + } + public function renderComments() { $post = $this->getPost(); @@ -141,6 +161,18 @@ final class PhamePostView extends AphrontView { $this->renderComments()); } + public function renderWithSummary() { + return phutil_render_tag( + 'div', + array( + 'class' => 'phame-post', + ), + $this->renderTitle(). + $this->renderDatePublished(). + $this->renderSummary(). + $this->renderComments()); + } + private function renderFacebookComments() { $fb_id = PhabricatorEnv::getEnvConfig('facebook.application-id'); if (!$fb_id) { diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php index 3a3c297d1e..093fe16716 100644 --- a/src/infrastructure/markup/PhabricatorMarkupEngine.php +++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php @@ -495,4 +495,54 @@ final class PhabricatorMarkupEngine { return $mentions; } + + /** + * Produce a corpus summary, in a way that shortens the underlying text + * without truncating it somewhere awkward. + * + * TODO: We could do a better job of this. + * + * @param string Remarkup corpus to summarize. + * @return string Summarized corpus. + */ + public static function summarize($corpus) { + + // Major goals here are: + // - Don't split in the middle of a character (utf-8). + // - Don't split in the middle of, e.g., **bold** text, since + // we end up with hanging '**' in the summary. + // - Try not to pick an image macro, header, embedded file, etc. + // - Hopefully don't return too much text. We don't explicitly limit + // this right now. + + $blocks = preg_split("/\n *\n\s*/", trim($corpus)); + + $best = null; + foreach ($blocks as $block) { + // This is a test for normal spaces in the block, i.e. a heuristic to + // distinguish standard paragraphs from things like image macros. It may + // not work well for non-latin text. We prefer to summarize with a + // paragraph of normal words over an image macro, if possible. + $has_space = preg_match('/\w\s\w/', $block); + + // This is a test to find embedded images and headers. We prefer to + // summarize with a normal paragraph over a header or an embedded object, + // if possible. + $has_embed = preg_match('/^[{=]/', $block); + + if ($has_space && !$has_embed) { + // This seems like a good summary, so return it. + return $block; + } + + if (!$best) { + // This is the first block we found; if everything is garbage just + // use the first block. + $best = $block; + } + } + + return $best; + } + }