[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/maniphest/conduit/ -> ManiphestConduitAPIMethod.php (source)

   1  <?php
   2  
   3  abstract class ManiphestConduitAPIMethod extends ConduitAPIMethod {
   4  
   5    final public function getApplication() {
   6      return PhabricatorApplication::getByClass(
   7        'PhabricatorManiphestApplication');
   8    }
   9  
  10    public function defineErrorTypes() {
  11      return array(
  12        'ERR-INVALID-PARAMETER' => 'Missing or malformed parameter.',
  13      );
  14    }
  15  
  16    protected function buildTaskInfoDictionary(ManiphestTask $task) {
  17      $results = $this->buildTaskInfoDictionaries(array($task));
  18      return idx($results, $task->getPHID());
  19    }
  20  
  21    protected function getTaskFields($is_new) {
  22      $fields = array();
  23  
  24      if (!$is_new) {
  25        $fields += array(
  26          'id'    => 'optional int',
  27          'phid'  => 'optional int',
  28        );
  29      }
  30  
  31      $fields += array(
  32        'title'         => $is_new ? 'required string' : 'optional string',
  33        'description'   => 'optional string',
  34        'ownerPHID'     => 'optional phid',
  35        'viewPolicy'    => 'optional phid or policy string',
  36        'editPolicy'    => 'optional phid or policy string',
  37        'ccPHIDs'       => 'optional list<phid>',
  38        'priority'      => 'optional int',
  39        'projectPHIDs'  => 'optional list<phid>',
  40        'auxiliary'     => 'optional dict',
  41      );
  42  
  43      if (!$is_new) {
  44        $fields += array(
  45          'status'    => 'optional string',
  46          'comments'  => 'optional string',
  47        );
  48      }
  49  
  50      return $fields;
  51    }
  52  
  53    protected function applyRequest(
  54      ManiphestTask $task,
  55      ConduitAPIRequest $request,
  56      $is_new) {
  57  
  58      $changes = array();
  59  
  60      if ($is_new) {
  61        $task->setTitle((string)$request->getValue('title'));
  62        $task->setDescription((string)$request->getValue('description'));
  63        $changes[ManiphestTransaction::TYPE_STATUS] =
  64          ManiphestTaskStatus::getDefaultStatus();
  65      } else {
  66  
  67        $comments = $request->getValue('comments');
  68        if (!$is_new && $comments !== null) {
  69          $changes[PhabricatorTransactions::TYPE_COMMENT] = null;
  70        }
  71  
  72        $title = $request->getValue('title');
  73        if ($title !== null) {
  74          $changes[ManiphestTransaction::TYPE_TITLE] = $title;
  75        }
  76  
  77        $desc = $request->getValue('description');
  78        if ($desc !== null) {
  79          $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $desc;
  80        }
  81  
  82        $status = $request->getValue('status');
  83        if ($status !== null) {
  84          $valid_statuses = ManiphestTaskStatus::getTaskStatusMap();
  85          if (!isset($valid_statuses[$status])) {
  86            throw id(new ConduitException('ERR-INVALID-PARAMETER'))
  87              ->setErrorDescription('Status set to invalid value.');
  88          }
  89          $changes[ManiphestTransaction::TYPE_STATUS] = $status;
  90        }
  91      }
  92  
  93      $priority = $request->getValue('priority');
  94      if ($priority !== null) {
  95        $valid_priorities = ManiphestTaskPriority::getTaskPriorityMap();
  96        if (!isset($valid_priorities[$priority])) {
  97          throw id(new ConduitException('ERR-INVALID-PARAMETER'))
  98            ->setErrorDescription('Priority set to invalid value.');
  99        }
 100        $changes[ManiphestTransaction::TYPE_PRIORITY] = $priority;
 101      }
 102  
 103      $owner_phid = $request->getValue('ownerPHID');
 104      if ($owner_phid !== null) {
 105        $this->validatePHIDList(
 106          array($owner_phid),
 107          PhabricatorPeopleUserPHIDType::TYPECONST,
 108          'ownerPHID');
 109        $changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
 110      }
 111  
 112      $ccs = $request->getValue('ccPHIDs');
 113      if ($ccs !== null) {
 114        $changes[ManiphestTransaction::TYPE_CCS] = $ccs;
 115      }
 116  
 117      $transactions = array();
 118  
 119      $view_policy = $request->getValue('viewPolicy');
 120      if ($view_policy !== null) {
 121        $transactions[] = id(new ManiphestTransaction())
 122          ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
 123          ->setNewValue($view_policy);
 124      }
 125  
 126      $edit_policy = $request->getValue('editPolicy');
 127      if ($edit_policy !== null) {
 128        $transactions[] = id(new ManiphestTransaction())
 129          ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
 130          ->setNewValue($edit_policy);
 131      }
 132  
 133      $project_phids = $request->getValue('projectPHIDs');
 134      if ($project_phids !== null) {
 135        $this->validatePHIDList(
 136          $project_phids,
 137          PhabricatorProjectProjectPHIDType::TYPECONST,
 138          'projectPHIDS');
 139  
 140        $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
 141        $transactions[] = id(new ManiphestTransaction())
 142          ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
 143          ->setMetadataValue('edge:type', $project_type)
 144          ->setNewValue(
 145            array(
 146              '=' => array_fuse($project_phids),
 147            ));
 148      }
 149  
 150      $template = new ManiphestTransaction();
 151  
 152      foreach ($changes as $type => $value) {
 153        $transaction = clone $template;
 154        $transaction->setTransactionType($type);
 155        if ($type == PhabricatorTransactions::TYPE_COMMENT) {
 156          $transaction->attachComment(
 157            id(new ManiphestTransactionComment())
 158              ->setContent($comments));
 159        } else {
 160          $transaction->setNewValue($value);
 161        }
 162  
 163        $transactions[] = $transaction;
 164      }
 165  
 166      $field_list = PhabricatorCustomField::getObjectFields(
 167        $task,
 168        PhabricatorCustomField::ROLE_EDIT);
 169      $field_list->readFieldsFromStorage($task);
 170  
 171      $auxiliary = $request->getValue('auxiliary');
 172      if ($auxiliary) {
 173        foreach ($field_list->getFields() as $key => $field) {
 174          if (!array_key_exists($key, $auxiliary)) {
 175            continue;
 176          }
 177          $transaction = clone $template;
 178          $transaction->setTransactionType(
 179            PhabricatorTransactions::TYPE_CUSTOMFIELD);
 180          $transaction->setMetadataValue('customfield:key', $key);
 181          $transaction->setOldValue(
 182            $field->getOldValueForApplicationTransactions());
 183          $transaction->setNewValue($auxiliary[$key]);
 184          $transactions[] = $transaction;
 185        }
 186      }
 187  
 188      if (!$transactions) {
 189        return;
 190      }
 191  
 192      $event = new PhabricatorEvent(
 193        PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK,
 194        array(
 195          'task'          => $task,
 196          'new'           => $is_new,
 197          'transactions'  => $transactions,
 198        ));
 199      $event->setUser($request->getUser());
 200      $event->setConduitRequest($request);
 201      PhutilEventEngine::dispatchEvent($event);
 202  
 203      $task = $event->getValue('task');
 204      $transactions = $event->getValue('transactions');
 205  
 206      $content_source = PhabricatorContentSource::newForSource(
 207        PhabricatorContentSource::SOURCE_CONDUIT,
 208        array());
 209  
 210      $editor = id(new ManiphestTransactionEditor())
 211        ->setActor($request->getUser())
 212        ->setContentSource($content_source)
 213        ->setContinueOnNoEffect(true);
 214  
 215      if (!$is_new) {
 216        $editor->setContinueOnMissingFields(true);
 217      }
 218  
 219      $editor->applyTransactions($task, $transactions);
 220  
 221      $event = new PhabricatorEvent(
 222        PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK,
 223        array(
 224          'task'          => $task,
 225          'new'           => $is_new,
 226          'transactions'  => $transactions,
 227        ));
 228      $event->setUser($request->getUser());
 229      $event->setConduitRequest($request);
 230      PhutilEventEngine::dispatchEvent($event);
 231    }
 232  
 233    protected function buildTaskInfoDictionaries(array $tasks) {
 234      assert_instances_of($tasks, 'ManiphestTask');
 235      if (!$tasks) {
 236        return array();
 237      }
 238  
 239      $task_phids = mpull($tasks, 'getPHID');
 240  
 241      $all_deps = id(new PhabricatorEdgeQuery())
 242        ->withSourcePHIDs($task_phids)
 243        ->withEdgeTypes(array(PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK));
 244      $all_deps->execute();
 245  
 246      $result = array();
 247      foreach ($tasks as $task) {
 248        // TODO: Batch this get as CustomField gets cleaned up.
 249        $field_list = PhabricatorCustomField::getObjectFields(
 250          $task,
 251          PhabricatorCustomField::ROLE_EDIT);
 252        $field_list->readFieldsFromStorage($task);
 253  
 254        $auxiliary = mpull(
 255          $field_list->getFields(),
 256          'getValueForStorage',
 257          'getFieldKey');
 258  
 259        $task_deps = $all_deps->getDestinationPHIDs(
 260          array($task->getPHID()),
 261          array(PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK));
 262  
 263        $result[$task->getPHID()] = array(
 264          'id'           => $task->getID(),
 265          'phid'         => $task->getPHID(),
 266          'authorPHID'   => $task->getAuthorPHID(),
 267          'ownerPHID'    => $task->getOwnerPHID(),
 268          'ccPHIDs'      => $task->getCCPHIDs(),
 269          'status'       => $task->getStatus(),
 270          'statusName'   => ManiphestTaskStatus::getTaskStatusName(
 271            $task->getStatus()),
 272          'isClosed'     => $task->isClosed(),
 273          'priority'     => ManiphestTaskPriority::getTaskPriorityName(
 274            $task->getPriority()),
 275          'priorityColor' => ManiphestTaskPriority::getTaskPriorityColor(
 276            $task->getPriority()),
 277          'title'        => $task->getTitle(),
 278          'description'  => $task->getDescription(),
 279          'projectPHIDs' => $task->getProjectPHIDs(),
 280          'uri'          => PhabricatorEnv::getProductionURI('/T'.$task->getID()),
 281          'auxiliary'    => $auxiliary,
 282  
 283          'objectName'   => 'T'.$task->getID(),
 284          'dateCreated'  => $task->getDateCreated(),
 285          'dateModified' => $task->getDateModified(),
 286          'dependsOnTaskPHIDs' => $task_deps,
 287        );
 288      }
 289  
 290      return $result;
 291    }
 292  
 293    /**
 294     * NOTE: This is a temporary stop gap since its easy to make malformed tasks.
 295     * Long-term, the values set in @{method:defineParamTypes} will be used to
 296     * validate data implicitly within the larger Conduit application.
 297     *
 298     * TODO: Remove this in favor of generalized Conduit hotness.
 299     */
 300    private function validatePHIDList(array $phid_list, $phid_type, $field) {
 301      $phid_groups = phid_group_by_type($phid_list);
 302      unset($phid_groups[$phid_type]);
 303      if (!empty($phid_groups)) {
 304        throw id(new ConduitException('ERR-INVALID-PARAMETER'))
 305          ->setErrorDescription('One or more PHIDs were invalid for '.$field.'.');
 306      }
 307  
 308      return true;
 309    }
 310  
 311  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1