diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -219,7 +219,12 @@ foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProjectTransaction::TYPE_MEMBERS: + case PhabricatorTransactions::TYPE_EDGE: + $type = $xaction->getMetadataValue('edge:type'); + if ($type != PhabricatorProjectProjectHasMemberEdgeType::EDGECONST) { + break; + } + if ($is_parent) { $errors[] = new PhabricatorApplicationTransactionValidationError( $xaction->getTransactionType(), @@ -792,27 +797,6 @@ $results = parent::expandTransactions($object, $xactions); - // Automatically add the author as a member when they create a project - // if they're using the web interface. - - $content_source = $this->getContentSource(); - $source_web = PhabricatorContentSource::SOURCE_WEB; - $is_web = ($content_source->getSource() === $source_web); - - if ($this->getIsNewObject() && $is_web) { - if ($actor_phid) { - $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; - - $results[] = id(new PhabricatorProjectTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $type_member) - ->setNewValue( - array( - '+' => array($actor_phid => $actor_phid), - )); - } - } - $is_milestone = $object->isMilestone(); foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -176,7 +176,7 @@ $milestone_phid = null; } - return array( + $fields = array( id(new PhabricatorHandlesEditField()) ->setKey('parent') ->setLabel(pht('Parent')) @@ -243,6 +243,49 @@ ->setConduitTypeDescription(pht('New list of slugs.')) ->setValue($slugs), ); + + $can_edit_members = (!$milestone) && + (!$object->isMilestone()) && + (!$object->getHasSubprojects()); + + if ($can_edit_members) { + + // Show this on the web UI when creating a project, but not when editing + // one. It is always available via Conduit. + $conduit_only = !$this->getIsCreate(); + + $members_field = id(new PhabricatorUsersEditField()) + ->setKey('members') + ->setAliases(array('memberPHIDs')) + ->setLabel(pht('Initial Members')) + ->setIsConduitOnly($conduit_only) + ->setUseEdgeTransactions(true) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue( + 'edge:type', + PhabricatorProjectProjectHasMemberEdgeType::EDGECONST) + ->setDescription(pht('Initial project members.')) + ->setConduitDescription(pht('Set project members.')) + ->setConduitTypeDescription(pht('New list of members.')) + ->setValue(array()); + + $members_field->setViewer($this->getViewer()); + + $edit_add = $members_field->getConduitEditType('members.add') + ->setConduitDescription(pht('Add members.')); + + $edit_set = $members_field->getConduitEditType('members.set') + ->setConduitDescription( + pht('Set members, overwriting the current value.')); + + $edit_rem = $members_field->getConduitEditType('members.remove') + ->setConduitDescription(pht('Remove members.')); + + $fields[] = $members_field; + } + + return $fields; + } }