diff --git a/src/deepclone/controller/DeepcloneController.php b/src/deepclone/controller/DeepcloneController.php --- a/src/deepclone/controller/DeepcloneController.php +++ b/src/deepclone/controller/DeepcloneController.php @@ -12,100 +12,17 @@ return new Aphront404Response(); } - $task = id(new ManiphestTaskQuery()) - ->setViewer($viewer) - ->withPHIDs(array($task_id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - ) - ) - ->needSubscriberPHIDs(true) - ->executeOne(); + $task = $this->getTask($task_id); if (!$task) { throw new Exception("Task ID: $task_id"); return new Aphront404Response(); } + $transactions = $this->getTransactions($task); + if ($request->isFormPost()) { - return $this->triggerTransaction($request, $task); - // $properties = $provider->readFormValuesFromRequest($request); - // list($errors, $issues, $properties) = $provider->processEditForm( - // $request, - // $properties); - - // $xactions = array(); - - // if (!$errors) { - // if ($is_new) { - // if (!phutil_nonempty_string($config->getProviderType())) { - // $config->setProviderType($provider->getProviderType()); - // } - // if (!phutil_nonempty_string($config->getProviderDomain())) { - // $config->setProviderDomain($provider->getProviderDomain()); - // } - // } - - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN) - // ->setNewValue($request->getInt('allowLogin', 0)); - - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION) - // ->setNewValue($request->getInt('allowRegistration', 0)); - - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_LINK) - // ->setNewValue($request->getInt('allowLink', 0)); - - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK) - // ->setNewValue($request->getInt('allowUnlink', 0)); - - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS) - // ->setNewValue($request->getInt('trustEmails', 0)); - - // if ($provider->supportsAutoLogin()) { - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN) - // ->setNewValue($request->getInt('autoLogin', 0)); - // } - - // foreach ($properties as $key => $value) { - // $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) - // ->setTransactionType( - // PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY) - // ->setMetadataValue('auth:property', $key) - // ->setNewValue($value); - // } - - // if ($is_new) { - // $config->save(); - // } - - // $editor = id(new PhabricatorAuthProviderConfigEditor()) - // ->setActor($viewer) - // ->setContentSourceFromRequest($request) - // ->setContinueOnNoEffect(true); - - // try { - // $editor->applyTransactions($config, $xactions); - // $next_uri = $config->getURI(); - - // return id(new AphrontRedirectResponse())->setURI($next_uri); - // } catch (Exception $ex) { - // $validation_exception = $ex; - // } - // } + return $this->handleClone($request, $task, $transactions); } else { return $this->buildForm($task); } @@ -121,18 +38,14 @@ ->addCheckbox( 'copy_comments', 1, - pht('Copy all the comments of the task/s to the new task/s'), - ) - ) + pht('Copy all the comments of the task/s to the new task/s'))) ->appendChild( id(new AphrontFormCheckboxControl()) ->setLabel('Deep Clone Task') ->addCheckbox( 'deep_clone', 1, - 'Create a clone of all the sub tasks of this task', - ) - ); + 'Create a clone of all the sub tasks of this task')); $handle = $this->getHandle($task); @@ -178,12 +91,167 @@ return $handle; } - private function triggerTransaction(AphrontRequest $request, ManiphestTask $task) { - $deepCloneRaw = $request->getStr('deep_clone'); - $deepClone = $deepCloneRaw === '1'; - $copyCommentsRaw = $request->getStr('copy_comments'); - $copyComments = $copyCommentsRaw === '1'; + private function getTask($task_id) { + $query = new ManiphestTaskQuery(); + + $task = $query + ->setViewer($this->getViewer()) + ->withPHIDs(array($task_id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->needSubscriberPHIDs(true) + ->executeOne(); + + $field_list = PhabricatorCustomField::getObjectFields( + $task, + PhabricatorCustomField::ROLE_VIEW); + $field_list + ->setViewer($this->getViewer()) + ->readFieldsFromStorage($task); + + return $task; + } + + private function getTransactions(ManiphestTask $task) { + $transactions = id(new ManiphestTransactionQuery()) + ->setViewer($this->getViewer()) + ->withObjectPHIDs(mpull([$task], 'getPHID')) + ->needComments(true) + ->execute(); + + return $transactions; + } + + private function handleClone( + AphrontRequest $request, + ManiphestTask $task, + array $transactions) { + $deep_clone = $request->getStr('deep_clone') === '1'; + $copy_comments = $request->getStr('copy_comments') === '1'; + + $transaction_editor = id(new ManiphestTransactionEditor()) + ->setActor($this->getViewer()) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true); + + $task_clone = $this->cloneTask( + $task, + $transactions, + $copy_comments, + $deep_clone, + $transaction_editor); + + return id(new AphrontRedirectResponse())->setURI($task_clone->getURI()); + } + + + private function cloneTask( + ManiphestTask $task, + array $transactions, + $copy_comments, + $deep_clone, + $transaction_editor, + $parent = null) { + $task_clone = new ManiphestTask(); + + $task_clone->setTitle($task->getTitle()); + $task_clone->setDescription($task->getDescription()); + $task_clone->setAuthorPHID($task->getAuthorPHID()); + $task_clone->setOwnerPHID($task->getOwnerPHID()); + $task_clone->setStatus($task->getStatus()); + $task_clone->setPriority(ManiphestTaskPriority::getDefaultPriority()); + $task_clone->setSubtype($task->getSubtype()); + $task_clone->setViewPolicy($task->getViewPolicy()); + $task_clone->setEditPolicy($task->getEditPolicy()); + + $xactions = []; + + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(PhabricatorCoreCreateTransaction::TRANSACTIONTYPE); + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE) + ->setNewValue( + $task->getPriorityKeyword()); + + foreach ($transactions as &$transaction) { + if ($transaction->getTransactionType() !== 'core:comment') { + continue; + } + + if ($copy_comments === false) { + continue; + } + + $transaction_clone = id(new ManiphestTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT); + + $transaction_clone->attachComment( + id(new ManiphestTransactionComment()) + ->setContent($transaction->getComment()->getContent())); + + $xactions[] = $transaction_clone; + } + + foreach ($transactions as &$transaction) { + if ($transaction->getTransactionType() !== 'core:customfield') { + continue; + } + + $transaction_clone = id(new ManiphestTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD); + + $transaction_clone->setMetadataValue('customfield:key', $transaction->getMetadataValue('customfield:key')); + $transaction_clone->setOldValue(null); + $transaction_clone->setNewValue($transaction->getNewValue()); + + $xactions[] = $transaction_clone; + } + + if ($parent !== null) { + $xactions[] = id(new ManiphestTransaction()) + ->setTransactionType(ManiphestTaskParentTransaction::TRANSACTIONTYPE) + ->setNewValue($parent->getPHID()); + } + + $transaction_editor->applyTransactions($task_clone, $xactions); + + $task_clone->save(); + + if ($deep_clone === false) { + return $task_clone; + } + + $task_graph = id(new ManiphestTaskGraph()) + ->setViewer($this->getViewer()) + ->setSeedPHID($task->getPHID()) + ->setLimit(200) + ->loadGraph(); + + if ($task_graph->isEmpty()) { + return id(new AphrontRedirectResponse())->setURI($task_clone->getURI()); + } + + $subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST; + $subtask_map = $task_graph->getEdges($subtask_type); + + $subtask_list = idx($subtask_map, $task->getPHID(), array()); + + foreach ($subtask_list as &$subtask_phid) { + $sub_task = $this->getTask($subtask_phid); + $sub_transactions = $this->getTransactions($task); + + $this->cloneTask( + $sub_task, + $sub_transactions, + $copy_comments, + $deep_clone, + $transaction_editor, + $task_clone); + } - throw new Exception("Deep Clone $deepClone $deepCloneRaw Copy Comments $copyComments $copyCommentsRaw"); + return $task_clone; } }