mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-16 01:31:06 +01:00
Prepare Diffusion for hovercards
Summary: Move Diffusion to be hovercard-ready, and expand our ability to resolve commit references. - Link unqualified hashes of 7 characters or more which match a commit. - Link qualified hashes of 5 characters or more which match a commit. - Support `{...}` syntax. Test Plan: {F33896} Reviewers: chad, vrana Reviewed By: vrana CC: aran Differential Revision: https://secure.phabricator.com/D5121
This commit is contained in:
parent
b5da7b3723
commit
fe78944c9d
11 changed files with 283 additions and 69 deletions
5
resources/sql/patches/20130226.commitkey.sql
Normal file
5
resources/sql/patches/20130226.commitkey.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository_commit
|
||||||
|
DROP KEY `repositoryID`;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository_commit
|
||||||
|
ADD UNIQUE KEY `key_commit_identity` (commitIdentifier, repositoryID);
|
|
@ -374,6 +374,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
|
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
|
||||||
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
|
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
|
||||||
'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php',
|
'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php',
|
||||||
|
'DiffusionCommitQuery' => 'applications/diffusion/query/DiffusionCommitQuery.php',
|
||||||
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
|
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
|
||||||
'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionCommitTagsQuery.php',
|
'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionCommitTagsQuery.php',
|
||||||
'DiffusionContainsQuery' => 'applications/diffusion/query/contains/DiffusionContainsQuery.php',
|
'DiffusionContainsQuery' => 'applications/diffusion/query/contains/DiffusionContainsQuery.php',
|
||||||
|
@ -1186,7 +1187,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRemarkupRuleMeme' => 'applications/macro/remarkup/PhabricatorRemarkupRuleMeme.php',
|
'PhabricatorRemarkupRuleMeme' => 'applications/macro/remarkup/PhabricatorRemarkupRuleMeme.php',
|
||||||
'PhabricatorRemarkupRuleMention' => 'applications/people/remarkup/PhabricatorRemarkupRuleMention.php',
|
'PhabricatorRemarkupRuleMention' => 'applications/people/remarkup/PhabricatorRemarkupRuleMention.php',
|
||||||
'PhabricatorRemarkupRuleObject' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObject.php',
|
'PhabricatorRemarkupRuleObject' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObject.php',
|
||||||
'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObjectName.php',
|
|
||||||
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php',
|
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php',
|
||||||
'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php',
|
'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php',
|
||||||
'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/PhabricatorRepositoryArcanistProject.php',
|
'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/PhabricatorRepositoryArcanistProject.php',
|
||||||
|
@ -1898,6 +1898,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionCommitController' => 'DiffusionController',
|
'DiffusionCommitController' => 'DiffusionController',
|
||||||
'DiffusionCommitEditController' => 'DiffusionController',
|
'DiffusionCommitEditController' => 'DiffusionController',
|
||||||
'DiffusionCommitParentsQuery' => 'DiffusionQuery',
|
'DiffusionCommitParentsQuery' => 'DiffusionQuery',
|
||||||
|
'DiffusionCommitQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'DiffusionCommitTagsController' => 'DiffusionController',
|
'DiffusionCommitTagsController' => 'DiffusionController',
|
||||||
'DiffusionCommitTagsQuery' => 'DiffusionQuery',
|
'DiffusionCommitTagsQuery' => 'DiffusionQuery',
|
||||||
'DiffusionContainsQuery' => 'DiffusionQuery',
|
'DiffusionContainsQuery' => 'DiffusionQuery',
|
||||||
|
@ -1953,7 +1954,7 @@ phutil_register_library_map(array(
|
||||||
'DiffusionPathValidateController' => 'DiffusionController',
|
'DiffusionPathValidateController' => 'DiffusionController',
|
||||||
'DiffusionPeopleMenuEventListener' => 'PhutilEventListener',
|
'DiffusionPeopleMenuEventListener' => 'PhutilEventListener',
|
||||||
'DiffusionRawDiffQuery' => 'DiffusionQuery',
|
'DiffusionRawDiffQuery' => 'DiffusionQuery',
|
||||||
'DiffusionRemarkupRule' => 'PhabricatorRemarkupRuleObjectName',
|
'DiffusionRemarkupRule' => 'PhabricatorRemarkupRuleObject',
|
||||||
'DiffusionRepositoryController' => 'DiffusionController',
|
'DiffusionRepositoryController' => 'DiffusionController',
|
||||||
'DiffusionSetupException' => 'AphrontUsageException',
|
'DiffusionSetupException' => 'AphrontUsageException',
|
||||||
'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
|
'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
|
||||||
|
@ -2661,7 +2662,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRemarkupRuleMeme' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleMeme' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleObject' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleObject' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule',
|
|
||||||
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRepository' =>
|
'PhabricatorRepository' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2673,7 +2673,11 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
|
'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
|
||||||
'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryCommit' =>
|
||||||
|
array(
|
||||||
|
0 => 'PhabricatorRepositoryDAO',
|
||||||
|
1 => 'PhabricatorPolicyInterface',
|
||||||
|
),
|
||||||
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||||
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
|
||||||
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
|
||||||
|
|
|
@ -30,6 +30,12 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRemarkupRules() {
|
||||||
|
return array(
|
||||||
|
new DiffusionRemarkupRule(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
return array(
|
||||||
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)'
|
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)'
|
||||||
|
|
140
src/applications/diffusion/query/DiffusionCommitQuery.php
Normal file
140
src/applications/diffusion/query/DiffusionCommitQuery.php
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DiffusionCommitQuery
|
||||||
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $identifiers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load commits by partial or full identifiers, e.g. "rXab82393", "rX1234",
|
||||||
|
* or "a9caf12". When an identifier matches multiple commits, they will all
|
||||||
|
* be returned; callers should be prepared to deal with more results than
|
||||||
|
* they queried for.
|
||||||
|
*/
|
||||||
|
public function withIdentifiers(array $identifiers) {
|
||||||
|
$this->identifiers = $identifiers;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadPage() {
|
||||||
|
$table = new PhabricatorRepositoryCommit();
|
||||||
|
$conn_r = $table->establishConnection('r');
|
||||||
|
|
||||||
|
$data = queryfx_all(
|
||||||
|
$conn_r,
|
||||||
|
'SELECT * FROM %T %Q %Q %Q',
|
||||||
|
$table->getTableName(),
|
||||||
|
$this->buildWhereClause($conn_r),
|
||||||
|
$this->buildOrderClause($conn_r),
|
||||||
|
$this->buildLimitClause($conn_r));
|
||||||
|
|
||||||
|
return $table->loadAllFromArray($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function willFilterPage(array $commits) {
|
||||||
|
if (!$commits) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$repository_ids = mpull($commits, 'getRepositoryID', 'getRepositoryID');
|
||||||
|
$repos = id(new PhabricatorRepositoryQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withIDs($repository_ids)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
foreach ($commits as $key => $commit) {
|
||||||
|
$repo = idx($repos, $commit->getRepositoryID());
|
||||||
|
if ($repo) {
|
||||||
|
$commit->attachRepository($repo);
|
||||||
|
} else {
|
||||||
|
unset($commits[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $commits;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
||||||
|
$where = array();
|
||||||
|
|
||||||
|
if ($this->identifiers) {
|
||||||
|
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
|
||||||
|
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
|
||||||
|
|
||||||
|
$refs = array();
|
||||||
|
$bare = array();
|
||||||
|
foreach ($this->identifiers as $identifier) {
|
||||||
|
$matches = null;
|
||||||
|
preg_match('/^(?:r([A-Z]+))?(.*)$/', $identifier, $matches);
|
||||||
|
$repo = nonempty($matches[1], null);
|
||||||
|
$identifier = nonempty($matches[2], null);
|
||||||
|
|
||||||
|
if ($repo === null) {
|
||||||
|
if (strlen($identifier) < $min_unqualified) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$bare[] = $identifier;
|
||||||
|
} else {
|
||||||
|
$refs[] = array(
|
||||||
|
'callsign' => $repo,
|
||||||
|
'identifier' => $identifier,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = array();
|
||||||
|
|
||||||
|
foreach ($bare as $identifier) {
|
||||||
|
$sql[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'(commitIdentifier LIKE %> AND LENGTH(commitIdentifier) = 40)',
|
||||||
|
$identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($refs) {
|
||||||
|
$callsigns = ipull($refs, 'callsign');
|
||||||
|
$repos = id(new PhabricatorRepositoryQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withCallsigns($callsigns)
|
||||||
|
->execute();
|
||||||
|
$repos = mpull($repos, null, 'getCallsign');
|
||||||
|
|
||||||
|
foreach ($refs as $key => $ref) {
|
||||||
|
$repo = idx($repos, $ref['callsign']);
|
||||||
|
if (!$repo) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($repo->isSVN()) {
|
||||||
|
$sql[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'(repositoryID = %d AND commitIdentifier = %d)',
|
||||||
|
$repo->getID(),
|
||||||
|
$ref['identifier']);
|
||||||
|
} else {
|
||||||
|
if (strlen($ref['identifier']) < $min_qualified) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$sql[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'(repositoryID = %d AND commitIdentifier LIKE %>)',
|
||||||
|
$repo->getID(),
|
||||||
|
$ref['identifier']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sql) {
|
||||||
|
$where[] = '('.implode(' OR ', $sql).')';
|
||||||
|
} else {
|
||||||
|
// If we discarded all possible identifiers (e.g., they all referenced
|
||||||
|
// bogus repositories or were all too short), make sure the query finds
|
||||||
|
// nothing.
|
||||||
|
$where[] = qsprintf($conn_r, '1 = 0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->formatWhereClause($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,79 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
|
||||||
* @group markup
|
|
||||||
*/
|
|
||||||
final class DiffusionRemarkupRule
|
final class DiffusionRemarkupRule
|
||||||
extends PhabricatorRemarkupRuleObjectName {
|
extends PhabricatorRemarkupRuleObject {
|
||||||
|
|
||||||
protected function getObjectNamePrefix() {
|
protected function getObjectNamePrefix() {
|
||||||
return 'r';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getObjectIDPattern() {
|
protected function getObjectIDPattern() {
|
||||||
return '[A-Z]+[a-f0-9]+';
|
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
|
||||||
|
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
|
||||||
|
|
||||||
|
return
|
||||||
|
'(?:r[A-Z]+)?[0-9]+'.
|
||||||
|
'|'.
|
||||||
|
'(?:r[A-Z]+)?[a-f0-9]{'.$min_qualified.',40}'.
|
||||||
|
'|'.
|
||||||
|
'[a-f0-9]{'.$min_unqualified.',40}';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadObjects(array $ids) {
|
||||||
|
$viewer = $this->getEngine()->getConfig('viewer');
|
||||||
|
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
|
||||||
|
|
||||||
|
if (!$viewer) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$commits = id(new DiffusionCommitQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIdentifiers($ids)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if (!$commits) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = array_fuse($ids);
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
foreach ($commits as $commit) {
|
||||||
|
$prefix = 'r'.$commit->getRepository()->getCallsign();
|
||||||
|
$suffix = $commit->getCommitIdentifier();
|
||||||
|
|
||||||
|
if ($commit->getRepository()->isSVN()) {
|
||||||
|
if (isset($ids[$prefix.$suffix])) {
|
||||||
|
$result[$prefix.$suffix][] = $commit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This awkward contruction is so we can link the commits up in O(N)
|
||||||
|
// time instead of O(N^2).
|
||||||
|
for ($ii = $min_qualified; $ii <= strlen($suffix); $ii++) {
|
||||||
|
$part = substr($suffix, 0, $ii);
|
||||||
|
if (isset($ids[$prefix.$part])) {
|
||||||
|
$result[$prefix.$part][] = $commit;
|
||||||
|
}
|
||||||
|
if (isset($ids[$part])) {
|
||||||
|
$result[$part][] = $commit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($result as $identifier => $commits) {
|
||||||
|
if (count($commits) == 1) {
|
||||||
|
$result[$identifier] = head($commits);
|
||||||
|
} else {
|
||||||
|
// This reference is ambiguous -- it matches more than one commit -- so
|
||||||
|
// don't link it. We could potentially improve this, but it's a bit
|
||||||
|
// tricky since the superclass expects a single object.
|
||||||
|
unset($result[$identifier]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,16 @@
|
||||||
final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
implements PhabricatorPolicyInterface {
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortest hash we'll recognize in raw "a829f32" form.
|
||||||
|
*/
|
||||||
|
const MINIMUM_UNQUALIFIED_HASH = 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortest hash we'll recognize in qualified "rXab7ef2f8" form.
|
||||||
|
*/
|
||||||
|
const MINIMUM_QUALIFIED_HASH = 5;
|
||||||
|
|
||||||
const TABLE_PATH = 'repository_path';
|
const TABLE_PATH = 'repository_path';
|
||||||
const TABLE_PATHCHANGE = 'repository_pathchange';
|
const TABLE_PATHCHANGE = 'repository_pathchange';
|
||||||
const TABLE_FILESYSTEM = 'repository_filesystem';
|
const TABLE_FILESYSTEM = 'repository_filesystem';
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorRepositoryCommit extends PhabricatorRepositoryDAO {
|
final class PhabricatorRepositoryCommit
|
||||||
|
extends PhabricatorRepositoryDAO
|
||||||
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
protected $repositoryID;
|
protected $repositoryID;
|
||||||
protected $phid;
|
protected $phid;
|
||||||
|
@ -14,6 +16,19 @@ final class PhabricatorRepositoryCommit extends PhabricatorRepositoryDAO {
|
||||||
private $commitData;
|
private $commitData;
|
||||||
private $audits;
|
private $audits;
|
||||||
private $isUnparsed;
|
private $isUnparsed;
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
public function attachRepository(PhabricatorRepository $repository) {
|
||||||
|
$this->repository = $repository;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRepository() {
|
||||||
|
if ($this->repository === null) {
|
||||||
|
throw new Exception("Call attachRepository() before getRepository()!");
|
||||||
|
}
|
||||||
|
return $this->repository;
|
||||||
|
}
|
||||||
|
|
||||||
public function setIsUnparsed($is_unparsed) {
|
public function setIsUnparsed($is_unparsed) {
|
||||||
$this->isUnparsed = $is_unparsed;
|
$this->isUnparsed = $is_unparsed;
|
||||||
|
@ -138,4 +153,22 @@ final class PhabricatorRepositoryCommit extends PhabricatorRepositoryDAO {
|
||||||
|
|
||||||
return $this->setAuditStatus($status);
|
return $this->setAuditStatus($status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
public function getCapabilities() {
|
||||||
|
return array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPolicy($capability) {
|
||||||
|
return $this->getRepository()->getPolicy($capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||||
|
return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ final class PhabricatorMarkupEngine {
|
||||||
|
|
||||||
private $objects = array();
|
private $objects = array();
|
||||||
private $viewer;
|
private $viewer;
|
||||||
private $version = 4;
|
private $version = 5;
|
||||||
|
|
||||||
|
|
||||||
/* -( Markup Pipeline )---------------------------------------------------- */
|
/* -( Markup Pipeline )---------------------------------------------------- */
|
||||||
|
@ -401,9 +401,6 @@ final class PhabricatorMarkupEngine {
|
||||||
$rules[] = new PhrictionRemarkupRule();
|
$rules[] = new PhrictionRemarkupRule();
|
||||||
|
|
||||||
$rules[] = new PhabricatorRemarkupRuleEmbedFile();
|
$rules[] = new PhabricatorRemarkupRuleEmbedFile();
|
||||||
|
|
||||||
$rules[] = new DiffusionRemarkupRule();
|
|
||||||
|
|
||||||
$rules[] = new PhabricatorCountdownRemarkupRule();
|
$rules[] = new PhabricatorCountdownRemarkupRule();
|
||||||
|
|
||||||
$applications = PhabricatorApplication::getAllInstalledApplications();
|
$applications = PhabricatorApplication::getAllInstalledApplications();
|
||||||
|
|
|
@ -36,9 +36,9 @@ abstract class PhabricatorRemarkupRuleObject
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderObjectRef($object, $handle, $anchor) {
|
protected function renderObjectRef($object, $handle, $anchor, $id) {
|
||||||
$href = $handle->getURI();
|
$href = $handle->getURI();
|
||||||
$text = $this->getObjectNamePrefix().$object->getID();
|
$text = $this->getObjectNamePrefix().$id;
|
||||||
if ($anchor) {
|
if ($anchor) {
|
||||||
$matches = null;
|
$matches = null;
|
||||||
if (preg_match('@^#(?:comment-)?(\d{1,7})$@', $anchor, $matches)) {
|
if (preg_match('@^#(?:comment-)?(\d{1,7})$@', $anchor, $matches)) {
|
||||||
|
@ -172,7 +172,11 @@ abstract class PhabricatorRemarkupRuleObject
|
||||||
$object = $objects[$spec['id']];
|
$object = $objects[$spec['id']];
|
||||||
switch ($spec['type']) {
|
switch ($spec['type']) {
|
||||||
case 'ref':
|
case 'ref':
|
||||||
$view = $this->renderObjectRef($object, $handle, $spec['anchor']);
|
$view = $this->renderObjectRef(
|
||||||
|
$object,
|
||||||
|
$handle,
|
||||||
|
$spec['anchor'],
|
||||||
|
$spec['id']);
|
||||||
break;
|
break;
|
||||||
case 'embed':
|
case 'embed':
|
||||||
$view = $this->renderObjectEmbed($object, $handle, $spec['options']);
|
$view = $this->renderObjectEmbed($object, $handle, $spec['options']);
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @group markup
|
|
||||||
*/
|
|
||||||
abstract class PhabricatorRemarkupRuleObjectName
|
|
||||||
extends PhutilRemarkupRule {
|
|
||||||
|
|
||||||
abstract protected function getObjectNamePrefix();
|
|
||||||
|
|
||||||
protected function getObjectIDPattern() {
|
|
||||||
return '[1-9]\d*';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function apply($text) {
|
|
||||||
$prefix = $this->getObjectNamePrefix();
|
|
||||||
$id = $this->getObjectIDPattern();
|
|
||||||
return preg_replace_callback(
|
|
||||||
"@\b({$prefix})({$id})(?:#([-\w\d]+))?\b@",
|
|
||||||
array($this, 'markupObjectNameLink'),
|
|
||||||
$text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function markupObjectNameLink($matches) {
|
|
||||||
list(, $prefix, $id) = $matches;
|
|
||||||
|
|
||||||
if (isset($matches[3])) {
|
|
||||||
$href = $matches[3];
|
|
||||||
$text = $matches[3];
|
|
||||||
if (preg_match('@^(?:comment-)?(\d{1,7})$@', $href, $matches)) {
|
|
||||||
// Maximum length is 7 because 12345678 could be a file hash.
|
|
||||||
$href = "comment-{$matches[1]}";
|
|
||||||
$text = $matches[1];
|
|
||||||
}
|
|
||||||
$href = "/{$prefix}{$id}#{$href}";
|
|
||||||
$text = "{$prefix}{$id}#{$text}";
|
|
||||||
} else {
|
|
||||||
$href = "/{$prefix}{$id}";
|
|
||||||
$text = "{$prefix}{$id}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getEngine()->storeText(
|
|
||||||
phutil_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => $href,
|
|
||||||
),
|
|
||||||
$text));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1153,6 +1153,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('20130222.dropchannel.sql'),
|
'name' => $this->getPatchPath('20130222.dropchannel.sql'),
|
||||||
),
|
),
|
||||||
|
'20130226.commitkey.sql' => array(
|
||||||
|
'type' => 'sql',
|
||||||
|
'name' => $this->getPatchPath('20130226.commitkey.sql'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue