Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/project/controller/PhabricatorProjectBoardImportController.php b/src/applications/project/controller/PhabricatorProjectBoardImportController.php
index c344bc0af0..67bddaaa52 100644
--- a/src/applications/project/controller/PhabricatorProjectBoardImportController.php
+++ b/src/applications/project/controller/PhabricatorProjectBoardImportController.php
@@ -1,98 +1,113 @@
<?php
final class PhabricatorProjectBoardImportController
extends PhabricatorProjectBoardController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$project_id = $request->getURIData('projectID');
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($project_id))
->executeOne();
if (!$project) {
return new Aphront404Response();
}
$this->setProject($project);
+ $project_id = $project->getID();
+ $board_uri = $this->getApplicationURI("board/{$project_id}/");
+
+ // See PHI1025. We only want to prevent the import if the board already has
+ // real columns. If it has proxy columns (for example, for milestones) you
+ // can still import columns from another board.
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array($project->getPHID()))
+ ->withIsProxyColumn(false)
->execute();
if ($columns) {
- return new Aphront400Response();
+ return $this->newDialog()
+ ->setTitle(pht('Workboard Already Has Columns'))
+ ->appendParagraph(
+ pht(
+ 'You can not import columns into this workboard because it '.
+ 'already has columns. You can only import into an empty '.
+ 'workboard.'))
+ ->addCancelButton($board_uri);
}
- $project_id = $project->getID();
- $board_uri = $this->getApplicationURI("board/{$project_id}/");
-
if ($request->isFormPost()) {
$import_phid = $request->getArr('importProjectPHID');
$import_phid = reset($import_phid);
$import_columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array($import_phid))
+ ->withIsProxyColumn(false)
->execute();
if (!$import_columns) {
- return new Aphront400Response();
+ return $this->newDialog()
+ ->setTitle(pht('Source Workboard Has No Columns'))
+ ->appendParagraph(
+ pht(
+ 'You can not import columns from that workboard because it has '.
+ 'no importable columns.'))
+ ->addCancelButton($board_uri);
}
$table = id(new PhabricatorProjectColumn())
->openTransaction();
foreach ($import_columns as $import_column) {
if ($import_column->isHidden()) {
continue;
}
- if ($import_column->getProxy()) {
- continue;
- }
$new_column = PhabricatorProjectColumn::initializeNewColumn($viewer)
->setSequence($import_column->getSequence())
->setProjectPHID($project->getPHID())
->setName($import_column->getName())
->setProperties($import_column->getProperties())
->save();
}
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
->setTransactionType(
PhabricatorProjectWorkboardTransaction::TRANSACTIONTYPE)
->setNewValue(1);
id(new PhabricatorProjectTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->applyTransactions($project, $xactions);
$table->saveTransaction();
return id(new AphrontRedirectResponse())->setURI($board_uri);
}
$proj_selector = id(new AphrontFormTokenizerControl())
->setName('importProjectPHID')
->setUser($viewer)
->setDatasource(id(new PhabricatorProjectDatasource())
->setParameters(array('mustHaveColumns' => true))
->setLimit(1));
return $this->newDialog()
->setTitle(pht('Import Columns'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->appendParagraph(pht('Choose a project to import columns from:'))
->appendChild($proj_selector)
->addCancelButton($board_uri)
->addSubmitButton(pht('Import'));
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnQuery.php b/src/applications/project/query/PhabricatorProjectColumnQuery.php
index 13f2f52a43..441c33e8cb 100644
--- a/src/applications/project/query/PhabricatorProjectColumnQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnQuery.php
@@ -1,166 +1,180 @@
<?php
final class PhabricatorProjectColumnQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $projectPHIDs;
private $proxyPHIDs;
private $statuses;
+ private $isProxyColumn;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProjectPHIDs(array $project_phids) {
$this->projectPHIDs = $project_phids;
return $this;
}
public function withProxyPHIDs(array $proxy_phids) {
$this->proxyPHIDs = $proxy_phids;
return $this;
}
public function withStatuses(array $status) {
$this->statuses = $status;
return $this;
}
+ public function withIsProxyColumn($is_proxy) {
+ $this->isProxyColumn = $is_proxy;
+ return $this;
+ }
+
public function newResultObject() {
return new PhabricatorProjectColumn();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function willFilterPage(array $page) {
$projects = array();
$project_phids = array_filter(mpull($page, 'getProjectPHID'));
if ($project_phids) {
$projects = id(new PhabricatorProjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->execute();
$projects = mpull($projects, null, 'getPHID');
}
foreach ($page as $key => $column) {
$phid = $column->getProjectPHID();
$project = idx($projects, $phid);
if (!$project) {
$this->didRejectResult($page[$key]);
unset($page[$key]);
continue;
}
$column->attachProject($project);
}
$proxy_phids = array_filter(mpull($page, 'getProjectPHID'));
return $page;
}
protected function didFilterPage(array $page) {
$proxy_phids = array();
foreach ($page as $column) {
$proxy_phid = $column->getProxyPHID();
if ($proxy_phid !== null) {
$proxy_phids[$proxy_phid] = $proxy_phid;
}
}
if ($proxy_phids) {
$proxies = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($proxy_phids)
->execute();
$proxies = mpull($proxies, null, 'getPHID');
} else {
$proxies = array();
}
foreach ($page as $key => $column) {
$proxy_phid = $column->getProxyPHID();
if ($proxy_phid !== null) {
$proxy = idx($proxies, $proxy_phid);
// Only attach valid proxies, so we don't end up getting surprised if
// an install somehow gets junk into their database.
if (!($proxy instanceof PhabricatorColumnProxyInterface)) {
$proxy = null;
}
if (!$proxy) {
$this->didRejectResult($column);
unset($page[$key]);
continue;
}
} else {
$proxy = null;
}
$column->attachProxy($proxy);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->projectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'projectPHID IN (%Ls)',
$this->projectPHIDs);
}
if ($this->proxyPHIDs !== null) {
$where[] = qsprintf(
$conn,
'proxyPHID IN (%Ls)',
$this->proxyPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ld)',
$this->statuses);
}
+ if ($this->isProxyColumn !== null) {
+ if ($this->isProxyColumn) {
+ $where[] = qsprintf($conn, 'proxyPHID IS NOT NULL');
+ } else {
+ $where[] = qsprintf($conn, 'proxyPHID IS NULL');
+ }
+ }
+
return $where;
}
public function getQueryApplicationClass() {
return 'PhabricatorProjectApplication';
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectDatasource.php b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
index e5b24335cf..5b999a997f 100644
--- a/src/applications/project/typeahead/PhabricatorProjectDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
@@ -1,156 +1,157 @@
<?php
final class PhabricatorProjectDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Projects');
}
public function getPlaceholderText() {
return pht('Type a project name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorProjectApplication';
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
// Allow users to type "#qa" or "qa" to find "Quality Assurance".
$raw_query = ltrim($raw_query, '#');
$tokens = self::tokenizeString($raw_query);
$query = id(new PhabricatorProjectQuery())
->needImages(true)
->needSlugs(true)
->setOrderVector(array('-status', 'id'));
if ($this->getPhase() == self::PHASE_PREFIX) {
$prefix = $this->getPrefixQuery();
$query->withNamePrefixes(array($prefix));
} else if ($tokens) {
$query->withNameTokens($tokens);
}
// If this is for policy selection, prevent users from using milestones.
$for_policy = $this->getParameter('policy');
if ($for_policy) {
$query->withIsMilestone(false);
}
$for_autocomplete = $this->getParameter('autocomplete');
$projs = $this->executeQuery($query);
$projs = mpull($projs, null, 'getPHID');
$must_have_cols = $this->getParameter('mustHaveColumns', false);
if ($must_have_cols) {
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array_keys($projs))
+ ->withIsProxyColumn(false)
->execute();
$has_cols = mgroup($columns, 'getProjectPHID');
} else {
$has_cols = array_fill_keys(array_keys($projs), true);
}
$is_browse = $this->getIsBrowse();
if ($is_browse && $projs) {
// TODO: This is a little ad-hoc, but we don't currently have
// infrastructure for bulk querying custom fields efficiently.
$table = new PhabricatorProjectCustomFieldStorage();
$descriptions = $table->loadAllWhere(
'objectPHID IN (%Ls) AND fieldIndex = %s',
array_keys($projs),
PhabricatorHash::digestForIndex('std:project:internal:description'));
$descriptions = mpull($descriptions, 'getFieldValue', 'getObjectPHID');
} else {
$descriptions = array();
}
$results = array();
foreach ($projs as $proj) {
$phid = $proj->getPHID();
if (!isset($has_cols[$phid])) {
continue;
}
$slug = $proj->getPrimarySlug();
if (!strlen($slug)) {
foreach ($proj->getSlugs() as $slug_object) {
$slug = $slug_object->getSlug();
if (strlen($slug)) {
break;
}
}
}
// If we're building results for the autocompleter and this project
// doesn't have any usable slugs, don't return it as a result.
if ($for_autocomplete && !strlen($slug)) {
continue;
}
$closed = null;
if ($proj->isArchived()) {
$closed = pht('Archived');
}
$all_strings = array();
// NOTE: We list the project's name first because results will be
// sorted into prefix vs content phases incorrectly if we don't: it
// will look like "Parent (Milestone)" matched "Parent" as a prefix,
// but it did not.
$all_strings[] = $proj->getName();
if ($proj->isMilestone()) {
$all_strings[] = $proj->getParentProject()->getName();
}
foreach ($proj->getSlugs() as $project_slug) {
$all_strings[] = $project_slug->getSlug();
}
$all_strings = implode("\n", $all_strings);
$proj_result = id(new PhabricatorTypeaheadResult())
->setName($all_strings)
->setDisplayName($proj->getDisplayName())
->setDisplayType($proj->getDisplayIconName())
->setURI($proj->getURI())
->setPHID($phid)
->setIcon($proj->getDisplayIconIcon())
->setColor($proj->getColor())
->setPriorityType('proj')
->setClosed($closed);
if (strlen($slug)) {
$proj_result->setAutocomplete('#'.$slug);
}
$proj_result->setImageURI($proj->getProfileImageURI());
if ($is_browse) {
$proj_result->addAttribute($proj->getDisplayIconName());
$description = idx($descriptions, $phid);
if (strlen($description)) {
$summary = PhabricatorMarkupEngine::summarizeSentence($description);
$proj_result->addAttribute($summary);
}
}
$results[] = $proj_result;
}
return $results;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 7:54 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
140895
Default Alt Text
(14 KB)

Event Timeline