3 final class PhabricatorImageMacroRemarkupRule
extends PhutilRemarkupRule
{
7 const KEY_RULE_MACRO
= 'rule.macro';
9 public function apply($text) {
10 return preg_replace_callback(
11 '@^\s*([a-zA-Z0-9:_\x7f-\xff-]+)$@m',
12 array($this, 'markupImageMacro'),
16 public function markupImageMacro(array $matches) {
17 if ($this->macros
=== null) {
18 $this->macros
= array();
20 $viewer = $this->getEngine()->getConfig('viewer');
21 $rows = id(new PhabricatorMacroQuery())
23 ->withStatus(PhabricatorMacroQuery
::STATUS_ACTIVE
)
26 $this->macros
= mpull($rows, 'getPHID', 'getName');
29 $name = (string)$matches[1];
30 if (empty($this->macros
[$name])) {
34 $engine = $this->getEngine();
37 $metadata_key = self
::KEY_RULE_MACRO
;
38 $metadata = $engine->getTextMetadata($metadata_key, array());
40 $token = $engine->storeText('<macro>');
43 'phid' => $this->macros
[$name],
47 $engine->setTextMetadata($metadata_key, $metadata);
52 public function didMarkupText() {
53 $engine = $this->getEngine();
54 $metadata_key = self
::KEY_RULE_MACRO
;
55 $metadata = $engine->getTextMetadata($metadata_key, array());
61 $phids = ipull($metadata, 'phid');
62 $viewer = $this->getEngine()->getConfig('viewer');
64 // Load all the macros.
65 $macros = id(new PhabricatorMacroQuery())
67 ->withStatus(PhabricatorMacroQuery
::STATUS_ACTIVE
)
70 $macros = mpull($macros, null, 'getPHID');
72 // Load all the images and audio.
73 $file_phids = array_merge(
74 array_values(mpull($macros, 'getFilePHID')),
75 array_values(mpull($macros, 'getAudioPHID')));
77 $file_phids = array_filter($file_phids);
81 $files = id(new PhabricatorFileQuery())
83 ->withPHIDs($file_phids)
85 $files = mpull($files, null, 'getPHID');
88 // Replace any macros that we couldn't load the macro or image for with
90 foreach ($metadata as $key => $spec) {
91 $macro = idx($macros, $spec['phid']);
93 $file = idx($files, $macro->getFilePHID());
99 $engine->overwriteStoredText($spec['token'], $spec['original']);
100 unset($metadata[$key]);
103 foreach ($metadata as $spec) {
104 $macro = $macros[$spec['phid']];
105 $file = $files[$macro->getFilePHID()];
106 $src_uri = $file->getBestURI();
108 if ($this->getEngine()->isTextMode()) {
109 $result = $spec['original'].' <'.$src_uri.'>';
110 $engine->overwriteStoredText($spec['token'], $result);
112 } else if ($this->getEngine()->isHTMLMailMode()) {
113 $src_uri = PhabricatorEnv
::getProductionURI($src_uri);
117 $audio = idx($files, $macro->getAudioPHID());
118 $should_play = ($audio && $macro->getAudioBehavior() !=
119 PhabricatorFileImageMacro
::AUDIO_BEHAVIOR_NONE
);
121 $id = celerity_generate_unique_node_id();
124 switch ($macro->getAudioBehavior()) {
125 case PhabricatorFileImageMacro
::AUDIO_BEHAVIOR_LOOP
:
130 Javelin
::initBehavior(
134 'audioURI' => $audio->getBestURI(),
139 $result = $this->newTag(
144 'alt' => $spec['original'],
145 'title' => $spec['original'],
146 'height' => $file->getImageHeight(),
147 'width' => $file->getImageWidth(),
148 'class' => 'phabricator-remarkup-macro',
151 $engine->overwriteStoredText($spec['token'], $result);
154 $engine->setTextMetadata($metadata_key, array());