Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/countdown/application/PhabricatorApplicationCountdown.php b/src/applications/countdown/application/PhabricatorApplicationCountdown.php
index e83525e124..a5dea04fd1 100644
--- a/src/applications/countdown/application/PhabricatorApplicationCountdown.php
+++ b/src/applications/countdown/application/PhabricatorApplicationCountdown.php
@@ -1,47 +1,53 @@
<?php
/**
* @group countdown
*/
final class PhabricatorApplicationCountdown extends PhabricatorApplication {
public function getBaseURI() {
return '/countdown/';
}
public function getIconName() {
return 'countdown';
}
public function getShortDescription() {
return pht('Countdown Timers');
}
public function getTitleGlyph() {
return "\xE2\x9A\xB2";
}
public function getFlavorText() {
return pht('Utilize the full capabilities of your ALU.');
}
public function getApplicationGroup() {
return self::GROUP_UTILITIES;
}
+ public function getRemarkupRules() {
+ return array(
+ new PhabricatorCountdownRemarkupRule(),
+ );
+ }
+
public function getRoutes() {
return array(
'/countdown/' => array(
''
=> 'PhabricatorCountdownListController',
'(?P<id>[1-9]\d*)/'
=> 'PhabricatorCountdownViewController',
'edit/(?:(?P<id>[1-9]\d*)/)?'
=> 'PhabricatorCountdownEditController',
'delete/(?P<id>[1-9]\d*)/'
=> 'PhabricatorCountdownDeleteController'
),
);
}
}
diff --git a/src/applications/diviner/application/PhabricatorApplicationDiviner.php b/src/applications/diviner/application/PhabricatorApplicationDiviner.php
index 25a8090b35..e698a25fb1 100644
--- a/src/applications/diviner/application/PhabricatorApplicationDiviner.php
+++ b/src/applications/diviner/application/PhabricatorApplicationDiviner.php
@@ -1,67 +1,73 @@
<?php
final class PhabricatorApplicationDiviner extends PhabricatorApplication {
public function getBaseURI() {
return '/diviner/';
}
public function getIconName() {
return 'diviner';
}
public function getShortDescription() {
return 'Documentation';
}
public function getTitleGlyph() {
return "\xE2\x97\x89";
}
public function getRoutes() {
return array(
'/diviner/' => array(
'' => 'DivinerLegacyController',
'query/((?<key>[^/]+)/)?' => 'DivinerAtomListController',
),
'/docs/(?P<keyword>[^/]+)/' => 'DivinerJumpController',
'/book/(?P<book>[^/]+)/' => 'DivinerBookController',
'/book/'.
'(?P<book>[^/]+)/'.
'(?P<type>[^/]+)/'.
'(?:(?P<context>[^/]+)/)?'.
'(?P<name>[^/]+)/'.
'(?:(?P<index>\d+)/)?' => 'DivinerAtomController',
);
}
public function getApplicationGroup() {
return self::GROUP_COMMUNICATION;
}
+ public function getRemarkupRules() {
+ return array(
+ new DivinerRemarkupRuleSymbol(),
+ );
+ }
+
public function buildMainMenuItems(
PhabricatorUser $user,
PhabricatorController $controller = null) {
$items = array();
$application = null;
if ($controller) {
$application = $controller->getCurrentApplication();
}
if ($application && $application->getHelpURI()) {
$item = new PHUIListItemView();
$item->setName(pht('%s Help', $application->getName()));
$item->addClass('core-menu-item');
$item->setIcon('help');
$item->setHref($application->getHelpURI());
$items[] = $item;
}
return $items;
}
}
diff --git a/src/applications/files/application/PhabricatorApplicationFiles.php b/src/applications/files/application/PhabricatorApplicationFiles.php
index 568fa00e97..f8d37755a8 100644
--- a/src/applications/files/application/PhabricatorApplicationFiles.php
+++ b/src/applications/files/application/PhabricatorApplicationFiles.php
@@ -1,56 +1,63 @@
<?php
final class PhabricatorApplicationFiles extends PhabricatorApplication {
public function getBaseURI() {
return '/file/';
}
public function getShortDescription() {
return 'Store and Share Files';
}
public function getIconName() {
return 'files';
}
public function getTitleGlyph() {
return "\xE2\x87\xAA";
}
public function getFlavorText() {
return pht('Blob store for Pokemon pictures.');
}
public function getApplicationGroup() {
return self::GROUP_UTILITIES;
}
public function getQuickCreateURI() {
return $this->getBaseURI().'upload/';
}
public function canUninstall() {
return false;
}
+ public function getRemarkupRules() {
+ return array(
+ new PhabricatorRemarkupRuleEmbedFile(),
+ );
+ }
+
+
public function getRoutes() {
return array(
'/F(?P<id>[1-9]\d*)' => 'PhabricatorFileShortcutController',
'/file/' => array(
'(query/(?P<key>[^/]+)/)?' => 'PhabricatorFileListController',
'upload/' => 'PhabricatorFileUploadController',
'dropupload/' => 'PhabricatorFileDropUploadController',
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController',
'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController',
'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*'
=> 'PhabricatorFileDataController',
'proxy/' => 'PhabricatorFileProxyController',
'xform/(?P<transform>[^/]+)/(?P<phid>[^/]+)/(?P<key>[^/]+)/'
=> 'PhabricatorFileTransformController',
'uploaddialog/' => 'PhabricatorFileUploadDialogController',
),
);
}
}
diff --git a/src/applications/people/application/PhabricatorApplicationPeople.php b/src/applications/people/application/PhabricatorApplicationPeople.php
index da9fbfd5b7..de1f738c13 100644
--- a/src/applications/people/application/PhabricatorApplicationPeople.php
+++ b/src/applications/people/application/PhabricatorApplicationPeople.php
@@ -1,91 +1,97 @@
<?php
final class PhabricatorApplicationPeople extends PhabricatorApplication {
public function getShortDescription() {
return 'User Accounts';
}
public function getBaseURI() {
return '/people/';
}
public function getTitleGlyph() {
return "\xE2\x99\x9F";
}
public function getIconName() {
return 'people';
}
public function getFlavorText() {
return pht('Sort of a social utility.');
}
public function getApplicationGroup() {
return self::GROUP_ORGANIZATION;
}
public function canUninstall() {
return false;
}
public function getEventListeners() {
return array(
new PhabricatorPeopleHovercardEventListener(),
);
}
public function getRoutes() {
return array(
'/people/' => array(
'(query/(?P<key>[^/]+)/)?' => 'PhabricatorPeopleListController',
'logs/' => 'PhabricatorPeopleLogsController',
'edit/(?:(?P<id>[1-9]\d*)/(?:(?P<view>\w+)/)?)?'
=> 'PhabricatorPeopleEditController',
'ldap/' => 'PhabricatorPeopleLdapController',
'editprofile/(?P<id>[1-9]\d*)/' =>
'PhabricatorPeopleProfileEditController',
),
'/p/(?P<username>[\w._-]+)/(?:(?P<page>\w+)/)?'
=> 'PhabricatorPeopleProfileController',
'/emailverify/(?P<code>[^/]+)/' =>
'PhabricatorEmailVerificationController',
);
}
+ public function getRemarkupRules() {
+ return array(
+ new PhabricatorRemarkupRuleMention(),
+ );
+ }
+
public function buildMainMenuItems(
PhabricatorUser $user,
PhabricatorController $controller = null) {
$items = array();
if ($user->isLoggedIn()) {
$image = $user->loadProfileImageURI();
$item = new PHUIListItemView();
$item->setName($user->getUsername());
$item->setHref('/p/'.$user->getUsername().'/');
$item->addClass('core-menu-item');
$classes = array(
'phabricator-core-menu-icon',
'phabricator-core-menu-profile-image',
);
$item->appendChild(
phutil_tag(
'span',
array(
'class' => implode(' ', $classes),
'style' => 'background-image: url('.$image.')',
),
''));
$items[] = $item;
}
return $items;
}
}
diff --git a/src/applications/phriction/application/PhabricatorApplicationPhriction.php b/src/applications/phriction/application/PhabricatorApplicationPhriction.php
index 82fda6cce6..e5ade45e25 100644
--- a/src/applications/phriction/application/PhabricatorApplicationPhriction.php
+++ b/src/applications/phriction/application/PhabricatorApplicationPhriction.php
@@ -1,59 +1,65 @@
<?php
final class PhabricatorApplicationPhriction extends PhabricatorApplication {
public function getShortDescription() {
return pht('Wiki');
}
public function getBaseURI() {
return '/w/';
}
public function getIconName() {
return 'phriction';
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Phriction_User_Guide.html');
}
public function getTitleGlyph() {
return "\xE2\x9A\xA1";
}
+ public function getRemarkupRules() {
+ return array(
+ new PhrictionRemarkupRule(),
+ );
+ }
+
public function getRoutes() {
return array(
// Match "/w/" with slug "/".
'/w(?P<slug>/)' => 'PhrictionDocumentController',
// Match "/w/x/y/z/" with slug "x/y/z/".
'/w/(?P<slug>.+/)' => 'PhrictionDocumentController',
'/phriction/' => array(
'' => 'PhrictionListController',
'list/(?P<view>[^/]+)/' => 'PhrictionListController',
'history(?P<slug>/)' => 'PhrictionHistoryController',
'history/(?P<slug>.+/)' => 'PhrictionHistoryController',
'edit/(?:(?P<id>[1-9]\d*)/)?' => 'PhrictionEditController',
'delete/(?P<id>[1-9]\d*)/' => 'PhrictionDeleteController',
'new/' => 'PhrictionNewController',
'move/(?:(?P<id>[1-9]\d*)/)?' => 'PhrictionMoveController',
'preview/' => 'PhrictionDocumentPreviewController',
'diff/(?P<id>[1-9]\d*)/' => 'PhrictionDiffController',
),
);
}
public function getApplicationGroup() {
return self::GROUP_COMMUNICATION;
}
public function getApplicationOrder() {
return 0.140;
}
}
diff --git a/src/applications/phriction/remarkup/PhrictionRemarkupRule.php b/src/applications/phriction/remarkup/PhrictionRemarkupRule.php
index 97ceec3f6f..7a0acc88ff 100644
--- a/src/applications/phriction/remarkup/PhrictionRemarkupRule.php
+++ b/src/applications/phriction/remarkup/PhrictionRemarkupRule.php
@@ -1,47 +1,53 @@
<?php
/**
* @group markup
*/
final class PhrictionRemarkupRule
extends PhutilRemarkupRule {
+ public function getPriority() {
+ return 350.0;
+ }
+
public function apply($text) {
return preg_replace_callback(
'@\B\\[\\[([^|\\]]+)(?:\\|([^\\]]+))?\\]\\]\B@U',
array($this, 'markupDocumentLink'),
$text);
}
public function markupDocumentLink($matches) {
$link = trim($matches[1]);
$name = trim(idx($matches, 2, $link));
- $name = explode('/', trim($name, '/'));
- $name = end($name);
+ if (empty($matches[2])) {
+ $name = explode('/', trim($name, '/'));
+ $name = end($name);
+ }
$uri = new PhutilURI($link);
$slug = $uri->getPath();
$fragment = $uri->getFragment();
$slug = PhabricatorSlug::normalize($slug);
$slug = PhrictionDocument::getSlugURI($slug);
- $href = (string) id(new PhutilURI($slug))->setFragment($fragment);
+ $href = (string)id(new PhutilURI($slug))->setFragment($fragment);
if ($this->getEngine()->getState('toc')) {
$text = $name;
} else if ($this->getEngine()->isTextMode()) {
return PhabricatorEnv::getProductionURI($href);
} else {
$text = phutil_tag(
'a',
array(
'href' => $href,
'class' => 'phriction-link',
),
$name);
}
return $this->getEngine()->storeText($text);
}
}
diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php
index 474de96972..7702660f9b 100644
--- a/src/infrastructure/markup/PhabricatorMarkupEngine.php
+++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php
@@ -1,597 +1,583 @@
<?php
/**
* Manages markup engine selection, configuration, application, caching and
* pipelining.
*
* @{class:PhabricatorMarkupEngine} can be used to render objects which
* implement @{interface:PhabricatorMarkupInterface} in a batched, cache-aware
* way. For example, if you have a list of comments written in remarkup (and
* the objects implement the correct interface) you can render them by first
* building an engine and adding the fields with @{method:addObject}.
*
* $field = 'field:body'; // Field you want to render. Each object exposes
* // one or more fields of markup.
*
* $engine = new PhabricatorMarkupEngine();
* foreach ($comments as $comment) {
* $engine->addObject($comment, $field);
* }
*
* Now, call @{method:process} to perform the actual cache/rendering
* step. This is a heavyweight call which does batched data access and
* transforms the markup into output.
*
* $engine->process();
*
* Finally, do something with the results:
*
* $results = array();
* foreach ($comments as $comment) {
* $results[] = $engine->getOutput($comment, $field);
* }
*
* If you have a single object to render, you can use the convenience method
* @{method:renderOneObject}.
*
* @task markup Markup Pipeline
* @task engine Engine Construction
*/
final class PhabricatorMarkupEngine {
private $objects = array();
private $viewer;
private $version = 7;
/* -( Markup Pipeline )---------------------------------------------------- */
/**
* Convenience method for pushing a single object through the markup
* pipeline.
*
* @param PhabricatorMarkupInterface The object to render.
* @param string The field to render.
* @param PhabricatorUser User viewing the markup.
* @return string Marked up output.
* @task markup
*/
public static function renderOneObject(
PhabricatorMarkupInterface $object,
$field,
PhabricatorUser $viewer) {
return id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->addObject($object, $field)
->process()
->getOutput($object, $field);
}
/**
* Queue an object for markup generation when @{method:process} is
* called. You can retrieve the output later with @{method:getOutput}.
*
* @param PhabricatorMarkupInterface The object to render.
* @param string The field to render.
* @return this
* @task markup
*/
public function addObject(PhabricatorMarkupInterface $object, $field) {
$key = $this->getMarkupFieldKey($object, $field);
$this->objects[$key] = array(
'object' => $object,
'field' => $field,
);
return $this;
}
/**
* Process objects queued with @{method:addObject}. You can then retrieve
* the output with @{method:getOutput}.
*
* @return this
* @task markup
*/
public function process() {
$keys = array();
foreach ($this->objects as $key => $info) {
if (!isset($info['markup'])) {
$keys[] = $key;
}
}
if (!$keys) {
return;
}
$objects = array_select_keys($this->objects, $keys);
// Build all the markup engines. We need an engine for each field whether
// we have a cache or not, since we still need to postprocess the cache.
$engines = array();
foreach ($objects as $key => $info) {
$engines[$key] = $info['object']->newMarkupEngine($info['field']);
$engines[$key]->setConfig('viewer', $this->viewer);
}
// Load or build the preprocessor caches.
$blocks = $this->loadPreprocessorCaches($engines, $objects);
$blocks = mpull($blocks, 'getCacheData');
$this->engineCaches = $blocks;
// Finalize the output.
foreach ($objects as $key => $info) {
$engine = $engines[$key];
$field = $info['field'];
$object = $info['object'];
$output = $engine->postprocessText($blocks[$key]);
$output = $object->didMarkupText($field, $output, $engine);
$this->objects[$key]['output'] = $output;
}
return $this;
}
/**
* Get the output of markup processing for a field queued with
* @{method:addObject}. Before you can call this method, you must call
* @{method:process}.
*
* @param PhabricatorMarkupInterface The object to retrieve.
* @param string The field to retrieve.
* @return string Processed output.
* @task markup
*/
public function getOutput(PhabricatorMarkupInterface $object, $field) {
$key = $this->getMarkupFieldKey($object, $field);
$this->requireKeyProcessed($key);
return $this->objects[$key]['output'];
}
/**
* Retrieve engine metadata for a given field.
*
* @param PhabricatorMarkupInterface The object to retrieve.
* @param string The field to retrieve.
* @param string The engine metadata field to retrieve.
* @param wild Optional default value.
* @task markup
*/
public function getEngineMetadata(
PhabricatorMarkupInterface $object,
$field,
$metadata_key,
$default = null) {
$key = $this->getMarkupFieldKey($object, $field);
$this->requireKeyProcessed($key);
return idx($this->engineCaches[$key]['metadata'], $metadata_key, $default);
}
/**
* @task markup
*/
private function requireKeyProcessed($key) {
if (empty($this->objects[$key])) {
throw new Exception(
"Call addObject() before using results (key = '{$key}').");
}
if (!isset($this->objects[$key]['output'])) {
throw new Exception(
"Call process() before using results.");
}
}
/**
* @task markup
*/
private function getMarkupFieldKey(
PhabricatorMarkupInterface $object,
$field) {
return $object->getMarkupFieldKey($field).'@'.$this->version;
}
/**
* @task markup
*/
private function loadPreprocessorCaches(array $engines, array $objects) {
$blocks = array();
$use_cache = array();
foreach ($objects as $key => $info) {
if ($info['object']->shouldUseMarkupCache($info['field'])) {
$use_cache[$key] = true;
}
}
if ($use_cache) {
try {
$blocks = id(new PhabricatorMarkupCache())->loadAllWhere(
'cacheKey IN (%Ls)',
array_keys($use_cache));
$blocks = mpull($blocks, null, 'getCacheKey');
} catch (Exception $ex) {
phlog($ex);
}
}
foreach ($objects as $key => $info) {
if (isset($blocks[$key])) {
// If we already have a preprocessing cache, we don't need to rebuild
// it.
continue;
}
$text = $info['object']->getMarkupText($info['field']);
$data = $engines[$key]->preprocessText($text);
// NOTE: This is just debugging information to help sort out cache issues.
// If one machine is misconfigured and poisoning caches you can use this
// field to hunt it down.
$metadata = array(
'host' => php_uname('n'),
);
$blocks[$key] = id(new PhabricatorMarkupCache())
->setCacheKey($key)
->setCacheData($data)
->setMetadata($metadata);
if (isset($use_cache[$key])) {
// This is just filling a cache and always safe, even on a read pathway.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$blocks[$key]->replace();
unset($unguarded);
}
}
return $blocks;
}
/**
* Set the viewing user. Used to implement object permissions.
*
* @param PhabricatorUser The viewing user.
* @return this
* @task markup
*/
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
/* -( Engine Construction )------------------------------------------------ */
/**
* @task engine
*/
public static function newManiphestMarkupEngine() {
return self::newMarkupEngine(array(
));
}
/**
* @task engine
*/
public static function newPhrictionMarkupEngine() {
return self::newMarkupEngine(array(
'header.generate-toc' => true,
));
}
/**
* @task engine
*/
public static function newPhameMarkupEngine() {
return self::newMarkupEngine(array(
'macros' => false,
));
}
/**
* @task engine
*/
public static function newFeedMarkupEngine() {
return self::newMarkupEngine(
array(
'macros' => false,
'youtube' => false,
));
}
/**
* @task engine
*/
public static function newDifferentialMarkupEngine(array $options = array()) {
return self::newMarkupEngine(array(
'custom-inline' => PhabricatorEnv::getEnvConfig(
'differential.custom-remarkup-rules'),
'custom-block' => PhabricatorEnv::getEnvConfig(
'differential.custom-remarkup-block-rules'),
'differential.diff' => idx($options, 'differential.diff'),
));
}
/**
* @task engine
*/
public static function newDiffusionMarkupEngine(array $options = array()) {
return self::newMarkupEngine(array(
));
}
/**
* @task engine
*/
public static function newProfileMarkupEngine() {
return self::newMarkupEngine(array(
));
}
/**
* @task engine
*/
public static function newSlowvoteMarkupEngine() {
return self::newMarkupEngine(array(
));
}
public static function newPonderMarkupEngine(array $options = array()) {
return self::newMarkupEngine($options);
}
/**
* @task engine
*/
public static function getEngine($ruleset = 'default') {
static $engines = array();
if (isset($engines[$ruleset])) {
return $engines[$ruleset];
}
$engine = null;
switch ($ruleset) {
case 'default':
$engine = self::newMarkupEngine(array());
break;
default:
throw new Exception("Unknown engine ruleset: {$ruleset}!");
}
$engines[$ruleset] = $engine;
return $engine;
}
/**
* @task engine
*/
private static function getMarkupEngineDefaultConfiguration() {
return array(
'pygments' => PhabricatorEnv::getEnvConfig('pygments.enabled'),
'youtube' => PhabricatorEnv::getEnvConfig(
'remarkup.enable-embedded-youtube'),
'custom-inline' => array(),
'custom-block' => array(),
'differential.diff' => null,
'header.generate-toc' => false,
'macros' => true,
'uri.allowed-protocols' => PhabricatorEnv::getEnvConfig(
'uri.allowed-protocols'),
'syntax-highlighter.engine' => PhabricatorEnv::getEnvConfig(
'syntax-highlighter.engine'),
'preserve-linebreaks' => true,
);
}
/**
* @task engine
*/
public static function newMarkupEngine(array $options) {
$options += self::getMarkupEngineDefaultConfiguration();
$engine = new PhutilRemarkupEngine();
$engine->setConfig('preserve-linebreaks', $options['preserve-linebreaks']);
$engine->setConfig('pygments.enabled', $options['pygments']);
$engine->setConfig(
'uri.allowed-protocols',
$options['uri.allowed-protocols']);
$engine->setConfig('differential.diff', $options['differential.diff']);
$engine->setConfig('header.generate-toc', $options['header.generate-toc']);
$engine->setConfig(
'syntax-highlighter.engine',
$options['syntax-highlighter.engine']);
$rules = array();
$rules[] = new PhutilRemarkupRuleEscapeRemarkup();
$rules[] = new PhutilRemarkupRuleMonospace();
$custom_rule_classes = $options['custom-inline'];
if ($custom_rule_classes) {
foreach ($custom_rule_classes as $custom_rule_class) {
$rules[] = newv($custom_rule_class, array());
}
}
$rules[] = new PhutilRemarkupRuleDocumentLink();
if ($options['youtube']) {
$rules[] = new PhabricatorRemarkupRuleYoutube();
}
$applications = PhabricatorApplication::getAllInstalledApplications();
foreach ($applications as $application) {
foreach ($application->getRemarkupRules() as $rule) {
$rules[] = $rule;
}
}
$rules[] = new PhutilRemarkupRuleHyperlink();
- $rules[] = new PhrictionRemarkupRule();
-
- $rules[] = new PhabricatorRemarkupRuleEmbedFile();
- $rules[] = new PhabricatorCountdownRemarkupRule();
if ($options['macros']) {
$rules[] = new PhabricatorRemarkupRuleImageMacro();
$rules[] = new PhabricatorRemarkupRuleMeme();
}
- $rules[] = new DivinerRemarkupRuleSymbol();
-
- $rules[] = new PhabricatorRemarkupRuleMention();
-
$rules[] = new PhutilRemarkupRuleBold();
$rules[] = new PhutilRemarkupRuleItalic();
$rules[] = new PhutilRemarkupRuleDel();
$blocks = array();
$blocks[] = new PhutilRemarkupEngineRemarkupQuotesBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupLiteralBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupHeaderBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupHorizontalRuleBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupListBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupCodeBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupNoteBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupTableBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupSimpleTableBlockRule();
- $blocks[] = new PhutilRemarkupEngineRemarkupDefaultBlockRule();
$custom_block_rule_classes = $options['custom-block'];
if ($custom_block_rule_classes) {
foreach ($custom_block_rule_classes as $custom_block_rule_class) {
$blocks[] = newv($custom_block_rule_class, array());
}
}
+ $blocks[] = new PhutilRemarkupEngineRemarkupDefaultBlockRule();
+
foreach ($blocks as $block) {
- if ($block instanceof PhutilRemarkupEngineRemarkupLiteralBlockRule) {
- $literal_rules = array();
- $literal_rules[] = new PhutilRemarkupRuleLinebreaks();
- $block->setMarkupRules($literal_rules);
- } else if (
- !($block instanceof PhutilRemarkupEngineRemarkupCodeBlockRule)) {
- $block->setMarkupRules($rules);
- }
+ $block->setMarkupRules($rules);
}
$engine->setBlockRules($blocks);
return $engine;
}
public static function extractPHIDsFromMentions(array $content_blocks) {
$mentions = array();
$engine = self::newDifferentialMarkupEngine();
$engine->setConfig('viewer', PhabricatorUser::getOmnipotentUser());
foreach ($content_blocks as $content_block) {
$engine->markupText($content_block);
$phids = $engine->getTextMetadata(
PhabricatorRemarkupRuleMention::KEY_MENTIONED,
array());
$mentions += $phids;
}
return $mentions;
}
public static function extractFilePHIDsFromEmbeddedFiles(
array $content_blocks) {
$files = array();
$engine = self::newDifferentialMarkupEngine();
$engine->setConfig('viewer', PhabricatorUser::getOmnipotentUser());
foreach ($content_blocks as $content_block) {
$engine->markupText($content_block);
$ids = $engine->getTextMetadata(
PhabricatorRemarkupRuleEmbedFile::KEY_EMBED_FILE_PHIDS,
array());
$files += $ids;
}
return $files;
}
/**
* Produce a corpus summary, in a way that shortens the underlying text
* without truncating it somewhere awkward.
*
* TODO: We could do a better job of this.
*
* @param string Remarkup corpus to summarize.
* @return string Summarized corpus.
*/
public static function summarize($corpus) {
// Major goals here are:
// - Don't split in the middle of a character (utf-8).
// - Don't split in the middle of, e.g., **bold** text, since
// we end up with hanging '**' in the summary.
// - Try not to pick an image macro, header, embedded file, etc.
// - Hopefully don't return too much text. We don't explicitly limit
// this right now.
$blocks = preg_split("/\n *\n\s*/", trim($corpus));
$best = null;
foreach ($blocks as $block) {
// This is a test for normal spaces in the block, i.e. a heuristic to
// distinguish standard paragraphs from things like image macros. It may
// not work well for non-latin text. We prefer to summarize with a
// paragraph of normal words over an image macro, if possible.
$has_space = preg_match('/\w\s\w/', $block);
// This is a test to find embedded images and headers. We prefer to
// summarize with a normal paragraph over a header or an embedded object,
// if possible.
$has_embed = preg_match('/^[{=]/', $block);
if ($has_space && !$has_embed) {
// This seems like a good summary, so return it.
return $block;
}
if (!$best) {
// This is the first block we found; if everything is garbage just
// use the first block.
$best = $block;
}
}
return $best;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, May 21, 11:33 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
126215
Default Alt Text
(29 KB)

Event Timeline