Differential D16111 Diff 38770 src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
Show First 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | abstract class PhabricatorApplicationTransactionEditor | ||||
private $heraldEmailPHIDs = array(); | private $heraldEmailPHIDs = array(); | ||||
private $heraldForcedEmailPHIDs = array(); | private $heraldForcedEmailPHIDs = array(); | ||||
private $heraldHeader; | private $heraldHeader; | ||||
private $mailToPHIDs = array(); | private $mailToPHIDs = array(); | ||||
private $mailCCPHIDs = array(); | private $mailCCPHIDs = array(); | ||||
private $feedNotifyPHIDs = array(); | private $feedNotifyPHIDs = array(); | ||||
private $feedRelatedPHIDs = array(); | private $feedRelatedPHIDs = array(); | ||||
private $modularTypes; | |||||
const STORAGE_ENCODING_BINARY = 'binary'; | const STORAGE_ENCODING_BINARY = 'binary'; | ||||
/** | /** | ||||
* Get the class name for the application this editor is a part of. | * Get the class name for the application this editor is a part of. | ||||
* | * | ||||
* Uninstalling the application will disable the editor. | * Uninstalling the application will disable the editor. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | if ($this->object instanceof PhabricatorProjectInterface || | ||||
$this->object instanceof PhabricatorMentionableInterface) { | $this->object instanceof PhabricatorMentionableInterface) { | ||||
$types[] = PhabricatorTransactions::TYPE_EDGE; | $types[] = PhabricatorTransactions::TYPE_EDGE; | ||||
} | } | ||||
if ($this->object instanceof PhabricatorSpacesInterface) { | if ($this->object instanceof PhabricatorSpacesInterface) { | ||||
$types[] = PhabricatorTransactions::TYPE_SPACE; | $types[] = PhabricatorTransactions::TYPE_SPACE; | ||||
} | } | ||||
$template = $this->object->getApplicationTransactionTemplate(); | |||||
if ($template instanceof PhabricatorModularTransaction) { | |||||
$xtypes = $template->newModularTransactionTypes(); | |||||
foreach ($xtypes as $xtype) { | |||||
$types[] = $xtype->getTransactionTypeConstant(); | |||||
} | |||||
} | |||||
return $types; | return $types; | ||||
} | } | ||||
private function adjustTransactionValues( | private function adjustTransactionValues( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
PhabricatorApplicationTransaction $xaction) { | PhabricatorApplicationTransaction $xaction) { | ||||
if ($xaction->shouldGenerateOldValue()) { | if ($xaction->shouldGenerateOldValue()) { | ||||
$old = $this->getTransactionOldValue($object, $xaction); | $old = $this->getTransactionOldValue($object, $xaction); | ||||
$xaction->setOldValue($old); | $xaction->setOldValue($old); | ||||
} | } | ||||
$new = $this->getTransactionNewValue($object, $xaction); | $new = $this->getTransactionNewValue($object, $xaction); | ||||
$xaction->setNewValue($new); | $xaction->setNewValue($new); | ||||
} | } | ||||
private function getTransactionOldValue( | private function getTransactionOldValue( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
PhabricatorApplicationTransaction $xaction) { | PhabricatorApplicationTransaction $xaction) { | ||||
switch ($xaction->getTransactionType()) { | |||||
$type = $xaction->getTransactionType(); | |||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
return $xtype->generateOldValue($object); | |||||
} | |||||
switch ($type) { | |||||
case PhabricatorTransactions::TYPE_CREATE: | case PhabricatorTransactions::TYPE_CREATE: | ||||
return null; | return null; | ||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS: | case PhabricatorTransactions::TYPE_SUBSCRIBERS: | ||||
return array_values($this->subscribers); | return array_values($this->subscribers); | ||||
case PhabricatorTransactions::TYPE_VIEW_POLICY: | case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
if ($this->getIsNewObject()) { | if ($this->getIsNewObject()) { | ||||
return null; | return null; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | switch ($type) { | ||||
default: | default: | ||||
return $this->getCustomTransactionOldValue($object, $xaction); | return $this->getCustomTransactionOldValue($object, $xaction); | ||||
} | } | ||||
} | } | ||||
private function getTransactionNewValue( | private function getTransactionNewValue( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
PhabricatorApplicationTransaction $xaction) { | PhabricatorApplicationTransaction $xaction) { | ||||
switch ($xaction->getTransactionType()) { | |||||
$type = $xaction->getTransactionType(); | |||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
return $xtype->generateNewValue($object, $xaction->getNewValue()); | |||||
} | |||||
switch ($type) { | |||||
case PhabricatorTransactions::TYPE_CREATE: | case PhabricatorTransactions::TYPE_CREATE: | ||||
return null; | return null; | ||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS: | case PhabricatorTransactions::TYPE_SUBSCRIBERS: | ||||
return $this->getPHIDTransactionNewValue($xaction); | return $this->getPHIDTransactionNewValue($xaction); | ||||
case PhabricatorTransactions::TYPE_VIEW_POLICY: | case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
case PhabricatorTransactions::TYPE_EDIT_POLICY: | case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
case PhabricatorTransactions::TYPE_JOIN_POLICY: | case PhabricatorTransactions::TYPE_JOIN_POLICY: | ||||
case PhabricatorTransactions::TYPE_BUILDABLE: | case PhabricatorTransactions::TYPE_BUILDABLE: | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | protected function applyInitialEffects( | ||||
array $xactions) { | array $xactions) { | ||||
throw new PhutilMethodNotImplementedException(); | throw new PhutilMethodNotImplementedException(); | ||||
} | } | ||||
private function applyInternalEffects( | private function applyInternalEffects( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
PhabricatorApplicationTransaction $xaction) { | PhabricatorApplicationTransaction $xaction) { | ||||
switch ($xaction->getTransactionType()) { | $type = $xaction->getTransactionType(); | ||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
return $xtype->applyInternalEffects($object, $xaction->getNewValue()); | |||||
} | |||||
switch ($type) { | |||||
case PhabricatorTransactions::TYPE_CUSTOMFIELD: | case PhabricatorTransactions::TYPE_CUSTOMFIELD: | ||||
$field = $this->getCustomFieldForTransaction($object, $xaction); | $field = $this->getCustomFieldForTransaction($object, $xaction); | ||||
return $field->applyApplicationTransactionInternalEffects($xaction); | return $field->applyApplicationTransactionInternalEffects($xaction); | ||||
case PhabricatorTransactions::TYPE_CREATE: | case PhabricatorTransactions::TYPE_CREATE: | ||||
case PhabricatorTransactions::TYPE_BUILDABLE: | case PhabricatorTransactions::TYPE_BUILDABLE: | ||||
case PhabricatorTransactions::TYPE_TOKEN: | case PhabricatorTransactions::TYPE_TOKEN: | ||||
case PhabricatorTransactions::TYPE_VIEW_POLICY: | case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
case PhabricatorTransactions::TYPE_EDIT_POLICY: | case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
case PhabricatorTransactions::TYPE_JOIN_POLICY: | case PhabricatorTransactions::TYPE_JOIN_POLICY: | ||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS: | case PhabricatorTransactions::TYPE_SUBSCRIBERS: | ||||
case PhabricatorTransactions::TYPE_INLINESTATE: | case PhabricatorTransactions::TYPE_INLINESTATE: | ||||
case PhabricatorTransactions::TYPE_EDGE: | case PhabricatorTransactions::TYPE_EDGE: | ||||
case PhabricatorTransactions::TYPE_SPACE: | case PhabricatorTransactions::TYPE_SPACE: | ||||
case PhabricatorTransactions::TYPE_COMMENT: | case PhabricatorTransactions::TYPE_COMMENT: | ||||
return $this->applyBuiltinInternalTransaction($object, $xaction); | return $this->applyBuiltinInternalTransaction($object, $xaction); | ||||
} | } | ||||
return $this->applyCustomInternalTransaction($object, $xaction); | return $this->applyCustomInternalTransaction($object, $xaction); | ||||
} | } | ||||
private function applyExternalEffects( | private function applyExternalEffects( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
PhabricatorApplicationTransaction $xaction) { | PhabricatorApplicationTransaction $xaction) { | ||||
switch ($xaction->getTransactionType()) { | |||||
$type = $xaction->getTransactionType(); | |||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
return $xtype->applyExternalEffects($object, $xaction->getNewValue()); | |||||
} | |||||
switch ($type) { | |||||
case PhabricatorTransactions::TYPE_SUBSCRIBERS: | case PhabricatorTransactions::TYPE_SUBSCRIBERS: | ||||
$subeditor = id(new PhabricatorSubscriptionsEditor()) | $subeditor = id(new PhabricatorSubscriptionsEditor()) | ||||
->setObject($object) | ->setObject($object) | ||||
->setActor($this->requireActor()); | ->setActor($this->requireActor()); | ||||
$old_map = array_fuse($xaction->getOldValue()); | $old_map = array_fuse($xaction->getOldValue()); | ||||
$new_map = array_fuse($xaction->getNewValue()); | $new_map = array_fuse($xaction->getNewValue()); | ||||
▲ Show 20 Lines • Show All 265 Lines • ▼ Show 20 Lines | if (!$is_preview) { | ||||
unset($errors[$key]); | unset($errors[$key]); | ||||
} | } | ||||
} | } | ||||
if ($errors) { | if ($errors) { | ||||
throw new PhabricatorApplicationTransactionValidationException($errors); | throw new PhabricatorApplicationTransactionValidationException($errors); | ||||
} | } | ||||
$this->willApplyTransactions($object, $xactions); | |||||
if ($object->getID()) { | if ($object->getID()) { | ||||
foreach ($xactions as $xaction) { | foreach ($xactions as $xaction) { | ||||
// If any of the transactions require a read lock, hold one and | // If any of the transactions require a read lock, hold one and | ||||
// reload the object. We need to do this fairly early so that the | // reload the object. We need to do this fairly early so that the | ||||
// call to `adjustTransactionValues()` (which populates old values) | // call to `adjustTransactionValues()` (which populates old values) | ||||
// is based on the synchronized state of the object, which may differ | // is based on the synchronized state of the object, which may differ | ||||
// from the state when it was originally loaded. | // from the state when it was originally loaded. | ||||
▲ Show 20 Lines • Show All 1,188 Lines • ▼ Show 20 Lines | |||||
* validation errors. | * validation errors. | ||||
*/ | */ | ||||
protected function validateTransaction( | protected function validateTransaction( | ||||
PhabricatorLiskDAO $object, | PhabricatorLiskDAO $object, | ||||
$type, | $type, | ||||
array $xactions) { | array $xactions) { | ||||
$errors = array(); | $errors = array(); | ||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
$errors[] = $xtype->validateTransactions($object, $xactions); | |||||
} | |||||
switch ($type) { | switch ($type) { | ||||
case PhabricatorTransactions::TYPE_VIEW_POLICY: | case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
$errors[] = $this->validatePolicyTransaction( | $errors[] = $this->validatePolicyTransaction( | ||||
$object, | $object, | ||||
$xactions, | $xactions, | ||||
$type, | $type, | ||||
PhabricatorPolicyCapability::CAN_VIEW); | PhabricatorPolicyCapability::CAN_VIEW); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 1,107 Lines • ▼ Show 20 Lines | private function extractFilePHIDs( | ||||
$phids = array(); | $phids = array(); | ||||
if ($blocks) { | if ($blocks) { | ||||
$phids[] = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles( | $phids[] = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles( | ||||
$this->getActor(), | $this->getActor(), | ||||
$blocks); | $blocks); | ||||
} | } | ||||
foreach ($xactions as $xaction) { | foreach ($xactions as $xaction) { | ||||
$type = $xaction->getTransactionType(); | |||||
$xtype = $this->getModularTransactionType($type); | |||||
if ($xtype) { | |||||
$phids[] = $xtype->extractFilePHIDs($object, $xaction->getNewValue()); | |||||
} else { | |||||
$phids[] = $this->extractFilePHIDsFromCustomTransaction( | $phids[] = $this->extractFilePHIDsFromCustomTransaction( | ||||
$object, | $object, | ||||
$xaction); | $xaction); | ||||
} | } | ||||
} | |||||
$phids = array_unique(array_filter(array_mergev($phids))); | $phids = array_unique(array_filter(array_mergev($phids))); | ||||
if (!$phids) { | if (!$phids) { | ||||
return array(); | return array(); | ||||
} | } | ||||
// Only let a user attach files they can actually see, since this would | // Only let a user attach files they can actually see, since this would | ||||
// otherwise let you access any file by attaching it to an object you have | // otherwise let you access any file by attaching it to an object you have | ||||
▲ Show 20 Lines • Show All 543 Lines • ▼ Show 20 Lines | private function updateWorkboardColumns($object, $const, $old, $new) { | ||||
queryfx( | queryfx( | ||||
$conn_w, | $conn_w, | ||||
'DELETE FROM %T WHERE objectPHID = %s AND columnPHID IN (%Ls)', | 'DELETE FROM %T WHERE objectPHID = %s AND columnPHID IN (%Ls)', | ||||
$position_table->getTableName(), | $position_table->getTableName(), | ||||
$object->getPHID(), | $object->getPHID(), | ||||
$proxy_phids); | $proxy_phids); | ||||
} | } | ||||
private function getModularTransactionTypes() { | |||||
if ($this->modularTypes === null) { | |||||
$template = $this->object->getApplicationTransactionTemplate(); | |||||
if ($template instanceof PhabricatorModularTransaction) { | |||||
$xtypes = $template->newModularTransactionTypes(); | |||||
foreach ($xtypes as $key => $xtype) { | |||||
$xtype = clone $xtype; | |||||
$xtype->setEditor($this); | |||||
$xtypes[$key] = $xtype; | |||||
} | |||||
} else { | |||||
$xtypes = array(); | |||||
} | |||||
$this->modularTypes = $xtypes; | |||||
} | |||||
return $this->modularTypes; | |||||
} | |||||
private function getModularTransactionType($type) { | |||||
$types = $this->getModularTransactionTypes(); | |||||
return idx($types, $type); | |||||
} | |||||
private function willApplyTransactions($object, array $xactions) { | |||||
foreach ($xactions as $xaction) { | |||||
$type = $xaction->getTransactionType(); | |||||
$xtype = $this->getModularTransactionType($type); | |||||
if (!$xtype) { | |||||
continue; | |||||
} | |||||
$xtype->willApplyTransactions($object, $xactions); | |||||
} | |||||
} | |||||
public function getCreateObjectTitle($author, $object) { | |||||
return pht('%s created this object.', $author); | |||||
} | |||||
public function getCreateObjectTitleForFeed($author, $object) { | |||||
return pht('%s created an object: %s.', $author, $object); | |||||
} | |||||
} | } |