Path: blob/master/src/applications/maniphest/storage/ManiphestTask.php
12256 views
<?php12final class ManiphestTask extends ManiphestDAO3implements4PhabricatorSubscribableInterface,5PhabricatorMarkupInterface,6PhabricatorPolicyInterface,7PhabricatorTokenReceiverInterface,8PhabricatorFlaggableInterface,9PhabricatorMentionableInterface,10PhrequentTrackableInterface,11PhabricatorCustomFieldInterface,12PhabricatorDestructibleInterface,13PhabricatorApplicationTransactionInterface,14PhabricatorProjectInterface,15PhabricatorSpacesInterface,16PhabricatorConduitResultInterface,17PhabricatorFulltextInterface,18PhabricatorFerretInterface,19DoorkeeperBridgedObjectInterface,20PhabricatorEditEngineSubtypeInterface,21PhabricatorEditEngineLockableInterface,22PhabricatorEditEngineMFAInterface,23PhabricatorPolicyCodexInterface,24PhabricatorUnlockableInterface {2526protected $authorPHID;27protected $ownerPHID;2829protected $status;30protected $priority;31protected $subpriority = 0;3233protected $title = '';34protected $description = '';35protected $originalEmailSource;36protected $mailKey;37protected $viewPolicy = PhabricatorPolicies::POLICY_USER;38protected $editPolicy = PhabricatorPolicies::POLICY_USER;3940protected $ownerOrdering;41protected $spacePHID;42protected $bridgedObjectPHID;43protected $properties = array();44protected $points;45protected $subtype;4647protected $closedEpoch;48protected $closerPHID;4950private $subscriberPHIDs = self::ATTACHABLE;51private $groupByProjectPHID = self::ATTACHABLE;52private $customFields = self::ATTACHABLE;53private $edgeProjectPHIDs = self::ATTACHABLE;54private $bridgedObject = self::ATTACHABLE;5556public static function initializeNewTask(PhabricatorUser $actor) {57$app = id(new PhabricatorApplicationQuery())58->setViewer($actor)59->withClasses(array('PhabricatorManiphestApplication'))60->executeOne();6162$view_policy = $app->getPolicy(ManiphestDefaultViewCapability::CAPABILITY);63$edit_policy = $app->getPolicy(ManiphestDefaultEditCapability::CAPABILITY);6465return id(new ManiphestTask())66->setStatus(ManiphestTaskStatus::getDefaultStatus())67->setPriority(ManiphestTaskPriority::getDefaultPriority())68->setAuthorPHID($actor->getPHID())69->setViewPolicy($view_policy)70->setEditPolicy($edit_policy)71->setSpacePHID($actor->getDefaultSpacePHID())72->setSubtype(PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT)73->attachProjectPHIDs(array())74->attachSubscriberPHIDs(array());75}7677protected function getConfiguration() {78return array(79self::CONFIG_AUX_PHID => true,80self::CONFIG_SERIALIZATION => array(81'properties' => self::SERIALIZATION_JSON,82),83self::CONFIG_COLUMN_SCHEMA => array(84'ownerPHID' => 'phid?',85'status' => 'text64',86'priority' => 'uint32',87'title' => 'sort',88'description' => 'text',89'mailKey' => 'bytes20',90'ownerOrdering' => 'text64?',91'originalEmailSource' => 'text255?',92'subpriority' => 'double',93'points' => 'double?',94'bridgedObjectPHID' => 'phid?',95'subtype' => 'text64',96'closedEpoch' => 'epoch?',97'closerPHID' => 'phid?',98),99self::CONFIG_KEY_SCHEMA => array(100'key_phid' => null,101'phid' => array(102'columns' => array('phid'),103'unique' => true,104),105'priority' => array(106'columns' => array('priority', 'status'),107),108'status' => array(109'columns' => array('status'),110),111'ownerPHID' => array(112'columns' => array('ownerPHID', 'status'),113),114'authorPHID' => array(115'columns' => array('authorPHID', 'status'),116),117'ownerOrdering' => array(118'columns' => array('ownerOrdering'),119),120'priority_2' => array(121'columns' => array('priority', 'subpriority'),122),123'key_dateCreated' => array(124'columns' => array('dateCreated'),125),126'key_dateModified' => array(127'columns' => array('dateModified'),128),129'key_title' => array(130'columns' => array('title(64)'),131),132'key_bridgedobject' => array(133'columns' => array('bridgedObjectPHID'),134'unique' => true,135),136'key_subtype' => array(137'columns' => array('subtype'),138),139'key_closed' => array(140'columns' => array('closedEpoch'),141),142'key_closer' => array(143'columns' => array('closerPHID', 'closedEpoch'),144),145),146) + parent::getConfiguration();147}148149public function loadDependsOnTaskPHIDs() {150return PhabricatorEdgeQuery::loadDestinationPHIDs(151$this->getPHID(),152ManiphestTaskDependsOnTaskEdgeType::EDGECONST);153}154155public function loadDependedOnByTaskPHIDs() {156return PhabricatorEdgeQuery::loadDestinationPHIDs(157$this->getPHID(),158ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);159}160161public function generatePHID() {162return PhabricatorPHID::generateNewPHID(ManiphestTaskPHIDType::TYPECONST);163}164165public function getSubscriberPHIDs() {166return $this->assertAttached($this->subscriberPHIDs);167}168169public function getProjectPHIDs() {170return $this->assertAttached($this->edgeProjectPHIDs);171}172173public function attachProjectPHIDs(array $phids) {174$this->edgeProjectPHIDs = $phids;175return $this;176}177178public function attachSubscriberPHIDs(array $phids) {179$this->subscriberPHIDs = $phids;180return $this;181}182183public function setOwnerPHID($phid) {184$this->ownerPHID = nonempty($phid, null);185return $this;186}187188public function getMonogram() {189return 'T'.$this->getID();190}191192public function getURI() {193return '/'.$this->getMonogram();194}195196public function attachGroupByProjectPHID($phid) {197$this->groupByProjectPHID = $phid;198return $this;199}200201public function getGroupByProjectPHID() {202return $this->assertAttached($this->groupByProjectPHID);203}204205public function save() {206if (!$this->mailKey) {207$this->mailKey = Filesystem::readRandomCharacters(20);208}209210$result = parent::save();211212return $result;213}214215public function isClosed() {216return ManiphestTaskStatus::isClosedStatus($this->getStatus());217}218219public function areCommentsLocked() {220if ($this->areEditsLocked()) {221return true;222}223224return ManiphestTaskStatus::areCommentsLockedInStatus($this->getStatus());225}226227public function areEditsLocked() {228return ManiphestTaskStatus::areEditsLockedInStatus($this->getStatus());229}230231public function setProperty($key, $value) {232$this->properties[$key] = $value;233return $this;234}235236public function getProperty($key, $default = null) {237return idx($this->properties, $key, $default);238}239240public function getCoverImageFilePHID() {241return idx($this->properties, 'cover.filePHID');242}243244public function getCoverImageThumbnailPHID() {245return idx($this->properties, 'cover.thumbnailPHID');246}247248public function getPriorityKeyword() {249$priority = $this->getPriority();250251$keyword = ManiphestTaskPriority::getKeywordForTaskPriority($priority);252if ($keyword !== null) {253return $keyword;254}255256return ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD;257}258259260/* -( PhabricatorSubscribableInterface )----------------------------------- */261262263public function isAutomaticallySubscribed($phid) {264return ($phid == $this->getOwnerPHID());265}266267268/* -( Markup Interface )--------------------------------------------------- */269270271/**272* @task markup273*/274public function getMarkupFieldKey($field) {275$content = $this->getMarkupText($field);276return PhabricatorMarkupEngine::digestRemarkupContent($this, $content);277}278279280/**281* @task markup282*/283public function getMarkupText($field) {284return $this->getDescription();285}286287288/**289* @task markup290*/291public function newMarkupEngine($field) {292return PhabricatorMarkupEngine::newManiphestMarkupEngine();293}294295296/**297* @task markup298*/299public function didMarkupText(300$field,301$output,302PhutilMarkupEngine $engine) {303return $output;304}305306307/**308* @task markup309*/310public function shouldUseMarkupCache($field) {311return (bool)$this->getID();312}313314315/* -( Policy Interface )--------------------------------------------------- */316317318public function getCapabilities() {319return array(320PhabricatorPolicyCapability::CAN_VIEW,321PhabricatorPolicyCapability::CAN_INTERACT,322PhabricatorPolicyCapability::CAN_EDIT,323);324}325326public function getPolicy($capability) {327switch ($capability) {328case PhabricatorPolicyCapability::CAN_VIEW:329return $this->getViewPolicy();330case PhabricatorPolicyCapability::CAN_INTERACT:331if ($this->areCommentsLocked()) {332return PhabricatorPolicies::POLICY_NOONE;333} else {334return $this->getViewPolicy();335}336case PhabricatorPolicyCapability::CAN_EDIT:337if ($this->areEditsLocked()) {338return PhabricatorPolicies::POLICY_NOONE;339} else {340return $this->getEditPolicy();341}342}343}344345public function hasAutomaticCapability($capability, PhabricatorUser $user) {346// The owner of a task can always view and edit it.347$owner_phid = $this->getOwnerPHID();348if ($owner_phid) {349$user_phid = $user->getPHID();350if ($user_phid == $owner_phid) {351return true;352}353}354355return false;356}357358359/* -( PhabricatorTokenReceiverInterface )---------------------------------- */360361362public function getUsersToNotifyOfTokenGiven() {363// Sort of ambiguous who this was intended for; just let them both know.364return array_filter(365array_unique(366array(367$this->getAuthorPHID(),368$this->getOwnerPHID(),369)));370}371372373/* -( PhabricatorCustomFieldInterface )------------------------------------ */374375376public function getCustomFieldSpecificationForRole($role) {377return PhabricatorEnv::getEnvConfig('maniphest.fields');378}379380public function getCustomFieldBaseClass() {381return 'ManiphestCustomField';382}383384public function getCustomFields() {385return $this->assertAttached($this->customFields);386}387388public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {389$this->customFields = $fields;390return $this;391}392393394/* -( PhabricatorDestructibleInterface )----------------------------------- */395396397public function destroyObjectPermanently(398PhabricatorDestructionEngine $engine) {399400$this->openTransaction();401$this->delete();402$this->saveTransaction();403}404405406/* -( PhabricatorApplicationTransactionInterface )------------------------- */407408409public function getApplicationTransactionEditor() {410return new ManiphestTransactionEditor();411}412413public function getApplicationTransactionTemplate() {414return new ManiphestTransaction();415}416417418/* -( PhabricatorSpacesInterface )----------------------------------------- */419420421public function getSpacePHID() {422return $this->spacePHID;423}424425426/* -( PhabricatorConduitResultInterface )---------------------------------- */427428429public function getFieldSpecificationsForConduit() {430return array(431id(new PhabricatorConduitSearchFieldSpecification())432->setKey('title')433->setType('string')434->setDescription(pht('The title of the task.')),435id(new PhabricatorConduitSearchFieldSpecification())436->setKey('description')437->setType('remarkup')438->setDescription(pht('The task description.')),439id(new PhabricatorConduitSearchFieldSpecification())440->setKey('authorPHID')441->setType('phid')442->setDescription(pht('Original task author.')),443id(new PhabricatorConduitSearchFieldSpecification())444->setKey('ownerPHID')445->setType('phid?')446->setDescription(pht('Current task owner, if task is assigned.')),447id(new PhabricatorConduitSearchFieldSpecification())448->setKey('status')449->setType('map<string, wild>')450->setDescription(pht('Information about task status.')),451id(new PhabricatorConduitSearchFieldSpecification())452->setKey('priority')453->setType('map<string, wild>')454->setDescription(pht('Information about task priority.')),455id(new PhabricatorConduitSearchFieldSpecification())456->setKey('points')457->setType('points')458->setDescription(pht('Point value of the task.')),459id(new PhabricatorConduitSearchFieldSpecification())460->setKey('subtype')461->setType('string')462->setDescription(pht('Subtype of the task.')),463id(new PhabricatorConduitSearchFieldSpecification())464->setKey('closerPHID')465->setType('phid?')466->setDescription(467pht('User who closed the task, if the task is closed.')),468id(new PhabricatorConduitSearchFieldSpecification())469->setKey('dateClosed')470->setType('int?')471->setDescription(472pht('Epoch timestamp when the task was closed.')),473);474}475476public function getFieldValuesForConduit() {477$status_value = $this->getStatus();478$status_info = array(479'value' => $status_value,480'name' => ManiphestTaskStatus::getTaskStatusName($status_value),481'color' => ManiphestTaskStatus::getStatusColor($status_value),482);483484$priority_value = (int)$this->getPriority();485$priority_info = array(486'value' => $priority_value,487'name' => ManiphestTaskPriority::getTaskPriorityName($priority_value),488'color' => ManiphestTaskPriority::getTaskPriorityColor($priority_value),489);490491$closed_epoch = $this->getClosedEpoch();492if ($closed_epoch !== null) {493$closed_epoch = (int)$closed_epoch;494}495496return array(497'name' => $this->getTitle(),498'description' => array(499'raw' => $this->getDescription(),500),501'authorPHID' => $this->getAuthorPHID(),502'ownerPHID' => $this->getOwnerPHID(),503'status' => $status_info,504'priority' => $priority_info,505'points' => $this->getPoints(),506'subtype' => $this->getSubtype(),507'closerPHID' => $this->getCloserPHID(),508'dateClosed' => $closed_epoch,509);510}511512public function getConduitSearchAttachments() {513return array(514id(new PhabricatorBoardColumnsSearchEngineAttachment())515->setAttachmentKey('columns'),516);517}518519public function newSubtypeObject() {520$subtype_key = $this->getEditEngineSubtype();521$subtype_map = $this->newEditEngineSubtypeMap();522return $subtype_map->getSubtype($subtype_key);523}524525/* -( PhabricatorFulltextInterface )--------------------------------------- */526527528public function newFulltextEngine() {529return new ManiphestTaskFulltextEngine();530}531532533/* -( DoorkeeperBridgedObjectInterface )----------------------------------- */534535536public function getBridgedObject() {537return $this->assertAttached($this->bridgedObject);538}539540public function attachBridgedObject(541DoorkeeperExternalObject $object = null) {542$this->bridgedObject = $object;543return $this;544}545546547/* -( PhabricatorEditEngineSubtypeInterface )------------------------------ */548549550public function getEditEngineSubtype() {551return $this->getSubtype();552}553554public function setEditEngineSubtype($value) {555return $this->setSubtype($value);556}557558public function newEditEngineSubtypeMap() {559$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');560return PhabricatorEditEngineSubtype::newSubtypeMap($config)561->setDatasource(new ManiphestTaskSubtypeDatasource());562}563564565/* -( PhabricatorEditEngineLockableInterface )----------------------------- */566567568public function newEditEngineLock() {569return new ManiphestTaskEditEngineLock();570}571572573/* -( PhabricatorFerretInterface )----------------------------------------- */574575576public function newFerretEngine() {577return new ManiphestTaskFerretEngine();578}579580581/* -( PhabricatorEditEngineMFAInterface )---------------------------------- */582583584public function newEditEngineMFAEngine() {585return new ManiphestTaskMFAEngine();586}587588589/* -( PhabricatorPolicyCodexInterface )------------------------------------ */590591592public function newPolicyCodex() {593return new ManiphestTaskPolicyCodex();594}595596597/* -( PhabricatorUnlockableInterface )------------------------------------- */598599600public function newUnlockEngine() {601return new ManiphestTaskUnlockEngine();602}603604}605606607