Page MenuHomePhabricator

D8180.id.diff
No OneTemporary

D8180.id.diff

Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -1830,9 +1830,12 @@
'PhabricatorProjectBoardEditController' => 'applications/project/controller/PhabricatorProjectBoardEditController.php',
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php',
+ 'PhabricatorProjectConfigOptions' => 'applications/project/config/PhabricatorProjectConfigOptions.php',
+ 'PhabricatorProjectConfiguredCustomField' => 'applications/project/customfield/PhabricatorProjectConfiguredCustomField.php',
'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php',
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php',
+ 'PhabricatorProjectCustomField' => 'applications/project/customfield/PhabricatorProjectCustomField.php',
'PhabricatorProjectCustomFieldNumericIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldNumericIndex.php',
'PhabricatorProjectCustomFieldStorage' => 'applications/project/storage/PhabricatorProjectCustomFieldStorage.php',
'PhabricatorProjectCustomFieldStringIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldStringIndex.php',
@@ -4557,6 +4560,7 @@
1 => 'PhabricatorFlaggableInterface',
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorSubscribableInterface',
+ 4 => 'PhabricatorCustomFieldInterface',
),
'PhabricatorProjectArchiveController' => 'PhabricatorProjectController',
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
@@ -4567,8 +4571,15 @@
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorProjectConfigOptions' => 'PhabricatorApplicationConfigOptions',
+ 'PhabricatorProjectConfiguredCustomField' =>
+ array(
+ 0 => 'PhabricatorProjectCustomField',
+ 1 => 'PhabricatorStandardCustomFieldInterface',
+ ),
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
+ 'PhabricatorProjectCustomField' => 'PhabricatorCustomField',
'PhabricatorProjectCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'PhabricatorProjectCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
'PhabricatorProjectCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
Index: src/applications/project/config/PhabricatorProjectConfigOptions.php
===================================================================
--- /dev/null
+++ src/applications/project/config/PhabricatorProjectConfigOptions.php
@@ -0,0 +1,43 @@
+<?php
+
+final class PhabricatorProjectConfigOptions
+ extends PhabricatorApplicationConfigOptions {
+
+ public function getName() {
+ return pht("Projects");
+ }
+
+ public function getDescription() {
+ return pht("Configure Projects.");
+ }
+
+ public function getOptions() {
+ // This is intentionally blank for now, until we can move more Project
+ // logic to custom fields.
+ $default_fields = array();
+
+ foreach ($default_fields as $key => $enabled) {
+ $default_fields[$key] = array(
+ 'disabled' => !$enabled,
+ );
+ }
+
+ $custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType';
+
+ return array(
+ $this->newOption('projects.custom-field-definitions', 'wild', array())
+ ->setSummary(pht('Custom Projects fields.'))
+ ->setDescription(
+ pht(
+ "Array of custom fields for Projects."))
+ ->addExample(
+ '{"mycompany:motto": {"name": "Project Motto", '.
+ '"type": "string"}}',
+ pht('Valid Setting')),
+ $this->newOption('projects.fields', $custom_field_type, $default_fields)
+ ->setCustomData(id(new PhabricatorProject())->getCustomFieldBaseClass())
+ ->setDescription(pht("Select and reorder project fields.")),
+ );
+ }
+
+}
Index: src/applications/project/controller/PhabricatorProjectProfileController.php
===================================================================
--- src/applications/project/controller/PhabricatorProjectProfileController.php
+++ src/applications/project/controller/PhabricatorProjectProfileController.php
@@ -266,6 +266,11 @@
? $this->renderHandlesForPHIDs($project->getMemberPHIDs(), ',')
: phutil_tag('em', array(), pht('None')));
+ $field_list = PhabricatorCustomField::getObjectFields(
+ $project,
+ PhabricatorCustomField::ROLE_VIEW);
+ $field_list->appendFieldsToPropertyList($project, $viewer, $view);
+
$view->addSectionHeader(pht('Description'));
$view->addTextContent(
PhabricatorMarkupEngine::renderOneObject(
Index: src/applications/project/controller/PhabricatorProjectProfileEditController.php
===================================================================
--- src/applications/project/controller/PhabricatorProjectProfileEditController.php
+++ src/applications/project/controller/PhabricatorProjectProfileEditController.php
@@ -10,12 +10,11 @@
}
public function processRequest() {
-
$request = $this->getRequest();
- $user = $request->getUser();
+ $viewer = $request->getUser();
$project = id(new PhabricatorProjectQuery())
- ->setViewer($user)
+ ->setViewer($viewer)
->withIDs(array($this->id))
->requireCapabilities(
array(
@@ -30,49 +29,80 @@
$profile = $project->getProfile();
+ $field_list = PhabricatorCustomField::getObjectFields(
+ $project,
+ PhabricatorCustomField::ROLE_EDIT);
+ $field_list
+ ->setViewer($viewer)
+ ->readFieldsFromStorage($project);
+
+ $view_uri = $this->getApplicationURI('view/'.$project->getID().'/');
+
$e_name = true;
+ $e_edit = null;
+
+ $v_name = $project->getName();
+ $v_desc = $profile->getBlurb();
+
+ $validation_exception = null;
- $errors = array();
if ($request->isFormPost()) {
- $xactions = array();
+ $e_name = null;
+
+ $v_name = $request->getStr('name');
+ $v_desc = $request->getStr('blurb');
+ $v_view = $request->getStr('can_view');
+ $v_edit = $request->getStr('can_edit');
+ $v_join = $request->getStr('can_join');
+
+ $xactions = $field_list->buildFieldTransactionsFromRequest(
+ new PhabricatorProjectTransaction(),
+ $request);
+
+ $type_name = PhabricatorProjectTransaction::TYPE_NAME;
+ $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)
+ ->setTransactionType($type_name)
->setNewValue($request->getStr('name'));
$xactions[] = id(new PhabricatorProjectTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
- ->setNewValue($request->getStr('can_view'));
+ ->setNewValue($v_view);
$xactions[] = id(new PhabricatorProjectTransaction())
- ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
- ->setNewValue($request->getStr('can_edit'));
+ ->setTransactionType($type_edit)
+ ->setNewValue($v_edit);
$xactions[] = id(new PhabricatorProjectTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)
- ->setNewValue($request->getStr('can_join'));
+ ->setNewValue($v_join);
$editor = id(new PhabricatorProjectTransactionEditor())
- ->setActor($user)
+ ->setActor($viewer)
->setContentSourceFromRequest($request)
- ->setContinueOnNoEffect(true)
- ->applyTransactions($project, $xactions);
+ ->setContinueOnNoEffect(true);
- $profile->setBlurb($request->getStr('blurb'));
+ try {
+ $editor->applyTransactions($project, $xactions);
- if (!strlen($project->getName())) {
- $e_name = pht('Required');
- $errors[] = pht('Project name is required.');
- } else {
- $e_name = null;
- }
-
- if (!$errors) {
- $project->save();
- $profile->setProjectPHID($project->getPHID());
+ // TODO: Move this into a custom field.
+ $profile->setBlurb($request->getStr('blurb'));
+ if (!$profile->getProjectPHID()) {
+ $profile->setProjectPHID($project->getPHID());
+ }
$profile->save();
- return id(new AphrontRedirectResponse())
- ->setURI('/project/view/'.$project->getID().'/');
+
+ return id(new AphrontRedirectResponse())->setURI($view_uri);
+ } catch (PhabricatorApplicationTransactionValidationException $ex) {
+ $validation_exception = $ex;
+
+ $e_name = $ex->getShortMessage($type_name);
+ $e_edit = $ex->getShortMessage($type_edit);
+
+ $project->setViewPolicy($v_view);
+ $project->setEditPolicy($v_edit);
+ $project->setJoinPolicy($v_join);
}
}
@@ -81,29 +111,33 @@
$action = '/project/edit/'.$project->getID().'/';
$policies = id(new PhabricatorPolicyQuery())
- ->setViewer($user)
+ ->setViewer($viewer)
->setObject($project)
->execute();
$form = new AphrontFormView();
$form
->setID('project-edit-form')
- ->setUser($user)
+ ->setUser($viewer)
->setAction($action)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
- ->setValue($project->getName())
+ ->setValue($v_name)
->setError($e_name))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Description'))
->setName('blurb')
- ->setValue($profile->getBlurb()))
+ ->setValue($v_desc));
+
+ $field_list->appendFieldsToForm($form);
+
+ $form
->appendChild(
id(new AphrontFormPolicyControl())
- ->setUser($user)
+ ->setUser($viewer)
->setName('can_view')
->setCaption(pht('Members can always view a project.'))
->setPolicyObject($project)
@@ -111,14 +145,15 @@
->setCapability(PhabricatorPolicyCapability::CAN_VIEW))
->appendChild(
id(new AphrontFormPolicyControl())
- ->setUser($user)
+ ->setUser($viewer)
->setName('can_edit')
->setPolicyObject($project)
->setPolicies($policies)
- ->setCapability(PhabricatorPolicyCapability::CAN_EDIT))
+ ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
+ ->setError($e_edit))
->appendChild(
id(new AphrontFormPolicyControl())
- ->setUser($user)
+ ->setUser($viewer)
->setName('can_join')
->setCaption(
pht('Users who can edit a project can always join a project.'))
@@ -127,18 +162,16 @@
->setCapability(PhabricatorPolicyCapability::CAN_JOIN))
->appendChild(
id(new AphrontFormSubmitControl())
- ->addCancelButton('/project/view/'.$project->getID().'/')
+ ->addCancelButton($view_uri)
->setValue(pht('Save')));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
- ->setFormErrors($errors)
+ ->setValidationException($validation_exception)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView())
- ->addTextCrumb(
- $project->getName(),
- '/project/view/'.$project->getID().'/')
+ ->addTextCrumb($project->getName(), $view_uri)
->addTextCrumb(pht('Edit Project'), $this->getApplicationURI());
return $this->buildApplicationPage(
Index: src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php
===================================================================
--- /dev/null
+++ src/applications/project/customfield/PhabricatorProjectConfiguredCustomField.php
@@ -0,0 +1,31 @@
+<?php
+
+final class PhabricatorProjectConfiguredCustomField
+ extends PhabricatorProjectCustomField
+ implements PhabricatorStandardCustomFieldInterface {
+
+ public function getStandardCustomFieldNamespace() {
+ return 'project';
+ }
+
+ public function createFields() {
+ return PhabricatorStandardCustomField::buildStandardFields(
+ $this,
+ PhabricatorEnv::getEnvConfig(
+ 'projects.custom-field-definitions',
+ array()));
+ }
+
+ public function newStorageObject() {
+ return new PhabricatorProjectCustomFieldStorage();
+ }
+
+ protected function newStringIndexStorage() {
+ return new PhabricatorProjectCustomFieldStringIndex();
+ }
+
+ protected function newNumericIndexStorage() {
+ return new PhabricatorProjectCustomFieldNumericIndex();
+ }
+
+}
Index: src/applications/project/customfield/PhabricatorProjectCustomField.php
===================================================================
--- /dev/null
+++ src/applications/project/customfield/PhabricatorProjectCustomField.php
@@ -0,0 +1,7 @@
+<?php
+
+abstract class PhabricatorProjectCustomField
+ extends PhabricatorCustomField {
+
+
+}
Index: src/applications/project/query/PhabricatorProjectQuery.php
===================================================================
--- src/applications/project/query/PhabricatorProjectQuery.php
+++ src/applications/project/query/PhabricatorProjectQuery.php
@@ -246,7 +246,7 @@
if ($this->memberPHIDs) {
return 'GROUP BY p.id';
} else {
- return '';
+ return $this->buildApplicationSearchGroupClause($conn_r);
}
}
@@ -270,6 +270,8 @@
PhabricatorEdgeConfig::TYPE_PROJ_MEMBER);
}
+ $joins[] = $this->buildApplicationSearchJoinClause($conn_r);
+
return implode(' ', $joins);
}
@@ -278,4 +280,8 @@
return 'PhabricatorApplicationProject';
}
+ protected function getApplicationSearchObjectPHIDColumn() {
+ return 'p.phid';
+ }
+
}
Index: src/applications/project/query/PhabricatorProjectSearchEngine.php
===================================================================
--- src/applications/project/query/PhabricatorProjectSearchEngine.php
+++ src/applications/project/query/PhabricatorProjectSearchEngine.php
@@ -3,6 +3,10 @@
final class PhabricatorProjectSearchEngine
extends PhabricatorApplicationSearchEngine {
+ public function getCustomFieldObject() {
+ return new PhabricatorProject();
+ }
+
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
@@ -11,6 +15,8 @@
$this->readUsersFromRequest($request, 'members'));
$saved->setParameter('status', $request->getStr('status'));
+ $this->readCustomFieldsFromRequest($request, $saved);
+
return $saved;
}
@@ -28,20 +34,22 @@
$query->withStatus($status);
}
+ $this->applyCustomFieldsToQuery($query, $saved);
+
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
- PhabricatorSavedQuery $saved_query) {
+ PhabricatorSavedQuery $saved) {
- $phids = $saved_query->getParameter('memberPHIDs', array());
+ $phids = $saved->getParameter('memberPHIDs', array());
$member_handles = id(new PhabricatorHandleQuery())
->setViewer($this->requireViewer())
->withPHIDs($phids)
->execute();
- $status = $saved_query->getParameter('status');
+ $status = $saved->getParameter('status');
$form
->appendChild(
@@ -56,6 +64,8 @@
->setName('status')
->setOptions($this->getStatusOptions())
->setValue($status));
+
+ $this->appendCustomFieldsToForm($form, $saved);
}
protected function getURI($path) {
Index: src/applications/project/storage/PhabricatorProject.php
===================================================================
--- src/applications/project/storage/PhabricatorProject.php
+++ src/applications/project/storage/PhabricatorProject.php
@@ -4,7 +4,8 @@
implements
PhabricatorFlaggableInterface,
PhabricatorPolicyInterface,
- PhabricatorSubscribableInterface {
+ PhabricatorSubscribableInterface,
+ PhabricatorCustomFieldInterface {
protected $name;
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
@@ -19,6 +20,7 @@
private $memberPHIDs = self::ATTACHABLE;
private $sparseMembers = self::ATTACHABLE;
private $profile = self::ATTACHABLE;
+ private $customFields = self::ATTACHABLE;
public static function initializeNewProject(PhabricatorUser $actor) {
return id(new PhabricatorProject())
@@ -168,4 +170,25 @@
}
+/* -( PhabricatorCustomFieldInterface )------------------------------------ */
+
+
+ public function getCustomFieldSpecificationForRole($role) {
+ return PhabricatorEnv::getEnvConfig('projects.fields');
+ }
+
+ public function getCustomFieldBaseClass() {
+ return 'PhabricatorProjectCustomField';
+ }
+
+ public function getCustomFields() {
+ return $this->assertAttached($this->customFields);
+ }
+
+ public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
+ $this->customFields = $fields;
+ return $this;
+ }
+
+
}

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 28, 5:55 AM (4 w, 15 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7427197
Default Alt Text
D8180.id.diff (17 KB)

Event Timeline