@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 149 lines 4.1 kB view raw
1<?php 2 3final class PhabricatorProjectMoveController 4 extends PhabricatorProjectController { 5 6 public function handleRequest(AphrontRequest $request) { 7 $viewer = $request->getViewer(); 8 $id = $request->getURIData('id'); 9 10 $request->validateCSRF(); 11 12 $column_phid = $request->getStr('columnPHID'); 13 $object_phid = $request->getStr('objectPHID'); 14 15 $after_phids = $request->getStrList('afterPHIDs'); 16 $before_phids = $request->getStrList('beforePHIDs'); 17 18 $order = $request->getStr('order'); 19 if (!strlen($order)) { 20 $order = PhabricatorProjectColumnNaturalOrder::ORDERKEY; 21 } 22 23 $ordering = PhabricatorProjectColumnOrder::getOrderByKey($order); 24 $ordering = id(clone $ordering) 25 ->setViewer($viewer); 26 27 // When the Workboard view is "Group By <something>" the header provides 28 // that context in JSON form 29 $edit_header = null; 30 $raw_header = $request->getStr('header'); 31 if (phutil_nonempty_string($raw_header)) { 32 $edit_header = phutil_json_decode($raw_header); 33 } else { 34 $edit_header = array(); 35 } 36 37 $project = id(new PhabricatorProjectQuery()) 38 ->setViewer($viewer) 39 ->requireCapabilities( 40 array( 41 PhabricatorPolicyCapability::CAN_VIEW, 42 )) 43 ->withIDs(array($id)) 44 ->executeOne(); 45 if (!$project) { 46 return new Aphront404Response(); 47 } 48 49 $cancel_uri = $this->getApplicationURI( 50 new PhutilURI( 51 urisprintf('board/%d/', $project->getID()), 52 array( 53 'order' => $order, 54 ))); 55 56 $board_phid = $project->getPHID(); 57 58 $object = id(new ManiphestTaskQuery()) 59 ->setViewer($viewer) 60 ->withPHIDs(array($object_phid)) 61 ->needProjectPHIDs(true) 62 ->requireCapabilities( 63 array( 64 PhabricatorPolicyCapability::CAN_VIEW, 65 PhabricatorPolicyCapability::CAN_EDIT, 66 )) 67 ->executeOne(); 68 69 if (!$object) { 70 return new Aphront404Response(); 71 } 72 73 $columns = id(new PhabricatorProjectColumnQuery()) 74 ->setViewer($viewer) 75 ->withProjectPHIDs(array($project->getPHID())) 76 ->needTriggers(true) 77 ->execute(); 78 79 $columns = mpull($columns, null, 'getPHID'); 80 $column = idx($columns, $column_phid); 81 if (!$column) { 82 // User is trying to drop this object into a nonexistent column, just kick 83 // them out. 84 return new Aphront404Response(); 85 } 86 87 $engine = id(new PhabricatorBoardLayoutEngine()) 88 ->setViewer($viewer) 89 ->setBoardPHIDs(array($board_phid)) 90 ->setObjectPHIDs(array($object_phid)) 91 ->executeLayout(); 92 93 $order_params = array( 94 'afterPHIDs' => $after_phids, 95 'beforePHIDs' => $before_phids, 96 ); 97 98 $xactions = array(); 99 $xactions[] = id(new ManiphestTransaction()) 100 ->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS) 101 ->setNewValue( 102 array( 103 array( 104 'columnPHID' => $column->getPHID(), 105 ) + $order_params, 106 )); 107 108 $header_xactions = $ordering->getColumnTransactions( 109 $object, 110 $edit_header); 111 foreach ($header_xactions as $header_xaction) { 112 $xactions[] = $header_xaction; 113 } 114 115 $sounds = array(); 116 if ($column->canHaveTrigger()) { 117 $trigger = $column->getTrigger(); 118 if ($trigger) { 119 $trigger_xactions = $trigger->newDropTransactions( 120 $viewer, 121 $column, 122 $object); 123 foreach ($trigger_xactions as $trigger_xaction) { 124 $xactions[] = $trigger_xaction; 125 } 126 127 foreach ($trigger->getSoundEffects() as $effect) { 128 $sounds[] = $effect; 129 } 130 } 131 } 132 133 $editor = id(new ManiphestTransactionEditor()) 134 ->setActor($viewer) 135 ->setContinueOnMissingFields(true) 136 ->setContinueOnNoEffect(true) 137 ->setContentSourceFromRequest($request) 138 ->setCancelURI($cancel_uri); 139 140 $editor->applyTransactions($object, $xactions); 141 142 return $this->newCardResponse( 143 $board_phid, 144 $object_phid, 145 $ordering, 146 $sounds); 147 } 148 149}