@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

Remarkup rule for rendering PHIDs as handles

Summary:
adds the `{{PHID....}}` rule. Should mostly be useful in UI code that refers to Objects.

It doesn't add any mention links/transactions.

Test Plan: Comment with this, see email (plain + html) and comment box.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D15488

authored by

Aviv Eyal and committed by
avivey
2b9d4f70 8f94aa8a

+112
+2
src/__phutil_library_map__.php
··· 2454 2454 'PhabricatorHandlePool' => 'applications/phid/handle/pool/PhabricatorHandlePool.php', 2455 2455 'PhabricatorHandlePoolTestCase' => 'applications/phid/handle/pool/__tests__/PhabricatorHandlePoolTestCase.php', 2456 2456 'PhabricatorHandleQuery' => 'applications/phid/query/PhabricatorHandleQuery.php', 2457 + 'PhabricatorHandleRemarkupRule' => 'applications/phid/remarkup/PhabricatorHandleRemarkupRule.php', 2457 2458 'PhabricatorHandlesEditField' => 'applications/transactions/editfield/PhabricatorHandlesEditField.php', 2458 2459 'PhabricatorHarbormasterApplication' => 'applications/harbormaster/application/PhabricatorHarbormasterApplication.php', 2459 2460 'PhabricatorHarbormasterConfigOptions' => 'applications/harbormaster/config/PhabricatorHarbormasterConfigOptions.php', ··· 6897 6898 'PhabricatorHandlePool' => 'Phobject', 6898 6899 'PhabricatorHandlePoolTestCase' => 'PhabricatorTestCase', 6899 6900 'PhabricatorHandleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6901 + 'PhabricatorHandleRemarkupRule' => 'PhutilRemarkupRule', 6900 6902 'PhabricatorHandlesEditField' => 'PhabricatorPHIDListEditField', 6901 6903 'PhabricatorHarbormasterApplication' => 'PhabricatorApplication', 6902 6904 'PhabricatorHarbormasterConfigOptions' => 'PhabricatorApplicationConfigOptions',
+109
src/applications/phid/remarkup/PhabricatorHandleRemarkupRule.php
··· 1 + <?php 2 + 3 + final class PhabricatorHandleRemarkupRule extends PhutilRemarkupRule { 4 + 5 + const KEY_RULE_HANDLE = 'rule.handle'; 6 + const KEY_RULE_HANDLE_ORIGINAL = 'rule.handle.original'; 7 + 8 + public function apply($text) { 9 + return preg_replace_callback( 10 + '/{(PHID-[a-zA-Z0-9-]*)}/', 11 + array($this, 'markupHandle'), 12 + $text); 13 + } 14 + 15 + public function markupHandle(array $matches) { 16 + $engine = $this->getEngine(); 17 + $viewer = $engine->getConfig('viewer'); 18 + 19 + if (!$this->isFlatText($matches[0])) { 20 + return $matches[0]; 21 + } 22 + 23 + $phid_type = phid_get_type($matches[1]); 24 + if ($phid_type == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { 25 + return $matches[0]; 26 + } 27 + 28 + $token = $engine->storeText($matches[0]); 29 + if ($engine->isTextMode()) { 30 + return $token; 31 + } 32 + 33 + $original_key = self::KEY_RULE_HANDLE_ORIGINAL; 34 + $original = $engine->getTextMetadata($original_key, array()); 35 + $original[$token] = $matches[0]; 36 + $engine->setTextMetadata($original_key, $original); 37 + 38 + $metadata_key = self::KEY_RULE_HANDLE; 39 + $metadata = $engine->getTextMetadata($metadata_key, array()); 40 + $phid = $matches[1]; 41 + if (empty($metadata[$phid])) { 42 + $metadata[$phid] = array(); 43 + } 44 + $metadata[$phid][] = $token; 45 + $engine->setTextMetadata($metadata_key, $metadata); 46 + 47 + return $token; 48 + } 49 + 50 + public function didMarkupText() { 51 + $engine = $this->getEngine(); 52 + 53 + $metadata_key = self::KEY_RULE_HANDLE; 54 + 55 + $metadata = $engine->getTextMetadata($metadata_key, array()); 56 + if (empty($metadata)) { 57 + // No mentions, or we already processed them. 58 + return; 59 + } 60 + 61 + $original_key = self::KEY_RULE_HANDLE_ORIGINAL; 62 + $original = $engine->getTextMetadata($original_key, array()); 63 + 64 + $phids = array_keys($metadata); 65 + 66 + $handles = id(new PhabricatorHandleQuery()) 67 + ->setViewer($this->getEngine()->getConfig('viewer')) 68 + ->withPHIDs($phids) 69 + ->execute(); 70 + 71 + foreach ($metadata as $phid => $tokens) { 72 + $handle = idx($handles, $phid); 73 + 74 + if ($handle->isComplete()) { 75 + if ($engine->isHTMLMailMode()) { 76 + $href = $handle->getURI(); 77 + $href = PhabricatorEnv::getProductionURI($href); 78 + 79 + $link = phutil_tag( 80 + 'a', 81 + array( 82 + 'href' => $href, 83 + 'style' => ' 84 + border-color: #f1f7ff; 85 + color: #19558d; 86 + background-color: #f1f7ff; 87 + border: 1px solid transparent; 88 + border-radius: 3px; 89 + font-weight: bold; 90 + padding: 0 4px;', 91 + ), 92 + $handle->getLinkName()); 93 + } else { 94 + $link = $handle->renderTag(); 95 + $link->setPHID($phid); 96 + } 97 + foreach ($tokens as $token) { 98 + $engine->overwriteStoredText($token, $link); 99 + } 100 + } else { 101 + foreach ($tokens as $token) { 102 + $engine->overwriteStoredText($token, idx($original, $token)); 103 + } 104 + } 105 + } 106 + 107 + $engine->setTextMetadata($metadata_key, array()); 108 + } 109 + }
+1
src/infrastructure/markup/PhabricatorMarkupEngine.php
··· 494 494 495 495 $rules[] = new PhabricatorIconRemarkupRule(); 496 496 $rules[] = new PhabricatorEmojiRemarkupRule(); 497 + $rules[] = new PhabricatorHandleRemarkupRule(); 497 498 498 499 $applications = PhabricatorApplication::getAllInstalledApplications(); 499 500 foreach ($applications as $application) {