@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 219 lines 8.7 kB view raw
1@title Configuring Custom Fields 2@group config 3 4How to add custom fields to applications which support them. 5 6= Overview = 7 8Several Phorge applications allow the configuration of custom fields. These 9fields allow you to add more information to objects, and in some cases reorder 10or remove builtin fields. 11 12For example, you could use custom fields to add an "Estimated Hours" field to 13tasks, a "Lead" field to projects, or a "T-Shirt Size" field to users. 14 15These applications currently support custom fields: 16 17| Application | Support | 18|-------------|---------| 19| Differential | Partial Support | 20| Diffusion | Limited Support | 21| Maniphest | Full Support | 22| Owners | Full Support | 23| People | Full Support | 24| Projects | Full Support | 25 26Custom fields can appear in many interfaces and support search, editing, and 27other features. 28 29= Basic Custom Fields = 30 31To get started with custom fields, you can use configuration to select and 32reorder fields and to add new simple fields. 33 34If you don't need complicated display controls or sophisticated validation, 35these simple fields should cover most use cases. They allow you to attach 36things like strings, numbers, and dropdown menus to objects. 37 38The relevant configuration settings are: 39 40| Application | Add Fields | Select Fields | 41|-------------|------------|---------------| 42| Differential | Planned | `differential.fields` | 43| Diffusion | Planned | Planned | 44| Maniphest | `maniphest.custom-field-definitions` | `maniphest.fields` | 45| Owners | `owners.custom-field-definitions` | `owners.fields` | 46| People | `user.custom-field-definitions` | `user.fields` | 47| Projects | `projects.custom-field-definitions` | `projects.fields` | 48 49When adding fields, you'll specify a JSON blob like this (for example, as the 50value of `maniphest.custom-field-definitions`): 51 52 { 53 "mycompany:estimated-hours": { 54 "name": "Estimated Hours", 55 "type": "int", 56 "caption": "Estimated number of hours this will take.", 57 "required": true 58 }, 59 "mycompany:actual-hours": { 60 "name": "Actual Hours", 61 "type": "int", 62 "caption": "Actual number of hours this took." 63 }, 64 "mycompany:company-jobs": { 65 "name": "Job Role", 66 "type": "select", 67 "options": { 68 "mycompany:engineer": "Engineer", 69 "mycompany:nonengineer": "Other" 70 } 71 }, 72 "mycompany:favorite-dinosaur": { 73 "name": "Favorite Dinosaur", 74 "type": "text" 75 } 76 } 77 78The fields will then appear in the other config option for the application 79(for example, in `maniphest.fields`) and you can enable, disable, or reorder 80them. 81 82For details on how to define a field, see the next section. 83 84= Custom Field Configuration = 85 86When defining custom fields using a configuration option like 87`maniphest.custom-field-definitions`, these options are available: 88 89 - **name**: Display label for the field on the edit and detail interfaces. 90 - **description**: Optional text shown when managing the field. 91 - **type**: Field type. The supported field types are: 92 - **int**: An integer, rendered as a text field. 93 - **text**: A string, rendered as a text field. 94 - **bool**: A boolean value, rendered as a checkbox. 95 - **select**: Allows the user to select from several options as defined 96 by **options**, rendered as a dropdown. 97 - **remarkup**: A text area which allows the user to enter markup. 98 - **users**: A typeahead which allows multiple users to be input. 99 - **date**: A date/time picker. 100 - **header**: Renders a visual divider which you can use to group fields. 101 - **link**: A text field which allows the user to enter a link. 102 - **edit**: Show this field on the application's edit interface (this 103 defaults to `true`). 104 - **view**: Show this field on the application's view interface (this 105 defaults to `true`). (Note: Empty fields are not shown.) 106 - **search**: Show this field on the application's search interface, allowing 107 users to filter objects by the field value. 108 - **fulltext**: Index the text in this field as part of the object's global 109 full-text index. This allows users to find the object by searching for 110 the field's contents using global search. 111 - **caption**: A caption to display underneath the field (optional). 112 - **required**: True if the user should be required to provide a value. 113 - **options**: If type is set to **select**, provide options for the dropdown 114 as a dictionary. 115 - **default**: Default field value. 116 - **strings**: Allows you to override specific strings based on the field 117 type. See below. 118 - **instructions**: Optional block of remarkup text which will appear 119 above the control when rendered on the edit view. 120 - **placeholder**: A placeholder text that appears on text boxes. Only 121 supported in text, int and remarkup fields (optional). 122 - **list**: If set to `icon`, `attribute` or `byline`, the value of the field 123 will be shown in list-view. 124 - **list.icon**: If `list` is set to `icon`, use this icon. These are the 125 same icons that can be used in the `{icon}` syntax for Remarkup. 126 - **list.label**: When rendering value in a list, use this label (instead of 127 `name`). 128 - **copy**: If true, this field's value will be copied when an object is 129 created using another object as a template. 130 - **limit**: For control types which use a tokenizer control to let the user 131 select a list of values, this limits how many values can be selected. For 132 example, a "users" field with a limit of "1" will behave like the "Owner" 133 field in Maniphest and only allow selection of a single user. 134 135The `strings` value supports different strings per control type. They are: 136 137 - **bool** 138 - **edit.checkbox** Text for the edit interface, no default. 139 - **view.yes** Text for the view interface, defaults to "Yes". 140 - **search.default** Text for the search interface, defaults to "(Any)". 141 - **search.require** Text for the search interface, defaults to "Require". 142 143Internally, Phorge implements some additional custom field types and 144options. These are not intended for general use and are subject to abrupt 145change, but are documented here for completeness: 146 147 - **Credentials**: Controls with type `credential` allow selection of a 148 Passphrase credential which provides `credential.provides`, and creation 149 of credentials of `credential.type`. 150 - **Datasource**: Controls with type `datasource` allow selection of tokens 151 from an arbitrary datasource, controlled with `datasource.class` and 152 `datasource.parameters`. 153 154= Advanced Custom Fields = 155 156If you want custom fields to have advanced behaviors (sophisticated rendering, 157advanced validation, complicated controls, interaction with other systems, etc), 158you can write a custom field as an extension and add it to Phorge. 159 160To do this, extend the appropriate `CustomField` class for the application you 161want to add a field to: 162 163| Application | Extend | 164|-------------|---------| 165| Differential | @{class:DifferentialCustomField} | 166| Diffusion | @{class:PhabricatorCommitCustomField} | 167| Maniphest | @{class:ManiphestCustomField} | 168| Owners | @{class:PhabricatorOwnersCustomField} | 169| People | @{class:PhabricatorUserCustomField} | 170| Projects | @{class:PhabricatorProjectCustomField} | 171 172The easiest way to get started is to drop your subclass into 173`phorge/src/extensions/`. If Phorge is configured in development 174mode, the class should immediately be available in the UI. If not, you can 175restart Phorge (for help, see @{article:Restarting Phorge}). 176 177For example, this is a simple template which adds a custom field to Maniphest: 178 179 name=ExampleManiphestCustomField.php 180 <?php 181 182 final class ExampleCustomField extends ManiphestCustomField { 183 184 public function getFieldKey() { 185 return 'example:test'; 186 } 187 188 public function shouldAppearInPropertyView() { 189 return true; 190 } 191 192 public function renderPropertyViewLabel() { 193 return pht('Example Custom Field'); 194 } 195 196 public function renderPropertyViewValue(array $handles) { 197 return phutil_tag( 198 'h1', 199 array( 200 'style' => 'color: #ff00ff', 201 ), 202 pht('It worked!')); 203 } 204 205 } 206 207Broadly, you can then add features by overriding more methods and implementing 208them. Many of the native fields are implemented on the custom field 209architecture, and it may be useful to look at them. For details on available 210integrations, see the base class for your application and 211@{class:PhabricatorCustomField}. 212 213= Next Steps = 214 215Continue by: 216 217 - learning more about extending Phorge with custom code in 218 @{article@contrib:Adding New Classes}; 219 - or returning to the @{article: Configuration Guide}.