diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -13,6 +13,72 @@ return $this->project; } + protected function loadProject() { + $viewer = $this->getViewer(); + $request = $this->getRequest(); + + $id = $request->getURIData('id'); + $slug = $request->getURIData('slug'); + + if ($slug) { + $normal_slug = PhabricatorSlug::normalizeProjectSlug($slug); + $is_abnormal = ($slug !== $normal_slug); + $normal_uri = "/tag/{$normal_slug}/"; + } else { + $is_abnormal = false; + } + + $query = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->needMembers(true) + ->needWatchers(true) + ->needImages(true) + ->needSlugs(true); + + if ($slug) { + $query->withSlugs(array($slug)); + } else { + $query->withIDs(array($id)); + } + + $policy_exception = null; + try { + $project = $query->executeOne(); + } catch (PhabricatorPolicyException $ex) { + $policy_exception = $ex; + $project = null; + } + + if (!$project) { + // This project legitimately does not exist, so just 404 the user. + if (!$policy_exception) { + return new Aphront404Response(); + } + + // Here, the project exists but the user can't see it. If they are + // using a non-canonical slug to view the project, redirect to the + // canonical slug. If they're already using the canonical slug, rethrow + // the exception to give them the policy error. + if ($is_abnormal) { + return id(new AphrontRedirectResponse())->setURI($normal_uri); + } else { + throw $policy_exception; + } + } + + // The user can view the project, but is using a noncanonical slug. + // Redirect to the canonical slug. + $primary_slug = $project->getPrimarySlug(); + if ($slug && ($slug !== $primary_slug)) { + $primary_uri = "/tag/{$primary_slug}/"; + return id(new AphrontRedirectResponse())->setURI($primary_uri); + } + + $this->setProject($project); + + return null; + } + public function buildApplicationMenu() { return $this->buildSideNavView(true)->getMenu(); } diff --git a/src/applications/project/controller/PhabricatorProjectFeedController.php b/src/applications/project/controller/PhabricatorProjectFeedController.php --- a/src/applications/project/controller/PhabricatorProjectFeedController.php +++ b/src/applications/project/controller/PhabricatorProjectFeedController.php @@ -8,38 +8,25 @@ } public function handleRequest(AphrontRequest $request) { - $user = $request->getUser(); + $viewer = $request->getUser(); - $query = id(new PhabricatorProjectQuery()) - ->setViewer($user) - ->needMembers(true) - ->needWatchers(true) - ->needImages(true) - ->needSlugs(true); - $id = $request->getURIData('id'); - $slug = $request->getURIData('slug'); - if ($slug) { - $query->withSlugs(array($slug)); - } else { - $query->withIDs(array($id)); - } - $project = $query->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - if ($slug && $slug != $project->getPrimarySlug()) { - return id(new AphrontRedirectResponse()) - ->setURI('/tag/'.$project->getPrimarySlug().'/'); + $response = $this->loadProject(); + if ($response) { + return $response; } - $query = new PhabricatorFeedQuery(); - $query->setFilterPHIDs( - array( - $project->getPHID(), - )); - $query->setLimit(50); - $query->setViewer($request->getUser()); - $stories = $query->execute(); + $project = $this->getProject(); + $id = $project->getID(); + + $stories = id(new PhabricatorFeedQuery()) + ->setViewer($viewer) + ->setFilterPHIDs( + array( + $project->getPHID(), + )) + ->setLimit(50) + ->execute(); + $feed = $this->renderStories($stories); $box = id(new PHUIObjectBoxView()) @@ -57,21 +44,6 @@ )); } - private function renderFeedPage(PhabricatorProject $project) { - - $query = new PhabricatorFeedQuery(); - $query->setFilterPHIDs(array($project->getPHID())); - $query->setViewer($this->getRequest()->getUser()); - $query->setLimit(100); - $stories = $query->execute(); - - if (!$stories) { - return pht('There are no stories about this project.'); - } - - return $this->renderStories($stories); - } - private function renderStories(array $stories) { assert_instances_of($stories, 'PhabricatorFeedStory'); @@ -85,5 +57,4 @@ $view->render()); } - } diff --git a/src/applications/project/controller/PhabricatorProjectMembersEditController.php b/src/applications/project/controller/PhabricatorProjectMembersEditController.php --- a/src/applications/project/controller/PhabricatorProjectMembersEditController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersEditController.php @@ -12,10 +12,6 @@ ->withIDs(array($id)) ->needMembers(true) ->needImages(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - )) ->executeOne(); if (!$project) { return new Aphront404Response(); diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -8,35 +8,20 @@ } public function handleRequest(AphrontRequest $request) { - $user = $request->getUser(); - - $query = id(new PhabricatorProjectQuery()) - ->setViewer($user) - ->needMembers(true) - ->needWatchers(true) - ->needImages(true) - ->needSlugs(true); - $id = $request->getURIData('id'); - $slug = $request->getURIData('slug'); - if ($slug) { - $query->withSlugs(array($slug)); - } else { - $query->withIDs(array($id)); - } - $project = $query->executeOne(); - if (!$project) { - return new Aphront404Response(); - } - if ($slug && $slug != $project->getPrimarySlug()) { - return id(new AphrontRedirectResponse()) - ->setURI('/tag/'.$project->getPrimarySlug().'/'); + $viewer = $request->getUser(); + + $response = $this->loadProject(); + if ($response) { + return $response; } + $project = $this->getProject(); + $id = $project->getID(); $picture = $project->getProfileImageURI(); $header = id(new PHUIHeaderView()) ->setHeader($project->getName()) - ->setUser($user) + ->setUser($viewer) ->setPolicyObject($project) ->setImage($picture); @@ -60,15 +45,13 @@ $nav = $this->buildIconNavView($project); $nav->selectFilter("profile/{$id}/"); - $nav->appendChild($object_box); - $nav->appendChild($timeline); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => $project->getName(), - 'pageObjects' => array($project->getPHID()), - )); + + return $this->newPage() + ->setNavigation($nav) + ->setTitle($project->getName()) + ->setPageObjectPHIDs(array($project->getPHID())) + ->appendChild($object_box) + ->appendChild($timeline); } private function buildActionListView(PhabricatorProject $project) { diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php --- a/src/applications/project/controller/PhabricatorProjectViewController.php +++ b/src/applications/project/controller/PhabricatorProjectViewController.php @@ -11,31 +11,11 @@ $request = $this->getRequest(); $viewer = $request->getViewer(); - $query = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->needMembers(true) - ->needWatchers(true) - ->needImages(true) - ->needSlugs(true); - $id = $request->getURIData('id'); - $slug = $request->getURIData('slug'); - if ($slug) { - $query->withSlugs(array($slug)); - } else { - $query->withIDs(array($id)); - } - $project = $query->executeOne(); - if (!$project) { - - // If this request corresponds to a project but just doesn't have the - // slug quite right, redirect to the proper URI. - $uri = $this->getNormalizedURI($slug); - if ($uri !== null) { - return id(new AphrontRedirectResponse())->setURI($uri); - } - - return new Aphront404Response(); + $response = $this->loadProject(); + if ($response) { + return $response; } + $project = $this->getProject(); $columns = id(new PhabricatorProjectColumnQuery()) ->setViewer($viewer) @@ -60,31 +40,4 @@ return $this->delegateToController($controller_object); } - private function getNormalizedURI($slug) { - if (!strlen($slug)) { - return null; - } - - $normal = PhabricatorSlug::normalizeProjectSlug($slug); - if ($normal === $slug) { - return null; - } - - $viewer = $this->getViewer(); - - // Do execute() instead of executeOne() here so we canonicalize before - // raising a policy exception. This is a little more polished than letting - // the user hit the error on any variant of the slug. - - $projects = id(new PhabricatorProjectQuery()) - ->setViewer($viewer) - ->withSlugs(array($normal)) - ->execute(); - if (!$projects) { - return null; - } - - return "/tag/{$normal}/"; - } - }