Changeset View
Changeset View
Standalone View
Standalone View
src/applications/project/engine/PhabricatorBoardLayoutEngine.php
| Show First 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | private function loadColumns(array $boards) { | ||||
| $columns = id(new PhabricatorProjectColumnQuery()) | $columns = id(new PhabricatorProjectColumnQuery()) | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->withProjectPHIDs(array_keys($boards)) | ->withProjectPHIDs(array_keys($boards)) | ||||
| ->execute(); | ->execute(); | ||||
| $columns = msort($columns, 'getSequence'); | $columns = msort($columns, 'getSequence'); | ||||
| $columns = mpull($columns, null, 'getPHID'); | $columns = mpull($columns, null, 'getPHID'); | ||||
| $this->columnMap = $columns; | $need_children = array(); | ||||
| foreach ($boards as $phid => $board) { | |||||
| if ($board->getHasMilestones() || $board->getHasSubprojects()) { | |||||
| $need_children[] = $phid; | |||||
| } | |||||
| } | |||||
| if ($need_children) { | |||||
| $children = id(new PhabricatorProjectQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withParentProjectPHIDs($need_children) | |||||
| ->execute(); | |||||
| $children = mpull($children, null, 'getPHID'); | |||||
| $children = mgroup($children, 'getParentProjectPHID'); | |||||
| } else { | |||||
| $children = array(); | |||||
| } | |||||
| $columns = mgroup($columns, 'getProjectPHID'); | $columns = mgroup($columns, 'getProjectPHID'); | ||||
| foreach ($boards as $board_phid => $board) { | |||||
| $board_columns = idx($columns, $board_phid, array()); | |||||
| // If the project has milestones, create any missing columns. | |||||
| if ($board->getHasMilestones() || $board->getHasSubprojects()) { | |||||
| $child_projects = idx($children, $board_phid, array()); | |||||
| $next_sequence = last($board_columns)->getSequence() + 1; | |||||
| $proxy_columns = mpull($board_columns, null, 'getProxyPHID'); | |||||
| foreach ($child_projects as $child_phid => $child) { | |||||
| if (isset($proxy_columns[$child_phid])) { | |||||
| continue; | |||||
| } | |||||
| $new_column = PhabricatorProjectColumn::initializeNewColumn($viewer) | |||||
| ->attachProject($board) | |||||
| ->attachProxy($child) | |||||
| ->setSequence($next_sequence++) | |||||
| ->setProjectPHID($board_phid) | |||||
| ->setProxyPHID($child_phid); | |||||
| $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
| $new_column->save(); | |||||
| unset($unguarded); | |||||
| $board_columns[$new_column->getPHID()] = $new_column; | |||||
| } | |||||
| } | |||||
| $columns[$board_phid] = $board_columns; | |||||
| } | |||||
| foreach ($columns as $board_phid => $board_columns) { | |||||
| foreach ($board_columns as $board_column) { | |||||
| $column_phid = $board_column->getPHID(); | |||||
| $this->columnMap[$column_phid] = $board_column; | |||||
| } | |||||
| } | |||||
| return $columns; | return $columns; | ||||
| } | } | ||||
| private function loadPositions(array $boards) { | private function loadPositions(array $boards) { | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| $object_phids = $this->getObjectPHIDs(); | $object_phids = $this->getObjectPHIDs(); | ||||
| Show All 12 Lines | private function loadPositions(array $boards) { | ||||
| return $positions; | return $positions; | ||||
| } | } | ||||
| private function layoutBoard( | private function layoutBoard( | ||||
| $board, | $board, | ||||
| array $columns, | array $columns, | ||||
| array $positions) { | array $positions) { | ||||
| $viewer = $this->getViewer(); | |||||
| $board_phid = $board->getPHID(); | $board_phid = $board->getPHID(); | ||||
| $position_groups = mgroup($positions, 'getObjectPHID'); | $position_groups = mgroup($positions, 'getObjectPHID'); | ||||
| $layout = array(); | $layout = array(); | ||||
| foreach ($columns as $column) { | foreach ($columns as $column) { | ||||
| $column_phid = $column->getPHID(); | $column_phid = $column->getPHID(); | ||||
| $layout[$column_phid] = array(); | $layout[$column_phid] = array(); | ||||
| if ($column->isDefaultColumn()) { | if ($column->isDefaultColumn()) { | ||||
| $default_phid = $column_phid; | $default_phid = $column_phid; | ||||
| } | } | ||||
| } | } | ||||
| // Find all the columns which are proxies for other objects. | |||||
| $proxy_map = array(); | |||||
| foreach ($columns as $column) { | |||||
| $proxy_phid = $column->getProxyPHID(); | |||||
| if ($proxy_phid) { | |||||
| $proxy_map[$proxy_phid] = $column->getPHID(); | |||||
| } | |||||
| } | |||||
| $object_phids = $this->getObjectPHIDs(); | $object_phids = $this->getObjectPHIDs(); | ||||
| // If we have proxies, we need to force cards into the correct proxy | |||||
| // columns. | |||||
| if ($proxy_map) { | |||||
| $edge_query = id(new PhabricatorEdgeQuery()) | |||||
| ->withSourcePHIDs($object_phids) | |||||
| ->withEdgeTypes( | |||||
| array( | |||||
| PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, | |||||
| )); | |||||
| $edge_query->execute(); | |||||
| $project_phids = $edge_query->getDestinationPHIDs(); | |||||
| $project_phids = array_fuse($project_phids); | |||||
| } else { | |||||
| $project_phids = array(); | |||||
| } | |||||
| if ($project_phids) { | |||||
| $projects = id(new PhabricatorProjectQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withPHIDs($project_phids) | |||||
| ->execute(); | |||||
| $projects = mpull($projects, null, 'getPHID'); | |||||
| } else { | |||||
| $projects = array(); | |||||
| } | |||||
| // Build a map from every project that any task is tagged with to the | |||||
| // ancestor project which has a column on this board, if one exists. | |||||
| $ancestor_map = array(); | |||||
| foreach ($projects as $phid => $project) { | |||||
| if (isset($proxy_map[$phid])) { | |||||
| $ancestor_map[$phid] = $proxy_map[$phid]; | |||||
| } else { | |||||
| $seen = array($phid); | |||||
| foreach ($project->getAncestorProjects() as $ancestor) { | |||||
| $ancestor_phid = $ancestor->getPHID(); | |||||
| $seen[] = $ancestor_phid; | |||||
| if (isset($proxy_map[$ancestor_phid])) { | |||||
| foreach ($seen as $project_phid) { | |||||
| $ancestor_map[$project_phid] = $proxy_map[$ancestor_phid]; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| foreach ($object_phids as $object_phid) { | foreach ($object_phids as $object_phid) { | ||||
| $positions = idx($position_groups, $object_phid, array()); | $positions = idx($position_groups, $object_phid, array()); | ||||
| // Remove any positions in columns which no longer exist. | // First, check for objects that have corresponding proxy columns. We're | ||||
| // going to overwrite normal column positions if a tag belongs to a proxy | |||||
| // column, since you can't be in normal columns if you're in proxy | |||||
| // columns. | |||||
| $proxy_hits = array(); | |||||
| if ($proxy_map) { | |||||
| $object_project_phids = $edge_query->getDestinationPHIDs( | |||||
| array( | |||||
| $object_phid, | |||||
| )); | |||||
| foreach ($object_project_phids as $project_phid) { | |||||
| if (isset($ancestor_map[$project_phid])) { | |||||
| $proxy_hits[] = $ancestor_map[$project_phid]; | |||||
| } | |||||
| } | |||||
| } | |||||
| if ($proxy_hits) { | |||||
| // TODO: For now, only one column hit is permissible. | |||||
| $proxy_hits = array_slice($proxy_hits, 0, 1); | |||||
| $proxy_hits = array_fuse($proxy_hits); | |||||
| // Check the object positions: we hope to find a position in each | |||||
| // column the object should be part of. We're going to drop any | |||||
| // invalid positions and create new positions where positions are | |||||
| // missing. | |||||
| foreach ($positions as $key => $position) { | |||||
| $column_phid = $position->getColumnPHID(); | |||||
| if (isset($proxy_hits[$column_phid])) { | |||||
| // Valid column, mark the position as found. | |||||
| unset($proxy_hits[$column_phid]); | |||||
| } else { | |||||
| // Invalid column, ignore the position. | |||||
| unset($positions[$key]); | |||||
| } | |||||
| } | |||||
| // Create new positions for anything we haven't found. | |||||
| foreach ($proxy_hits as $proxy_hit) { | |||||
| $new_position = id(new PhabricatorProjectColumnPosition()) | |||||
| ->setBoardPHID($board_phid) | |||||
| ->setColumnPHID($proxy_hit) | |||||
| ->setObjectPHID($object_phid) | |||||
| ->setSequence(0); | |||||
| $this->addQueue[] = $new_position; | |||||
| $positions[] = $new_position; | |||||
| } | |||||
| } else { | |||||
| // Ignore any positions in columns which no longer exist. We don't | |||||
| // actively destory them because the rest of the code ignores them and | |||||
| // there's no real need to destroy the data. | |||||
| foreach ($positions as $key => $position) { | foreach ($positions as $key => $position) { | ||||
| $column_phid = $position->getColumnPHID(); | $column_phid = $position->getColumnPHID(); | ||||
| if (empty($columns[$column_phid])) { | if (empty($columns[$column_phid])) { | ||||
| $this->remQueue[] = $position; | |||||
| unset($positions[$key]); | unset($positions[$key]); | ||||
| } | } | ||||
| } | } | ||||
| // If the object has no position, put it on the default column. | // If the object has no position, put it on the default column. | ||||
| if (!$positions) { | if (!$positions) { | ||||
| $new_position = id(new PhabricatorProjectColumnPosition()) | $new_position = id(new PhabricatorProjectColumnPosition()) | ||||
| ->setBoardPHID($board_phid) | ->setBoardPHID($board_phid) | ||||
| ->setColumnPHID($default_phid) | ->setColumnPHID($default_phid) | ||||
| ->setObjectPHID($object_phid) | ->setObjectPHID($object_phid) | ||||
| ->setSequence(0); | ->setSequence(0); | ||||
| $this->addQueue[] = $new_position; | $this->addQueue[] = $new_position; | ||||
| $positions = array( | $positions = array( | ||||
| $new_position, | $new_position, | ||||
| ); | ); | ||||
| } | } | ||||
| } | |||||
| foreach ($positions as $position) { | foreach ($positions as $position) { | ||||
| $column_phid = $position->getColumnPHID(); | $column_phid = $position->getColumnPHID(); | ||||
| $layout[$column_phid][$object_phid] = $position; | $layout[$column_phid][$object_phid] = $position; | ||||
| } | } | ||||
| } | } | ||||
| foreach ($layout as $column_phid => $map) { | foreach ($layout as $column_phid => $map) { | ||||
| Show All 12 Lines | |||||