mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Add cached summarization to PhamePost
Summary: Restore summarization. Use the remarkup cache, and try to do it somewhat-intelligently (pick the first paragraph that looks like it's text). Test Plan: {F21323} {F21324} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1373 Differential Revision: https://secure.phabricator.com/D3715
This commit is contained in:
parent
83bbad8ba0
commit
44c6109bf2
7 changed files with 99 additions and 105 deletions
|
@ -1152,7 +1152,6 @@ phutil_register_library_map(array(
|
||||||
'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php',
|
'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php',
|
||||||
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
|
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
|
||||||
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
|
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
|
||||||
'PhameBlogDetailView' => 'applications/phame/view/PhameBlogDetailView.php',
|
|
||||||
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
|
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
|
||||||
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
|
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
|
||||||
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
|
||||||
|
@ -2286,7 +2285,6 @@ phutil_register_library_map(array(
|
||||||
2 => 'PhabricatorMarkupInterface',
|
2 => 'PhabricatorMarkupInterface',
|
||||||
),
|
),
|
||||||
'PhameBlogDeleteController' => 'PhameController',
|
'PhameBlogDeleteController' => 'PhameController',
|
||||||
'PhameBlogDetailView' => 'AphrontView',
|
|
||||||
'PhameBlogEditController' => 'PhameController',
|
'PhameBlogEditController' => 'PhameController',
|
||||||
'PhameBlogListController' => 'PhameController',
|
'PhameBlogListController' => 'PhameController',
|
||||||
'PhameBlogLiveController' => 'PhameController',
|
'PhameBlogLiveController' => 'PhameController',
|
||||||
|
|
|
@ -39,6 +39,8 @@ extends PhameController {
|
||||||
PhamePost::MARKUP_FIELD_BODY,
|
PhamePost::MARKUP_FIELD_BODY,
|
||||||
$user);
|
$user);
|
||||||
|
|
||||||
|
$content = '<div class="phabricator-remarkup">'.$content.'</div>';
|
||||||
|
|
||||||
return id(new AphrontAjaxResponse())->setContent($content);
|
return id(new AphrontAjaxResponse())->setContent($content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,17 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderPostList(array $posts) {
|
protected function renderPostList(array $posts) {
|
||||||
|
$summaries = array();
|
||||||
|
foreach ($posts as $post) {
|
||||||
|
$summaries[] = $post->renderWithSummary();
|
||||||
|
}
|
||||||
|
|
||||||
$list = phutil_render_tag(
|
$list = phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'phame-post-list',
|
'class' => 'phame-post-list',
|
||||||
),
|
),
|
||||||
id(new AphrontNullView())->appendChild($posts)->render());
|
id(new AphrontNullView())->appendChild($summaries)->render());
|
||||||
|
|
||||||
$pager = $this->renderOlderPageLink().$this->renderNewerPageLink();
|
$pager = $this->renderOlderPageLink().$this->renderNewerPageLink();
|
||||||
if ($pager) {
|
if ($pager) {
|
||||||
|
@ -224,6 +229,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
$phids = array();
|
$phids = array();
|
||||||
foreach ($posts as $post) {
|
foreach ($posts as $post) {
|
||||||
$engine->addObject($post, PhamePost::MARKUP_FIELD_BODY);
|
$engine->addObject($post, PhamePost::MARKUP_FIELD_BODY);
|
||||||
|
$engine->addObject($post, PhamePost::MARKUP_FIELD_SUMMARY);
|
||||||
|
|
||||||
$phids[] = $post->getBloggerPHID();
|
$phids[] = $post->getBloggerPHID();
|
||||||
}
|
}
|
||||||
|
@ -240,6 +246,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin {
|
||||||
->setSkin($this)
|
->setSkin($this)
|
||||||
->setPost($post)
|
->setPost($post)
|
||||||
->setBody($engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))
|
->setBody($engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))
|
||||||
|
->setSummary($engine->getOutput($post, PhamePost::MARKUP_FIELD_SUMMARY))
|
||||||
->setAuthor($handles[$post->getBloggerPHID()]);
|
->setAuthor($handles[$post->getBloggerPHID()]);
|
||||||
|
|
||||||
$post->makeEphemeral();
|
$post->makeEphemeral();
|
||||||
|
|
|
@ -23,6 +23,7 @@ final class PhamePost extends PhameDAO
|
||||||
implements PhabricatorPolicyInterface, PhabricatorMarkupInterface {
|
implements PhabricatorPolicyInterface, PhabricatorMarkupInterface {
|
||||||
|
|
||||||
const MARKUP_FIELD_BODY = 'markup:body';
|
const MARKUP_FIELD_BODY = 'markup:body';
|
||||||
|
const MARKUP_FIELD_SUMMARY = 'markup:summary';
|
||||||
|
|
||||||
const VISIBILITY_DRAFT = 0;
|
const VISIBILITY_DRAFT = 0;
|
||||||
const VISIBILITY_PUBLISHED = 1;
|
const VISIBILITY_PUBLISHED = 1;
|
||||||
|
@ -193,9 +194,13 @@ final class PhamePost extends PhameDAO
|
||||||
|
|
||||||
|
|
||||||
public function getMarkupText($field) {
|
public function getMarkupText($field) {
|
||||||
|
switch ($field) {
|
||||||
|
case self::MARKUP_FIELD_BODY:
|
||||||
return $this->getBody();
|
return $this->getBody();
|
||||||
|
case self::MARKUP_FIELD_SUMMARY:
|
||||||
|
return PhabricatorMarkupEngine::summarize($this->getBody());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function didMarkupText(
|
public function didMarkupText(
|
||||||
$field,
|
$field,
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2012 Facebook, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group phame
|
|
||||||
*/
|
|
||||||
final class PhameBlogDetailView extends AphrontView {
|
|
||||||
|
|
||||||
private $user;
|
|
||||||
private $blog;
|
|
||||||
private $bloggers;
|
|
||||||
|
|
||||||
public function setUser(PhabricatorUser $user) {
|
|
||||||
$this->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[] = '<strong>'.phutil_escape_html($blogger->getName()).'</strong>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return implode(' · ', $arr);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,6 +26,8 @@ final class PhamePostView extends AphrontView {
|
||||||
private $viewer;
|
private $viewer;
|
||||||
private $body;
|
private $body;
|
||||||
private $skin;
|
private $skin;
|
||||||
|
private $summary;
|
||||||
|
|
||||||
|
|
||||||
public function setSkin(PhameBlogSkin $skin) {
|
public function setSkin(PhameBlogSkin $skin) {
|
||||||
$this->skin = $skin;
|
$this->skin = $skin;
|
||||||
|
@ -72,6 +74,15 @@ final class PhamePostView extends AphrontView {
|
||||||
return $this->body;
|
return $this->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setSummary($summary) {
|
||||||
|
$this->summary = $summary;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummary() {
|
||||||
|
return $this->summary;
|
||||||
|
}
|
||||||
|
|
||||||
public function renderTitle() {
|
public function renderTitle() {
|
||||||
$href = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle());
|
$href = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle());
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
|
@ -111,6 +122,15 @@ final class PhamePostView extends AphrontView {
|
||||||
$this->getBody());
|
$this->getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderSummary() {
|
||||||
|
return phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'phame-post-body',
|
||||||
|
),
|
||||||
|
$this->getSummary());
|
||||||
|
}
|
||||||
|
|
||||||
public function renderComments() {
|
public function renderComments() {
|
||||||
$post = $this->getPost();
|
$post = $this->getPost();
|
||||||
|
|
||||||
|
@ -141,6 +161,18 @@ final class PhamePostView extends AphrontView {
|
||||||
$this->renderComments());
|
$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() {
|
private function renderFacebookComments() {
|
||||||
$fb_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
|
$fb_id = PhabricatorEnv::getEnvConfig('facebook.application-id');
|
||||||
if (!$fb_id) {
|
if (!$fb_id) {
|
||||||
|
|
|
@ -495,4 +495,54 @@ final class PhabricatorMarkupEngine {
|
||||||
return $mentions;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue