Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/nuance/controller/NuanceItemEditController.php b/src/applications/nuance/controller/NuanceItemEditController.php
index 89bfbda5c9..bad409a801 100644
--- a/src/applications/nuance/controller/NuanceItemEditController.php
+++ b/src/applications/nuance/controller/NuanceItemEditController.php
@@ -1,32 +1,93 @@
<?php
final class NuanceItemEditController extends NuanceController {
public function handleRequest(AphrontRequest $request) {
- $viewer = $request->getViewer();
+ $viewer = $this->getViewer();
$id = $request->getURIData('id');
- if (!$id) {
- $item = new NuanceItem();
- } else {
- $item = id(new NuanceItemQuery())
- ->setViewer($viewer)
- ->withIDs(array($id))
- ->executeOne();
- }
-
+ $item = id(new NuanceItemQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
if (!$item) {
return new Aphront404Response();
}
+ $title = pht('Item %d', $item->getID());
+
$crumbs = $this->buildApplicationCrumbs();
- $title = 'TODO';
+ $crumbs->addTextCrumb($title);
+ $crumbs->addTextCrumb(pht('Edit'));
+
+ $properties = $this->buildPropertyView($item);
+ $actions = $this->buildActionView($item);
+ $properties->setActionList($actions);
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->addPropertyList($properties);
return $this->buildApplicationPage(
- $crumbs,
+ array(
+ $crumbs,
+ $box,
+ ),
array(
'title' => $title,
));
}
+ private function buildPropertyView(NuanceItem $item) {
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer)
+ ->setObject($item);
+
+ $properties->addProperty(
+ pht('Date Created'),
+ phabricator_datetime($item->getDateCreated(), $viewer));
+
+ $properties->addProperty(
+ pht('Requestor'),
+ $viewer->renderHandle($item->getRequestorPHID()));
+
+ $properties->addProperty(
+ pht('Source'),
+ $viewer->renderHandle($item->getSourcePHID()));
+
+ $source = $item->getSource();
+ $definition = $source->requireDefinition();
+
+ $definition->renderItemEditProperties(
+ $viewer,
+ $item,
+ $properties);
+
+ return $properties;
+ }
+
+ private function buildActionView(NuanceItem $item) {
+ $viewer = $this->getViewer();
+ $id = $item->getID();
+
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($viewer);
+
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('View Item'))
+ ->setIcon('fa-eye')
+ ->setHref($this->getApplicationURI("item/view/{$id}/")));
+
+ return $actions;
+ }
+
+
}
diff --git a/src/applications/nuance/controller/NuanceItemViewController.php b/src/applications/nuance/controller/NuanceItemViewController.php
index 9c7401cafe..d325afbd29 100644
--- a/src/applications/nuance/controller/NuanceItemViewController.php
+++ b/src/applications/nuance/controller/NuanceItemViewController.php
@@ -1,27 +1,86 @@
<?php
final class NuanceItemViewController extends NuanceController {
public function handleRequest(AphrontRequest $request) {
- $viewer = $request->getViewer();
+ $viewer = $this->getViewer();
$id = $request->getURIData('id');
$item = id(new NuanceItemQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
-
if (!$item) {
return new Aphront404Response();
}
+ $title = pht('Item %d', $item->getID());
+
$crumbs = $this->buildApplicationCrumbs();
- $title = 'TODO';
+ $crumbs->addTextCrumb($title);
+
+ $properties = $this->buildPropertyView($item);
+ $actions = $this->buildActionView($item);
+ $properties->setActionList($actions);
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->addPropertyList($properties);
return $this->buildApplicationPage(
- $crumbs,
+ array(
+ $crumbs,
+ $box,
+ ),
array(
'title' => $title,
));
}
+
+ private function buildPropertyView(NuanceItem $item) {
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer)
+ ->setObject($item);
+
+ $properties->addProperty(
+ pht('Date Created'),
+ phabricator_datetime($item->getDateCreated(), $viewer));
+
+ $source = $item->getSource();
+ $definition = $source->requireDefinition();
+
+ $definition->renderItemViewProperties(
+ $viewer,
+ $item,
+ $properties);
+
+ return $properties;
+ }
+
+ private function buildActionView(NuanceItem $item) {
+ $viewer = $this->getViewer();
+ $id = $item->getID();
+
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($viewer);
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $item,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Item'))
+ ->setIcon('fa-pencil')
+ ->setHref($this->getApplicationURI("item/edit/{$id}/"))
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit));
+
+ return $actions;
+ }
+
+
}
diff --git a/src/applications/nuance/phid/NuanceRequestorPHIDType.php b/src/applications/nuance/phid/NuanceRequestorPHIDType.php
index 0e08322a80..2cf06bbb10 100644
--- a/src/applications/nuance/phid/NuanceRequestorPHIDType.php
+++ b/src/applications/nuance/phid/NuanceRequestorPHIDType.php
@@ -1,37 +1,39 @@
<?php
final class NuanceRequestorPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'NUAR';
public function getTypeName() {
return pht('Requestor');
}
public function newObject() {
return new NuanceRequestor();
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new NuanceRequestorQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$requestor = $objects[$phid];
- $handle->setName($requestor->getBestName());
+ // TODO: This is currently useless and should be far more informative.
+ $handle->setName(pht('Requestor %d', $requestor->getID()));
+
$handle->setURI($requestor->getURI());
}
}
}
diff --git a/src/applications/nuance/query/NuanceItemQuery.php b/src/applications/nuance/query/NuanceItemQuery.php
index cc3f79c915..fbcac6e5b7 100644
--- a/src/applications/nuance/query/NuanceItemQuery.php
+++ b/src/applications/nuance/query/NuanceItemQuery.php
@@ -1,68 +1,85 @@
<?php
final class NuanceItemQuery
extends NuanceQuery {
private $ids;
private $phids;
private $sourcePHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
- public function withSourcePHIDs($source_phids) {
+ public function withSourcePHIDs(array $source_phids) {
$this->sourcePHIDs = $source_phids;
return $this;
}
+ public function newResultObject() {
+ return new NuanceItem();
+ }
+
protected function loadPage() {
- $table = new NuanceItem();
- $conn = $table->establishConnection('r');
-
- $data = queryfx_all(
- $conn,
- '%Q FROM %T %Q %Q %Q',
- $this->buildSelectClause($conn),
- $table->getTableName(),
- $this->buildWhereClause($conn),
- $this->buildOrderClause($conn),
- $this->buildLimitClause($conn));
-
- return $table->loadAllFromArray($data);
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function willFilterPage(array $items) {
+ $source_phids = mpull($items, 'getSourcePHID');
+
+ // NOTE: We always load sources, even if the viewer can't formally see
+ // them. If they can see the item, they're allowed to be aware of the
+ // source in some sense.
+ $sources = id(new NuanceSourceQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($source_phids)
+ ->execute();
+ $sources = mpull($sources, null, 'getPHID');
+
+ foreach ($items as $key => $item) {
+ $source = idx($sources, $item->getSourcePHID());
+ if (!$source) {
+ $this->didRejectResult($items[$key]);
+ unset($items[$key]);
+ continue;
+ }
+ $item->attachSource($source);
+ }
+
+ return $items;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->sourcePHIDs !== null) {
$where[] = qsprintf(
$conn,
'sourcePHID IN (%Ls)',
$this->sourcePHIDs);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
return $where;
}
}
diff --git a/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php b/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php
index 4cc3d7c610..607b0eda6c 100644
--- a/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php
+++ b/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php
@@ -1,103 +1,132 @@
<?php
final class NuancePhabricatorFormSourceDefinition
extends NuanceSourceDefinition {
public function getName() {
return pht('Phabricator Form');
}
public function getSourceDescription() {
return pht('Create a web form that submits into a Nuance queue.');
}
public function getSourceTypeConstant() {
return 'phabricator-form';
}
public function getSourceViewActions(AphrontRequest $request) {
$actions = array();
$actions[] = id(new PhabricatorActionView())
->setName(pht('View Form'))
->setIcon('fa-align-justify')
->setHref($this->getActionURI());
return $actions;
}
public function updateItems() {
return null;
}
protected function augmentEditForm(
AphrontFormView $form,
PhabricatorApplicationTransactionValidationException $ex = null) {
/* TODO - add a box to allow for custom fields to be defined here, so that
* these NuanceSource objects made from this definition can be used to
* capture arbitrary data */
return $form;
}
protected function buildTransactions(AphrontRequest $request) {
$transactions = parent::buildTransactions($request);
// TODO -- as above
return $transactions;
}
public function renderView() {}
public function renderListView() {}
public function handleActionRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
// TODO: As above, this would eventually be driven by custom logic.
if ($request->isFormPost()) {
$properties = array(
- 'complaint' => (string)$request->getStr('text'),
+ 'complaint' => (string)$request->getStr('complaint'),
);
$content_source = PhabricatorContentSource::newFromRequest($request);
$requestor = NuanceRequestor::newFromPhabricatorUser(
$viewer,
$content_source);
$item = $this->newItemFromProperties(
$requestor,
$properties,
$content_source);
$uri = $item->getURI();
return id(new AphrontRedirectResponse())->setURI($uri);
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendRemarkupInstructions(
pht('IMPORTANT: This is a very rough prototype.'))
->appendRemarkupInstructions(
pht('Got a complaint? Complain here! We love complaints.'))
->appendChild(
id(new AphrontFormTextAreaControl())
->setName('complaint')
->setLabel(pht('Complaint')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Submit Complaint')));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Complaint Form'))
->appendChild($form);
return $box;
}
+ public function renderItemViewProperties(
+ PhabricatorUser $viewer,
+ NuanceItem $item,
+ PHUIPropertyListView $view) {
+ $this->renderItemCommonProperties($viewer, $item, $view);
+ }
+
+ public function renderItemEditProperties(
+ PhabricatorUser $viewer,
+ NuanceItem $item,
+ PHUIPropertyListView $view) {
+ $this->renderItemCommonProperties($viewer, $item, $view);
+ }
+
+ private function renderItemCommonProperties(
+ PhabricatorUser $viewer,
+ NuanceItem $item,
+ PHUIPropertyListView $view) {
+
+ $complaint = $item->getNuanceProperty('complaint');
+ $complaint = PhabricatorMarkupEngine::renderOneObject(
+ id(new PhabricatorMarkupOneOff())->setContent($complaint),
+ 'default',
+ $viewer);
+
+ $view->addSectionHeader(pht('Complaint'));
+ $view->addTextContent($complaint);
+ }
+
}
diff --git a/src/applications/nuance/source/NuanceSourceDefinition.php b/src/applications/nuance/source/NuanceSourceDefinition.php
index 2c030badfa..06d302f587 100644
--- a/src/applications/nuance/source/NuanceSourceDefinition.php
+++ b/src/applications/nuance/source/NuanceSourceDefinition.php
@@ -1,284 +1,298 @@
<?php
/**
* @task action Handling Action Requests
*/
abstract class NuanceSourceDefinition extends Phobject {
private $actor;
private $sourceObject;
public function setActor(PhabricatorUser $actor) {
$this->actor = $actor;
return $this;
}
public function getActor() {
return $this->actor;
}
public function requireActor() {
$actor = $this->getActor();
if (!$actor) {
throw new PhutilInvalidStateException('setActor');
}
return $actor;
}
public function setSourceObject(NuanceSource $source) {
$source->setType($this->getSourceTypeConstant());
$this->sourceObject = $source;
return $this;
}
public function getSourceObject() {
return $this->sourceObject;
}
public function requireSourceObject() {
$source = $this->getSourceObject();
if (!$source) {
throw new PhutilInvalidStateException('setSourceObject');
}
return $source;
}
public function getSourceViewActions(AphrontRequest $request) {
return array();
}
public static function getAllDefinitions() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getSourceTypeConstant')
->execute();
}
/**
* A human readable string like "Twitter" or "Phabricator Form".
*/
abstract public function getName();
/**
* Human readable description of this source, a sentence or two long.
*/
abstract public function getSourceDescription();
/**
* This should be a any VARCHAR(32).
*
* @{method:getAllDefinitions} will throw if you choose a string that
* collides with another @{class:NuanceSourceDefinition} class.
*/
abstract public function getSourceTypeConstant();
/**
* Code to create and update @{class:NuanceItem}s and
* @{class:NuanceRequestor}s via daemons goes here.
*
* If that does not make sense for the @{class:NuanceSource} you are
* defining, simply return null. For example,
* @{class:NuancePhabricatorFormSourceDefinition} since these are one-way
* contact forms.
*/
abstract public function updateItems();
private function loadSourceObjectPolicies(
PhabricatorUser $user,
NuanceSource $source) {
$user = $this->requireActor();
$source = $this->requireSourceObject();
return id(new PhabricatorPolicyQuery())
->setViewer($user)
->setObject($source)
->execute();
}
final public function getEditTitle() {
$source = $this->requireSourceObject();
if ($source->getPHID()) {
$title = pht('Edit "%s" source.', $source->getName());
} else {
$title = pht('Create a new "%s" source.', $this->getName());
}
return $title;
}
final public function buildEditLayout(AphrontRequest $request) {
$actor = $this->requireActor();
$source = $this->requireSourceObject();
$form_errors = array();
$error_messages = array();
$transactions = array();
$validation_exception = null;
if ($request->isFormPost()) {
$transactions = $this->buildTransactions($request);
try {
$editor = id(new NuanceSourceEditor())
->setActor($actor)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->applyTransactions($source, $transactions);
return id(new AphrontRedirectResponse())
->setURI($source->getURI());
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
}
}
$form = $this->renderEditForm($validation_exception);
$layout = id(new PHUIObjectBoxView())
->setHeaderText($this->getEditTitle())
->setValidationException($validation_exception)
->setFormErrors($error_messages)
->setForm($form);
return $layout;
}
/**
* Code to create a form to edit the @{class:NuanceItem} you are defining.
*
* return @{class:AphrontFormView}
*/
private function renderEditForm(
PhabricatorApplicationTransactionValidationException $ex = null) {
$user = $this->requireActor();
$source = $this->requireSourceObject();
$policies = $this->loadSourceObjectPolicies($user, $source);
$e_name = null;
if ($ex) {
$e_name = $ex->getShortMessage(NuanceSourceTransaction::TYPE_NAME);
}
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setError($e_name)
->setValue($source->getName()));
$form = $this->augmentEditForm($form, $ex);
$form
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($user)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($source)
->setPolicies($policies)
->setName('viewPolicy'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($user)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($source)
->setPolicies($policies)
->setName('editPolicy'))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($source->getURI())
->setValue(pht('Save')));
return $form;
}
/**
* return @{class:AphrontFormView}
*/
protected function augmentEditForm(
AphrontFormView $form,
PhabricatorApplicationTransactionValidationException $ex = null) {
return $form;
}
/**
* Hook to build up @{class:PhabricatorTransactions}.
*
* return array $transactions
*/
protected function buildTransactions(AphrontRequest $request) {
$transactions = array();
$transactions[] = id(new NuanceSourceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($request->getStr('editPolicy'));
$transactions[] = id(new NuanceSourceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($request->getStr('viewPolicy'));
$transactions[] = id(new NuanceSourceTransaction())
->setTransactionType(NuanceSourceTransaction::TYPE_NAME)
->setNewvalue($request->getStr('name'));
return $transactions;
}
abstract public function renderView();
abstract public function renderListView();
protected function newItemFromProperties(
NuanceRequestor $requestor,
array $properties,
PhabricatorContentSource $content_source) {
// TODO: Should we have a tighter actor/viewer model? Requestors will
// often have no real user associated with them...
$actor = PhabricatorUser::getOmnipotentUser();
$source = $this->requireSourceObject();
$item = NuanceItem::initializeNewItem();
$xactions = array();
$xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_SOURCE)
->setNewValue($source->getPHID());
$xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_REQUESTOR)
->setNewValue($requestor->getPHID());
foreach ($properties as $key => $property) {
$xactions[] = id(new NuanceItemTransaction())
->setTransactionType(NuanceItemTransaction::TYPE_PROPERTY)
->setMetadataValue(NuanceItemTransaction::PROPERTY_KEY, $key)
->setNewValue($property);
}
$editor = id(new NuanceItemEditor())
->setActor($actor)
->setActingAsPHID($requestor->getActingAsPHID())
->setContentSource($content_source);
$editor->applyTransactions($item, $xactions);
return $item;
}
+ public function renderItemViewProperties(
+ PhabricatorUser $viewer,
+ NuanceItem $item,
+ PHUIPropertyListView $view) {
+ return;
+ }
+
+ public function renderItemEditProperties(
+ PhabricatorUser $viewer,
+ NuanceItem $item,
+ PHUIPropertyListView $view) {
+ return;
+ }
+
/* -( Handling Action Requests )------------------------------------------- */
public function handleActionRequest(AphrontRequest $request) {
return new Aphront404Response();
}
public function getActionURI($path = null) {
$source_id = $this->getSourceObject()->getID();
return '/action/'.$source_id.'/'.ltrim($path, '/');
}
}
diff --git a/src/applications/nuance/storage/NuanceItem.php b/src/applications/nuance/storage/NuanceItem.php
index 196afc44ca..2335cd4d42 100644
--- a/src/applications/nuance/storage/NuanceItem.php
+++ b/src/applications/nuance/storage/NuanceItem.php
@@ -1,171 +1,173 @@
<?php
final class NuanceItem
extends NuanceDAO
implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface {
const STATUS_OPEN = 0;
const STATUS_ASSIGNED = 10;
const STATUS_CLOSED = 20;
protected $status;
protected $ownerPHID;
protected $requestorPHID;
protected $sourcePHID;
protected $sourceLabel;
protected $data = array();
protected $mailKey;
protected $dateNuanced;
+ private $source = self::ATTACHABLE;
+
public static function initializeNewItem() {
return id(new NuanceItem())
->setDateNuanced(time())
->setStatus(self::STATUS_OPEN);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'data' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'ownerPHID' => 'phid?',
'sourceLabel' => 'text255?',
'status' => 'uint32',
'mailKey' => 'bytes20',
'dateNuanced' => 'epoch',
),
self::CONFIG_KEY_SCHEMA => array(
'key_source' => array(
'columns' => array('sourcePHID', 'status', 'dateNuanced', 'id'),
),
'key_owner' => array(
'columns' => array('ownerPHID', 'status', 'dateNuanced', 'id'),
),
'key_contacter' => array(
'columns' => array('requestorPHID', 'status', 'dateNuanced', 'id'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
NuanceItemPHIDType::TYPECONST);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
public function getURI() {
return '/nuance/item/view/'.$this->getID().'/';
}
public function getLabel(PhabricatorUser $viewer) {
// this is generated at the time the item is created based on
// the configuration from the item source. It is typically
// something like 'Twitter'.
$source_label = $this->getSourceLabel();
return pht(
'Item via %s @ %s.',
$source_label,
phabricator_datetime($this->getDateCreated(), $viewer));
}
public function getRequestor() {
return $this->assertAttached($this->requestor);
}
public function attachRequestor(NuanceRequestor $requestor) {
return $this->requestor = $requestor;
}
public function getSource() {
return $this->assertAttached($this->source);
}
public function attachSource(NuanceSource $source) {
$this->source = $source;
}
public function getNuanceProperty($key, $default = null) {
return idx($this->data, $key, $default);
}
public function setNuanceProperty($key, $value) {
$this->data[$key] = $value;
return $this;
}
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
// TODO - this should be based on the queues the item currently resides in
return PhabricatorPolicies::POLICY_USER;
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
// TODO - requestors should get auto access too!
return $viewer->getPHID() == $this->ownerPHID;
}
public function describeAutomaticCapability($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht('Owners of an item can always view it.');
case PhabricatorPolicyCapability::CAN_EDIT:
return pht('Owners of an item can always edit it.');
}
return null;
}
public function toDictionary() {
return array(
'id' => $this->getID(),
'phid' => $this->getPHID(),
'ownerPHID' => $this->getOwnerPHID(),
'requestorPHID' => $this->getRequestorPHID(),
'sourcePHID' => $this->getSourcePHID(),
'sourceLabel' => $this->getSourceLabel(),
'dateCreated' => $this->getDateCreated(),
'dateModified' => $this->getDateModified(),
'dateNuanced' => $this->getDateNuanced(),
);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new NuanceItemEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new NuanceItemTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 19:56 (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128208
Default Alt Text
(26 KB)

Event Timeline