Page MenuHomePhabricator

D18111.id43613.diff
No OneTemporary

D18111.id43613.diff

diff --git a/resources/sql/autopatches/20170614.taskstatus.sql b/resources/sql/autopatches/20170614.taskstatus.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20170614.taskstatus.sql
@@ -0,0 +1,4 @@
+/* Extend from 12 characters to 64. */
+
+ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
+ CHANGE status status VARCHAR(64) COLLATE utf8mb4_bin NOT NULL;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1503,6 +1503,7 @@
'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php',
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
+ 'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php',
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
'ManiphestSubtypesConfigOptionsType' => 'applications/maniphest/config/ManiphestSubtypesConfigOptionsType.php',
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
@@ -6598,6 +6599,7 @@
'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
+ 'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestSubpriorityController' => 'ManiphestController',
'ManiphestSubtypesConfigOptionsType' => 'PhabricatorConfigJSONOptionType',
'ManiphestTask' => array(
diff --git a/src/applications/maniphest/__tests__/ManiphestTaskTestCase.php b/src/applications/maniphest/__tests__/ManiphestTaskTestCase.php
--- a/src/applications/maniphest/__tests__/ManiphestTaskTestCase.php
+++ b/src/applications/maniphest/__tests__/ManiphestTaskTestCase.php
@@ -194,11 +194,14 @@
$dst,
$is_after);
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head($keyword_map[$pri]);
+
$xactions = array();
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($pri);
+ ->setNewValue($keyword);
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskSubpriorityTransaction::TRANSACTIONTYPE)
@@ -217,11 +220,14 @@
$target_priority,
$is_end);
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head($keyword_map[$pri]);
+
$xactions = array();
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($pri);
+ ->setNewValue($keyword);
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskSubpriorityTransaction::TRANSACTIONTYPE)
diff --git a/src/applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php b/src/applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php
--- a/src/applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php
+++ b/src/applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php
@@ -285,6 +285,11 @@
'=' => array_fuse($value),
));
break;
+ case ManiphestTaskPriorityTransaction::TRANSACTIONTYPE:
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $value));
+ $xaction->setNewValue($keyword);
+ break;
default:
$xaction->setNewValue($value);
break;
diff --git a/src/applications/maniphest/command/ManiphestPriorityEmailCommand.php b/src/applications/maniphest/command/ManiphestPriorityEmailCommand.php
--- a/src/applications/maniphest/command/ManiphestPriorityEmailCommand.php
+++ b/src/applications/maniphest/command/ManiphestPriorityEmailCommand.php
@@ -49,18 +49,8 @@
array $argv) {
$xactions = array();
- $target = phutil_utf8_strtolower(head($argv));
- $priority = null;
-
- $keywords = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
- foreach ($keywords as $key => $words) {
- foreach ($words as $word) {
- if ($word == $target) {
- $priority = $key;
- break;
- }
- }
- }
+ $keyword = phutil_utf8_strtolower(head($argv));
+ $priority = ManiphestTaskPriority::getTaskPriorityFromKeyword($keyword);
if ($priority === null) {
return array();
@@ -72,7 +62,7 @@
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($priority);
+ ->setNewValue($keyword);
return $xactions;
}
diff --git a/src/applications/maniphest/conduit/ManiphestConduitAPIMethod.php b/src/applications/maniphest/conduit/ManiphestConduitAPIMethod.php
--- a/src/applications/maniphest/conduit/ManiphestConduitAPIMethod.php
+++ b/src/applications/maniphest/conduit/ManiphestConduitAPIMethod.php
@@ -99,7 +99,9 @@
throw id(new ConduitException('ERR-INVALID-PARAMETER'))
->setErrorDescription(pht('Priority set to invalid value.'));
}
- $changes[ManiphestTaskPriorityTransaction::TRANSACTIONTYPE] = $priority;
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $priority));
+ $changes[ManiphestTaskPriorityTransaction::TRANSACTIONTYPE] = $keyword;
}
$owner_phid = $request->getValue('ownerPHID');
diff --git a/src/applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php b/src/applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php
--- a/src/applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php
+++ b/src/applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php
@@ -33,4 +33,14 @@
return $results;
}
+ public function getMethodStatus() {
+ return self::METHOD_STATUS_FROZEN;
+ }
+
+ public function getMethodStatusDescription() {
+ return pht(
+ 'This method is frozen and will eventually be deprecated. New code '.
+ 'should use "maniphest.status.search" instead.');
+ }
+
}
diff --git a/src/applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php b/src/applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php
@@ -0,0 +1,52 @@
+<?php
+
+final class ManiphestStatusSearchConduitAPIMethod
+ extends ManiphestConduitAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'maniphest.status.search';
+ }
+
+ public function getMethodSummary() {
+ return pht('Read information about task statuses.');
+ }
+
+ public function getMethodDescription() {
+ return pht(
+ 'Returns information about the possible statuses for Maniphest '.
+ 'tasks.');
+ }
+
+ protected function defineParamTypes() {
+ return array();
+ }
+
+ protected function defineReturnType() {
+ return 'map<string, wild>';
+ }
+
+ public function getRequiredScope() {
+ return self::SCOPE_ALWAYS;
+ }
+
+ protected function execute(ConduitAPIRequest $request) {
+ $config = PhabricatorEnv::getEnvConfig('maniphest.statuses');
+ $results = array();
+ foreach ($config as $code => $status) {
+ $stripped_status = array(
+ 'name' => $status['name'],
+ 'value' => $code,
+ 'closed' => !empty($status['closed']),
+ );
+
+ if (isset($status['special'])) {
+ $stripped_status['special'] = $status['special'];
+ }
+
+ $results[] = $stripped_status;
+ }
+
+ return array('data' => $results);
+ }
+
+}
diff --git a/src/applications/maniphest/constants/ManiphestTaskPriority.php b/src/applications/maniphest/constants/ManiphestTaskPriority.php
--- a/src/applications/maniphest/constants/ManiphestTaskPriority.php
+++ b/src/applications/maniphest/constants/ManiphestTaskPriority.php
@@ -2,6 +2,8 @@
final class ManiphestTaskPriority extends ManiphestConstants {
+ const UNKNOWN_PRIORITY_KEYWORD = '!!unknown!!';
+
/**
* Get the priorities and their full descriptions.
*
@@ -105,6 +107,18 @@
return 'fa-arrow-right';
}
+ public static function getTaskPriorityFromKeyword($keyword) {
+ $map = self::getTaskPriorityKeywordsMap();
+
+ foreach ($map as $priority => $keywords) {
+ if (in_array($keyword, $keywords)) {
+ return $priority;
+ }
+ }
+
+ return null;
+ }
+
public static function isDisabledPriority($priority) {
$config = idx(self::getConfig(), $priority, array());
return idx($config, 'disabled', false);
@@ -116,6 +130,18 @@
return $config;
}
+ private static function isValidPriorityKeyword($keyword) {
+ if (!strlen($keyword) || strlen($keyword) > 64) {
+ return false;
+ }
+
+ // Alphanumeric, but not exclusively numeric
+ if (!preg_match('/^(?![0-9]*$)[a-zA-Z0-9]+$/', $keyword)) {
+ return false;
+ }
+ return true;
+ }
+
public static function validateConfiguration($config) {
if (!is_array($config)) {
throw new Exception(
@@ -147,9 +173,24 @@
'name' => 'string',
'short' => 'optional string',
'color' => 'optional string',
- 'keywords' => 'optional list<string>',
+ 'keywords' => 'list<string>',
'disabled' => 'optional bool',
));
+
+ $keywords = $value['keywords'];
+ foreach ($keywords as $keyword) {
+ if (!self::isValidPriorityKeyword($keyword)) {
+ throw new Exception(
+ pht(
+ 'Key "%s" is not a valid priority keyword. Priority keywords '.
+ 'must be 1-64 alphanumeric characters and cannot be '.
+ 'exclusively digits. For example, "%s" or "%s" are '.
+ 'reasonable choices.',
+ $keyword,
+ 'low',
+ 'critical'));
+ }
+ }
}
}
diff --git a/src/applications/maniphest/constants/ManiphestTaskStatus.php b/src/applications/maniphest/constants/ManiphestTaskStatus.php
--- a/src/applications/maniphest/constants/ManiphestTaskStatus.php
+++ b/src/applications/maniphest/constants/ManiphestTaskStatus.php
@@ -232,16 +232,17 @@
* @task validate
*/
public static function isValidStatusConstant($constant) {
- if (strlen($constant) > 12) {
+ if (!strlen($constant) || strlen($constant) > 64) {
return false;
}
- if (!preg_match('/^[a-z0-9]+\z/', $constant)) {
+
+ // Alphanumeric, but not exclusively numeric
+ if (!preg_match('/^(?![0-9]*$)[a-zA-Z0-9]+$/', $constant)) {
return false;
}
return true;
}
-
/**
* @task validate
*/
@@ -250,10 +251,9 @@
if (!self::isValidStatusConstant($key)) {
throw new Exception(
pht(
- 'Key "%s" is not a valid status constant. Status constants must '.
- 'be 1-12 characters long and contain only lowercase letters (a-z) '.
- 'and digits (0-9). For example, "%s" or "%s" are reasonable '.
- 'choices.',
+ 'Key "%s" is not a valid status constant. Status constants '.
+ 'must be 1-64 alphanumeric characters and cannot be exclusively '.
+ 'digits. For example, "%s" or "%s" are reasonable choices.',
$key,
'open',
'closed'));
diff --git a/src/applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php b/src/applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php
--- a/src/applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php
+++ b/src/applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php
@@ -10,10 +10,15 @@
'duplicate2' => true,
'' => false,
- 'longlonglonglong' => false,
+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' =>
+ false,
'.' => false,
- 'ABCD' => false,
+ ' ' => false,
+ 'ABCD' => true,
'a b c ' => false,
+ '1' => false,
+ '111' => false,
+ '11a' => true,
);
foreach ($map as $input => $expect) {
diff --git a/src/applications/maniphest/controller/ManiphestSubpriorityController.php b/src/applications/maniphest/controller/ManiphestSubpriorityController.php
--- a/src/applications/maniphest/controller/ManiphestSubpriorityController.php
+++ b/src/applications/maniphest/controller/ManiphestSubpriorityController.php
@@ -40,11 +40,14 @@
$is_end = false);
}
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $pri));
+
$xactions = array();
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($pri);
+ ->setNewValue($keyword);
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskSubpriorityTransaction::TRANSACTIONTYPE)
diff --git a/src/applications/maniphest/editor/ManiphestEditEngine.php b/src/applications/maniphest/editor/ManiphestEditEngine.php
--- a/src/applications/maniphest/editor/ManiphestEditEngine.php
+++ b/src/applications/maniphest/editor/ManiphestEditEngine.php
@@ -215,7 +215,7 @@
->setConduitTypeDescription(pht('New task priority constant.'))
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
- ->setValue($object->getPriority())
+ ->setValue($object->getPriorityKeyword())
->setOptions($priority_map)
->setCommentActionLabel(pht('Change Priority')),
);
@@ -289,29 +289,29 @@
private function getTaskPriorityMap(ManiphestTask $task) {
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
+ $priority_keywords = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$current_priority = $task->getPriority();
-
- // If the current value isn't a legitimate one, put it in the dropdown
- // anyway so saving the form doesn't cause a side effects.
- if (idx($priority_map, $current_priority) === null) {
- $priority_map[$current_priority] = pht(
- '<Unknown: %s>',
- $current_priority);
- }
+ $results = array();
foreach ($priority_map as $priority => $priority_name) {
- // Always keep the current priority.
- if ($priority == $current_priority) {
+ $disabled = ManiphestTaskPriority::isDisabledPriority($priority);
+ if ($disabled && !($priority == $current_priority)) {
continue;
}
- if (ManiphestTaskPriority::isDisabledPriority($priority)) {
- unset($priority_map[$priority]);
- continue;
- }
+ $keyword = head(idx($priority_keywords, $priority));
+ $results[$keyword] = $priority_name;
+ }
+
+ // If the current value isn't a legitimate one, put it in the dropdown
+ // anyway so saving the form doesn't cause any side effects.
+ if (idx($priority_map, $current_priority) === null) {
+ $results[ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD] = pht(
+ '<Unknown: %s>',
+ $current_priority);
}
- return $priority_map;
+ return $results;
}
protected function newEditResponse(
diff --git a/src/applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php b/src/applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php
--- a/src/applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php
+++ b/src/applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php
@@ -39,12 +39,15 @@
return;
}
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $priority));
+
$xaction = $adapter->newTransaction()
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($priority);
+ ->setNewValue($keyword);
$adapter->queueTransaction($xaction);
- $this->logEffect(self::DO_PRIORITY, $priority);
+ $this->logEffect(self::DO_PRIORITY, $keyword);
}
public function getHeraldActionStandardType() {
diff --git a/src/applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php b/src/applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php
--- a/src/applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php
+++ b/src/applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php
@@ -100,7 +100,10 @@
}
public function generateTaskPriority() {
- return array_rand(ManiphestTaskPriority::getTaskPriorityMap());
+ $pri = array_rand(ManiphestTaskPriority::getTaskPriorityMap());
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $pri));
+ return $keyword;
}
public function generateTaskSubPriority() {
diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php
--- a/src/applications/maniphest/storage/ManiphestTask.php
+++ b/src/applications/maniphest/storage/ManiphestTask.php
@@ -79,7 +79,7 @@
),
self::CONFIG_COLUMN_SCHEMA => array(
'ownerPHID' => 'phid?',
- 'status' => 'text12',
+ 'status' => 'text64',
'priority' => 'uint32',
'title' => 'sort',
'originalTitle' => 'text',
@@ -245,6 +245,14 @@
);
}
+ public function getPriorityKeyword() {
+ $priority = $this->getPriority();
+ $map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $default = array(ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD);
+ $keywords = idx($map, $priority, $default);
+ return head($keywords);
+ }
+
private function comparePriorityTo(ManiphestTask $other) {
$upri = $this->getPriority();
$vpri = $other->getPriority();
diff --git a/src/applications/maniphest/xaction/ManiphestTaskPriorityTransaction.php b/src/applications/maniphest/xaction/ManiphestTaskPriorityTransaction.php
--- a/src/applications/maniphest/xaction/ManiphestTaskPriorityTransaction.php
+++ b/src/applications/maniphest/xaction/ManiphestTaskPriorityTransaction.php
@@ -12,6 +12,19 @@
return $object->getPriority();
}
+ public function generateNewValue($object, $value) {
+ // `$value` is supposed to be a keyword, but if the priority
+ // assigned to a task has been removed from the config,
+ // no such keyword will be available. Other edits to the task
+ // should still be allowed, even if the priority is no longer
+ // valid, so treat this as a no-op.
+ if ($value === ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD) {
+ return $object->getPriority();
+ }
+
+ return (string)ManiphestTaskPriority::getTaskPriorityFromKeyword($value);
+ }
+
public function applyInternalEffects($object, $value) {
$object->setPriority($value);
}
diff --git a/src/applications/project/controller/PhabricatorProjectMoveController.php b/src/applications/project/controller/PhabricatorProjectMoveController.php
--- a/src/applications/project/controller/PhabricatorProjectMoveController.php
+++ b/src/applications/project/controller/PhabricatorProjectMoveController.php
@@ -153,11 +153,14 @@
break;
}
+ $keyword_map = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
+ $keyword = head(idx($keyword_map, $pri));
+
$xactions = array();
if ($pri !== null) {
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
- ->setNewValue($pri);
+ ->setNewValue($keyword);
$xactions[] = id(new ManiphestTransaction())
->setTransactionType(
ManiphestTaskSubpriorityTransaction::TRANSACTIONTYPE)

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 30, 8:12 PM (5 d, 14 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7727480
Default Alt Text
D18111.id43613.diff (19 KB)

Event Timeline