Skip to content

Commit 56be700

Browse files
author
epriestley
committedNov 30, 2015
Improve code structure of PHID fields in EditEngine
Summary: Ref T9132. I had some hacks in place for dealing with Edge/Subscribers stuff. Clean that up so it's structured a little better. Test Plan: - Edited subscribers and projects. - Verified things still show up in Conduit. - Made concurrent edits (added a project in one window, removed it in another window, got a clean result with a correct merge of the two edits). Reviewers: chad Reviewed By: chad Maniphest Tasks: T9132 Differential Revision: https://secure.phabricator.com/D14601
1 parent 50f257a commit 56be700

12 files changed

+209
-128
lines changed
 

‎src/__phutil_library_map__.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
'AphrontJavelinView' => 'view/AphrontJavelinView.php',
146146
'AphrontKeyboardShortcutsAvailableView' => 'view/widget/AphrontKeyboardShortcutsAvailableView.php',
147147
'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php',
148+
'AphrontListHTTPParameterType' => 'aphront/httpparametertype/AphrontListHTTPParameterType.php',
148149
'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php',
149150
'AphrontMoreView' => 'view/layout/AphrontMoreView.php',
150151
'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php',
@@ -2580,6 +2581,7 @@
25802581
'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php',
25812582
'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php',
25822583
'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php',
2584+
'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php',
25832585
'PhabricatorPHIDResolver' => 'applications/phid/resolver/PhabricatorPHIDResolver.php',
25842586
'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php',
25852587
'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php',
@@ -3943,18 +3945,19 @@
39433945
'AphrontJavelinView' => 'AphrontView',
39443946
'AphrontKeyboardShortcutsAvailableView' => 'AphrontView',
39453947
'AphrontListFilterView' => 'AphrontView',
3948+
'AphrontListHTTPParameterType' => 'AphrontHTTPParameterType',
39463949
'AphrontMalformedRequestException' => 'AphrontException',
39473950
'AphrontMoreView' => 'AphrontView',
39483951
'AphrontMultiColumnView' => 'AphrontView',
39493952
'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
39503953
'AphrontNullView' => 'AphrontView',
39513954
'AphrontPHIDHTTPParameterType' => 'AphrontHTTPParameterType',
3952-
'AphrontPHIDListHTTPParameterType' => 'AphrontHTTPParameterType',
3955+
'AphrontPHIDListHTTPParameterType' => 'AphrontListHTTPParameterType',
39533956
'AphrontPHPHTTPSink' => 'AphrontHTTPSink',
39543957
'AphrontPageView' => 'AphrontView',
39553958
'AphrontPlainTextResponse' => 'AphrontResponse',
39563959
'AphrontProgressBarView' => 'AphrontBarView',
3957-
'AphrontProjectListHTTPParameterType' => 'AphrontHTTPParameterType',
3960+
'AphrontProjectListHTTPParameterType' => 'AphrontListHTTPParameterType',
39583961
'AphrontProxyResponse' => array(
39593962
'AphrontResponse',
39603963
'AphrontResponseProducerInterface',
@@ -3974,13 +3977,13 @@
39743977
'AphrontStackTraceView' => 'AphrontView',
39753978
'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse',
39763979
'AphrontStringHTTPParameterType' => 'AphrontHTTPParameterType',
3977-
'AphrontStringListHTTPParameterType' => 'AphrontHTTPParameterType',
3980+
'AphrontStringListHTTPParameterType' => 'AphrontListHTTPParameterType',
39783981
'AphrontTableView' => 'AphrontView',
39793982
'AphrontTagView' => 'AphrontView',
39803983
'AphrontTokenizerTemplateView' => 'AphrontView',
39813984
'AphrontTypeaheadTemplateView' => 'AphrontView',
39823985
'AphrontUnhandledExceptionResponse' => 'AphrontStandaloneHTMLResponse',
3983-
'AphrontUserListHTTPParameterType' => 'AphrontHTTPParameterType',
3986+
'AphrontUserListHTTPParameterType' => 'AphrontListHTTPParameterType',
39843987
'AphrontView' => array(
39853988
'Phobject',
39863989
'PhutilSafeHTMLProducerInterface',
@@ -6752,6 +6755,7 @@
67526755
'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions',
67536756
'PhabricatorPHID' => 'Phobject',
67546757
'PhabricatorPHIDConstants' => 'Phobject',
6758+
'PhabricatorPHIDListEditField' => 'PhabricatorEditField',
67556759
'PhabricatorPHIDResolver' => 'Phobject',
67566760
'PhabricatorPHIDType' => 'Phobject',
67576761
'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase',
@@ -7437,7 +7441,7 @@
74377441
'PhabricatorTokenReceiverQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
74387442
'PhabricatorTokenTokenPHIDType' => 'PhabricatorPHIDType',
74397443
'PhabricatorTokenUIEventListener' => 'PhabricatorEventListener',
7440-
'PhabricatorTokenizerEditField' => 'PhabricatorEditField',
7444+
'PhabricatorTokenizerEditField' => 'PhabricatorPHIDListEditField',
74417445
'PhabricatorTokensApplication' => 'PhabricatorApplication',
74427446
'PhabricatorTokensSettingsPanel' => 'PhabricatorSettingsPanel',
74437447
'PhabricatorTooltipUIExample' => 'PhabricatorUIExample',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
abstract class AphrontListHTTPParameterType
4+
extends AphrontHTTPParameterType {
5+
6+
protected function getParameterDefault() {
7+
return array();
8+
}
9+
10+
}

‎src/aphront/httpparametertype/AphrontPHIDListHTTPParameterType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
final class AphrontPHIDListHTTPParameterType
4-
extends AphrontHTTPParameterType {
4+
extends AphrontListHTTPParameterType {
55

66
protected function getParameterValue(AphrontRequest $request, $key) {
77
$type = new AphrontStringListHTTPParameterType();

‎src/aphront/httpparametertype/AphrontProjectListHTTPParameterType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
final class AphrontProjectListHTTPParameterType
4-
extends AphrontHTTPParameterType {
4+
extends AphrontListHTTPParameterType {
55

66
protected function getParameterValue(AphrontRequest $request, $key) {
77
$type = new AphrontStringListHTTPParameterType();

‎src/aphront/httpparametertype/AphrontStringListHTTPParameterType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
final class AphrontStringListHTTPParameterType
4-
extends AphrontHTTPParameterType {
4+
extends AphrontListHTTPParameterType {
55

66
protected function getParameterValue(AphrontRequest $request, $key) {
77
$list = $request->getArr($key, null);

‎src/aphront/httpparametertype/AphrontUserListHTTPParameterType.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22

33
final class AphrontUserListHTTPParameterType
4-
extends AphrontHTTPParameterType {
4+
extends AphrontListHTTPParameterType {
55

66
protected function getParameterValue(AphrontRequest $request, $key) {
77
$type = new AphrontStringListHTTPParameterType();

‎src/applications/project/editor/PhabricatorProjectsEditEngineExtension.php

+5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public function buildCustomEditFields(
4848
->setEditTypeKey('projects')
4949
->setDescription(pht('Add or remove associated projects.'))
5050
->setAliases(array('project', 'projects'))
51+
->setUseEdgeTransactions(true)
52+
->setEdgeTransactionDescriptions(
53+
pht('Add projects.'),
54+
pht('Remove projects.'),
55+
pht('Set associated projects, overwriting current value.'))
5156
->setTransactionType($edge_type)
5257
->setMetadataValue('edge:type', $project_edge_type)
5358
->setValue($project_phids);

‎src/applications/subscriptions/editor/PhabricatorSubscriptionsEditEngineExtension.php

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public function buildCustomEditFields(
4545
->setEditTypeKey('subscribers')
4646
->setDescription(pht('Manage subscribers.'))
4747
->setAliases(array('subscriber', 'subscribers'))
48+
->setUseEdgeTransactions(true)
49+
->setEdgeTransactionDescriptions(
50+
pht('Add subscribers.'),
51+
pht('Remove subscribers.'),
52+
pht('Set subscribers, overwriting current value.'))
4853
->setTransactionType($subscribers_type)
4954
->setValue($sub_phids);
5055

‎src/applications/transactions/editengine/PhabricatorEditEngine.php

+5
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,11 @@ private function getAllEditTypesFromFields(array $fields) {
10481048
$types = array();
10491049
foreach ($fields as $field) {
10501050
$field_types = $field->getEditTransactionTypes();
1051+
1052+
if ($field_types === null) {
1053+
continue;
1054+
}
1055+
10511056
foreach ($field_types as $field_type) {
10521057
$field_type->setField($field);
10531058
$types[$field_type->getEditType()] = $field_type;

‎src/applications/transactions/editfield/PhabricatorEditField.php

+51-52
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ abstract class PhabricatorEditField extends Phobject {
77
private $label;
88
private $aliases = array();
99
private $value;
10+
private $initialValue;
1011
private $hasValue = false;
1112
private $object;
1213
private $transactionType;
@@ -262,6 +263,7 @@ protected function getValue() {
262263

263264
public function setValue($value) {
264265
$this->hasValue = true;
266+
$this->initialValue = $value;
265267
$this->value = $value;
266268
return $this;
267269
}
@@ -289,6 +291,10 @@ public function setMetadataValue($key, $value) {
289291
return $this;
290292
}
291293

294+
public function getMetadata() {
295+
return $this->metadata;
296+
}
297+
292298
protected function getValueForTransaction() {
293299
return $this->getValue();
294300
}
@@ -348,6 +354,31 @@ protected function getValueFromRequest(AphrontRequest $request, $key) {
348354
return $this->getValueFromSubmit($request, $key);
349355
}
350356

357+
358+
/**
359+
* Read and return the value the object had when the user first loaded the
360+
* form.
361+
*
362+
* This is the initial value from the user's point of view when they started
363+
* the edit process, and used primarily to prevent race conditions for fields
364+
* like "Projects" and "Subscribers" that use tokenizers and support edge
365+
* transactions.
366+
*
367+
* Most fields do not need to store these values or deal with initial value
368+
* handling.
369+
*
370+
* @param AphrontRequest Request to read from.
371+
* @param string Key to read.
372+
* @return wild Value read from request.
373+
*/
374+
protected function getInitialValueFromSubmit(AphrontRequest $request, $key) {
375+
return null;
376+
}
377+
378+
public function getInitialValue() {
379+
return $this->initialValue;
380+
}
381+
351382
public function readValueFromSubmit(AphrontRequest $request) {
352383
$key = $this->getKey();
353384
if ($this->getValueExistsInSubmit($request, $key)) {
@@ -356,6 +387,10 @@ public function readValueFromSubmit(AphrontRequest $request) {
356387
$value = $this->getDefaultValue();
357388
}
358389
$this->value = $value;
390+
391+
$initial_value = $this->getInitialValueFromSubmit($request, $key);
392+
$this->initialValue = $initial_value;
393+
359394
return $this;
360395
}
361396

@@ -414,66 +449,30 @@ protected function newEditType() {
414449
->setValueType($this->getHTTPParameterType()->getTypeName());
415450
}
416451

417-
public function getEditTransactionTypes() {
452+
protected function getEditTransactionType() {
418453
$transaction_type = $this->getTransactionType();
454+
419455
if ($transaction_type === null) {
420-
return array();
456+
return null;
421457
}
422458

423459
$type_key = $this->getEditTypeKey();
424460

425-
// TODO: This is a pretty big pile of hard-coded hacks for now.
426-
427-
$edge_types = array(
428-
PhabricatorTransactions::TYPE_EDGE => array(
429-
'+' => pht('Add projects.'),
430-
'-' => pht('Remove projects.'),
431-
'=' => pht('Set associated projects, overwriting current value.'),
432-
),
433-
PhabricatorTransactions::TYPE_SUBSCRIBERS => array(
434-
'+' => pht('Add subscribers.'),
435-
'-' => pht('Remove subscribers.'),
436-
'=' => pht('Set subscribers, overwriting current value.'),
437-
),
438-
);
439-
440-
if (isset($edge_types[$transaction_type])) {
441-
$base = id(new PhabricatorEdgeEditType())
442-
->setTransactionType($transaction_type)
443-
->setMetadata($this->metadata);
444-
445-
$strings = $edge_types[$transaction_type];
446-
447-
$add = id(clone $base)
448-
->setEditType($type_key.'.add')
449-
->setEdgeOperation('+')
450-
->setDescription($strings['+'])
451-
->setValueDescription(pht('List of PHIDs to add.'));
452-
$rem = id(clone $base)
453-
->setEditType($type_key.'.remove')
454-
->setEdgeOperation('-')
455-
->setDescription($strings['-'])
456-
->setValueDescription(pht('List of PHIDs to remove.'));
457-
$set = id(clone $base)
458-
->setEditType($type_key.'.set')
459-
->setEdgeOperation('=')
460-
->setDescription($strings['='])
461-
->setValueDescription(pht('List of PHIDs to set.'));
462-
463-
return array(
464-
$add,
465-
$rem,
466-
$set,
467-
);
461+
return $this->newEditType()
462+
->setEditType($type_key)
463+
->setTransactionType($transaction_type)
464+
->setDescription($this->getDescription())
465+
->setMetadata($this->getMetadata());
466+
}
467+
468+
public function getEditTransactionTypes() {
469+
$edit_type = $this->getEditTransactionType();
470+
471+
if ($edit_type === null) {
472+
return null;
468473
}
469474

470-
return array(
471-
$this->newEditType()
472-
->setEditType($type_key)
473-
->setTransactionType($transaction_type)
474-
->setDescription($this->getDescription())
475-
->setMetadata($this->metadata),
476-
);
475+
return array($edit_type);
477476
}
478477

479478
}

0 commit comments

Comments
 (0)
Failed to load comments.