Page MenuHomePhabricator

D14093.id34066.diff
No OneTemporary

D14093.id34066.diff

diff --git a/resources/sql/autopatches/20150910.owners.custom.1.sql b/resources/sql/autopatches/20150910.owners.custom.1.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150910.owners.custom.1.sql
@@ -0,0 +1,25 @@
+CREATE TABLE {$NAMESPACE}_owners.owners_customfieldstorage (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectPHID VARBINARY(64) NOT NULL,
+ fieldIndex BINARY(12) NOT NULL,
+ fieldValue LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ UNIQUE KEY (objectPHID, fieldIndex)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_owners.owners_customfieldstringindex (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectPHID VARBINARY(64) NOT NULL,
+ indexKey BINARY(12) NOT NULL,
+ indexValue LONGTEXT NOT NULL COLLATE {$COLLATE_SORT},
+ KEY `key_join` (objectPHID, indexKey, indexValue(64)),
+ KEY `key_find` (indexKey, indexValue(64))
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_owners.owners_customfieldnumericindex (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ objectPHID VARBINARY(64) NOT NULL,
+ indexKey BINARY(12) NOT NULL,
+ indexValue BIGINT NOT NULL,
+ KEY `key_join` (objectPHID, indexKey, indexValue),
+ KEY `key_find` (indexKey, indexValue)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2437,7 +2437,12 @@
'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php',
'PhabricatorOwnersApplication' => 'applications/owners/application/PhabricatorOwnersApplication.php',
'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php',
+ 'PhabricatorOwnersConfiguredCustomField' => 'applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php',
'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php',
+ 'PhabricatorOwnersCustomField' => 'applications/owners/customfield/PhabricatorOwnersCustomField.php',
+ 'PhabricatorOwnersCustomFieldNumericIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php',
+ 'PhabricatorOwnersCustomFieldStorage' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php',
+ 'PhabricatorOwnersCustomFieldStringIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php',
'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php',
'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php',
'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php',
@@ -6425,7 +6430,15 @@
'PhabricatorOwnerPathQuery' => 'Phobject',
'PhabricatorOwnersApplication' => 'PhabricatorApplication',
'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions',
+ 'PhabricatorOwnersConfiguredCustomField' => array(
+ 'PhabricatorOwnersCustomField',
+ 'PhabricatorStandardCustomFieldInterface',
+ ),
'PhabricatorOwnersController' => 'PhabricatorController',
+ 'PhabricatorOwnersCustomField' => 'PhabricatorCustomField',
+ 'PhabricatorOwnersCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
+ 'PhabricatorOwnersCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
+ 'PhabricatorOwnersCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
@@ -6435,6 +6448,7 @@
'PhabricatorOwnersDAO',
'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorCustomFieldInterface',
),
'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
diff --git a/src/applications/owners/config/PhabricatorOwnersConfigOptions.php b/src/applications/owners/config/PhabricatorOwnersConfigOptions.php
--- a/src/applications/owners/config/PhabricatorOwnersConfigOptions.php
+++ b/src/applications/owners/config/PhabricatorOwnersConfigOptions.php
@@ -20,9 +20,35 @@
}
public function getOptions() {
+ $custom_field_type = 'custom:PhabricatorCustomFieldConfigOptionType';
+ $default_fields = array();
+
+ $field_base_class = id(new PhabricatorOwnersPackage())
+ ->getCustomFieldBaseClass();
+
+ $fields_example = array(
+ 'mycompany:lore' => array(
+ 'name' => pht('Package Lore'),
+ 'type' => 'remarkup',
+ 'caption' => pht('Tales of adventure for this package.'),
+ ),
+ );
+ $fields_example = id(new PhutilJSON())->encodeFormatted($fields_example);
+
return array(
$this->newOption('metamta.package.subject-prefix', 'string', '[Package]')
->setDescription(pht('Subject prefix for Owners email.')),
+ $this->newOption('owners.fields', $custom_field_type, $default_fields)
+ ->setCustomData($field_base_class)
+ ->setDescription(pht('Select and reorder package fields.')),
+ $this->newOption('owners.custom-field-definitions', 'wild', array())
+ ->setSummary(pht('Custom Owners fields.'))
+ ->setDescription(
+ pht(
+ 'Map of custom fields for Owners packages. For details on '.
+ 'adding custom fields to Owners, see "Configuring Custom '.
+ 'Fields" in the documentation.'))
+ ->addExample($fields_example, pht('Valid Setting')),
);
}
diff --git a/src/applications/owners/controller/PhabricatorOwnersDetailController.php b/src/applications/owners/controller/PhabricatorOwnersDetailController.php
--- a/src/applications/owners/controller/PhabricatorOwnersDetailController.php
+++ b/src/applications/owners/controller/PhabricatorOwnersDetailController.php
@@ -37,8 +37,15 @@
$repositories = array();
}
+ $field_list = PhabricatorCustomField::getObjectFields(
+ $package,
+ PhabricatorCustomField::ROLE_VIEW);
+ $field_list
+ ->setViewer($viewer)
+ ->readFieldsFromStorage($package);
+
$actions = $this->buildPackageActionView($package);
- $properties = $this->buildPackagePropertyView($package);
+ $properties = $this->buildPackagePropertyView($package, $field_list);
$properties->setActionList($actions);
if ($package->isArchived()) {
@@ -156,7 +163,10 @@
}
- private function buildPackagePropertyView(PhabricatorOwnersPackage $package) {
+ private function buildPackagePropertyView(
+ PhabricatorOwnersPackage $package,
+ PhabricatorCustomFieldList $field_list) {
+
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
@@ -187,6 +197,13 @@
$viewer));
}
+ $view->invokeWillRenderEvent();
+
+ $field_list->appendFieldsToPropertyList(
+ $package,
+ $viewer,
+ $view);
+
return $view;
}
diff --git a/src/applications/owners/controller/PhabricatorOwnersEditController.php b/src/applications/owners/controller/PhabricatorOwnersEditController.php
--- a/src/applications/owners/controller/PhabricatorOwnersEditController.php
+++ b/src/applications/owners/controller/PhabricatorOwnersEditController.php
@@ -36,6 +36,11 @@
$v_description = $package->getDescription();
$v_status = $package->getStatus();
+ $field_list = PhabricatorCustomField::getObjectFields(
+ $package,
+ PhabricatorCustomField::ROLE_EDIT);
+ $field_list->setViewer($viewer);
+ $field_list->readFieldsFromStorage($package);
$errors = array();
if ($request->isFormPost()) {
@@ -75,6 +80,12 @@
->setNewValue($v_status);
}
+ $field_xactions = $field_list->buildFieldTransactionsFromRequest(
+ new PhabricatorOwnersPackageTransaction(),
+ $request);
+
+ $xactions = array_merge($xactions, $field_xactions);
+
$editor = id(new PhabricatorOwnersPackageTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
@@ -126,41 +137,44 @@
->setName('owners')
->setValue($v_owners));
- if (!$is_new) {
- $form->appendChild(
- id(new AphrontFormSelectControl())
- ->setLabel(pht('Status'))
- ->setName('status')
- ->setValue($v_status)
- ->setOptions($package->getStatusNameMap()));
- }
-
+ if (!$is_new) {
$form->appendChild(
id(new AphrontFormSelectControl())
- ->setName('auditing')
- ->setLabel(pht('Auditing'))
- ->setCaption(
- pht(
- 'With auditing enabled, all future commits that touch '.
- 'this package will be reviewed to make sure an owner '.
- 'of the package is involved and the commit message has '.
- 'a valid revision, reviewed by, and author.'))
- ->setOptions(
- array(
- 'disabled' => pht('Disabled'),
- 'enabled' => pht('Enabled'),
- ))
- ->setValue(($v_auditing ? 'enabled' : 'disabled')))
+ ->setLabel(pht('Status'))
+ ->setName('status')
+ ->setValue($v_status)
+ ->setOptions($package->getStatusNameMap()));
+ }
+
+ $form->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setName('auditing')
+ ->setLabel(pht('Auditing'))
+ ->setCaption(
+ pht(
+ 'With auditing enabled, all future commits that touch '.
+ 'this package will be reviewed to make sure an owner '.
+ 'of the package is involved and the commit message has '.
+ 'a valid revision, reviewed by, and author.'))
+ ->setOptions(
+ array(
+ 'disabled' => pht('Disabled'),
+ 'enabled' => pht('Enabled'),
+ ))
+ ->setValue(($v_auditing ? 'enabled' : 'disabled')))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setLabel(pht('Description'))
->setName('description')
- ->setValue($v_description))
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->addCancelButton($cancel_uri)
- ->setValue($button_text));
+ ->setValue($v_description));
+
+ $field_list->appendFieldsToForm($form);
+
+ $form->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton($cancel_uri)
+ ->setValue($button_text));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
diff --git a/src/applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php b/src/applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php
@@ -0,0 +1,23 @@
+<?php
+
+final class PhabricatorOwnersConfiguredCustomField
+ extends PhabricatorOwnersCustomField
+ implements PhabricatorStandardCustomFieldInterface {
+
+ public function getStandardCustomFieldNamespace() {
+ return 'owners';
+ }
+
+ public function createFields($object) {
+ $config = PhabricatorEnv::getEnvConfig(
+ 'owners.custom-field-definitions',
+ array());
+
+ $fields = PhabricatorStandardCustomField::buildStandardFields(
+ $this,
+ $config);
+
+ return $fields;
+ }
+
+}
diff --git a/src/applications/owners/customfield/PhabricatorOwnersCustomField.php b/src/applications/owners/customfield/PhabricatorOwnersCustomField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/owners/customfield/PhabricatorOwnersCustomField.php
@@ -0,0 +1,18 @@
+<?php
+
+abstract class PhabricatorOwnersCustomField
+ extends PhabricatorCustomField {
+
+ public function newStorageObject() {
+ return new PhabricatorOwnersCustomFieldStorage();
+ }
+
+ protected function newStringIndexStorage() {
+ return new PhabricatorOwnersCustomFieldStringIndex();
+ }
+
+ protected function newNumericIndexStorage() {
+ return new PhabricatorOwnersCustomFieldNumericIndex();
+ }
+
+}
diff --git a/src/applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php b/src/applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php
new file mode 100644
--- /dev/null
+++ b/src/applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorOwnersCustomFieldNumericIndex
+ extends PhabricatorCustomFieldNumericIndexStorage {
+
+ public function getApplicationName() {
+ return 'owners';
+ }
+
+}
diff --git a/src/applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php b/src/applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php
new file mode 100644
--- /dev/null
+++ b/src/applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorOwnersCustomFieldStorage
+ extends PhabricatorCustomFieldStorage {
+
+ public function getApplicationName() {
+ return 'owners';
+ }
+
+}
diff --git a/src/applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php b/src/applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php
new file mode 100644
--- /dev/null
+++ b/src/applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorOwnersCustomFieldStringIndex
+ extends PhabricatorCustomFieldStringIndexStorage {
+
+ public function getApplicationName() {
+ return 'owners';
+ }
+
+}
diff --git a/src/applications/owners/storage/PhabricatorOwnersPackage.php b/src/applications/owners/storage/PhabricatorOwnersPackage.php
--- a/src/applications/owners/storage/PhabricatorOwnersPackage.php
+++ b/src/applications/owners/storage/PhabricatorOwnersPackage.php
@@ -4,7 +4,8 @@
extends PhabricatorOwnersDAO
implements
PhabricatorPolicyInterface,
- PhabricatorApplicationTransactionInterface {
+ PhabricatorApplicationTransactionInterface,
+ PhabricatorCustomFieldInterface {
protected $name;
protected $originalName;
@@ -16,6 +17,7 @@
private $paths = self::ATTACHABLE;
private $owners = self::ATTACHABLE;
+ private $customFields = self::ATTACHABLE;
const STATUS_ACTIVE = 'active';
const STATUS_ARCHIVED = 'archived';
@@ -304,4 +306,25 @@
return $timeline;
}
+
+/* -( PhabricatorCustomFieldInterface )------------------------------------ */
+
+
+ public function getCustomFieldSpecificationForRole($role) {
+ return PhabricatorEnv::getEnvConfig('owners.fields');
+ }
+
+ public function getCustomFieldBaseClass() {
+ return 'PhabricatorOwnersCustomField';
+ }
+
+ public function getCustomFields() {
+ return $this->assertAttached($this->customFields);
+ }
+
+ public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
+ $this->customFields = $fields;
+ return $this;
+ }
+
}
diff --git a/src/docs/user/configuration/custom_fields.diviner b/src/docs/user/configuration/custom_fields.diviner
--- a/src/docs/user/configuration/custom_fields.diviner
+++ b/src/docs/user/configuration/custom_fields.diviner
@@ -16,11 +16,12 @@
| Application | Support |
|-------------|---------|
-| Maniphest | Full Support |
-| Projects | Full Support |
-| People | Full Support |
| Differential | Partial Support |
| Diffusion | Limited Support |
+| Maniphest | Full Support |
+| Owners | Full Support |
+| People | Full Support |
+| Projects | Full Support |
Custom fields can appear in many interfaces and support search, editing, and
other features.
@@ -38,11 +39,12 @@
| Application | Add Fields | Select Fields |
|-------------|------------|---------------|
-| Maniphest | `maniphest.custom-field-definitions` | `maniphest.fields` |
-| Projects | `projects.custom-field-definitions` | `projects.fields` |
-| People | `user.custom-field-definitions` | `user.fields` |
| Differential | Planned | `differential.fields` |
| Diffusion | Planned | Planned |
+| Maniphest | `maniphest.custom-field-definitions` | `maniphest.fields` |
+| Owners | `owners.custom-field-definitions` | `owners.fields` |
+| People | `user.custom-field-definitions` | `user.fields` |
+| Projects | `projects.custom-field-definitions` | `projects.fields` |
When adding fields, you'll specify a JSON blob like this (for example, as the
value of `maniphest.custom-field-definitions`):
@@ -157,11 +159,12 @@
| Application | Extend |
|-------------|---------|
-| Maniphest | @{class:ManiphestCustomField} |
-| Projects | @{class:PhabricatorProjectCustomField} |
-| People | @{class:PhabricatorUserCustomField} |
| Differential | @{class:DifferentialCustomField} |
| Diffusion | @{class:PhabricatorCommitCustomField} |
+| Maniphest | @{class:ManiphestCustomField} |
+| Owners | @{class:PhabricatorOwnersCustomField} |
+| People | @{class:PhabricatorUserCustomField} |
+| Projects | @{class:PhabricatorProjectCustomField} |
The easiest way to get started is to drop your subclass into
`phabricator/src/extensions/`, which should make it immediately available in the

File Metadata

Mime Type
text/plain
Expires
Wed, May 8, 9:48 PM (2 w, 10 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6273156
Default Alt Text
D14093.id34066.diff (17 KB)

Event Timeline