mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-01 03:02:43 +01:00
96fe8c0b83
Summary: Ref T9979. This uses ngrams (specifically, trigrams) to build a reasonably efficient index for substring matching. Specifically, for a package like "Example", with ID 123, we store rows like this: ``` < ex, 123> <exa, 123> <xam, 123> <amp, 123> <mpl, 123> <ple, 123> <le , 123> ``` When the user searches for `exam`, we join this table for packages with tokens `exa` and `xam`. MySQL can do this a lot more efficiently than it can process a `LIKE "%exam%"` query against a huge table. When the user searches for a one-letter or two-letter string, we only search the beginnings of words. This is probably what they want, the only thing we can do quickly, and a reasonable/expected behavior for typeaheads. Test Plan: - Ran storage upgrades and search indexer. - Searched for stuff with "name contains". - Used typehaead and got sensible results. - Searched for `aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz` and saw only 16 joins. Reviewers: chad Reviewed By: chad Maniphest Tasks: T9979 Differential Revision: https://secure.phabricator.com/D14846
240 lines
6.4 KiB
PHP
240 lines
6.4 KiB
PHP
<?php
|
|
|
|
final class PhabricatorOwnersPackageTransaction
|
|
extends PhabricatorApplicationTransaction {
|
|
|
|
const TYPE_NAME = 'owners.name';
|
|
const TYPE_PRIMARY = 'owners.primary';
|
|
const TYPE_OWNERS = 'owners.owners';
|
|
const TYPE_AUDITING = 'owners.auditing';
|
|
const TYPE_DESCRIPTION = 'owners.description';
|
|
const TYPE_PATHS = 'owners.paths';
|
|
const TYPE_STATUS = 'owners.status';
|
|
|
|
public function getApplicationName() {
|
|
return 'owners';
|
|
}
|
|
|
|
public function getApplicationTransactionType() {
|
|
return PhabricatorOwnersPackagePHIDType::TYPECONST;
|
|
}
|
|
|
|
public function getRequiredHandlePHIDs() {
|
|
$phids = parent::getRequiredHandlePHIDs();
|
|
|
|
$old = $this->getOldValue();
|
|
$new = $this->getNewValue();
|
|
|
|
switch ($this->getTransactionType()) {
|
|
case self::TYPE_OWNERS:
|
|
if (!is_array($old)) {
|
|
$old = array();
|
|
}
|
|
|
|
if (!is_array($new)) {
|
|
$new = array();
|
|
}
|
|
|
|
$add = array_diff($new, $old);
|
|
foreach ($add as $phid) {
|
|
$phids[] = $phid;
|
|
}
|
|
$rem = array_diff($old, $new);
|
|
foreach ($rem as $phid) {
|
|
$phids[] = $phid;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return $phids;
|
|
}
|
|
|
|
public function shouldHide() {
|
|
$old = $this->getOldValue();
|
|
$new = $this->getNewValue();
|
|
|
|
switch ($this->getTransactionType()) {
|
|
case self::TYPE_DESCRIPTION:
|
|
if ($old === null) {
|
|
return true;
|
|
}
|
|
break;
|
|
case self::TYPE_PRIMARY:
|
|
// TODO: Eventually, remove these transactions entirely.
|
|
return true;
|
|
}
|
|
|
|
return parent::shouldHide();
|
|
}
|
|
|
|
public function getTitle() {
|
|
$old = $this->getOldValue();
|
|
$new = $this->getNewValue();
|
|
$author_phid = $this->getAuthorPHID();
|
|
|
|
switch ($this->getTransactionType()) {
|
|
case PhabricatorTransactions::TYPE_CREATE:
|
|
return pht(
|
|
'%s created this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
case self::TYPE_NAME:
|
|
if ($old === null) {
|
|
return pht(
|
|
'%s created this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
} else {
|
|
return pht(
|
|
'%s renamed this package from "%s" to "%s".',
|
|
$this->renderHandleLink($author_phid),
|
|
$old,
|
|
$new);
|
|
}
|
|
case self::TYPE_OWNERS:
|
|
$add = array_diff($new, $old);
|
|
$rem = array_diff($old, $new);
|
|
if ($add && !$rem) {
|
|
return pht(
|
|
'%s added %s owner(s): %s.',
|
|
$this->renderHandleLink($author_phid),
|
|
count($add),
|
|
$this->renderHandleList($add));
|
|
} else if ($rem && !$add) {
|
|
return pht(
|
|
'%s removed %s owner(s): %s.',
|
|
$this->renderHandleLink($author_phid),
|
|
count($rem),
|
|
$this->renderHandleList($rem));
|
|
} else {
|
|
return pht(
|
|
'%s changed %s package owner(s), added %s: %s; removed %s: %s.',
|
|
$this->renderHandleLink($author_phid),
|
|
count($add) + count($rem),
|
|
count($add),
|
|
$this->renderHandleList($add),
|
|
count($rem),
|
|
$this->renderHandleList($rem));
|
|
}
|
|
case self::TYPE_AUDITING:
|
|
if ($new) {
|
|
return pht(
|
|
'%s enabled auditing for this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
} else {
|
|
return pht(
|
|
'%s disabled auditing for this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
}
|
|
case self::TYPE_DESCRIPTION:
|
|
return pht(
|
|
'%s updated the description for this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
case self::TYPE_PATHS:
|
|
// TODO: Flesh this out.
|
|
return pht(
|
|
'%s updated paths for this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
case self::TYPE_STATUS:
|
|
if ($new == PhabricatorOwnersPackage::STATUS_ACTIVE) {
|
|
return pht(
|
|
'%s activated this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
} else if ($new == PhabricatorOwnersPackage::STATUS_ARCHIVED) {
|
|
return pht(
|
|
'%s archived this package.',
|
|
$this->renderHandleLink($author_phid));
|
|
}
|
|
}
|
|
|
|
return parent::getTitle();
|
|
}
|
|
|
|
public function hasChangeDetails() {
|
|
switch ($this->getTransactionType()) {
|
|
case self::TYPE_DESCRIPTION:
|
|
return ($this->getOldValue() !== null);
|
|
case self::TYPE_PATHS:
|
|
return true;
|
|
}
|
|
|
|
return parent::hasChangeDetails();
|
|
}
|
|
|
|
public function renderChangeDetails(PhabricatorUser $viewer) {
|
|
switch ($this->getTransactionType()) {
|
|
case self::TYPE_DESCRIPTION:
|
|
$old = $this->getOldValue();
|
|
$new = $this->getNewValue();
|
|
|
|
return $this->renderTextCorpusChangeDetails(
|
|
$viewer,
|
|
$old,
|
|
$new);
|
|
case self::TYPE_PATHS:
|
|
$old = $this->getOldValue();
|
|
$new = $this->getNewValue();
|
|
|
|
$diffs = PhabricatorOwnersPath::getTransactionValueChanges($old, $new);
|
|
list($rem, $add) = $diffs;
|
|
|
|
$rows = array();
|
|
foreach ($rem as $ref) {
|
|
$rows[] = array(
|
|
'class' => 'diff-removed',
|
|
'change' => '-',
|
|
) + $ref;
|
|
}
|
|
|
|
foreach ($add as $ref) {
|
|
$rows[] = array(
|
|
'class' => 'diff-added',
|
|
'change' => '+',
|
|
) + $ref;
|
|
}
|
|
|
|
$rowc = array();
|
|
foreach ($rows as $key => $row) {
|
|
$rowc[] = $row['class'];
|
|
$rows[$key] = array(
|
|
$row['change'],
|
|
$row['excluded'] ? pht('Exclude') : pht('Include'),
|
|
$viewer->renderHandle($row['repositoryPHID']),
|
|
$row['path'],
|
|
);
|
|
}
|
|
|
|
$table = id(new AphrontTableView($rows))
|
|
->setRowClasses($rowc)
|
|
->setHeaders(
|
|
array(
|
|
null,
|
|
pht('Type'),
|
|
pht('Repository'),
|
|
pht('Path'),
|
|
))
|
|
->setColumnClasses(
|
|
array(
|
|
null,
|
|
null,
|
|
null,
|
|
'wide',
|
|
));
|
|
|
|
return $table;
|
|
}
|
|
|
|
return parent::renderChangeDetails($viewer);
|
|
}
|
|
|
|
public function getRemarkupBlocks() {
|
|
$blocks = parent::getRemarkupBlocks();
|
|
|
|
switch ($this->getTransactionType()) {
|
|
case self::TYPE_DESCRIPTION:
|
|
$blocks[] = $this->getNewValue();
|
|
break;
|
|
}
|
|
|
|
return $blocks;
|
|
}
|
|
|
|
}
|