Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
final class PhabricatorImageRemarkupRule extends PhutilRemarkupRule {
|
2018-03-08 05:00:07 -08:00
|
|
|
|
|
|
|
|
const KEY_RULE_EXTERNAL_IMAGE = 'rule.external-image';
|
|
|
|
|
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
public function getPriority() {
|
|
|
|
|
return 200.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function apply($text) {
|
|
|
|
|
return preg_replace_callback(
|
|
|
|
|
'@{(image|img) ((?:[^}\\\\]+|\\\\.)*)}@m',
|
|
|
|
|
array($this, 'markupImage'),
|
|
|
|
|
$text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function markupImage(array $matches) {
|
|
|
|
|
if (!$this->isFlatText($matches[0])) {
|
|
|
|
|
return $matches[0];
|
|
|
|
|
}
|
2018-03-08 05:00:07 -08:00
|
|
|
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
$args = array();
|
|
|
|
|
$defaults = array(
|
|
|
|
|
'uri' => null,
|
|
|
|
|
'alt' => null,
|
|
|
|
|
'width' => null,
|
|
|
|
|
'height' => null,
|
|
|
|
|
);
|
2018-03-08 05:00:07 -08:00
|
|
|
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
$trimmed_match = trim($matches[2]);
|
|
|
|
|
if ($this->isURI($trimmed_match)) {
|
2018-03-08 05:00:07 -08:00
|
|
|
$args['uri'] = $trimmed_match;
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
} else {
|
|
|
|
|
$parser = new PhutilSimpleOptions();
|
|
|
|
|
$keys = $parser->parse($trimmed_match);
|
|
|
|
|
|
|
|
|
|
$uri_key = '';
|
|
|
|
|
foreach (array('src', 'uri', 'url') as $key) {
|
|
|
|
|
if (array_key_exists($key, $keys)) {
|
|
|
|
|
$uri_key = $key;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($uri_key) {
|
2018-03-08 05:00:07 -08:00
|
|
|
$args['uri'] = $keys[$uri_key];
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
}
|
|
|
|
|
$args += $keys;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$args += $defaults;
|
|
|
|
|
|
2018-03-08 05:00:07 -08:00
|
|
|
if (!strlen($args['uri'])) {
|
|
|
|
|
return $matches[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure this is something that looks roughly like a real URI. We'll
|
|
|
|
|
// validate it more carefully before proxying it, but if whatever the user
|
|
|
|
|
// has typed isn't even close, just decline to activate the rule behavior.
|
|
|
|
|
try {
|
|
|
|
|
$uri = new PhutilURI($args['uri']);
|
|
|
|
|
|
|
|
|
|
if (!strlen($uri->getProtocol())) {
|
|
|
|
|
return $matches[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$args['uri'] = (string)$uri;
|
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
|
return $matches[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$engine = $this->getEngine();
|
|
|
|
|
$metadata_key = self::KEY_RULE_EXTERNAL_IMAGE;
|
|
|
|
|
$metadata = $engine->getTextMetadata($metadata_key, array());
|
|
|
|
|
|
|
|
|
|
$token = $engine->storeText('<img>');
|
|
|
|
|
|
|
|
|
|
$metadata[] = array(
|
|
|
|
|
'token' => $token,
|
|
|
|
|
'args' => $args,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$engine->setTextMetadata($metadata_key, $metadata);
|
|
|
|
|
|
|
|
|
|
return $token;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function didMarkupText() {
|
|
|
|
|
$engine = $this->getEngine();
|
|
|
|
|
$metadata_key = self::KEY_RULE_EXTERNAL_IMAGE;
|
|
|
|
|
$images = $engine->getTextMetadata($metadata_key, array());
|
|
|
|
|
$engine->setTextMetadata($metadata_key, array());
|
|
|
|
|
|
|
|
|
|
if (!$images) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-08 06:44:18 -08:00
|
|
|
// Look for images we've already successfully fetched that aren't about
|
|
|
|
|
// to get eaten by the GC. For any we find, we can just emit a normal
|
|
|
|
|
// "<img />" tag pointing directly to the file.
|
|
|
|
|
|
|
|
|
|
// For files which we don't hit in the cache, we emit a placeholder
|
|
|
|
|
// instead and use AJAX to actually perform the fetch.
|
|
|
|
|
|
|
|
|
|
$digests = array();
|
2018-03-08 05:00:07 -08:00
|
|
|
foreach ($images as $image) {
|
2018-03-08 06:44:18 -08:00
|
|
|
$uri = $image['args']['uri'];
|
|
|
|
|
$digests[] = PhabricatorHash::digestForIndex($uri);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$caches = id(new PhabricatorFileExternalRequest())->loadAllWhere(
|
|
|
|
|
'uriIndex IN (%Ls) AND isSuccessful = 1 AND ttl > %d',
|
|
|
|
|
$digests,
|
|
|
|
|
PhabricatorTime::getNow() + phutil_units('1 hour in seconds'));
|
|
|
|
|
|
|
|
|
|
$file_phids = array();
|
|
|
|
|
foreach ($caches as $cache) {
|
|
|
|
|
$file_phids[$cache->getFilePHID()] = $cache->getURI();
|
|
|
|
|
}
|
2018-03-08 05:00:07 -08:00
|
|
|
|
2018-03-08 06:44:18 -08:00
|
|
|
$file_map = array();
|
|
|
|
|
if ($file_phids) {
|
|
|
|
|
$files = id(new PhabricatorFileQuery())
|
|
|
|
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
|
|
|
|
->withPHIDs(array_keys($file_phids))
|
|
|
|
|
->execute();
|
|
|
|
|
foreach ($files as $file) {
|
|
|
|
|
$phid = $file->getPHID();
|
2018-03-08 05:00:07 -08:00
|
|
|
|
2018-03-08 06:44:18 -08:00
|
|
|
$file_remote_uri = $file_phids[$phid];
|
|
|
|
|
$file_view_uri = $file->getViewURI();
|
|
|
|
|
|
|
|
|
|
$file_map[$file_remote_uri] = $file_view_uri;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($images as $image) {
|
|
|
|
|
$args = $image['args'];
|
|
|
|
|
$uri = $args['uri'];
|
|
|
|
|
|
|
|
|
|
$direct_uri = idx($file_map, $uri);
|
|
|
|
|
if ($direct_uri) {
|
|
|
|
|
$img = phutil_tag(
|
|
|
|
|
'img',
|
|
|
|
|
array(
|
|
|
|
|
'src' => $direct_uri,
|
|
|
|
|
'alt' => $args['alt'],
|
|
|
|
|
'width' => $args['width'],
|
|
|
|
|
'height' => $args['height'],
|
|
|
|
|
));
|
|
|
|
|
} else {
|
|
|
|
|
$src_uri = id(new PhutilURI('/file/imageproxy/'))
|
2019-02-12 13:35:59 -08:00
|
|
|
->replaceQueryParam('uri', $uri);
|
2018-03-08 06:44:18 -08:00
|
|
|
|
|
|
|
|
$img = id(new PHUIRemarkupImageView())
|
|
|
|
|
->setURI($src_uri)
|
|
|
|
|
->setAlt($args['alt'])
|
|
|
|
|
->setWidth($args['width'])
|
|
|
|
|
->setHeight($args['height']);
|
|
|
|
|
}
|
2018-03-08 05:00:07 -08:00
|
|
|
|
|
|
|
|
$engine->overwriteStoredText($image['token'], $img);
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function isURI($uri_string) {
|
|
|
|
|
// Very simple check to make sure it starts with either http or https.
|
|
|
|
|
// If it does, we'll try to treat it like a valid URI
|
|
|
|
|
return preg_match('~^https?\:\/\/.*\z~i', $uri_string);
|
|
|
|
|
}
|
2018-03-08 05:00:07 -08:00
|
|
|
|
Remarkup rule to embed images
Summary:
Ref T4190. Added the remarkup rule to embed images:
Syntax is as follows:
`{image <IMAGE_URL>}`
Parameters are also supported, like:
`{image uri=<IMAGE_URI>, width=500px, height=200px, alt=picture of a moose, href=google.com}`
URLs without a protocol are not supported.
Test Plan: Tested with many of the syntax variations. If the provided URL doesn't point to an image, then a broken image icon will be shown.
Reviewers: epriestley, #blessed_reviewers
Reviewed By: epriestley, #blessed_reviewers
Subscribers: Korvin, epriestley, yelirekim
Maniphest Tasks: T4190
Differential Revision: https://secure.phabricator.com/D16597
2016-09-26 09:56:49 -04:00
|
|
|
}
|