Remove product literal strings in "pht()", part 5
[phabricator.git] / src / applications / files / markup / PhabricatorImageRemarkupRule.php
blob57ad75bbc5a49d22776263a7c969b05de65b4e56
1 <?php
3 final class PhabricatorImageRemarkupRule extends PhutilRemarkupRule {
5 const KEY_RULE_EXTERNAL_IMAGE = 'rule.external-image';
7 public function getPriority() {
8 return 200.0;
11 public function apply($text) {
12 return preg_replace_callback(
13 '@{(image|img) ((?:[^}\\\\]+|\\\\.)*)}@m',
14 array($this, 'markupImage'),
15 $text);
18 public function markupImage(array $matches) {
19 if (!$this->isFlatText($matches[0])) {
20 return $matches[0];
23 $args = array();
24 $defaults = array(
25 'uri' => null,
26 'alt' => null,
27 'width' => null,
28 'height' => null,
31 $trimmed_match = trim($matches[2]);
32 if ($this->isURI($trimmed_match)) {
33 $args['uri'] = $trimmed_match;
34 } else {
35 $parser = new PhutilSimpleOptions();
36 $keys = $parser->parse($trimmed_match);
38 $uri_key = '';
39 foreach (array('src', 'uri', 'url') as $key) {
40 if (array_key_exists($key, $keys)) {
41 $uri_key = $key;
44 if ($uri_key) {
45 $args['uri'] = $keys[$uri_key];
47 $args += $keys;
50 $args += $defaults;
52 if (!strlen($args['uri'])) {
53 return $matches[0];
56 // Make sure this is something that looks roughly like a real URI. We'll
57 // validate it more carefully before proxying it, but if whatever the user
58 // has typed isn't even close, just decline to activate the rule behavior.
59 try {
60 $uri = new PhutilURI($args['uri']);
62 if (!strlen($uri->getProtocol())) {
63 return $matches[0];
66 $args['uri'] = (string)$uri;
67 } catch (Exception $ex) {
68 return $matches[0];
71 $engine = $this->getEngine();
72 $metadata_key = self::KEY_RULE_EXTERNAL_IMAGE;
73 $metadata = $engine->getTextMetadata($metadata_key, array());
75 $token = $engine->storeText('<img>');
77 $metadata[] = array(
78 'token' => $token,
79 'args' => $args,
82 $engine->setTextMetadata($metadata_key, $metadata);
84 return $token;
87 public function didMarkupText() {
88 $engine = $this->getEngine();
89 $metadata_key = self::KEY_RULE_EXTERNAL_IMAGE;
90 $images = $engine->getTextMetadata($metadata_key, array());
91 $engine->setTextMetadata($metadata_key, array());
93 if (!$images) {
94 return;
97 // Look for images we've already successfully fetched that aren't about
98 // to get eaten by the GC. For any we find, we can just emit a normal
99 // "<img />" tag pointing directly to the file.
101 // For files which we don't hit in the cache, we emit a placeholder
102 // instead and use AJAX to actually perform the fetch.
104 $digests = array();
105 foreach ($images as $image) {
106 $uri = $image['args']['uri'];
107 $digests[] = PhabricatorHash::digestForIndex($uri);
110 $caches = id(new PhabricatorFileExternalRequest())->loadAllWhere(
111 'uriIndex IN (%Ls) AND isSuccessful = 1 AND ttl > %d',
112 $digests,
113 PhabricatorTime::getNow() + phutil_units('1 hour in seconds'));
115 $file_phids = array();
116 foreach ($caches as $cache) {
117 $file_phids[$cache->getFilePHID()] = $cache->getURI();
120 $file_map = array();
121 if ($file_phids) {
122 $files = id(new PhabricatorFileQuery())
123 ->setViewer(PhabricatorUser::getOmnipotentUser())
124 ->withPHIDs(array_keys($file_phids))
125 ->execute();
126 foreach ($files as $file) {
127 $phid = $file->getPHID();
129 $file_remote_uri = $file_phids[$phid];
130 $file_view_uri = $file->getViewURI();
132 $file_map[$file_remote_uri] = $file_view_uri;
136 foreach ($images as $image) {
137 $args = $image['args'];
138 $uri = $args['uri'];
140 $direct_uri = idx($file_map, $uri);
141 if ($direct_uri) {
142 $img = phutil_tag(
143 'img',
144 array(
145 'src' => $direct_uri,
146 'alt' => $args['alt'],
147 'width' => $args['width'],
148 'height' => $args['height'],
150 } else {
151 $src_uri = id(new PhutilURI('/file/imageproxy/'))
152 ->replaceQueryParam('uri', $uri);
154 $img = id(new PHUIRemarkupImageView())
155 ->setURI($src_uri)
156 ->setAlt($args['alt'])
157 ->setWidth($args['width'])
158 ->setHeight($args['height']);
161 $engine->overwriteStoredText($image['token'], $img);
165 private function isURI($uri_string) {
166 // Very simple check to make sure it starts with either http or https.
167 // If it does, we'll try to treat it like a valid URI
168 return preg_match('~^https?\:\/\/.*\z~i', $uri_string);