Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
index 1dfc466712..4b6ad566a7 100644
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -1,398 +1,393 @@
<?php
final class PhabricatorProjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
private $slugs;
private $phrictionSlugs;
private $names;
- private $datasourceQuery;
+ private $nameTokens;
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;
+ public function withNameTokens(array $tokens) {
+ $this->nameTokens = array_values($tokens);
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 getDefaultOrderVector() {
return array('name');
}
public function getOrderableColumns() {
return array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'reverse' => true,
'type' => 'string',
'unique' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$project = $this->loadCursorObject($cursor);
return array(
'name' => $project->getName(),
);
}
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) {
$where[] = qsprintf(
$conn_r,
'slug.slug IN (%Ls)',
$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) {
+ if ($this->memberPHIDs || $this->nameTokens) {
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();
+ if ($this->nameTokens !== null) {
+ foreach ($this->nameTokens as $key => $token) {
+ $token_table = 'token_'.$key;
+ $joins[] = qsprintf(
+ $conn_r,
+ 'JOIN %T %T ON %T.projectID = p.id AND %T.token LIKE %>',
+ PhabricatorProject::TABLE_DATASOURCE_TOKEN,
+ $token_table,
+ $token_table,
+ $token_table,
+ $token);
}
-
- $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 getPrimaryTableAlias() {
return 'p';
}
}
diff --git a/src/applications/project/query/PhabricatorProjectSearchEngine.php b/src/applications/project/query/PhabricatorProjectSearchEngine.php
index ff2b1c790f..66462d5ecc 100644
--- a/src/applications/project/query/PhabricatorProjectSearchEngine.php
+++ b/src/applications/project/query/PhabricatorProjectSearchEngine.php
@@ -1,240 +1,241 @@
<?php
final class PhabricatorProjectSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Projects');
}
public function getApplicationClassName() {
return 'PhabricatorProjectApplication';
}
public function getCustomFieldObject() {
return new PhabricatorProject();
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'memberPHIDs',
$this->readUsersFromRequest($request, 'members'));
$saved->setParameter('status', $request->getStr('status'));
$saved->setParameter('name', $request->getStr('name'));
$saved->setParameter(
'icons',
$this->readListFromRequest($request, 'icons'));
$saved->setParameter(
'colors',
$this->readListFromRequest($request, 'colors'));
$this->readCustomFieldsFromRequest($request, $saved);
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorProjectQuery())
->needImages(true);
$member_phids = $saved->getParameter('memberPHIDs', array());
if ($member_phids && is_array($member_phids)) {
$query->withMemberPHIDs($member_phids);
}
$status = $saved->getParameter('status');
$status = idx($this->getStatusValues(), $status);
if ($status) {
$query->withStatus($status);
}
$name = $saved->getParameter('name');
if (strlen($name)) {
- $query->withDatasourceQuery($name);
+ $tokens = PhabricatorTypeaheadDatasource::tokenizeString($name);
+ $query->withNameTokens($tokens);
}
$icons = $saved->getParameter('icons');
if ($icons) {
$query->withIcons($icons);
}
$colors = $saved->getParameter('colors');
if ($colors) {
$query->withColors($colors);
}
$this->applyCustomFieldsToQuery($query, $saved);
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$member_phids = $saved->getParameter('memberPHIDs', array());
$status = $saved->getParameter('status');
$name_match = $saved->getParameter('name');
$icons = array_fuse($saved->getParameter('icons', array()));
$colors = array_fuse($saved->getParameter('colors', array()));
$icon_control = id(new AphrontFormCheckboxControl())
->setLabel(pht('Icons'));
foreach (PhabricatorProjectIcon::getIconMap() as $icon => $name) {
$image = id(new PHUIIconView())
->setIconFont($icon);
$icon_control->addCheckbox(
'icons[]',
$icon,
array($image, ' ', $name),
isset($icons[$icon]));
}
$color_control = id(new AphrontFormCheckboxControl())
->setLabel(pht('Colors'));
foreach (PhabricatorProjectIcon::getColorMap() as $color => $name) {
$tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setShade($color)
->setName($name);
$color_control->addCheckbox(
'colors[]',
$color,
$tag,
isset($colors[$color]));
}
$form
->appendChild(
id(new AphrontFormTextControl())
->setName('name')
->setLabel(pht('Name'))
->setValue($name_match))
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource())
->setName('members')
->setLabel(pht('Members'))
->setValue($member_phids))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
->setOptions($this->getStatusOptions())
->setValue($status))
->appendChild($icon_control)
->appendChild($color_control);
$this->appendCustomFieldsToForm($form, $saved);
}
protected function getURI($path) {
return '/project/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['joined'] = pht('Joined');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query
->setParameter('status', 'active');
case 'joined':
return $query
->setParameter('memberPHIDs', array($viewer_phid))
->setParameter('status', 'active');
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
'active' => pht('Show Only Active Projects'),
'all' => pht('Show All Projects'),
);
}
private function getStatusValues() {
return array(
'active' => PhabricatorProjectQuery::STATUS_ACTIVE,
'all' => PhabricatorProjectQuery::STATUS_ANY,
);
}
private function getColorValues() {}
private function getIconValues() {}
protected function getRequiredHandlePHIDsForResultList(
array $projects,
PhabricatorSavedQuery $query) {
return mpull($projects, 'getPHID');
}
protected function renderResultList(
array $projects,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($projects, 'PhabricatorProject');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
$can_edit_projects = id(new PhabricatorPolicyFilter())
->setViewer($viewer)
->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))
->apply($projects);
foreach ($projects as $key => $project) {
$id = $project->getID();
$tag_list = id(new PHUIHandleTagListView())
->setSlim(true)
->setHandles(array($handles[$project->getPHID()]));
$item = id(new PHUIObjectItemView())
->setHeader($project->getName())
->setHref($this->getApplicationURI("view/{$id}/"))
->setImageURI($project->getProfileImageURI())
->addAttribute($tag_list);
if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED) {
$item->addIcon('delete-grey', pht('Archived'));
$item->setDisabled(true);
}
$list->addItem($item);
}
return $list;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectDatasource.php b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
index 4b31e4bc80..9b92c66620 100644
--- a/src/applications/project/typeahead/PhabricatorProjectDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
@@ -1,77 +1,78 @@
<?php
final class PhabricatorProjectDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a project name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorProjectApplication';
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
// Allow users to type "#qa" or "qa" to find "Quality Assurance".
$raw_query = ltrim($raw_query, '#');
+ $tokens = self::tokenizeString($raw_query);
- if (!strlen($raw_query)) {
- return array();
+ $query = id(new PhabricatorProjectQuery())
+ ->needImages(true)
+ ->needSlugs(true);
+
+ if ($tokens) {
+ $query->withNameTokens($tokens);
}
- $projs = id(new PhabricatorProjectQuery())
- ->setViewer($viewer)
- ->needImages(true)
- ->needSlugs(true)
- ->withDatasourceQuery($raw_query)
- ->execute();
+ $projs = $this->executeQuery($query);
+
$projs = mpull($projs, null, 'getPHID');
$must_have_cols = $this->getParameter('mustHaveColumns', false);
if ($must_have_cols) {
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array_keys($projs))
->execute();
$has_cols = mgroup($columns, 'getProjectPHID');
} else {
$has_cols = array_fill_keys(array_keys($projs), true);
}
$results = array();
foreach ($projs as $proj) {
if (!isset($has_cols[$proj->getPHID()])) {
continue;
}
$closed = null;
if ($proj->isArchived()) {
$closed = pht('Archived');
}
$all_strings = mpull($proj->getSlugs(), 'getSlug');
$all_strings[] = $proj->getName();
$all_strings = implode(' ', $all_strings);
$proj_result = id(new PhabricatorTypeaheadResult())
->setName($all_strings)
->setDisplayName($proj->getName())
->setDisplayType('Project')
->setURI('/tag/'.$proj->getPrimarySlug().'/')
->setPHID($proj->getPHID())
->setIcon($proj->getIcon().' bluegrey')
->setPriorityType('proj')
->setClosed($closed);
$proj_result->setImageURI($proj->getProfileImageURI());
$results[] = $proj_result;
}
return $results;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Feb 24, 9:22 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
851368
Default Alt Text
(20 KB)

Event Timeline