1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-20 20:40:56 +01:00

Update Project for handleRequest

Summary: Updates Projects to use handleRequest

Test Plan: New Project, Edit Project, Archive, Watch, Create Workboards, Import Workboards, Edit Column, New Column, Change Icon, Add/Remove Members

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D13829
This commit is contained in:
Chad Little 2015-08-08 10:34:55 -07:00
parent d2ef273ecd
commit 44f18cfb12
16 changed files with 90 additions and 185 deletions

View file

@ -3,19 +3,13 @@
final class PhabricatorProjectArchiveController final class PhabricatorProjectArchiveController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) { $id = $request->getURIData('id');
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,

View file

@ -3,15 +3,9 @@
final class PhabricatorProjectBoardImportController final class PhabricatorProjectBoardImportController
extends PhabricatorProjectBoardController { extends PhabricatorProjectBoardController {
private $projectID; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) { $project_id = $request->getURIData('projectID');
$this->projectID = $data['projectID'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -20,7 +14,7 @@ final class PhabricatorProjectBoardImportController
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($project_id))
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
return new Aphront404Response(); return new Aphront404Response();

View file

@ -3,15 +3,9 @@
final class PhabricatorProjectBoardReorderController final class PhabricatorProjectBoardReorderController
extends PhabricatorProjectBoardController { extends PhabricatorProjectBoardController {
private $projectID; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) { $projectid = $request->getURIData('projectID');
$this->projectID = $data['projectID'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -20,15 +14,13 @@ final class PhabricatorProjectBoardReorderController
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($projectid))
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
return new Aphront404Response(); return new Aphront404Response();
} }
$this->setProject($project); $this->setProject($project);
$project_id = $project->getID(); $project_id = $project->getID();
$board_uri = $this->getApplicationURI("board/{$project_id}/"); $board_uri = $this->getApplicationURI("board/{$project_id}/");

View file

@ -3,17 +3,10 @@
final class PhabricatorProjectColumnDetailController final class PhabricatorProjectColumnDetailController
extends PhabricatorProjectBoardController { extends PhabricatorProjectBoardController {
private $id; public function handleRequest(AphrontRequest $request) {
private $projectID; $viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { $project_id = $request->getURIData('projectID');
$this->projectID = $data['projectID'];
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -21,7 +14,7 @@ final class PhabricatorProjectColumnDetailController
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($project_id))
->needImages(true) ->needImages(true)
->executeOne(); ->executeOne();
@ -32,7 +25,7 @@ final class PhabricatorProjectColumnDetailController
$column = id(new PhabricatorProjectColumnQuery()) $column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,

View file

@ -3,17 +3,10 @@
final class PhabricatorProjectColumnEditController final class PhabricatorProjectColumnEditController
extends PhabricatorProjectBoardController { extends PhabricatorProjectBoardController {
private $id; public function handleRequest(AphrontRequest $request) {
private $projectID; $viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { $project_id = $request->getURIData('projectID');
$this->projectID = $data['projectID'];
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -22,7 +15,7 @@ final class PhabricatorProjectColumnEditController
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($project_id))
->needImages(true) ->needImages(true)
->executeOne(); ->executeOne();
@ -31,12 +24,12 @@ final class PhabricatorProjectColumnEditController
} }
$this->setProject($project); $this->setProject($project);
$is_new = ($this->id ? false : true); $is_new = ($id ? false : true);
if (!$is_new) { if (!$is_new) {
$column = id(new PhabricatorProjectColumnQuery()) $column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
@ -57,12 +50,12 @@ final class PhabricatorProjectColumnEditController
$v_name = $column->getName(); $v_name = $column->getName();
$validation_exception = null; $validation_exception = null;
$base_uri = '/board/'.$this->projectID.'/'; $base_uri = '/board/'.$project_id.'/';
if ($is_new) { if ($is_new) {
// we want to go back to the board // we want to go back to the board
$view_uri = $this->getApplicationURI($base_uri); $view_uri = $this->getApplicationURI($base_uri);
} else { } else {
$view_uri = $this->getApplicationURI($base_uri.'column/'.$this->id.'/'); $view_uri = $this->getApplicationURI($base_uri.'column/'.$id.'/');
} }
if ($request->isFormPost()) { if ($request->isFormPost()) {

View file

@ -3,17 +3,11 @@
final class PhabricatorProjectColumnHideController final class PhabricatorProjectColumnHideController
extends PhabricatorProjectBoardController { extends PhabricatorProjectBoardController {
private $id; public function handleRequest(AphrontRequest $request) {
private $projectID; $viewer = $request->getViewer();
$id = $request->getURIData('id');
$project_id = $request->getURIData('projectID');
public function willProcessRequest(array $data) {
$this->projectID = $data['projectID'];
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->requireCapabilities( ->requireCapabilities(
@ -21,7 +15,7 @@ final class PhabricatorProjectColumnHideController
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_EDIT,
)) ))
->withIDs(array($this->projectID)) ->withIDs(array($project_id))
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
@ -31,7 +25,7 @@ final class PhabricatorProjectColumnHideController
$column = id(new PhabricatorProjectColumnQuery()) $column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
@ -44,7 +38,7 @@ final class PhabricatorProjectColumnHideController
$column_phid = $column->getPHID(); $column_phid = $column->getPHID();
$view_uri = $this->getApplicationURI('/board/'.$this->projectID.'/'); $view_uri = $this->getApplicationURI('/board/'.$project_id.'/');
$view_uri = new PhutilURI($view_uri); $view_uri = new PhutilURI($view_uri);
foreach ($request->getPassthroughRequestData() as $key => $value) { foreach ($request->getPassthroughRequestData() as $key => $value) {
$view_uri->setQueryParam($key, $value); $view_uri->setQueryParam($key, $value);

View file

@ -3,23 +3,17 @@
final class PhabricatorProjectEditDetailsController final class PhabricatorProjectEditDetailsController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { if ($id) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if ($this->id) {
$id = $request->getURIData('id'); $id = $request->getURIData('id');
$is_new = false; $is_new = false;
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needSlugs(true) ->needSlugs(true)
->needImages(true) ->needImages(true)
->requireCapabilities( ->requireCapabilities(

View file

@ -3,20 +3,14 @@
final class PhabricatorProjectEditIconController final class PhabricatorProjectEditIconController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { if ($id) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if ($this->id) {
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->requireCapabilities( ->requireCapabilities(
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,

View file

@ -3,20 +3,13 @@
final class PhabricatorProjectEditPictureController final class PhabricatorProjectEditPictureController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$id = $request->getURIData('id'); $id = $request->getURIData('id');
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needImages(true) ->needImages(true)
->requireCapabilities( ->requireCapabilities(
array( array(

View file

@ -3,19 +3,16 @@
final class PhabricatorProjectListController final class PhabricatorProjectListController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $queryKey;
public function shouldAllowPublic() { public function shouldAllowPublic() {
return true; return true;
} }
public function willProcessRequest(array $data) { public function handleRequest(AphrontRequest $request) {
$this->queryKey = idx($data, 'queryKey'); $viewer = $request->getViewer();
} $query_key = $request->getURIData('queryKey');
public function processRequest() {
$controller = id(new PhabricatorApplicationSearchController()) $controller = id(new PhabricatorApplicationSearchController())
->setQueryKey($this->queryKey) ->setQueryKey($query_key)
->setSearchEngine(new PhabricatorProjectSearchEngine()) ->setSearchEngine(new PhabricatorProjectSearchEngine())
->setNavigation($this->buildSideNavView()); ->setNavigation($this->buildSideNavView());

View file

@ -3,20 +3,13 @@
final class PhabricatorProjectMembersEditController final class PhabricatorProjectMembersEditController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$id = $request->getURIData('id'); $id = $request->getURIData('id');
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($user) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needMembers(true) ->needMembers(true)
->needImages(true) ->needImages(true)
->requireCapabilities( ->requireCapabilities(
@ -53,7 +46,7 @@ final class PhabricatorProjectMembersEditController
->setNewValue($member_spec); ->setNewValue($member_spec);
$editor = id(new PhabricatorProjectTransactionEditor($project)) $editor = id(new PhabricatorProjectTransactionEditor($project))
->setActor($user) ->setActor($viewer)
->setContentSourceFromRequest($request) ->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true) ->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true) ->setContinueOnMissingFields(true)
@ -75,7 +68,7 @@ final class PhabricatorProjectMembersEditController
} }
$can_edit = PhabricatorPolicyFilter::hasCapability( $can_edit = PhabricatorPolicyFilter::hasCapability(
$user, $viewer,
$project, $project,
PhabricatorPolicyCapability::CAN_EDIT); PhabricatorPolicyCapability::CAN_EDIT);
@ -87,7 +80,7 @@ final class PhabricatorProjectMembersEditController
$form = new AphrontFormView(); $form = new AphrontFormView();
$form $form
->setUser($user) ->setUser($viewer)
->appendControl( ->appendControl(
id(new AphrontFormTokenizerControl()) id(new AphrontFormTokenizerControl())
->setName('phids') ->setName('phids')

View file

@ -3,19 +3,13 @@
final class PhabricatorProjectMembersRemoveController final class PhabricatorProjectMembersRemoveController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) { $id = $request->getURIData('id');
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needMembers(true) ->needMembers(true)
->requireCapabilities( ->requireCapabilities(
array( array(

View file

@ -3,15 +3,9 @@
final class PhabricatorProjectMoveController final class PhabricatorProjectMoveController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
public function willProcessRequest(array $data) { $id = $request->getURIData('id');
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$column_phid = $request->getStr('columnPHID'); $column_phid = $request->getStr('columnPHID');
$object_phid = $request->getStr('objectPHID'); $object_phid = $request->getStr('objectPHID');
@ -26,7 +20,7 @@ final class PhabricatorProjectMoveController
array( array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
)) ))
->withIDs(array($this->id)) ->withIDs(array($id))
->executeOne(); ->executeOne();
if (!$project) { if (!$project) {
return new Aphront404Response(); return new Aphront404Response();

View file

@ -3,24 +3,17 @@
final class PhabricatorProjectUpdateController final class PhabricatorProjectUpdateController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
private $action; $viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { $action = $request->getURIData('action');
$this->id = $data['id'];
$this->action = $data['action'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$capabilities = array( $capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_VIEW,
); );
$process_action = false; $process_action = false;
switch ($this->action) { switch ($action) {
case 'join': case 'join':
$capabilities[] = PhabricatorPolicyCapability::CAN_JOIN; $capabilities[] = PhabricatorPolicyCapability::CAN_JOIN;
$process_action = $request->isFormPost(); $process_action = $request->isFormPost();
@ -33,8 +26,8 @@ final class PhabricatorProjectUpdateController
} }
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($user) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needMembers(true) ->needMembers(true)
->requireCapabilities($capabilities) ->requireCapabilities($capabilities)
->executeOne(); ->executeOne();
@ -47,7 +40,7 @@ final class PhabricatorProjectUpdateController
if ($process_action) { if ($process_action) {
$edge_action = null; $edge_action = null;
switch ($this->action) { switch ($action) {
case 'join': case 'join':
$edge_action = '+'; $edge_action = '+';
break; break;
@ -58,7 +51,7 @@ final class PhabricatorProjectUpdateController
$type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
$member_spec = array( $member_spec = array(
$edge_action => array($user->getPHID() => $user->getPHID()), $edge_action => array($viewer->getPHID() => $viewer->getPHID()),
); );
$xactions = array(); $xactions = array();
@ -68,7 +61,7 @@ final class PhabricatorProjectUpdateController
->setNewValue($member_spec); ->setNewValue($member_spec);
$editor = id(new PhabricatorProjectTransactionEditor($project)) $editor = id(new PhabricatorProjectTransactionEditor($project))
->setActor($user) ->setActor($viewer)
->setContentSourceFromRequest($request) ->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true) ->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true) ->setContinueOnMissingFields(true)
@ -78,10 +71,10 @@ final class PhabricatorProjectUpdateController
} }
$dialog = null; $dialog = null;
switch ($this->action) { switch ($action) {
case 'leave': case 'leave':
$dialog = new AphrontDialogView(); $dialog = new AphrontDialogView();
$dialog->setUser($user); $dialog->setUser($viewer);
if ($this->userCannotLeave($project)) { if ($this->userCannotLeave($project)) {
$dialog->setTitle(pht('You can not leave this project.')); $dialog->setTitle(pht('You can not leave this project.'));
$body = pht('The membership is locked for this project.'); $body = pht('The membership is locked for this project.');
@ -107,12 +100,12 @@ final class PhabricatorProjectUpdateController
* this logic to render a better form for users hitting this case. * this logic to render a better form for users hitting this case.
*/ */
private function userCannotLeave(PhabricatorProject $project) { private function userCannotLeave(PhabricatorProject $project) {
$user = $this->getRequest()->getUser(); $viewer = $this->getViewer();
return return
$project->getIsMembershipLocked() && $project->getIsMembershipLocked() &&
!PhabricatorPolicyFilter::hasCapability( !PhabricatorPolicyFilter::hasCapability(
$user, $viewer,
$project, $project,
PhabricatorPolicyCapability::CAN_EDIT); PhabricatorPolicyCapability::CAN_EDIT);
} }

View file

@ -9,10 +9,10 @@ final class PhabricatorProjectViewController
public function handleRequest(AphrontRequest $request) { public function handleRequest(AphrontRequest $request) {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser(); $viewer = $request->getViewer();
$query = id(new PhabricatorProjectQuery()) $query = id(new PhabricatorProjectQuery())
->setViewer($user) ->setViewer($viewer)
->needMembers(true) ->needMembers(true)
->needWatchers(true) ->needWatchers(true)
->needImages(true) ->needImages(true)
@ -31,7 +31,7 @@ final class PhabricatorProjectViewController
$columns = id(new PhabricatorProjectColumnQuery()) $columns = id(new PhabricatorProjectColumnQuery())
->setViewer($user) ->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID())) ->withProjectPHIDs(array($project->getPHID()))
->execute(); ->execute();
if ($columns) { if ($columns) {

View file

@ -3,21 +3,14 @@
final class PhabricatorProjectWatchController final class PhabricatorProjectWatchController
extends PhabricatorProjectController { extends PhabricatorProjectController {
private $id; public function handleRequest(AphrontRequest $request) {
private $action; $viewer = $request->getViewer();
$id = $request->getURIData('id');
public function willProcessRequest(array $data) { $action = $request->getURIData('action');
$this->id = $data['id'];
$this->action = $data['action'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery()) $project = id(new PhabricatorProjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withIDs(array($this->id)) ->withIDs(array($id))
->needMembers(true) ->needMembers(true)
->needWatchers(true) ->needWatchers(true)
->executeOne(); ->executeOne();
@ -34,7 +27,7 @@ final class PhabricatorProjectWatchController
if ($request->isDialogFormPost()) { if ($request->isDialogFormPost()) {
$edge_action = null; $edge_action = null;
switch ($this->action) { switch ($action) {
case 'watch': case 'watch':
$edge_action = '+'; $edge_action = '+';
$force_subscribe = true; $force_subscribe = true;
@ -67,7 +60,7 @@ final class PhabricatorProjectWatchController
} }
$dialog = null; $dialog = null;
switch ($this->action) { switch ($action) {
case 'watch': case 'watch':
$title = pht('Watch Project?'); $title = pht('Watch Project?');
$body = pht( $body = pht(