Page MenuHomePhabricator

D14888.id35996.diff
No OneTemporary

D14888.id35996.diff

diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
--- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
+++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
@@ -493,6 +493,90 @@
$this->assertFalse((bool)$this->refreshProject($child, $user2));
}
+ public function testSlugMaps() {
+ // When querying by slugs, slugs should be normalized and the mapping
+ // should be reported correctly.
+ $user = $this->createUser();
+ $user->save();
+
+ $name = 'queryslugproject';
+ $name2 = 'QUERYslugPROJECT';
+ $slug = 'queryslugextra';
+ $slug2 = 'QuErYSlUgExTrA';
+
+ $project = PhabricatorProject::initializeNewProject($user);
+
+ $xactions = array();
+
+ $xactions[] = id(new PhabricatorProjectTransaction())
+ ->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)
+ ->setNewValue($name);
+
+ $xactions[] = id(new PhabricatorProjectTransaction())
+ ->setTransactionType(PhabricatorProjectTransaction::TYPE_SLUGS)
+ ->setNewValue(array($slug));
+
+ $this->applyTransactions($project, $user, $xactions);
+
+ $project_query = id(new PhabricatorProjectQuery())
+ ->setViewer($user)
+ ->withSlugs(array($name));
+ $project_query->execute();
+ $map = $project_query->getSlugMap();
+
+ $this->assertEqual(
+ array(
+ $name => $project->getPHID(),
+ ),
+ ipull($map, 'projectPHID'));
+
+ $project_query = id(new PhabricatorProjectQuery())
+ ->setViewer($user)
+ ->withSlugs(array($slug));
+ $project_query->execute();
+ $map = $project_query->getSlugMap();
+
+ $this->assertEqual(
+ array(
+ $slug => $project->getPHID(),
+ ),
+ ipull($map, 'projectPHID'));
+
+ $project_query = id(new PhabricatorProjectQuery())
+ ->setViewer($user)
+ ->withSlugs(array($name, $slug, $name2, $slug2));
+ $project_query->execute();
+ $map = $project_query->getSlugMap();
+
+ $expect = array(
+ $name => $project->getPHID(),
+ $slug => $project->getPHID(),
+ $name2 => $project->getPHID(),
+ $slug2 => $project->getPHID(),
+ );
+
+ $actual = ipull($map, 'projectPHID');
+
+ ksort($expect);
+ ksort($actual);
+
+ $this->assertEqual($expect, $actual);
+
+ $expect = array(
+ $name => $name,
+ $slug => $slug,
+ $name2 => $name,
+ $slug2 => $slug,
+ );
+
+ $actual = ipull($map, 'slug');
+
+ ksort($expect);
+ ksort($actual);
+
+ $this->assertEqual($expect, $actual);
+ }
+
private function attemptProjectEdit(
PhabricatorProject $proj,
PhabricatorUser $user,
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -7,6 +7,8 @@
private $phids;
private $memberPHIDs;
private $slugs;
+ private $slugNormals;
+ private $slugMap;
private $names;
private $nameTokens;
private $icons;
@@ -157,6 +159,24 @@
);
}
+ public function getSlugMap() {
+ if ($this->slugMap === null) {
+ throw new PhutilInvalidStateException('execute');
+ }
+ return $this->slugMap;
+ }
+
+ protected function willExecute() {
+ $this->slugMap = array();
+ $this->slugNormals = array();
+ if ($this->slugs) {
+ foreach ($this->slugs as $slug) {
+ $normal = PhabricatorSlug::normalizeProjectSlug($slug);
+ $this->slugNormals[$slug] = $normal;
+ }
+ }
+ }
+
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
@@ -287,17 +307,7 @@
}
}
- 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);
- }
- }
+ $this->loadSlugs($projects);
return $projects;
}
@@ -356,7 +366,7 @@
$where[] = qsprintf(
$conn,
'slug.slug IN (%Ls)',
- $this->slugs);
+ $this->slugNormals);
}
if ($this->names !== null) {
@@ -583,4 +593,76 @@
return $ancestors;
}
+ private function loadSlugs(array $projects) {
+ // Build a map from primary slugs to projects.
+ $primary_map = array();
+ foreach ($projects as $project) {
+ $primary_slug = $project->getPrimarySlug();
+ if ($primary_slug === null) {
+ continue;
+ }
+
+ $primary_map[$primary_slug] = $project;
+ }
+
+ // Link up all of the queried slugs which correspond to primary
+ // slugs. If we can link up everything from this (no slugs were queried,
+ // or only primary slugs were queried) we don't need to load anything
+ // else.
+ $unknown = $this->slugNormals;
+ foreach ($unknown as $input => $normal) {
+ if (!isset($primary_map[$normal])) {
+ continue;
+ }
+
+ $this->slugMap[$input] = array(
+ 'slug' => $normal,
+ 'projectPHID' => $primary_map[$normal]->getPHID(),
+ );
+
+ unset($unknown[$input]);
+ }
+
+ // If we need slugs, we have to load everything.
+ // If we still have some queried slugs which we haven't mapped, we only
+ // need to look for them.
+ // If we've mapped everything, we don't have to do any work.
+ $project_phids = mpull($projects, 'getPHID');
+ if ($this->needSlugs) {
+ $slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
+ 'projectPHID IN (%Ls)',
+ $project_phids);
+ } else if ($unknown) {
+ $slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
+ 'projectPHID IN (%Ls) AND slug IN (%Ls)',
+ $project_phids,
+ $unknown);
+ } else {
+ $slugs = array();
+ }
+
+ // Link up any slugs we were not able to link up earlier.
+ $extra_map = mpull($slugs, 'getProjectPHID', 'getSlug');
+ foreach ($unknown as $input => $normal) {
+ if (!isset($extra_map[$normal])) {
+ continue;
+ }
+
+ $this->slugMap[$input] = array(
+ 'slug' => $normal,
+ 'projectPHID' => $extra_map[$normal],
+ );
+
+ unset($unknown[$input]);
+ }
+
+ if ($this->needSlugs) {
+ $slug_groups = mgroup($slugs, 'getProjectPHID');
+ foreach ($projects as $project) {
+ $project_slugs = idx($slug_groups, $project->getPHID(), array());
+ $project->attachSlugs($project_slugs);
+ }
+ }
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 12:35 PM (1 d, 15 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6720092
Default Alt Text
D14888.id35996.diff (6 KB)

Event Timeline