Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
index ccae58d03e..89ca641b91 100644
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -1,456 +1,447 @@
<?php
final class PhabricatorProjectTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorProjectApplication';
}
public function getEditorObjectsDescription() {
return pht('Projects');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_JOIN_POLICY;
$types[] = PhabricatorProjectTransaction::TYPE_NAME;
$types[] = PhabricatorProjectTransaction::TYPE_SLUGS;
$types[] = PhabricatorProjectTransaction::TYPE_STATUS;
$types[] = PhabricatorProjectTransaction::TYPE_IMAGE;
$types[] = PhabricatorProjectTransaction::TYPE_ICON;
$types[] = PhabricatorProjectTransaction::TYPE_COLOR;
$types[] = PhabricatorProjectTransaction::TYPE_LOCKED;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorProjectTransaction::TYPE_SLUGS:
$slugs = $object->getSlugs();
$slugs = mpull($slugs, 'getSlug', 'getSlug');
unset($slugs[$object->getPrimarySlug()]);
return $slugs;
case PhabricatorProjectTransaction::TYPE_STATUS:
return $object->getStatus();
case PhabricatorProjectTransaction::TYPE_IMAGE:
return $object->getProfileImagePHID();
case PhabricatorProjectTransaction::TYPE_ICON:
return $object->getIcon();
case PhabricatorProjectTransaction::TYPE_COLOR:
return $object->getColor();
case PhabricatorProjectTransaction::TYPE_LOCKED:
return (int) $object->getIsMembershipLocked();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_NAME:
case PhabricatorProjectTransaction::TYPE_SLUGS:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
case PhabricatorProjectTransaction::TYPE_ICON:
case PhabricatorProjectTransaction::TYPE_COLOR:
case PhabricatorProjectTransaction::TYPE_LOCKED:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
+ // TODO - this is really "setPrimarySlug"
$object->setPhrictionSlug($xaction->getNewValue());
return;
case PhabricatorProjectTransaction::TYPE_SLUGS:
return;
case PhabricatorProjectTransaction::TYPE_STATUS:
$object->setStatus($xaction->getNewValue());
return;
case PhabricatorProjectTransaction::TYPE_IMAGE:
$object->setProfileImagePHID($xaction->getNewValue());
return;
case PhabricatorProjectTransaction::TYPE_ICON:
$object->setIcon($xaction->getNewValue());
return;
case PhabricatorProjectTransaction::TYPE_COLOR:
$object->setColor($xaction->getNewValue());
return;
case PhabricatorProjectTransaction::TYPE_LOCKED:
$object->setIsMembershipLocked($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
case PhabricatorTransactions::TYPE_EDGE:
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
$object->setViewPolicy($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_EDIT_POLICY:
$object->setEditPolicy($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_JOIN_POLICY:
$object->setJoinPolicy($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_NAME:
- // First, remove the old and new slugs. Removing the old slug is
- // important when changing the project's capitalization or punctuation.
- // Removing the new slug is important when changing the project's name
- // so that one of its secondary slugs is now the primary slug.
+ // First, add the old name as a secondary slug; this is helpful
+ // for renames and generally a good thing to do.
if ($old !== null) {
- $this->removeSlug($object, $old);
+ $this->addSlug($object, $old);
}
- $this->removeSlug($object, $new);
-
- $new_slug = id(new PhabricatorProjectSlug())
- ->setSlug($object->getPrimarySlug())
- ->setProjectPHID($object->getPHID())
- ->save();
+ $this->addSlug($object, $new);
return;
case PhabricatorProjectTransaction::TYPE_SLUGS:
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add) {
$add_slug_template = id(new PhabricatorProjectSlug())
->setProjectPHID($object->getPHID());
foreach ($add as $add_slug_str) {
$add_slug = id(clone $add_slug_template)
->setSlug($add_slug_str)
->save();
}
}
if ($rem) {
$rem_slugs = id(new PhabricatorProjectSlug())
->loadAllWhere('slug IN (%Ls)', $rem);
foreach ($rem_slugs as $rem_slug) {
$rem_slug->delete();
}
}
return;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
case PhabricatorProjectTransaction::TYPE_ICON:
case PhabricatorProjectTransaction::TYPE_COLOR:
case PhabricatorProjectTransaction::TYPE_LOCKED:
return;
case PhabricatorTransactions::TYPE_EDGE:
$edge_type = $xaction->getMetadataValue('edge:type');
switch ($edge_type) {
case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST:
case PhabricatorObjectHasWatcherEdgeType::EDGECONST:
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
// When adding members or watchers, we add subscriptions.
$add = array_keys(array_diff_key($new, $old));
// When removing members, we remove their subscription too.
// When unwatching, we leave subscriptions, since it's fine to be
// subscribed to a project but not be a member of it.
$edge_const = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
if ($edge_type == $edge_const) {
$rem = array_keys(array_diff_key($old, $new));
} else {
$rem = array();
}
// NOTE: The subscribe is "explicit" because there's no implicit
// unsubscribe, so Join -> Leave -> Join doesn't resubscribe you
// if we use an implicit subscribe, even though you never willfully
// unsubscribed. Not sure if adding implicit unsubscribe (which
// would not write the unsubscribe row) is justified to deal with
// this, which is a fairly weird edge case and pretty arguable both
// ways.
// Subscriptions caused by watches should also clearly be explicit,
// and that case is unambiguous.
id(new PhabricatorSubscriptionsEditor())
->setActor($this->requireActor())
->setObject($object)
->subscribeExplicit($add)
->unsubscribe($rem)
->save();
if ($rem) {
// When removing members, also remove any watches on the project.
$edge_editor = new PhabricatorEdgeEditor();
foreach ($rem as $rem_phid) {
$edge_editor->removeEdge(
$object->getPHID(),
PhabricatorObjectHasWatcherEdgeType::EDGECONST,
$rem_phid);
}
$edge_editor->save();
}
break;
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorProjectTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Project name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
if (!$xactions) {
break;
}
$name = last($xactions)->getNewValue();
$name_used_already = id(new PhabricatorProjectQuery())
->setViewer($this->getActor())
->withNames(array($name))
->executeOne();
if ($name_used_already &&
($name_used_already->getPHID() != $object->getPHID())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Duplicate'),
pht('Project name is already used.'),
nonempty(last($xactions), null));
$errors[] = $error;
}
$slug_builder = clone $object;
$slug_builder->setPhrictionSlug($name);
$slug = $slug_builder->getPrimarySlug();
$slug_used_already = id(new PhabricatorProjectSlug())
->loadOneWhere('slug = %s', $slug);
if ($slug_used_already &&
$slug_used_already->getProjectPHID() != $object->getPHID()) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Duplicate'),
pht('Project name can not be used due to hashtag collision.'),
nonempty(last($xactions), null));
$errors[] = $error;
}
break;
case PhabricatorProjectTransaction::TYPE_SLUGS:
if (!$xactions) {
break;
}
$slug_xaction = last($xactions);
$new = $slug_xaction->getNewValue();
if ($new) {
$slugs_used_already = id(new PhabricatorProjectSlug())
->loadAllWhere('slug IN (%Ls)', $new);
} else {
// The project doesn't have any extra slugs.
$slugs_used_already = array();
}
$slugs_used_already = mgroup($slugs_used_already, 'getProjectPHID');
foreach ($slugs_used_already as $project_phid => $used_slugs) {
$used_slug_strs = mpull($used_slugs, 'getSlug');
if ($project_phid == $object->getPHID()) {
if (in_array($object->getPrimarySlug(), $used_slug_strs)) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Project hashtag %s is already the primary hashtag.',
$object->getPrimarySlug()),
$slug_xaction);
$errors[] = $error;
}
continue;
}
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'%d project hashtag(s) are already used: %s.',
count($used_slug_strs),
implode(', ', $used_slug_strs)),
$slug_xaction);
$errors[] = $error;
}
break;
}
return $errors;
}
protected function requireCapabilities(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_NAME:
case PhabricatorProjectTransaction::TYPE_STATUS:
case PhabricatorProjectTransaction::TYPE_IMAGE:
case PhabricatorProjectTransaction::TYPE_ICON:
case PhabricatorProjectTransaction::TYPE_COLOR:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
return;
case PhabricatorProjectTransaction::TYPE_LOCKED:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
newv($this->getEditorApplicationClass(), array()),
ProjectCanLockProjectsCapability::CAPABILITY);
return;
case PhabricatorTransactions::TYPE_EDGE:
switch ($xaction->getMetadataValue('edge:type')) {
case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST:
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$add = array_keys(array_diff_key($new, $old));
$rem = array_keys(array_diff_key($old, $new));
$actor_phid = $this->requireActor()->getPHID();
$is_join = (($add === array($actor_phid)) && !$rem);
$is_leave = (($rem === array($actor_phid)) && !$add);
if ($is_join) {
// You need CAN_JOIN to join a project.
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_JOIN);
} else if ($is_leave) {
// You usually don't need any capabilities to leave a project.
if ($object->getIsMembershipLocked()) {
// you must be able to edit though to leave locked projects
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
}
} else {
// You need CAN_EDIT to change members other than yourself.
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
}
return;
}
break;
}
return parent::requireCapabilities($object, $xaction);
}
protected function supportsSearch() {
return true;
}
protected function extractFilePHIDsFromCustomTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectTransaction::TYPE_IMAGE:
$new = $xaction->getNewValue();
if ($new) {
return array($new);
}
break;
}
return parent::extractFilePHIDsFromCustomTransaction($object, $xaction);
}
- private function removeSlug(
+ private function addSlug(
PhabricatorLiskDAO $object,
$name) {
$object = (clone $object);
$object->setPhrictionSlug($name);
$slug = $object->getPrimarySlug();
$slug_object = id(new PhabricatorProjectSlug())->loadOneWhere(
'slug = %s',
$slug);
- if (!$slug_object) {
+ if ($slug_object) {
return;
}
- if ($slug_object->getProjectPHID() != $object->getPHID()) {
- throw new Exception(
- pht('Trying to remove slug owned by another project!'));
- }
-
- $slug_object->delete();
+ $new_slug = id(new PhabricatorProjectSlug())
+ ->setSlug($slug)
+ ->setProjectPHID($object->getPHID())
+ ->save();
}
-
}
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
index 71ad3e6cdc..486055691a 100644
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -1,392 +1,387 @@
<?php
final class PhabricatorProjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
private $slugs;
private $phrictionSlugs;
private $names;
private $datasourceQuery;
private $icons;
private $colors;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ACTIVE = 'status-active';
const STATUS_ARCHIVED = 'status-archived';
private $needSlugs;
private $needMembers;
private $needWatchers;
private $needImages;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withMemberPHIDs(array $member_phids) {
$this->memberPHIDs = $member_phids;
return $this;
}
public function withSlugs(array $slugs) {
$this->slugs = $slugs;
return $this;
}
public function withPhrictionSlugs(array $slugs) {
$this->phrictionSlugs = $slugs;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withDatasourceQuery($string) {
$this->datasourceQuery = $string;
return $this;
}
public function withIcons(array $icons) {
$this->icons = $icons;
return $this;
}
public function withColors(array $colors) {
$this->colors = $colors;
return $this;
}
public function needMembers($need_members) {
$this->needMembers = $need_members;
return $this;
}
public function needWatchers($need_watchers) {
$this->needWatchers = $need_watchers;
return $this;
}
public function needImages($need_images) {
$this->needImages = $need_images;
return $this;
}
public function needSlugs($need_slugs) {
$this->needSlugs = $need_slugs;
return $this;
}
protected function getPagingColumn() {
return 'name';
}
protected function getPagingValue($result) {
return $result->getName();
}
protected function getReversePaging() {
return true;
}
protected function loadPage() {
$table = new PhabricatorProject();
$conn_r = $table->establishConnection('r');
// NOTE: Because visibility checks for projects depend on whether or not
// the user is a project member, we always load their membership. If we're
// loading all members anyway we can piggyback on that; otherwise we
// do an explicit join.
$select_clause = '';
if (!$this->needMembers) {
$select_clause = ', vm.dst viewerIsMember';
}
$data = queryfx_all(
$conn_r,
'SELECT p.* %Q FROM %T p %Q %Q %Q %Q %Q',
$select_clause,
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$projects = $table->loadAllFromArray($data);
if ($projects) {
$viewer_phid = $this->getViewer()->getPHID();
$project_phids = mpull($projects, 'getPHID');
$member_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
$watcher_type = PhabricatorObjectHasWatcherEdgeType::EDGECONST;
$need_edge_types = array();
if ($this->needMembers) {
$need_edge_types[] = $member_type;
} else {
foreach ($data as $row) {
$projects[$row['id']]->setIsUserMember(
$viewer_phid,
($row['viewerIsMember'] !== null));
}
}
if ($this->needWatchers) {
$need_edge_types[] = $watcher_type;
}
if ($need_edge_types) {
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($project_phids)
->withEdgeTypes($need_edge_types)
->execute();
if ($this->needMembers) {
foreach ($projects as $project) {
$phid = $project->getPHID();
$project->attachMemberPHIDs(
array_keys($edges[$phid][$member_type]));
$project->setIsUserMember(
$viewer_phid,
isset($edges[$phid][$member_type][$viewer_phid]));
}
}
if ($this->needWatchers) {
foreach ($projects as $project) {
$phid = $project->getPHID();
$project->attachWatcherPHIDs(
array_keys($edges[$phid][$watcher_type]));
$project->setIsUserWatcher(
$viewer_phid,
isset($edges[$phid][$watcher_type][$viewer_phid]));
}
}
}
}
return $projects;
}
protected function didFilterPage(array $projects) {
if ($this->needImages) {
$default = null;
$file_phids = mpull($projects, 'getProfileImagePHID');
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($projects as $project) {
$file = idx($files, $project->getProfileImagePHID());
if (!$file) {
if (!$default) {
$default = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'project.png');
}
$file = $default;
}
$project->attachProfileImageFile($file);
}
}
if ($this->needSlugs) {
$slugs = id(new PhabricatorProjectSlug())
->loadAllWhere(
'projectPHID IN (%Ls)',
mpull($projects, 'getPHID'));
$slugs = mgroup($slugs, 'getProjectPHID');
foreach ($projects as $project) {
$project_slugs = idx($slugs, $project->getPHID(), array());
$project->attachSlugs($project_slugs);
}
}
return $projects;
}
private function buildWhereClause($conn_r) {
$where = array();
if ($this->status != self::STATUS_ANY) {
switch ($this->status) {
case self::STATUS_OPEN:
case self::STATUS_ACTIVE:
$filter = array(
PhabricatorProjectStatus::STATUS_ACTIVE,
);
break;
case self::STATUS_CLOSED:
case self::STATUS_ARCHIVED:
$filter = array(
PhabricatorProjectStatus::STATUS_ARCHIVED,
);
break;
default:
throw new Exception(
"Unknown project status '{$this->status}'!");
}
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
$filter);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'e.dst IN (%Ls)',
$this->memberPHIDs);
}
if ($this->slugs !== null) {
- $slugs = array();
- foreach ($this->slugs as $slug) {
- $slugs[] = rtrim(PhabricatorSlug::normalize($slug), '/');
- }
-
$where[] = qsprintf(
$conn_r,
'slug.slug IN (%Ls)',
- $slugs);
+ $this->slugs);
}
if ($this->phrictionSlugs !== null) {
$where[] = qsprintf(
$conn_r,
'phrictionSlug IN (%Ls)',
$this->phrictionSlugs);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
if ($this->icons !== null) {
$where[] = qsprintf(
$conn_r,
'icon IN (%Ls)',
$this->icons);
}
if ($this->colors !== null) {
$where[] = qsprintf(
$conn_r,
'color IN (%Ls)',
$this->colors);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function buildGroupClause($conn_r) {
if ($this->memberPHIDs || $this->datasourceQuery) {
return 'GROUP BY p.id';
} else {
return $this->buildApplicationSearchGroupClause($conn_r);
}
}
private function buildJoinClause($conn_r) {
$joins = array();
if (!$this->needMembers !== null) {
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T vm ON vm.src = p.phid AND vm.type = %d AND vm.dst = %s',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectProjectHasMemberEdgeType::EDGECONST,
$this->getViewer()->getPHID());
}
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T e ON e.src = p.phid AND e.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectProjectHasMemberEdgeType::EDGECONST);
}
if ($this->slugs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T slug on slug.projectPHID = p.phid',
id(new PhabricatorProjectSlug())->getTableName());
}
if ($this->datasourceQuery !== null) {
$tokens = PhabricatorTypeaheadDatasource::tokenizeString(
$this->datasourceQuery);
if (!$tokens) {
throw new PhabricatorEmptyQueryException();
}
$likes = array();
foreach ($tokens as $token) {
$likes[] = qsprintf($conn_r, 'token.token LIKE %>', $token);
}
$joins[] = qsprintf(
$conn_r,
'JOIN %T token ON token.projectID = p.id AND (%Q)',
PhabricatorProject::TABLE_DATASOURCE_TOKEN,
'('.implode(') OR (', $likes).')');
}
$joins[] = $this->buildApplicationSearchJoinClause($conn_r);
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorProjectApplication';
}
protected function getApplicationSearchObjectPHIDColumn() {
return 'p.phid';
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Aug 14, 11:32 AM (6 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
202268
Default Alt Text
(27 KB)

Event Timeline