@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
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Don't consider file references inside quoted text blocks to grant "attachment intent"

Summary:
Ref T13682. This is a marginal case, but if you quote someone else's text and it has a file reference embedded in it, that isn't good enough to generate "attachment intent".

Since you need both a reference and an explicit attachment, this should never actually affect any user-visible behavior today, but makes the ruleset more thorough.

Test Plan: Dragged and dropped a file, referencing it in either a quoted or unquoted block. Saw it attach only for a quoted block.

Maniphest Tasks: T13682

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

+79 -8
+37 -6
src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php
··· 5 5 6 6 private $viewer; 7 7 8 - const KEY_EMBED_FILE_PHIDS = 'phabricator.embedded-file-phids'; 8 + const KEY_ATTACH_INTENT_FILE_PHIDS = 'files.attach-intent'; 9 9 10 10 protected function getObjectNamePrefix() { 11 11 return 'F'; ··· 23 23 PhabricatorFileThumbnailTransform::TRANSFORM_PREVIEW, 24 24 )) 25 25 ->execute(); 26 + $objects = mpull($objects, null, 'getID'); 26 27 27 - $phids_key = self::KEY_EMBED_FILE_PHIDS; 28 - $phids = $engine->getTextMetadata($phids_key, array()); 29 - foreach (mpull($objects, 'getPHID') as $phid) { 30 - $phids[] = $phid; 28 + 29 + // Identify files embedded in the block with "attachment intent", i.e. 30 + // those files which the user appears to want to attach to the object. 31 + // Files referenced inside quoted blocks are not considered to have this 32 + // attachment intent. 33 + 34 + $metadata_key = self::KEY_RULE_OBJECT.'.'.$this->getObjectNamePrefix(); 35 + $metadata = $engine->getTextMetadata($metadata_key, array()); 36 + 37 + $attach_key = self::KEY_ATTACH_INTENT_FILE_PHIDS; 38 + $attach_phids = $engine->getTextMetadata($attach_key, array()); 39 + 40 + foreach ($metadata as $item) { 41 + 42 + // If this reference was inside a quoted block, don't count it. Quoting 43 + // someone else doesn't establish an intent to attach a file. 44 + $depth = idx($item, 'quote.depth'); 45 + if ($depth > 0) { 46 + continue; 47 + } 48 + 49 + $id = $item['id']; 50 + $file = idx($objects, $id); 51 + 52 + if (!$file) { 53 + continue; 54 + } 55 + 56 + $attach_phids[] = $file->getPHID(); 31 57 } 32 - $engine->setTextMetadata($phids_key, $phids); 58 + 59 + $attach_phids = array_fuse($attach_phids); 60 + $attach_phids = array_keys($attach_phids); 61 + 62 + $engine->setTextMetadata($attach_key, $attach_phids); 63 + 33 64 34 65 return $objects; 35 66 }
+1 -1
src/infrastructure/markup/PhabricatorMarkupEngine.php
··· 632 632 foreach ($content_blocks as $content_block) { 633 633 $engine->markupText($content_block); 634 634 $phids = $engine->getTextMetadata( 635 - PhabricatorEmbedFileRemarkupRule::KEY_EMBED_FILE_PHIDS, 635 + PhabricatorEmbedFileRemarkupRule::KEY_ATTACH_INTENT_FILE_PHIDS, 636 636 array()); 637 637 foreach ($phids as $phid) { 638 638 $files[$phid] = $phid;
+8
src/infrastructure/markup/blockrule/PhutilRemarkupBlockRule.php
··· 43 43 return; 44 44 } 45 45 46 + public function willMarkupChildBlocks() { 47 + return; 48 + } 49 + 50 + public function didMarkupChildBlocks() { 51 + return; 52 + } 53 + 46 54 final public function setEngine(PhutilRemarkupEngine $engine) { 47 55 $this->engine = $engine; 48 56 $this->updateRules();
+16
src/infrastructure/markup/blockrule/PhutilRemarkupQuotedBlockRule.php
··· 7 7 return true; 8 8 } 9 9 10 + public function willMarkupChildBlocks() { 11 + $engine = $this->getEngine(); 12 + 13 + $depth = $engine->getQuoteDepth(); 14 + $depth = $depth + 1; 15 + $engine->setQuoteDepth($depth); 16 + } 17 + 18 + public function didMarkupChildBlocks() { 19 + $engine = $this->getEngine(); 20 + 21 + $depth = $engine->getQuoteDepth(); 22 + $depth = $depth - 1; 23 + $engine->setQuoteDepth($depth); 24 + } 25 + 10 26 final protected function normalizeQuotedBody($text) { 11 27 $text = phutil_split_lines($text, true); 12 28 foreach ($text as $key => $line) {
+15 -1
src/infrastructure/markup/remarkup/PhutilRemarkupEngine.php
··· 42 42 return $this->mode & self::MODE_HTML_MAIL; 43 43 } 44 44 45 + public function getQuoteDepth() { 46 + return $this->getConfig('runtime.quote.depth', 0); 47 + } 48 + 49 + public function setQuoteDepth($depth) { 50 + return $this->setConfig('runtime.quote.depth', $depth); 51 + } 52 + 45 53 public function setBlockRules(array $rules) { 46 54 assert_instances_of($rules, 'PhutilRemarkupBlockRule'); 47 55 ··· 255 263 } 256 264 257 265 private function markupBlock(array $block) { 266 + $rule = $block['rule']; 267 + 268 + $rule->willMarkupChildBlocks(); 269 + 258 270 $children = array(); 259 271 foreach ($block['children'] as $child) { 260 272 $children[] = $this->markupBlock($child); 261 273 } 262 274 275 + $rule->didMarkupChildBlocks(); 276 + 263 277 if ($children) { 264 278 $children = $this->flattenOutput($children); 265 279 } else { 266 280 $children = null; 267 281 } 268 282 269 - return $block['rule']->markupText($block['text'], $children); 283 + return $rule->markupText($block['text'], $children); 270 284 } 271 285 272 286 private function flattenOutput(array $output) {
+2
src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
··· 318 318 'id' => $matches[1], 319 319 'options' => idx($matches, 2), 320 320 'original' => $matches[0], 321 + 'quote.depth' => $engine->getQuoteDepth(), 321 322 )); 322 323 } 323 324 ··· 337 338 'id' => $matches[1], 338 339 'anchor' => idx($matches, 2), 339 340 'original' => $matches[0], 341 + 'quote.depth' => $engine->getQuoteDepth(), 340 342 )); 341 343 } 342 344