1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 12:00:55 +01:00

Refactor Phabricator mention rule to do data fetching in post processing

Summary:
This accomplishes two goals:

  - Data fetching is now grouped across blocks.
  - Demonstrates that D737 actually works.

Test Plan: Used @mentions in Phriction preview, they rendered properly. Verified
only one service call was being made across blocks.
Reviewed By: jungejason
Reviewers: hunterbridges, jungejason, tuomaspelkonen, aran
CC: aran, jungejason, epriestley
Differential Revision: 738
This commit is contained in:
epriestley 2011-07-27 12:41:21 -07:00
parent d064c6efa8
commit 6cd58b17b4
2 changed files with 68 additions and 48 deletions

View file

@ -26,7 +26,7 @@ class PhabricatorMarkupEngine {
foreach ($content_blocks as $content_block) {
$engine->markupText($content_block);
$phids = $engine->getTextMetadata(
'phabricator.mentioned-user-phids',
PhabricatorRemarkupRuleMention::KEY_MENTIONED,
array());
$mentions += $phids;
}

View file

@ -22,7 +22,8 @@
class PhabricatorRemarkupRuleMention
extends PhutilRemarkupRule {
private $actualUsers;
const KEY_RULE_MENTION = 'rule.mention';
const KEY_MENTIONED = 'phabricator.mentioned-user-phids';
public function apply($text) {
@ -33,17 +34,40 @@ class PhabricatorRemarkupRuleMention
// matching "@joe.com" while allowing us to match "hey, @joe.".
$regexp = '/(?<!\w)@([a-zA-Z0-9]+)\b(?![.]\w)/';
$matches = null;
$ok = preg_match_all($regexp, $text, $matches);
if (!$ok) {
// No mentions in this text.
return $text;
return preg_replace_callback(
$regexp,
array($this, 'markupMention'),
$text);
}
private function markupMention($matches) {
$username = strtolower($matches[1]);
$engine = $this->getEngine();
$token = $engine->storeText('');
$metadata_key = self::KEY_RULE_MENTION;
$metadata = $engine->getTextMetadata($metadata_key, array());
if (empty($metadata[$username])) {
$metadata[$username] = array();
}
$metadata[$username][] = $token;
$engine->setTextMetadata($metadata_key, $metadata);
return $token;
}
public function didMarkupText() {
$engine = $this->getEngine();
$metadata_key = self::KEY_RULE_MENTION;
$metadata = $engine->getTextMetadata($metadata_key, array());
if (empty($metadata)) {
// No mentions, or we already processed them.
return;
}
$usernames = $matches[1];
// TODO: This is a little sketchy perf-wise. Once APC comes up, it is an
// ideal candidate to back with an APC cache.
$usernames = array_keys($metadata);
$user_table = new PhabricatorUser();
$real_user_names = queryfx_all(
$user_table->establishConnection('r'),
@ -51,52 +75,48 @@ class PhabricatorRemarkupRuleMention
$user_table->getTableName(),
$usernames);
$engine = $this->getEngine();
$metadata_key = 'phabricator.mentioned-user-phids';
$mentioned = $engine->getTextMetadata($metadata_key, array());
$actual_users = array();
$mentioned_key = self::KEY_MENTIONED;
$mentioned = $engine->getTextMetadata($mentioned_key, array());
foreach ($real_user_names as $row) {
$this->actualUsers[strtolower($row['username'])] = $row;
$actual_users[strtolower($row['username'])] = $row;
$mentioned[$row['phid']] = $row['phid'];
}
$engine->setTextMetadata($metadata_key, $mentioned);
$engine->setTextMetadata($mentioned_key, $mentioned);
return preg_replace_callback(
$regexp,
array($this, 'markupMention'),
$text);
}
foreach ($metadata as $username => $tokens) {
$exists = isset($actual_users[$username]);
$class = $exists
? 'phabricator-remarkup-mention-exists'
: 'phabricator-remarkup-mention-unknown';
public function markupMention($matches) {
$username = strtolower($matches[1]);
$exists = isset($this->actualUsers[$username]);
$class = $exists
? 'phabricator-remarkup-mention-exists'
: 'phabricator-remarkup-mention-unknown';
if ($exists) {
$real = $this->actualUsers[$username]['realName'];
$tag = phutil_render_tag(
'a',
array(
'class' => $class,
'href' => '/p/'.$username.'/',
'target' => '_blank',
'title' => $real,
),
phutil_escape_html('@'.$username));
} else {
$tag = phutil_render_tag(
'span',
array(
'class' => $class,
),
phutil_escape_html('@'.$username));
if ($exists) {
$tag = phutil_render_tag(
'a',
array(
'class' => $class,
'href' => '/p/'.$username.'/',
'target' => '_blank',
'title' => $actual_users[$username]['realName'],
),
phutil_escape_html('@'.$username));
} else {
$tag = phutil_render_tag(
'span',
array(
'class' => $class,
),
phutil_escape_html('@'.$username));
}
foreach ($tokens as $token) {
$engine->overwriteStoredText($token, $tag);
}
}
return $this->getEngine()->storeText($tag);
// Don't re-process these mentions.
$engine->setTextMetadata($metadata_key, array());
}
}