3 final class PhabricatorBoardResponseEngine
extends Phobject
{
8 private $visiblePHIDs = array();
9 private $updatePHIDs = array();
13 public function setViewer(PhabricatorUser
$viewer) {
14 $this->viewer
= $viewer;
18 public function getViewer() {
22 public function setBoardPHID($board_phid) {
23 $this->boardPHID
= $board_phid;
27 public function getBoardPHID() {
28 return $this->boardPHID
;
31 public function setObjects(array $objects) {
32 $this->objects
= $objects;
36 public function getObjects() {
37 return $this->objects
;
40 public function setVisiblePHIDs(array $visible_phids) {
41 $this->visiblePHIDs
= $visible_phids;
45 public function getVisiblePHIDs() {
46 return $this->visiblePHIDs
;
49 public function setUpdatePHIDs(array $update_phids) {
50 $this->updatePHIDs
= $update_phids;
54 public function getUpdatePHIDs() {
55 return $this->updatePHIDs
;
58 public function setOrdering(PhabricatorProjectColumnOrder
$ordering) {
59 $this->ordering
= $ordering;
63 public function getOrdering() {
64 return $this->ordering
;
67 public function setSounds(array $sounds) {
68 $this->sounds
= $sounds;
72 public function getSounds() {
76 public function buildResponse() {
77 $viewer = $this->getViewer();
78 $board_phid = $this->getBoardPHID();
79 $ordering = $this->getOrdering();
81 $update_phids = $this->getUpdatePHIDs();
82 $update_phids = array_fuse($update_phids);
84 $visible_phids = $this->getVisiblePHIDs();
85 $visible_phids = array_fuse($visible_phids);
87 $all_phids = $update_phids +
$visible_phids;
89 // Load all the other tasks that are visible in the affected columns and
90 // perform layout for them.
92 if ($this->objects
!== null) {
93 $all_objects = $this->getObjects();
94 $all_objects = mpull($all_objects, null, 'getPHID');
96 $all_objects = id(new ManiphestTaskQuery())
98 ->withPHIDs($all_phids)
100 $all_objects = mpull($all_objects, null, 'getPHID');
103 // NOTE: The board layout engine is sensitive to PHID input order, and uses
104 // the input order as a component of the "natural" column ordering if no
105 // explicit ordering is specified. Rearrange the PHIDs in ID order.
107 $all_objects = msort($all_objects, 'getID');
108 $ordered_phids = mpull($all_objects, 'getPHID');
110 $layout_engine = id(new PhabricatorBoardLayoutEngine())
112 ->setBoardPHIDs(array($board_phid))
113 ->setObjectPHIDs($ordered_phids)
118 $update_columns = array();
119 foreach ($update_phids as $update_phid) {
120 $update_columns +
= $layout_engine->getObjectColumns(
125 foreach ($update_columns as $column_phid => $column) {
126 $column_object_phids = $layout_engine->getColumnObjectPHIDs(
129 $natural[$column_phid] = array_values($column_object_phids);
133 $vectors = $ordering->getSortVectorsForObjects($all_objects);
134 $header_keys = $ordering->getHeaderKeysForObjects($all_objects);
135 $headers = $ordering->getHeadersForObjects($all_objects);
136 $headers = mpull($headers, 'toDictionary');
139 $header_keys = array();
143 $templates = $this->newCardTemplates();
146 foreach ($all_objects as $card_phid => $object) {
148 'vectors' => array(),
149 'headers' => array(),
150 'properties' => array(),
151 'nodeHTMLTemplate' => null,
155 $order_key = $ordering->getColumnOrderKey();
157 $vector = idx($vectors, $card_phid);
158 if ($vector !== null) {
159 $card['vectors'][$order_key] = $vector;
162 $header = idx($header_keys, $card_phid);
163 if ($header !== null) {
164 $card['headers'][$order_key] = $header;
167 $card['properties'] = self
::newTaskProperties($object);
170 if (isset($templates[$card_phid])) {
171 $card['nodeHTMLTemplate'] = hsprintf('%s', $templates[$card_phid]);
172 $card['update'] = true;
174 $card['update'] = false;
177 $card['vectors'] = (object)$card['vectors'];
178 $card['headers'] = (object)$card['headers'];
179 $card['properties'] = (object)$card['properties'];
181 $cards[$card_phid] = $card;
184 // Mark cards which are currently visible on the client but not visible
185 // on the board on the server for removal from the client view of the
187 foreach ($visible_phids as $card_phid) {
188 if (!isset($cards[$card_phid])) {
189 $cards[$card_phid] = array(
196 'columnMaps' => $natural,
198 'headers' => $headers,
199 'sounds' => $this->getSounds(),
202 return id(new AphrontAjaxResponse())
203 ->setContent($payload);
206 public static function newTaskProperties($task) {
208 'points' => (double)$task->getPoints(),
209 'status' => $task->getStatus(),
210 'priority' => (int)$task->getPriority(),
211 'owner' => $task->getOwnerPHID(),
215 private function loadExcludedProjectPHIDs() {
216 $viewer = $this->getViewer();
217 $board_phid = $this->getBoardPHID();
219 $exclude_phids = array($board_phid);
221 $descendants = id(new PhabricatorProjectQuery())
223 ->withAncestorProjectPHIDs($exclude_phids)
226 foreach ($descendants as $descendant) {
227 $exclude_phids[] = $descendant->getPHID();
230 return array_fuse($exclude_phids);
233 private function newCardTemplates() {
234 $viewer = $this->getViewer();
236 $update_phids = $this->getUpdatePHIDs();
237 if (!$update_phids) {
240 $update_phids = array_fuse($update_phids);
242 if ($this->objects
=== null) {
243 $objects = id(new ManiphestTaskQuery())
245 ->withPHIDs($update_phids)
246 ->needProjectPHIDs(true)
249 $objects = $this->getObjects();
250 $objects = mpull($objects, null, 'getPHID');
251 $objects = array_select_keys($objects, $update_phids);
258 $excluded_phids = $this->loadExcludedProjectPHIDs();
260 $rendering_engine = id(new PhabricatorBoardRenderingEngine())
262 ->setObjects($objects)
263 ->setExcludedProjectPHIDs($excluded_phids);
265 $templates = array();
266 foreach ($objects as $object) {
267 $object_phid = $object->getPHID();
269 $card = $rendering_engine->renderCard($object_phid);
270 $item = $card->getItem();
271 $template = hsprintf('%s', $item);
273 $templates[$object_phid] = $template;