2012-12-11 13:59:20 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
abstract class PhabricatorApplicationTransaction
|
|
|
|
extends PhabricatorLiskDAO
|
2014-05-01 18:25:30 -07:00
|
|
|
implements
|
|
|
|
PhabricatorPolicyInterface,
|
2014-07-21 23:59:22 +10:00
|
|
|
PhabricatorDestructibleInterface {
|
2012-12-11 13:59:20 -08:00
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
const TARGET_TEXT = 'text';
|
|
|
|
const TARGET_HTML = 'html';
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
protected $phid;
|
|
|
|
protected $objectPHID;
|
|
|
|
protected $authorPHID;
|
|
|
|
protected $viewPolicy;
|
|
|
|
protected $editPolicy;
|
|
|
|
|
|
|
|
protected $commentPHID;
|
|
|
|
protected $commentVersion = 0;
|
|
|
|
protected $transactionType;
|
|
|
|
protected $oldValue;
|
|
|
|
protected $newValue;
|
2013-03-28 08:34:34 -07:00
|
|
|
protected $metadata = array();
|
2012-12-11 13:59:20 -08:00
|
|
|
|
|
|
|
protected $contentSource;
|
|
|
|
|
|
|
|
private $comment;
|
|
|
|
private $commentNotLoaded;
|
|
|
|
|
|
|
|
private $handles;
|
2012-12-11 14:00:07 -08:00
|
|
|
private $renderingTarget = self::TARGET_HTML;
|
2013-03-09 19:23:50 -08:00
|
|
|
private $transactionGroup = array();
|
2013-09-23 14:32:22 -07:00
|
|
|
private $viewer = self::ATTACHABLE;
|
2014-02-18 16:32:35 -08:00
|
|
|
private $object = self::ATTACHABLE;
|
2014-03-05 10:44:21 -08:00
|
|
|
private $oldValueHasBeenSet = false;
|
2012-12-11 13:59:20 -08:00
|
|
|
|
2014-02-25 12:36:02 -08:00
|
|
|
private $ignoreOnNoEffect;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag this transaction as a pure side-effect which should be ignored when
|
|
|
|
* applying transactions if it has no effect, even if transaction application
|
|
|
|
* would normally fail. This both provides users with better error messages
|
|
|
|
* and allows transactions to perform optional side effects.
|
|
|
|
*/
|
|
|
|
public function setIgnoreOnNoEffect($ignore) {
|
|
|
|
$this->ignoreOnNoEffect = $ignore;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIgnoreOnNoEffect() {
|
|
|
|
return $this->ignoreOnNoEffect;
|
|
|
|
}
|
|
|
|
|
2014-03-03 15:58:00 -08:00
|
|
|
public function shouldGenerateOldValue() {
|
|
|
|
switch ($this->getTransactionType()) {
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
2014-04-21 15:33:59 -07:00
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
2014-03-03 15:58:00 -08:00
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
abstract public function getApplicationTransactionType();
|
2013-08-20 10:04:33 -07:00
|
|
|
|
|
|
|
private function getApplicationObjectTypeName() {
|
|
|
|
$types = PhabricatorPHIDType::getAllTypes();
|
|
|
|
|
|
|
|
$type = idx($types, $this->getApplicationTransactionType());
|
|
|
|
if ($type) {
|
|
|
|
return $type->getTypeName();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pht('Object');
|
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
|
2013-08-20 10:00:25 -07:00
|
|
|
public function getApplicationTransactionCommentObject() {
|
2014-06-09 11:36:49 -07:00
|
|
|
throw new Exception('Not implemented!');
|
2013-08-20 10:00:25 -07:00
|
|
|
}
|
|
|
|
|
2013-03-09 19:23:50 -08:00
|
|
|
public function getApplicationTransactionViewObject() {
|
|
|
|
return new PhabricatorApplicationTransactionView();
|
|
|
|
}
|
|
|
|
|
2013-03-28 08:34:34 -07:00
|
|
|
public function getMetadataValue($key, $default = null) {
|
|
|
|
return idx($this->metadata, $key, $default);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setMetadataValue($key, $value) {
|
|
|
|
$this->metadata[$key] = $value;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function generatePHID() {
|
2013-07-29 06:51:19 -07:00
|
|
|
$type = PhabricatorApplicationTransactionPHIDTypeTransaction::TYPECONST;
|
2012-12-11 13:59:20 -08:00
|
|
|
$subtype = $this->getApplicationTransactionType();
|
|
|
|
|
|
|
|
return PhabricatorPHID::generateNewPHID($type, $subtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getConfiguration() {
|
|
|
|
return array(
|
|
|
|
self::CONFIG_AUX_PHID => true,
|
|
|
|
self::CONFIG_SERIALIZATION => array(
|
|
|
|
'oldValue' => self::SERIALIZATION_JSON,
|
|
|
|
'newValue' => self::SERIALIZATION_JSON,
|
2013-03-28 08:34:34 -07:00
|
|
|
'metadata' => self::SERIALIZATION_JSON,
|
2012-12-11 13:59:20 -08:00
|
|
|
),
|
|
|
|
) + parent::getConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setContentSource(PhabricatorContentSource $content_source) {
|
|
|
|
$this->contentSource = $content_source->serialize();
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getContentSource() {
|
|
|
|
return PhabricatorContentSource::newFromSerialized($this->contentSource);
|
|
|
|
}
|
|
|
|
|
Modernize Macro application
Summary: Adds feed, email, notifications, comments, partial editing, subscriptions, enable/disable, flags and crumbs to Macro.
Test Plan:
{F26839}
{F26840}
{F26841}
{F26842}
{F26843}
{F26844}
{F26845}
Reviewers: vrana, btrahan, chad
Reviewed By: vrana
CC: aran
Maniphest Tasks: T2157, T175, T2104
Differential Revision: https://secure.phabricator.com/D4141
2012-12-11 14:01:03 -08:00
|
|
|
public function hasComment() {
|
|
|
|
return $this->getComment() && strlen($this->getComment()->getContent());
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function getComment() {
|
|
|
|
if ($this->commentNotLoaded) {
|
2014-06-09 11:36:49 -07:00
|
|
|
throw new Exception('Comment for this transaction was not loaded.');
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
return $this->comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function attachComment(
|
|
|
|
PhabricatorApplicationTransactionComment $comment) {
|
|
|
|
$this->comment = $comment;
|
|
|
|
$this->commentNotLoaded = false;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setCommentNotLoaded($not_loaded) {
|
|
|
|
$this->commentNotLoaded = $not_loaded;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-02-18 16:32:35 -08:00
|
|
|
public function attachObject($object) {
|
|
|
|
$this->object = $object;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getObject() {
|
|
|
|
return $this->assertAttached($this->object);
|
|
|
|
}
|
|
|
|
|
2014-02-28 15:20:45 -08:00
|
|
|
public function getRemarkupBlocks() {
|
|
|
|
$blocks = array();
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$field = $this->getTransactionCustomField();
|
|
|
|
if ($field) {
|
|
|
|
$custom_blocks = $field->getApplicationTransactionRemarkupBlocks(
|
|
|
|
$this);
|
|
|
|
foreach ($custom_blocks as $custom_block) {
|
|
|
|
$blocks[] = $custom_block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->getComment()) {
|
|
|
|
$blocks[] = $this->getComment()->getContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $blocks;
|
|
|
|
}
|
|
|
|
|
2014-03-05 10:44:21 -08:00
|
|
|
public function setOldValue($value) {
|
|
|
|
$this->oldValueHasBeenSet = true;
|
|
|
|
$this->writeField('oldValue', $value);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasOldValue() {
|
|
|
|
return $this->oldValueHasBeenSet;
|
|
|
|
}
|
|
|
|
|
2014-02-28 15:20:45 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
/* -( Rendering )---------------------------------------------------------- */
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
public function setRenderingTarget($rendering_target) {
|
|
|
|
$this->renderingTarget = $rendering_target;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRenderingTarget() {
|
|
|
|
return $this->renderingTarget;
|
|
|
|
}
|
|
|
|
|
2013-09-23 14:32:22 -07:00
|
|
|
public function attachViewer(PhabricatorUser $viewer) {
|
|
|
|
$this->viewer = $viewer;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getViewer() {
|
|
|
|
return $this->assertAttached($this->viewer);
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function getRequiredHandlePHIDs() {
|
|
|
|
$phids = array();
|
|
|
|
|
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
|
|
|
|
$phids[] = array($this->getAuthorPHID());
|
|
|
|
switch ($this->getTransactionType()) {
|
2014-02-21 11:53:37 -08:00
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$field = $this->getTransactionCustomField();
|
|
|
|
if ($field) {
|
|
|
|
$phids[] = $field->getApplicationTransactionRequiredHandlePHIDs(
|
|
|
|
$this);
|
|
|
|
}
|
|
|
|
break;
|
2012-12-11 13:59:20 -08:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
$phids[] = $old;
|
|
|
|
$phids[] = $new;
|
|
|
|
break;
|
2013-03-28 08:34:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDGE:
|
|
|
|
$phids[] = ipull($old, 'dst');
|
|
|
|
$phids[] = ipull($new, 'dst');
|
|
|
|
break;
|
2013-05-26 08:43:09 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
2013-05-26 08:43:09 -07:00
|
|
|
if (!PhabricatorPolicyQuery::isGlobalPolicy($old)) {
|
|
|
|
$phids[] = array($old);
|
|
|
|
}
|
|
|
|
if (!PhabricatorPolicyQuery::isGlobalPolicy($new)) {
|
|
|
|
$phids[] = array($new);
|
|
|
|
}
|
|
|
|
break;
|
2014-04-21 15:33:59 -07:00
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
|
|
|
break;
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
$phid = $this->getMetadataValue('harbormaster:buildablePHID');
|
|
|
|
if ($phid) {
|
|
|
|
$phids[] = array($phid);
|
|
|
|
}
|
|
|
|
break;
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
|
2014-05-05 10:55:32 -07:00
|
|
|
if ($this->getComment()) {
|
|
|
|
$phids[] = array($this->getComment()->getAuthorPHID());
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
return array_mergev($phids);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setHandles(array $handles) {
|
|
|
|
$this->handles = $handles;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getHandle($phid) {
|
|
|
|
if (empty($this->handles[$phid])) {
|
|
|
|
throw new Exception(
|
2014-02-21 11:54:08 -08:00
|
|
|
pht(
|
|
|
|
'Transaction ("%s") requires a handle ("%s") that it did not '.
|
|
|
|
'load.',
|
|
|
|
$this->getPHID(),
|
|
|
|
$phid));
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
return $this->handles[$phid];
|
|
|
|
}
|
|
|
|
|
2013-05-26 09:51:14 -07:00
|
|
|
public function getHandleIfExists($phid) {
|
|
|
|
return idx($this->handles, $phid);
|
|
|
|
}
|
|
|
|
|
2013-01-24 17:23:05 -08:00
|
|
|
public function getHandles() {
|
|
|
|
if ($this->handles === null) {
|
|
|
|
throw new Exception(
|
|
|
|
'Transaction requires handles and it did not load them.'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return $this->handles;
|
|
|
|
}
|
|
|
|
|
2013-06-18 10:02:34 -07:00
|
|
|
public function renderHandleLink($phid) {
|
2012-12-11 14:00:07 -08:00
|
|
|
if ($this->renderingTarget == self::TARGET_HTML) {
|
|
|
|
return $this->getHandle($phid)->renderLink();
|
|
|
|
} else {
|
2013-10-01 09:37:18 -07:00
|
|
|
return $this->getHandle($phid)->getLinkName();
|
2012-12-11 14:00:07 -08:00
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
|
2013-06-18 10:02:34 -07:00
|
|
|
public function renderHandleList(array $phids) {
|
2012-12-11 13:59:20 -08:00
|
|
|
$links = array();
|
|
|
|
foreach ($phids as $phid) {
|
|
|
|
$links[] = $this->renderHandleLink($phid);
|
|
|
|
}
|
2013-10-01 09:37:18 -07:00
|
|
|
if ($this->renderingTarget == self::TARGET_HTML) {
|
|
|
|
return phutil_implode_html(', ', $links);
|
|
|
|
} else {
|
|
|
|
return implode(', ', $links);
|
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
|
2014-03-14 14:27:45 -07:00
|
|
|
private function renderSubscriberList(array $phids, $change_type) {
|
|
|
|
if ($this->getRenderingTarget() == self::TARGET_TEXT) {
|
|
|
|
return $this->renderHandleList($phids);
|
|
|
|
} else {
|
|
|
|
$handles = array_select_keys($this->getHandles(), $phids);
|
|
|
|
return id(new SubscriptionListStringBuilder())
|
|
|
|
->setHandles($handles)
|
|
|
|
->setObjectPHID($this->getPHID())
|
|
|
|
->buildTransactionString($change_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-29 10:57:32 -07:00
|
|
|
protected function renderPolicyName($phid, $state = 'old') {
|
2013-09-26 17:27:21 -07:00
|
|
|
$policy = PhabricatorPolicy::newFromPolicyAndHandle(
|
|
|
|
$phid,
|
|
|
|
$this->getHandleIfExists($phid));
|
|
|
|
if ($this->renderingTarget == self::TARGET_HTML) {
|
2014-04-29 09:42:54 -07:00
|
|
|
switch ($policy->getType()) {
|
|
|
|
case PhabricatorPolicyType::TYPE_CUSTOM:
|
|
|
|
$policy->setHref('/transactions/'.$state.'/'.$this->getPHID().'/');
|
|
|
|
$policy->setWorkflow(true);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-09-26 17:27:21 -07:00
|
|
|
$output = $policy->renderDescription();
|
|
|
|
} else {
|
|
|
|
$output = hsprintf('%s', $policy->getFullName());
|
|
|
|
}
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:35 -08:00
|
|
|
public function getIcon() {
|
Modernize Macro application
Summary: Adds feed, email, notifications, comments, partial editing, subscriptions, enable/disable, flags and crumbs to Macro.
Test Plan:
{F26839}
{F26840}
{F26841}
{F26842}
{F26843}
{F26844}
{F26845}
Reviewers: vrana, btrahan, chad
Reviewed By: vrana
CC: aran
Maniphest Tasks: T2157, T175, T2104
Differential Revision: https://secure.phabricator.com/D4141
2012-12-11 14:01:03 -08:00
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
2014-05-05 12:00:27 -07:00
|
|
|
$comment = $this->getComment();
|
|
|
|
if ($comment && $comment->getIsRemoved()) {
|
|
|
|
return 'fa-eraser';
|
|
|
|
}
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-comment';
|
Modernize Macro application
Summary: Adds feed, email, notifications, comments, partial editing, subscriptions, enable/disable, flags and crumbs to Macro.
Test Plan:
{F26839}
{F26840}
{F26841}
{F26842}
{F26843}
{F26844}
{F26845}
Reviewers: vrana, btrahan, chad
Reviewed By: vrana
CC: aran
Maniphest Tasks: T2157, T175, T2104
Differential Revision: https://secure.phabricator.com/D4141
2012-12-11 14:01:03 -08:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-envelope';
|
Modernize Macro application
Summary: Adds feed, email, notifications, comments, partial editing, subscriptions, enable/disable, flags and crumbs to Macro.
Test Plan:
{F26839}
{F26840}
{F26841}
{F26842}
{F26843}
{F26844}
{F26845}
Reviewers: vrana, btrahan, chad
Reviewed By: vrana
CC: aran
Maniphest Tasks: T2157, T175, T2104
Differential Revision: https://secure.phabricator.com/D4141
2012-12-11 14:01:03 -08:00
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-lock';
|
2013-03-28 08:34:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDGE:
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-link';
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-wrench';
|
2014-04-21 15:33:59 -07:00
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
2014-05-12 10:08:32 -07:00
|
|
|
return 'fa-trophy';
|
Modernize Macro application
Summary: Adds feed, email, notifications, comments, partial editing, subscriptions, enable/disable, flags and crumbs to Macro.
Test Plan:
{F26839}
{F26840}
{F26841}
{F26842}
{F26843}
{F26844}
{F26845}
Reviewers: vrana, btrahan, chad
Reviewed By: vrana
CC: aran
Maniphest Tasks: T2157, T175, T2104
Differential Revision: https://secure.phabricator.com/D4141
2012-12-11 14:01:03 -08:00
|
|
|
}
|
|
|
|
|
2014-04-22 08:25:54 -07:00
|
|
|
return 'fa-pencil';
|
2012-12-11 13:59:35 -08:00
|
|
|
}
|
|
|
|
|
2014-04-21 15:33:59 -07:00
|
|
|
public function getToken() {
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
if ($new) {
|
|
|
|
$icon = substr($new, 10);
|
|
|
|
} else {
|
|
|
|
$icon = substr($old, 10);
|
|
|
|
}
|
|
|
|
return array($icon, !$this->getNewValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
return array(null, null);
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:35 -08:00
|
|
|
public function getColor() {
|
2014-04-17 16:04:14 -07:00
|
|
|
switch ($this->getTransactionType()) {
|
2014-05-05 12:00:27 -07:00
|
|
|
case PhabricatorTransactions::TYPE_COMMENT;
|
|
|
|
$comment = $this->getComment();
|
|
|
|
if ($comment && $comment->getIsRemoved()) {
|
|
|
|
return 'black';
|
|
|
|
}
|
|
|
|
break;
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
|
|
|
case HarbormasterBuildable::STATUS_PASSED:
|
|
|
|
return 'green';
|
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
|
|
|
return 'red';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-12-11 13:59:35 -08:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
protected function getTransactionCustomField() {
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$key = $this->getMetadataValue('customfield:key');
|
|
|
|
if (!$key) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$field = PhabricatorCustomField::getObjectField(
|
|
|
|
$this->getObject(),
|
|
|
|
PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS,
|
|
|
|
$key);
|
|
|
|
if (!$field) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$field->setViewer($this->getViewer());
|
|
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function shouldHide() {
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
2012-12-11 13:59:20 -08:00
|
|
|
if ($this->getOldValue() === null) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
2014-03-08 11:21:38 -08:00
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$field = $this->getTransactionCustomField();
|
|
|
|
if ($field) {
|
|
|
|
return $field->shouldHideInApplicationTransactions($this);
|
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-25 15:29:10 -08:00
|
|
|
public function shouldHideForMail(array $xactions) {
|
2014-04-17 16:04:14 -07:00
|
|
|
switch ($this->getTransactionType()) {
|
2014-04-21 15:33:59 -07:00
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
|
|
|
return true;
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
2014-05-15 07:02:30 -07:00
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
|
|
|
// For now, only ever send mail when builds fail. We might let
|
2014-04-17 16:04:14 -07:00
|
|
|
// you customize this later, but in most cases this is probably
|
|
|
|
// completely uninteresting.
|
2014-05-15 07:02:30 -07:00
|
|
|
return false;
|
2014-04-17 16:04:14 -07:00
|
|
|
}
|
2014-05-15 07:02:30 -07:00
|
|
|
return true;
|
2014-04-17 16:04:14 -07:00
|
|
|
}
|
|
|
|
|
2013-07-29 08:38:25 -07:00
|
|
|
return $this->shouldHide();
|
|
|
|
}
|
|
|
|
|
2014-03-04 17:01:33 -08:00
|
|
|
public function shouldHideForFeed() {
|
2014-04-21 15:33:59 -07:00
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
|
|
|
return true;
|
2014-04-29 11:10:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
2014-05-15 07:02:30 -07:00
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
2014-04-29 11:10:34 -07:00
|
|
|
// For now, don't notify on build passes either. These are pretty
|
|
|
|
// high volume and annoying, with very little present value. We
|
|
|
|
// might want to turn them back on in the specific case of
|
|
|
|
// build successes on the current document?
|
2014-05-15 07:02:30 -07:00
|
|
|
return false;
|
2014-04-29 11:10:34 -07:00
|
|
|
}
|
2014-05-15 07:02:30 -07:00
|
|
|
return true;
|
2014-04-21 15:33:59 -07:00
|
|
|
}
|
|
|
|
|
2014-03-04 17:01:33 -08:00
|
|
|
return $this->shouldHide();
|
|
|
|
}
|
|
|
|
|
2014-02-25 15:29:10 -08:00
|
|
|
public function getTitleForMail() {
|
|
|
|
return id(clone $this)->setRenderingTarget('text')->getTitle();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getBodyForMail() {
|
|
|
|
$comment = $this->getComment();
|
|
|
|
if ($comment && strlen($comment->getContent())) {
|
|
|
|
return $comment->getContent();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
Add ApplicationTransaction handling for transactions with no effect
Summary:
When a user submits an action with no effect (like an empty comment, an "abandon" on an already-accepted revision, or a "close, resolved" on a closed task) we want to alert them that their action isn't effective. These warnings fall into two general buckets:
- User is submitting two or more actions, and some aren't effective but some are. Prompt them to apply the effective actions only.
- A special case of this is where the only effective action is a comment. We provide tailored text ("Post Comment") in this case.
- User is submitting one action, which isn't effective. Tell them they're out of luck.
- A special case of this is an empty comment. We provide tailored text in this case.
By default, the transaction editor throws when transactions have no effect. The caller can then deal with this, or use `PhabricatorApplicationTransactionNoEffectResponse` to provide a standard dialog that gives the user information as above. For cases where we expect transactions to have no effect (notably, "edit" forms) we just continue on no-effect unconditionally.
Also fix an issue where new, combined or filtered transactions would not be represented properly in the Ajax response (i.e., return final transactions from `applyTransactions()`), and translate some strings.
Test Plan:
- Submitted empty and nonempy comments in Macro and Pholio.
- Submitted comments with new and existing "@mentions".
- Submitted edits in both applications.
Reviewers: btrahan, vrana
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T912, T2104
Differential Revision: https://secure.phabricator.com/D4160
2012-12-11 17:27:40 -08:00
|
|
|
public function getNoEffectDescription() {
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return pht('You can not post an empty comment.');
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
return pht(
|
|
|
|
'This %s already has that view policy.',
|
|
|
|
$this->getApplicationObjectTypeName());
|
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
|
|
|
return pht(
|
|
|
|
'This %s already has that edit policy.',
|
|
|
|
$this->getApplicationObjectTypeName());
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
|
|
|
return pht(
|
|
|
|
'This %s already has that join policy.',
|
|
|
|
$this->getApplicationObjectTypeName());
|
Add ApplicationTransaction handling for transactions with no effect
Summary:
When a user submits an action with no effect (like an empty comment, an "abandon" on an already-accepted revision, or a "close, resolved" on a closed task) we want to alert them that their action isn't effective. These warnings fall into two general buckets:
- User is submitting two or more actions, and some aren't effective but some are. Prompt them to apply the effective actions only.
- A special case of this is where the only effective action is a comment. We provide tailored text ("Post Comment") in this case.
- User is submitting one action, which isn't effective. Tell them they're out of luck.
- A special case of this is an empty comment. We provide tailored text in this case.
By default, the transaction editor throws when transactions have no effect. The caller can then deal with this, or use `PhabricatorApplicationTransactionNoEffectResponse` to provide a standard dialog that gives the user information as above. For cases where we expect transactions to have no effect (notably, "edit" forms) we just continue on no-effect unconditionally.
Also fix an issue where new, combined or filtered transactions would not be represented properly in the Ajax response (i.e., return final transactions from `applyTransactions()`), and translate some strings.
Test Plan:
- Submitted empty and nonempy comments in Macro and Pholio.
- Submitted comments with new and existing "@mentions".
- Submitted edits in both applications.
Reviewers: btrahan, vrana
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T912, T2104
Differential Revision: https://secure.phabricator.com/D4160
2012-12-11 17:27:40 -08:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
return pht(
|
|
|
|
'All users are already subscribed to this %s.',
|
|
|
|
$this->getApplicationObjectTypeName());
|
2013-03-28 08:34:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDGE:
|
|
|
|
return pht('Edges already exist; transaction has no effect.');
|
Add ApplicationTransaction handling for transactions with no effect
Summary:
When a user submits an action with no effect (like an empty comment, an "abandon" on an already-accepted revision, or a "close, resolved" on a closed task) we want to alert them that their action isn't effective. These warnings fall into two general buckets:
- User is submitting two or more actions, and some aren't effective but some are. Prompt them to apply the effective actions only.
- A special case of this is where the only effective action is a comment. We provide tailored text ("Post Comment") in this case.
- User is submitting one action, which isn't effective. Tell them they're out of luck.
- A special case of this is an empty comment. We provide tailored text in this case.
By default, the transaction editor throws when transactions have no effect. The caller can then deal with this, or use `PhabricatorApplicationTransactionNoEffectResponse` to provide a standard dialog that gives the user information as above. For cases where we expect transactions to have no effect (notably, "edit" forms) we just continue on no-effect unconditionally.
Also fix an issue where new, combined or filtered transactions would not be represented properly in the Ajax response (i.e., return final transactions from `applyTransactions()`), and translate some strings.
Test Plan:
- Submitted empty and nonempy comments in Macro and Pholio.
- Submitted comments with new and existing "@mentions".
- Submitted edits in both applications.
Reviewers: btrahan, vrana
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T912, T2104
Differential Revision: https://secure.phabricator.com/D4160
2012-12-11 17:27:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return pht('Transaction has no effect.');
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
public function getTitle() {
|
|
|
|
$author_phid = $this->getAuthorPHID();
|
|
|
|
|
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return pht(
|
|
|
|
'%s added a comment.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the visibility of this %s from "%s" to "%s".',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->getApplicationObjectTypeName(),
|
2014-04-29 09:42:54 -07:00
|
|
|
$this->renderPolicyName($old, 'old'),
|
|
|
|
$this->renderPolicyName($new, 'new'));
|
2012-12-11 13:59:20 -08:00
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the edit policy of this %s from "%s" to "%s".',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->getApplicationObjectTypeName(),
|
2014-04-29 09:42:54 -07:00
|
|
|
$this->renderPolicyName($old, 'old'),
|
|
|
|
$this->renderPolicyName($new, 'new'));
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the join policy of this %s from "%s" to "%s".',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->getApplicationObjectTypeName(),
|
2014-04-29 09:42:54 -07:00
|
|
|
$this->renderPolicyName($old, 'old'),
|
|
|
|
$this->renderPolicyName($new, 'new'));
|
2012-12-11 13:59:20 -08:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
$add = array_diff($new, $old);
|
|
|
|
$rem = array_diff($old, $new);
|
|
|
|
|
|
|
|
if ($add && $rem) {
|
|
|
|
return pht(
|
|
|
|
'%s edited subscriber(s), added %d: %s; removed %d: %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
count($add),
|
2014-03-14 14:27:45 -07:00
|
|
|
$this->renderSubscriberList($add, 'add'),
|
2012-12-11 13:59:20 -08:00
|
|
|
count($rem),
|
2014-03-14 14:27:45 -07:00
|
|
|
$this->renderSubscriberList($rem, 'rem'));
|
2012-12-11 13:59:20 -08:00
|
|
|
} else if ($add) {
|
|
|
|
return pht(
|
|
|
|
'%s added %d subscriber(s): %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
count($add),
|
2014-03-14 14:27:45 -07:00
|
|
|
$this->renderSubscriberList($add, 'add'));
|
2013-09-23 14:29:59 -07:00
|
|
|
} else if ($rem) {
|
2012-12-11 13:59:20 -08:00
|
|
|
return pht(
|
2013-02-17 09:13:40 -08:00
|
|
|
'%s removed %d subscriber(s): %s.',
|
2012-12-11 13:59:20 -08:00
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
count($rem),
|
2014-03-14 14:27:45 -07:00
|
|
|
$this->renderSubscriberList($rem, 'rem'));
|
2013-09-23 14:29:59 -07:00
|
|
|
} else {
|
|
|
|
// This is used when rendering previews, before the user actually
|
|
|
|
// selects any CCs.
|
|
|
|
return pht(
|
|
|
|
'%s updated subscribers...',
|
|
|
|
$this->renderHandleLink($author_phid));
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|
|
|
|
break;
|
2013-03-28 08:34:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDGE:
|
2013-07-19 15:59:29 -07:00
|
|
|
$new = ipull($new, 'dst');
|
|
|
|
$old = ipull($old, 'dst');
|
|
|
|
$add = array_diff($new, $old);
|
|
|
|
$rem = array_diff($old, $new);
|
2013-03-28 08:34:34 -07:00
|
|
|
$type = $this->getMetadata('edge:type');
|
2013-07-19 15:59:29 -07:00
|
|
|
$type = head($type);
|
|
|
|
|
2014-07-17 15:41:54 -07:00
|
|
|
$type_obj = PhabricatorEdgeType::getByConstant($type);
|
|
|
|
|
2013-07-19 15:59:29 -07:00
|
|
|
if ($add && $rem) {
|
2014-07-17 15:41:54 -07:00
|
|
|
return $type_obj->getTransactionEditString(
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleLink($author_phid),
|
2014-07-17 15:41:54 -07:00
|
|
|
new PhutilNumber(count($add) + count($rem)),
|
|
|
|
new PhutilNumber(count($add)),
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleList($add),
|
2014-07-17 15:41:54 -07:00
|
|
|
new PhutilNumber(count($rem)),
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleList($rem));
|
|
|
|
} else if ($add) {
|
2014-07-17 15:41:54 -07:00
|
|
|
return $type_obj->getTransactionAddString(
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleLink($author_phid),
|
2014-07-17 15:41:54 -07:00
|
|
|
new PhutilNumber(count($add)),
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleList($add));
|
2014-02-25 12:36:39 -08:00
|
|
|
} else if ($rem) {
|
2014-07-17 15:41:54 -07:00
|
|
|
return $type_obj->getTransactionRemoveString(
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleLink($author_phid),
|
2014-07-17 15:41:54 -07:00
|
|
|
new PhutilNumber(count($rem)),
|
2013-07-19 15:59:29 -07:00
|
|
|
$this->renderHandleList($rem));
|
2014-02-25 12:36:39 -08:00
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s edited edge metadata.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
2013-07-19 15:59:29 -07:00
|
|
|
}
|
|
|
|
|
2013-09-23 14:29:40 -07:00
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
$field = $this->getTransactionCustomField();
|
2013-09-23 14:29:40 -07:00
|
|
|
if ($field) {
|
|
|
|
return $field->getApplicationTransactionTitle($this);
|
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s edited a custom field.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
|
|
|
}
|
|
|
|
|
2014-04-21 15:33:59 -07:00
|
|
|
case PhabricatorTransactions::TYPE_TOKEN:
|
|
|
|
if ($old && $new) {
|
|
|
|
return pht(
|
|
|
|
'%s updated a token.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
|
|
|
} else if ($old) {
|
|
|
|
return pht(
|
|
|
|
'%s rescinded a token.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s awarded a token.',
|
|
|
|
$this->renderHandleLink($author_phid));
|
|
|
|
}
|
|
|
|
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
2014-05-15 07:02:30 -07:00
|
|
|
case HarbormasterBuildable::STATUS_BUILDING:
|
|
|
|
return pht(
|
|
|
|
'%s started building %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')));
|
2014-04-17 16:04:14 -07:00
|
|
|
case HarbormasterBuildable::STATUS_PASSED:
|
|
|
|
return pht(
|
|
|
|
'%s completed building %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')));
|
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
|
|
|
return pht(
|
|
|
|
'%s failed to build %s!',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')));
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
default:
|
|
|
|
return pht(
|
|
|
|
'%s edited this %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->getApplicationObjectTypeName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-18 15:15:25 -07:00
|
|
|
public function getTitleForFeed(PhabricatorFeedStory $story) {
|
2012-12-11 14:00:21 -08:00
|
|
|
$author_phid = $this->getAuthorPHID();
|
|
|
|
$object_phid = $this->getObjectPHID();
|
|
|
|
|
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return pht(
|
|
|
|
'%s added a comment to %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the visibility for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the edit policy for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
|
|
|
return pht(
|
|
|
|
'%s changed the join policy for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
2012-12-11 14:00:21 -08:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
return pht(
|
|
|
|
'%s updated subscribers of %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
2013-03-28 08:34:34 -07:00
|
|
|
case PhabricatorTransactions::TYPE_EDGE:
|
2014-07-17 15:41:54 -07:00
|
|
|
$new = ipull($new, 'dst');
|
|
|
|
$old = ipull($old, 'dst');
|
|
|
|
$add = array_diff($new, $old);
|
|
|
|
$rem = array_diff($old, $new);
|
2013-07-19 15:59:29 -07:00
|
|
|
$type = $this->getMetadata('edge:type');
|
|
|
|
$type = head($type);
|
2014-07-17 15:41:54 -07:00
|
|
|
|
|
|
|
$type_obj = PhabricatorEdgeType::getByConstant($type);
|
|
|
|
|
|
|
|
if ($add && $rem) {
|
|
|
|
return $type_obj->getFeedEditString(
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid),
|
|
|
|
new PhutilNumber(count($add) + count($rem)),
|
|
|
|
new PhutilNumber(count($add)),
|
|
|
|
$this->renderHandleList($add),
|
|
|
|
new PhutilNumber(count($rem)),
|
|
|
|
$this->renderHandleList($rem));
|
|
|
|
} else if ($add) {
|
|
|
|
return $type_obj->getFeedAddString(
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid),
|
|
|
|
new PhutilNumber(count($add)),
|
|
|
|
$this->renderHandleList($add));
|
|
|
|
} else if ($rem) {
|
|
|
|
return $type_obj->getFeedRemoveString(
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid),
|
|
|
|
new PhutilNumber(count($rem)),
|
|
|
|
$this->renderHandleList($rem));
|
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s edited edge metadata for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
}
|
|
|
|
|
2013-09-24 14:51:36 -07:00
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
$field = $this->getTransactionCustomField();
|
2013-09-24 14:51:36 -07:00
|
|
|
if ($field) {
|
|
|
|
return $field->getApplicationTransactionTitleForFeed($this, $story);
|
|
|
|
} else {
|
|
|
|
return pht(
|
|
|
|
'%s edited a custom field on %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
}
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
2014-05-15 07:02:30 -07:00
|
|
|
case HarbormasterBuildable::STATUS_BUILDING:
|
|
|
|
return pht(
|
|
|
|
'%s started building %s for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')),
|
|
|
|
$this->renderHandleLink($object_phid));
|
2014-04-17 16:04:14 -07:00
|
|
|
case HarbormasterBuildable::STATUS_PASSED:
|
|
|
|
return pht(
|
|
|
|
'%s completed building %s for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
|
|
|
return pht(
|
|
|
|
'%s failed to build %s for %s.',
|
|
|
|
$this->renderHandleLink($author_phid),
|
|
|
|
$this->renderHandleLink(
|
|
|
|
$this->getMetadataValue('harbormaster:buildablePHID')),
|
|
|
|
$this->renderHandleLink($object_phid));
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
2013-09-24 14:51:36 -07:00
|
|
|
|
2012-12-11 14:00:21 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return $this->getTitle();
|
|
|
|
}
|
|
|
|
|
2013-08-19 11:51:22 -07:00
|
|
|
public function getBodyForFeed(PhabricatorFeedStory $story) {
|
2013-07-25 16:59:36 -07:00
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
|
|
|
|
$body = null;
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
$text = $this->getComment()->getContent();
|
|
|
|
$body = phutil_escape_html_newlines(
|
|
|
|
phutil_utf8_shorten($text, 128));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return $body;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
public function getActionStrength() {
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return 0.5;
|
2014-05-19 12:23:32 -07:00
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
$old = $this->getOldValue();
|
|
|
|
$new = $this->getNewValue();
|
|
|
|
|
|
|
|
$add = array_diff($old, $new);
|
|
|
|
$rem = array_diff($new, $old);
|
|
|
|
|
|
|
|
// If this action is the actor subscribing or unsubscribing themselves,
|
|
|
|
// it is less interesting. In particular, if someone makes a comment and
|
|
|
|
// also implicitly subscribes themselves, we should treat the
|
|
|
|
// transaction group as "comment", not "subscribe". In this specific
|
|
|
|
// case (one affected user, and that affected user it the actor),
|
|
|
|
// decrease the action strength.
|
|
|
|
|
|
|
|
if ((count($add) + count($rem)) != 1) {
|
|
|
|
// Not exactly one CC change.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$affected_phid = head(array_merge($add, $rem));
|
|
|
|
if ($affected_phid != $this->getAuthorPHID()) {
|
|
|
|
// Affected user is someone else.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make this weaker than TYPE_COMMENT.
|
|
|
|
return 0.25;
|
2012-12-11 14:00:07 -08:00
|
|
|
}
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
2014-02-24 15:57:35 -08:00
|
|
|
public function isCommentTransaction() {
|
|
|
|
if ($this->hasComment()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-12-11 14:00:07 -08:00
|
|
|
public function getActionName() {
|
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_COMMENT:
|
|
|
|
return pht('Commented On');
|
|
|
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
|
|
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
2013-10-22 13:49:37 -07:00
|
|
|
case PhabricatorTransactions::TYPE_JOIN_POLICY:
|
2012-12-11 14:00:07 -08:00
|
|
|
return pht('Changed Policy');
|
|
|
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
|
|
|
return pht('Changed Subscribers');
|
2014-04-17 16:04:14 -07:00
|
|
|
case PhabricatorTransactions::TYPE_BUILDABLE:
|
|
|
|
switch ($this->getNewValue()) {
|
|
|
|
case HarbormasterBuildable::STATUS_PASSED:
|
|
|
|
return pht('Build Passed');
|
|
|
|
case HarbormasterBuildable::STATUS_FAILED:
|
|
|
|
return pht('Build Failed');
|
|
|
|
default:
|
|
|
|
return pht('Build Status');
|
|
|
|
}
|
2012-12-11 14:00:07 -08:00
|
|
|
default:
|
|
|
|
return pht('Updated');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getMailTags() {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2013-02-17 06:37:02 -08:00
|
|
|
public function hasChangeDetails() {
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$field = $this->getTransactionCustomField();
|
|
|
|
if ($field) {
|
|
|
|
return $field->getApplicationTransactionHasChangeDetails($this);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2013-02-17 06:37:02 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-03-04 12:54:20 -08:00
|
|
|
public function renderChangeDetails(PhabricatorUser $viewer) {
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
switch ($this->getTransactionType()) {
|
|
|
|
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
|
|
|
|
$field = $this->getTransactionCustomField();
|
|
|
|
if ($field) {
|
|
|
|
return $field->getApplicationTransactionChangeDetails($this, $viewer);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-05-04 11:11:46 -07:00
|
|
|
return $this->renderTextCorpusChangeDetails(
|
|
|
|
$viewer,
|
|
|
|
$this->getOldValue(),
|
|
|
|
$this->getNewValue());
|
Allow CustomField to provide ApplicationTransaction change details
Summary:
Ref T3886. Ref T418. For fields like "Summary" and "Test Plan" where changes can't be summarized in one line, allow CustomField to provide a "(Show Details)" link and render a diff.
Also consolidate some of the existing copy/paste, and simplify this featuer slightly now that we've move to dialogs.
Test Plan:
{F115918}
- Viewed "description"-style field changes in phlux, pholio, legalpad, maniphest, differential, ponder (questions), ponder (answers), and repositories.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T3886, T418
Differential Revision: https://secure.phabricator.com/D8284
2014-02-21 11:53:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public function renderTextCorpusChangeDetails(
|
|
|
|
PhabricatorUser $viewer,
|
|
|
|
$old,
|
|
|
|
$new) {
|
|
|
|
|
|
|
|
require_celerity_resource('differential-changeset-view-css');
|
|
|
|
|
|
|
|
$view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setOldText($old)
|
|
|
|
->setNewText($new);
|
|
|
|
|
|
|
|
return $view->render();
|
2013-02-17 06:37:02 -08:00
|
|
|
}
|
2012-12-11 13:59:20 -08:00
|
|
|
|
2013-03-09 19:23:50 -08:00
|
|
|
public function attachTransactionGroup(array $group) {
|
|
|
|
assert_instances_of($group, 'PhabricatorApplicationTransaction');
|
|
|
|
$this->transactionGroup = $group;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getTransactionGroup() {
|
|
|
|
return $this->transactionGroup;
|
|
|
|
}
|
|
|
|
|
2013-12-27 05:51:15 -08:00
|
|
|
/**
|
|
|
|
* Should this transaction be visually grouped with an existing transaction
|
|
|
|
* group?
|
|
|
|
*
|
|
|
|
* @param list<PhabricatorApplicationTransaction> List of transactions.
|
|
|
|
* @return bool True to display in a group with the other transactions.
|
|
|
|
*/
|
|
|
|
public function shouldDisplayGroupWith(array $group) {
|
|
|
|
$this_source = null;
|
|
|
|
if ($this->getContentSource()) {
|
|
|
|
$this_source = $this->getContentSource()->getSource();
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($group as $xaction) {
|
|
|
|
// Don't group transactions by different authors.
|
|
|
|
if ($xaction->getAuthorPHID() != $this->getAuthorPHID()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't group transactions for different objects.
|
|
|
|
if ($xaction->getObjectPHID() != $this->getObjectPHID()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't group anything into a group which already has a comment.
|
2014-02-24 15:57:35 -08:00
|
|
|
if ($xaction->isCommentTransaction()) {
|
2013-12-27 05:51:15 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't group transactions from different content sources.
|
|
|
|
$other_source = null;
|
|
|
|
if ($xaction->getContentSource()) {
|
|
|
|
$other_source = $xaction->getContentSource()->getSource();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($other_source != $this_source) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't group transactions which happened more than 2 minutes apart.
|
|
|
|
$apart = abs($xaction->getDateCreated() - $this->getDateCreated());
|
|
|
|
if ($apart > (60 * 2)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-04-17 15:57:34 -07:00
|
|
|
public function renderExtraInformationLink() {
|
|
|
|
$herald_xscript_id = $this->getMetadataValue('herald:transcriptID');
|
|
|
|
|
|
|
|
if ($herald_xscript_id) {
|
|
|
|
return phutil_tag(
|
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => '/herald/transcript/'.$herald_xscript_id.'/',
|
|
|
|
),
|
|
|
|
pht('View Herald Transcript'));
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-03-09 19:23:50 -08:00
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function getCapabilities() {
|
|
|
|
return array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPolicy($capability) {
|
|
|
|
switch ($capability) {
|
|
|
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
|
|
|
return $this->getViewPolicy();
|
|
|
|
case PhabricatorPolicyCapability::CAN_EDIT:
|
|
|
|
return $this->getEditPolicy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
|
|
return ($viewer->getPHID() == $this->getAuthorPHID());
|
|
|
|
}
|
|
|
|
|
2013-09-27 08:43:41 -07:00
|
|
|
public function describeAutomaticCapability($capability) {
|
|
|
|
// TODO: (T603) Exact policies are unclear here.
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-21 23:59:22 +10:00
|
|
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
2014-05-01 18:25:30 -07:00
|
|
|
|
|
|
|
|
|
|
|
public function destroyObjectPermanently(
|
|
|
|
PhabricatorDestructionEngine $engine) {
|
|
|
|
|
|
|
|
$this->openTransaction();
|
|
|
|
$comment_template = null;
|
|
|
|
try {
|
|
|
|
$comment_template = $this->getApplicationTransactionCommentObject();
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
// Continue; no comments for these transactions.
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($comment_template) {
|
|
|
|
$comments = $comment_template->loadAllWhere(
|
|
|
|
'transactionPHID = %s',
|
|
|
|
$this->getPHID());
|
|
|
|
foreach ($comments as $comment) {
|
|
|
|
$engine->destroyObject($comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->delete();
|
|
|
|
$this->saveTransaction();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-11 13:59:20 -08:00
|
|
|
}
|