Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/config/option/PhabricatorCoreConfigOptions.php b/src/applications/config/option/PhabricatorCoreConfigOptions.php
index 56975bd66f..6d7a66b146 100644
--- a/src/applications/config/option/PhabricatorCoreConfigOptions.php
+++ b/src/applications/config/option/PhabricatorCoreConfigOptions.php
@@ -1,254 +1,264 @@
<?php
final class PhabricatorCoreConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Core');
}
public function getDescription() {
return pht('Configure core options, including URIs.');
}
public function getOptions() {
if (phutil_is_windows()) {
$paths = array();
} else {
$paths = array(
'/bin',
'/usr/bin',
'/usr/local/bin',
);
}
$path = getenv('PATH');
return array(
$this->newOption('phabricator.base-uri', 'string', null)
->setLocked(true)
->setSummary(pht('URI where Phabricator is installed.'))
->setDescription(
pht(
'Set the URI where Phabricator is installed. Setting this '.
'improves security by preventing cookies from being set on other '.
'domains, and allows daemons to send emails with links that have '.
'the correct domain.'))
->addExample('http://phabricator.example.com/', pht('Valid Setting')),
$this->newOption('phabricator.production-uri', 'string', null)
->setSummary(
pht('Primary install URI, for multi-environment installs.'))
->setDescription(
pht(
'If you have multiple Phabricator environments (like a '.
'development/staging environment for working on testing '.
'Phabricator, and a production environment for deploying it), '.
'set the production environment URI here so that emails and other '.
'durable URIs will always generate with links pointing at the '.
'production environment. If unset, defaults to '.
'{{phabricator.base-uri}}. Most installs do not need to set '.
'this option.'))
->addExample('http://phabricator.example.com/', pht('Valid Setting')),
$this->newOption('phabricator.allowed-uris', 'list<string>', array())
->setLocked(true)
->setSummary(pht('Alternative URIs that can access Phabricator.'))
->setDescription(
pht(
"These alternative URIs will be able to access 'normal' pages ".
"on your Phabricator install. Other features such as OAuth ".
"won't work. The major use case for this is moving installs ".
"across domains."))
->addExample(
"http://phabricator2.example.com/\n".
"http://phabricator3.example.com/",
pht('Valid Setting')),
$this->newOption('phabricator.timezone', 'string', null)
->setSummary(
pht('The timezone Phabricator should use.'))
->setDescription(
pht(
"PHP requires that you set a timezone in your php.ini before ".
"using date functions, or it will emit a warning. If this isn't ".
"possible (for instance, because you are using HPHP) you can set ".
"some valid constant for date_default_timezone_set() here and ".
"Phabricator will set it on your behalf, silencing the warning."))
->addExample('America/New_York', pht('US East (EDT)'))
->addExample('America/Chicago', pht('US Central (CDT)'))
->addExample('America/Boise', pht('US Mountain (MDT)'))
->addExample('America/Los_Angeles', pht('US West (PDT)')),
$this->newOption('phabricator.cookie-prefix', 'string', null)
->setSummary(
pht('Set a string Phabricator should use to prefix '.
'cookie names'))
->setDescription(
pht(
'Cookies set for x.com are also sent for y.x.com. Assuming '.
'Phabricator instances are running on both domains, this will '.
'create a collision preventing you from logging in.'))
->addExample('dev', pht('Prefix cookie with "dev"')),
$this->newOption('phabricator.show-beta-applications', 'bool', false)
->setBoolOptions(
array(
pht('Install Beta Applications'),
pht('Uninstall Beta Applications')
))
->setSummary(
pht(
'Install applications which are still under development.'))
->setDescription(
pht(
"Phabricator includes 'Beta' applications which are in an early ".
"stage of development. They range from very rough prototypes to ".
"relatively complete (but unpolished) applications.\n\n".
"By default, Beta applications are not installed. You can enable ".
"this option to install them if you're interested in previewing ".
"upcoming features.\n\n".
"After enabling Beta applications, you can selectively uninstall ".
"them (like normal applications).")),
$this->newOption('phabricator.serious-business', 'bool', false)
->setBoolOptions(
array(
pht('Serious business'),
pht('Shenanigans'), // That should be interesting to translate. :P
))
->setSummary(
pht('Allows you to remove levity and jokes from the UI.'))
->setDescription(
pht(
'By default, Phabricator includes some flavor text in the UI, '.
'like a prompt to "Weigh In" rather than "Add Comment" in '.
'Maniphest. If you\'d prefer more traditional UI strings like '.
'"Add Comment", you can set this flag to disable most of the '.
'extra flavor.')),
- $this->newOption('environment.append-paths', 'list<string>', $paths)
+ $this->newOption('remarkup.ignored-object-names', 'string', '/^(Q|V)\d$/')
+ ->setSummary(
+ pht('Text values that match this regex and are also object names '.
+ 'will not be linked.'))
+ ->setDescription(
+ pht(
+ 'By default, Phabricator links object names in Remarkup fields '.
+ 'to the corresponding object. This regex can be used to modify '.
+ 'this behavior; object names that match this regex will not be '.
+ 'linked.')),
+ $this->newOption('environment.append-paths', 'list<string>', $paths)
->setSummary(
pht('These paths get appended to your \$PATH envrionment variable.'))
->setDescription(
pht(
"Phabricator occasionally shells out to other binaries on the ".
"server. An example of this is the `pygmentize` command, used ".
"to syntax-highlight code written in languages other than PHP. ".
"By default, it is assumed that these binaries are in the \$PATH ".
"of the user running Phabricator (normally 'apache', 'httpd', or ".
"'nobody'). Here you can add extra directories to the \$PATH ".
"environment variable, for when these binaries are in ".
"non-standard locations.\n\n".
"Note that you can also put binaries in ".
"`phabricator/support/bin/` (for example, by symlinking them).\n\n".
"The current value of PATH after configuration is applied is:\n\n".
" lang=text\n".
" %s", $path))
->setLocked(true)
->addExample('/usr/local/bin', pht('Add One Path'))
->addExample("/usr/bin\n/usr/local/bin", pht('Add Multiple Paths')),
$this->newOption('config.lock', 'set', array())
->setLocked(true)
->setDescription(pht('Additional configuration options to lock.')),
$this->newOption('config.hide', 'set', array())
->setLocked(true)
->setDescription(pht('Additional configuration options to hide.')),
$this->newOption('config.mask', 'set', array())
->setLocked(true)
->setDescription(pht('Additional configuration options to mask.')),
$this->newOption('config.ignore-issues', 'set', array())
->setLocked(true)
->setDescription(pht('Setup issues to ignore.')),
$this->newOption('phabricator.env', 'string', null)
->setLocked(true)
->setDescription(pht('Internal.')),
$this->newOption('test.value', 'wild', null)
->setLocked(true)
->setDescription(pht('Unit test value.')),
$this->newOption('phabricator.uninstalled-applications', 'set', array())
->setLocked(true)
->setDescription(
pht('Array containing list of Uninstalled applications.')),
$this->newOption('phabricator.application-settings', 'wild', array())
->setLocked(true)
->setDescription(
pht('Customized settings for Phabricator applications.')),
$this->newOption('welcome.html', 'string', null)
->setLocked(true)
->setDescription(
pht('Custom HTML to show on the main Phabricator dashboard.')),
$this->newOption('phabricator.cache-namespace', 'string', null)
->setLocked(true)
->setDescription(pht('Cache namespace.')),
$this->newOption('phabricator.allow-email-users', 'bool', false)
->setBoolOptions(
array(
pht('Allow'),
pht('Disallow'),
))->setDescription(
pht(
'Allow non-members to interact with tasks over email.')),
);
}
protected function didValidateOption(
PhabricatorConfigOption $option,
$value) {
$key = $option->getKey();
if ($key == 'phabricator.base-uri' ||
$key == 'phabricator.production-uri') {
$uri = new PhutilURI($value);
$protocol = $uri->getProtocol();
if ($protocol !== 'http' && $protocol !== 'https') {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The URI must start with ".
"'http://' or 'https://'.",
$key));
}
$domain = $uri->getDomain();
if (strpos($domain, '.') === false) {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The URI must contain a dot ('.'), ".
"like 'http://example.com/', not just a bare name like ".
"'http://example/'. Some web browsers will not set cookies on ".
"domains with no TLD.",
$key));
}
$path = $uri->getPath();
if ($path !== '' && $path !== '/') {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The URI must NOT have a path, ".
"e.g. 'http://phabricator.example.com/' is OK, but ".
"'http://example.com/phabricator/' is not. Phabricator must be ".
"installed on an entire domain; it can not be installed on a ".
"path.",
$key));
}
}
if ($key === 'phabricator.timezone') {
$old = date_default_timezone_get();
$ok = @date_default_timezone_set($value);
@date_default_timezone_set($old);
if (!$ok) {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The timezone identifier must ".
"be a valid timezone identifier recognized by PHP, like ".
"'America/Los_Angeles'. You can find a list of valid identifiers ".
"here: %s",
$key,
'http://php.net/manual/timezones.php'));
}
}
}
}
diff --git a/src/applications/ponder/remarkup/PonderRemarkupRule.php b/src/applications/ponder/remarkup/PonderRemarkupRule.php
index 2509e24ade..1de64ab3c4 100644
--- a/src/applications/ponder/remarkup/PonderRemarkupRule.php
+++ b/src/applications/ponder/remarkup/PonderRemarkupRule.php
@@ -1,29 +1,17 @@
<?php
final class PonderRemarkupRule extends PhabricatorObjectRemarkupRule {
protected function getObjectNamePrefix() {
return 'Q';
}
protected function loadObjects(array $ids) {
$viewer = $this->getEngine()->getConfig('viewer');
return id(new PonderQuestionQuery())
->setViewer($viewer)
->withIDs($ids)
->execute();
}
- protected function shouldMarkupObject(array $params) {
- // NOTE: Q1, Q2, Q3 and Q4 are often used to refer to quarters of the year;
- // mark them up only in the {Q1} format.
- if ($params['type'] == 'ref') {
- if ($params['id'] <= 4) {
- return false;
- }
- }
-
- return true;
- }
-
}
diff --git a/src/docs/user/userguide/remarkup.diviner b/src/docs/user/userguide/remarkup.diviner
index 0d1e2c5550..f5b379b80b 100644
--- a/src/docs/user/userguide/remarkup.diviner
+++ b/src/docs/user/userguide/remarkup.diviner
@@ -1,563 +1,565 @@
@title Remarkup Reference
@group userguide
Explains how to make bold text; this makes your words louder so you can win
arguments.
= Overview =
Phabricator uses a lightweight markup language called "Remarkup", similar to
other lightweight markup languages like Markdown and Wiki markup.
This document describes how to format text using Remarkup.
= Quick Reference =
All the syntax is explained in more detail below, but this is a quick guide to
formatting text in Remarkup.
These are inline styles, and can be applied to most text:
**bold** //italic// `monospaced` ##monospaced## ~~deleted~~ __underlined__
D123 T123 rX123 # Link to Objects
{D123} {T123} # Link to Objects (Full Name)
{F123} # Embed Images
{M123} # Embed Pholio Mock
@username # Mention a User
#project # Mention a Project
[[wiki page]] # Link to Phriction
[[wiki page | name]] # Named link to Phriction
http://xyz/ # Link to web
[[http://xyz/ | name]] # Named link to web
[name](http://xyz/) # Alternate Link
These are block styles, and must be separated from surrounding text by
empty lines:
= Large Header =
== Smaller Header ==
## This is a Header As Well
Also a Large Header
===================
Also a Smaller Header
---------------------
> Quoted Text
Use "- " or "* " for bulleted lists, and "# " for numbered lists.
Use ``` or indent two spaces for code.
Use %%% for a literal block.
Use | ... | ... for tables.
= Basic Styling =
Format **basic text styles** like this:
**bold text**
//italic text//
`monospaced text`
##monospaced text##
~~deleted text~~
__underlined text__
Those produce **bold text**, //italic text//, `monospaced text`, ##monospaced
text##, ~~deleted text~~, and __underlined text__, respectively.
= Layout =
Make **headers** like this:
= Large Header =
== Smaller Header ==
===== Very Small Header =====
Alternate Large Header
======================
Alternate Smaller Header
------------------------
You can optionally omit the trailing `=` signs -- that is, these are the same:
== Smaller Header ==
== Smaller Header
This produces headers like the ones in this document. Make sure you have an
empty line before and after the header.
Make **lists** by beginning each item with a "-" or a "*":
lang=text
- milk
- eggs
- bread
* duck
* duck
* goose
This produces a list like this:
- milk
- eggs
- bread
(Note that you need to put a space after the "-" or "*".)
You can make numbered lists with a "#" instead of "-" or "*":
# Articuno
# Zapdos
# Moltres
You can also nest lists:
```- Body
- Head
- Arm
- Elbow
- Hand
# Thumb
# Index
# Middle
# Ring
# Pinkie
- Leg
- Knee
- Foot```
...which produces:
- Body
- Head
- Arm
- Elbow
- Hand
# Thumb
# Index
# Middle
# Ring
# Pinkie
- Leg
- Knee
- Foot
If you prefer, you can indent lists using multiple characters to show indent
depth, like this:
```- Tree
-- Branch
--- Twig```
As expected, this produces:
- Tree
-- Branch
--- Twig
You can add checkboxes to items by prefacing them with `[ ]` or `[X]`, like
this:
```
- [X] Preheat oven to 450 degrees.
- [ ] Zest 35 lemons.
```
When rendered, this produces:
- [X] Preheat oven to 450 degrees.
- [ ] Zest 35 lemons.
Make **code blocks** by indenting two spaces:
f(x, y);
You can also use three backticks to enclose the code block:
```f(x, y);
g(f);```
You can specify a language for syntax highlighting with "lang=xxx":
lang=text
lang=html
<a href="#">...</a>
This will highlight the block using a highlighter for that language, if one is
available (in most cases, this means you need to configure Pygments):
lang=html
<a href="#">...</a>
You can also use a "COUNTEREXAMPLE" header to show that a block of code is
bad and shouldn't be copied:
lang=text
COUNTEREXAMPLE
function f() {
global $$variable_variable;
}
This produces a block like this:
COUNTEREXAMPLE
function f() {
global $$variable_variable;
}
You can use `lines=N` to limit the vertical size of a chunk of code, and
`name=some_name.ext` to give it a name. For example, this:
lang=text
lang=html, name=example.html, lines=12, counterexample
...
...produces this:
lang=html, name=example.html, lines=12, counterexample
<p>Apple</p>
<p>Apricot</p>
<p>Avocado</p>
<p>Banana</p>
<p>Bilberry</p>
<p>Blackberry</p>
<p>Blackcurrant</p>
<p>Blueberry</p>
<p>Currant</p>
<p>Cherry</p>
<p>Cherimoya</p>
<p>Clementine</p>
<p>Date</p>
<p>Damson</p>
<p>Durian</p>
<p>Eggplant</p>
<p>Elderberry</p>
<p>Feijoa</p>
<p>Gooseberry</p>
<p>Grape</p>
<p>Grapefruit</p>
<p>Guava</p>
<p>Huckleberry</p>
<p>Jackfruit</p>
<p>Jambul</p>
<p>Kiwi fruit</p>
<p>Kumquat</p>
<p>Legume</p>
<p>Lemon</p>
<p>Lime</p>
<p>Lychee</p>
<p>Mandarine</p>
<p>Mango</p>
<p>Mangostine</p>
<p>Melon</p>
You can also use "NOTE:", "WARNING:", or "IMPORTANT:" to call out an important
idea.
NOTE: Best practices in proton pack operation include not crossing the streams.
WARNING: Crossing the streams can result in total protonic reversal!
IMPORTANT: Don't cross the streams!
In addition, you can use "(NOTE)", "(WARNING)", or "(IMPORTANT)" to get the
same effect but without "(NOTE)", "(WARNING)", or "(IMPORTANT)" appearing in
the rendered result. For example
(NOTE) Dr. Egon Spengler is the best resource for additional proton pack
questions.
= Linking URIs =
URIs are automatically linked: http://phabricator.org/
If you have a URI with problematic characters in it, like
"`http://comma.org/,`", you can surround it with angle brackets:
<http://comma.org/,>
This will force the parser to consume the whole URI: <http://comma.org/,>
You can also use create named links, where you choose the displayed text. These
work within Phabricator or on the internet at large:
[[/herald/transcript/ | Herald Transcripts]]
[[http://www.boring-legal-documents.com/ | exciting legal documents]]
Markdown-style links are also supported:
[Toil](http://www.trouble.com)
= Linking to Objects =
-You can link to Differential revisions, Diffusion commits and Maniphest tasks
-by mentioning the name of an object:
+You can link to Phabricator objects, such as Differential revisions, Diffusion
+commits and Maniphest tasks, by mentioning the name of an object:
D123 # Link to Differential revision D123
rX123 # Link to SVN commit 123 from the "X" repository
rXaf3192cd5 # Link to Git commit "af3192cd5..." from the "X" repository.
# You must specify at least 7 characters of the hash.
T123 # Link to Maniphest task T123
You can also link directly to a comment in Maniphest and Differential:
T123#4 # Link to comment #4 of T123
+See the Phabricator configuraton setting `remarkup.ignored-object-names` to
+modify this behavior.
+
= Embedding Objects
You can also generate full-name references to some objects by using braces:
{D123} # Link to Differential revision D123 with the full name
{T123} # Link to Maniphest task T123 with the full name
These references will also show when an object changes state (for instance, a
task or revision is closed). Some types of objects support rich embedding.
== Linking to Project Tags
Projects can be linked to with the use of a hashtag (#). This works by default
using the name of the Project (lowercase, underscored). Additionally you
can set multiple additional hashtags by editing the Project details.
#qa, #quality_assurance
== Embedding Mocks (Pholio)
You can embed a Pholio mock by using braces to refer to it:
{M123}
By default the first four images from the mock set are displayed. This behavior
can be overridden with the **image** option. With the **image** option you can
provide one or more image IDs to display.
You can set the image (or images) to display like this:
{M123, image=12345}
{M123, image=12345 & 6789}
== Embedding Pastes
You can embed a Paste using braces:
{P123}
You can adjust the embed height with the `lines` option:
{P123, lines=15}
You can highlight specific lines with the `highlight` option:
{P123, highlight=15}
{P123, highlight="23-25, 31"}
== Embedding Images
You can embed an image or other file by using braces to refer to it:
{F123}
In most interfaces, you can drag-and-drop an image from your computer into the
text area to upload and reference it.
Some browsers (e.g. Chrome) support uploading an image data just by pasting them
from clipboard into the text area.
You can set file display options like this:
{F123, layout=left, float, size=full, alt="a duckling"}
Valid options are:
- **layout** left (default), center, right, inline, link (render a link
instead of a thumbnail for images)
- **float** If layout is set to left or right, the image will be floated so
text wraps around it.
- **size** thumb (default), full
- **name** with `layout=link` or for non-images, use this name for the link
text
- **width** Scale image to a specific width.
- **height** Scale image to a specific height.
- **alt** Provide alternate text for assistive technologies.
== Embedding Countdowns
You can embed a countdown by using braces:
{C123}
= Quoting Text =
To quote text, preface it with an ">":
> This is quoted text.
This appears like this:
> This is quoted text.
= Embedding Media =
If you set a configuration flag, you can embed media directly in text:
- **remarkup.enable-embedded-youtube**: allows you to paste in YouTube videos
and have them render inline.
This option is disabled by default because it has security and/or
-silliness implications. Read the description in `default.conf.php` before
-enabling it.
+silliness implications. Carefully read the description before enabling it.
= Image Macros =
You can upload image macros (More Stuff -> Macro) which will replace text
strings with the image you specify. For instance, you could upload an image of a
dancing banana to create a macro named "peanutbutterjellytime", and then any
time you type that string on a separate line it will be replaced with the image
of a dancing banana.
= Memes =
You can also use image macros in the context of memes. For example, if you
have an image macro named "grumpy", you can create a meme by doing the
following:
{meme, src = grumpy, above = toptextgoeshere, below = bottomtextgoeshere}
By default, the font used to create the text for the meme is `tuffy.ttf`. For
the more authentic feel of `impact.ttf`, you simply have to place the Impact
TrueType font in the Phabricator subfolder `/resources/font/`. If Remarkup
detects the presence of `impact.ttf`, it will automatically use it.
= Mentioning Users =
In Differential and Maniphest, you can mention another user by writing:
@username
When you submit your comment, this will add them as a CC on the revision or task
if they aren't already CC'd.
Icons
=====
You can add icons to comments using the `{icon ...}` syntax. For example:
{icon camera}
This renders: {icon camera}
You can select a color for icons:
{icon camera color=blue}
This renders: {icon camera color=blue}
For a list of available icons and colors, check the UIExamples application.
(The icons are sourced from
[[ http://fortawesome.github.io/Font-Awesome/ | FontAwesome ]], so you can also
browse the collection there.)
= Phriction Documents =
You can link to Phriction documents with a name or path:
Make sure you sign and date your [[legal/Letter of Marque and Reprisal]]!
With a pipe (`|`), you can retitle the link. Use this to mislead your
opponents:
Check out these [[legal/boring_documents/ | exciting legal documents]]!
= Literal Blocks =
To place text in a literal block use "%%%":
%%%Text that won't be processed by remarkup
[[http://www.example.com | example]]
%%%
Remarkup will not process the text inside of literal blocks (other than to
escape HTML and preserve line breaks).
= Tables =
Remarkup supports simple table syntax. For example, this:
| Fruit | Color | Price | Peel?
| ----- | ----- | ----- | -----
| Apple | red | `$0.93` | no
| Banana | yellow | `$0.19` | **YES**
...produces this:
| Fruit | Color | Price | Peel?
| ----- | ----- | ----- | -----
| Apple | red | `$0.93` | no
| Banana | yellow | `$0.19` | **YES**
Remarkup also supports a simplified HTML table syntax. For example, this:
<table>
<tr>
<th>Fruit</th>
<th>Color</th>
<th>Price</th>
<th>Peel?</th>
</tr>
<tr>
<td>Apple</td>
<td>red</td>
<td>`$0.93`</td>
<td>no</td>
</tr>
<tr>
<td>Banana</td>
<td>yellow</td>
<td>`$0.19`</td>
<td>**YES**</td>
</tr>
</table>
...produces this:
<table>
<tr>
<th>Fruit</th>
<th>Color</th>
<th>Price</th>
<th>Peel?</th>
</tr>
<tr>
<td>Apple</td>
<td>red</td>
<td>`$0.93`</td>
<td>no</td>
</tr>
<tr>
<td>Banana</td>
<td>yellow</td>
<td>`$0.19`</td>
<td>**YES**</td>
</tr>
</table>
Some general notes about this syntax:
- your tags must all be properly balanced;
- your tags must NOT include attributes (`<td>` is OK, `<td style="...">` is
not);
- you can use other Remarkup rules (like **bold**, //italics//, etc.) inside
table cells.
= Fullscreen Mode =
Remarkup editors provide a fullscreen composition mode. This can make it easier
to edit large blocks of text, or improve focus by removing distractions. You can
exit **Fullscreen** mode by clicking the button again or by pressing escape.
diff --git a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
index 3cc7e13c48..fc64eb33fa 100644
--- a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
+++ b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
@@ -1,233 +1,239 @@
<?php
abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
const KEY_RULE_OBJECT = 'rule.object';
const KEY_MENTIONED_OBJECTS = 'rule.object.mentioned';
abstract protected function getObjectNamePrefix();
abstract protected function loadObjects(array $ids);
public function getPriority() {
return 450.0;
}
protected function getObjectNamePrefixBeginsWithWordCharacter() {
$prefix = $this->getObjectNamePrefix();
return preg_match('/^\w/', $prefix);
}
protected function getObjectIDPattern() {
return '[1-9]\d*';
}
protected function shouldMarkupObject(array $params) {
return true;
}
protected function loadHandles(array $objects) {
$phids = mpull($objects, 'getPHID');
$handles = id(new PhabricatorHandleQuery($phids))
->withPHIDs($phids)
->setViewer($this->getEngine()->getConfig('viewer'))
->execute();
$result = array();
foreach ($objects as $id => $object) {
$result[$id] = $handles[$object->getPHID()];
}
return $result;
}
protected function getObjectHref($object, $handle, $id) {
return $handle->getURI();
}
protected function renderObjectRef($object, $handle, $anchor, $id) {
$href = $this->getObjectHref($object, $handle, $id);
$text = $this->getObjectNamePrefix().$id;
if ($anchor) {
$href = $href.'#'.$anchor;
$text = $text.'#'.$anchor;
}
if ($this->getEngine()->isTextMode()) {
return PhabricatorEnv::getProductionURI($href);
}
$status_closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
$attr = array(
'phid' => $handle->getPHID(),
'closed' => ($handle->getStatus() == $status_closed),
);
return $this->renderHovertag($text, $href, $attr);
}
protected function renderObjectEmbed($object, $handle, $options) {
$name = $handle->getFullName();
$href = $handle->getURI();
$status_closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
if ($this->getEngine()->isTextMode()) {
return $name.' <'.PhabricatorEnv::getProductionURI($href).'>';
}
$attr = array(
'phid' => $handle->getPHID(),
'closed' => ($handle->getStatus() == $status_closed),
);
return $this->renderHovertag($name, $href, $attr);
}
protected function renderHovertag($name, $href, array $attr = array()) {
return id(new PHUITagView())
->setName($name)
->setHref($href)
->setType(PHUITagView::TYPE_OBJECT)
->setPHID(idx($attr, 'phid'))
->setClosed(idx($attr, 'closed'))
->render();
}
public function apply($text) {
$prefix = $this->getObjectNamePrefix();
$prefix = preg_quote($prefix, '@');
$id = $this->getObjectIDPattern();
$text = preg_replace_callback(
'@\B{'.$prefix.'('.$id.')((?:[^}\\\\]|\\\\.)*)}\B@',
array($this, 'markupObjectEmbed'),
$text);
// If the prefix starts with a word character (like "D"), we want to
// require a word boundary so that we don't match "XD1" as "D1". If the
// prefix does not start with a word character, we want to require no word
// boundary for the same reasons. Test if the prefix starts with a word
// character.
if ($this->getObjectNamePrefixBeginsWithWordCharacter()) {
$boundary = '\\b';
} else {
$boundary = '\\B';
}
// NOTE: The "(?<!#)" prevents us from linking "#abcdef" or similar.
// The "\b" allows us to link "(abcdef)" or similar without linking things
// in the middle of words.
$text = preg_replace_callback(
'((?<!#)'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?\b)',
array($this, 'markupObjectReference'),
$text);
return $text;
}
public function markupObjectEmbed($matches) {
if (!$this->isFlatText($matches[0])) {
return $matches[0];
}
return $this->markupObject(array(
'type' => 'embed',
'id' => $matches[1],
'options' => idx($matches, 2),
'original' => $matches[0],
));
}
public function markupObjectReference($matches) {
if (!$this->isFlatText($matches[0])) {
return $matches[0];
}
return $this->markupObject(array(
'type' => 'ref',
'id' => $matches[1],
'anchor' => idx($matches, 2),
'original' => $matches[0],
));
}
private function markupObject(array $params) {
if (!$this->shouldMarkupObject($params)) {
return $params['original'];
}
+ $regex = trim(
+ PhabricatorEnv::getEnvConfig('remarkup.ignored-object-names'));
+ if ($regex && preg_match($regex, $params['original'])) {
+ return $params['original'];
+ }
+
$engine = $this->getEngine();
$token = $engine->storeText('x');
$metadata_key = self::KEY_RULE_OBJECT.'.'.$this->getObjectNamePrefix();
$metadata = $engine->getTextMetadata($metadata_key, array());
$metadata[] = array(
'token' => $token,
) + $params;
$engine->setTextMetadata($metadata_key, $metadata);
return $token;
}
public function didMarkupText() {
$engine = $this->getEngine();
$metadata_key = self::KEY_RULE_OBJECT.'.'.$this->getObjectNamePrefix();
$metadata = $engine->getTextMetadata($metadata_key, array());
if (!$metadata) {
return;
}
$ids = ipull($metadata, 'id');
$objects = $this->loadObjects($ids);
// For objects that are invalid or which the user can't see, just render
// the original text.
// TODO: We should probably distinguish between these cases and render a
// "you can't see this" state for nonvisible objects.
foreach ($metadata as $key => $spec) {
if (empty($objects[$spec['id']])) {
$engine->overwriteStoredText(
$spec['token'],
$spec['original']);
unset($metadata[$key]);
}
}
$phids = $engine->getTextMetadata(self::KEY_MENTIONED_OBJECTS, array());
foreach ($objects as $object) {
$phids[$object->getPHID()] = $object->getPHID();
}
$engine->setTextMetadata(self::KEY_MENTIONED_OBJECTS, $phids);
$handles = $this->loadHandles($objects);
foreach ($metadata as $key => $spec) {
$handle = $handles[$spec['id']];
$object = $objects[$spec['id']];
switch ($spec['type']) {
case 'ref':
$view = $this->renderObjectRef(
$object,
$handle,
$spec['anchor'],
$spec['id']);
break;
case 'embed':
$spec['options'] = $this->assertFlatText($spec['options']);
$view = $this->renderObjectEmbed($object, $handle, $spec['options']);
break;
}
$engine->overwriteStoredText($spec['token'], $view);
}
$engine->setTextMetadata($metadata_key, array());
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jul 2, 11:09 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
164883
Default Alt Text
(34 KB)

Event Timeline