$spec) { $map[$key] = idx($spec, 'name', $key); } return $map; } /** * Get the priorities and their command keywords. * * @return map Priorities to lists of command keywords. */ public static function getTaskPriorityKeywordsMap() { $map = self::getConfig(); foreach ($map as $key => $spec) { $words = idx($spec, 'keywords', array()); if (!is_array($words)) { $words = array($words); } foreach ($words as $word_key => $word) { $words[$word_key] = phutil_utf8_strtolower($word); } $words = array_unique($words); $map[$key] = $words; } return $map; } /** * Get the canonical keyword for a given priority constant. * * @return string|null Keyword, or `null` if no keyword is configured. */ public static function getKeywordForTaskPriority($priority) { $map = self::getConfig(); $spec = idx($map, $priority); if (!$spec) { return null; } $keywords = idx($spec, 'keywords'); if (!$keywords) { return null; } return head($keywords); } /** * Get a map of supported alternate names for each priority. * * Keys are aliases, like "wish" and "wishlist". Values are canonical * priority keywords, like "wishlist". * * @return map Map of aliases to canonical priority keywords. */ public static function getTaskPriorityAliasMap() { $keyword_map = self::getTaskPriorityKeywordsMap(); $result = array(); foreach ($keyword_map as $key => $keywords) { $target = self::getKeywordForTaskPriority($key); if ($target === null) { continue; } // NOTE: Include the raw priority value, like "25", in the list of // aliases. This supports legacy sources like saved EditEngine forms. $result[$key] = $target; foreach ($keywords as $keyword) { $result[$keyword] = $target; } } return $result; } /** * Get the priorities and their related short (one-word) descriptions. * * @return map Priorities to short descriptions. */ public static function getShortNameMap() { $map = self::getConfig(); foreach ($map as $key => $spec) { $map[$key] = idx($spec, 'short', idx($spec, 'name', $key)); } return $map; } /** * Get a map from priority constants to their colors. * * @return map Priorities to colors. */ public static function getColorMap() { $map = self::getConfig(); foreach ($map as $key => $spec) { $map[$key] = idx($spec, 'color', 'grey'); } return $map; } /** * Return the default priority for this instance of Phabricator. * * @return int The value of the default priority constant. */ public static function getDefaultPriority() { return PhabricatorEnv::getEnvConfig('maniphest.default-priority'); } /** * Retrieve the full name of the priority level provided. * * @param int $priority A priority level. * @return string The priority name if the level is a valid one. */ public static function getTaskPriorityName($priority) { return idx(self::getTaskPriorityMap(), $priority, $priority); } /** * Retrieve the color of the priority level given * * @param int $priority A priority level. * @return string The color of the priority if the level is valid, * or black if it is not. */ public static function getTaskPriorityColor($priority) { return idx(self::getColorMap(), $priority, 'black'); } public static function getTaskPriorityIcon($priority) { 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); } public static function getConfig() { $config = PhabricatorEnv::getEnvConfig('maniphest.priorities'); krsort($config); 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( pht( 'Configuration is not valid. Maniphest priority configurations '. 'must be dictionaries.')); } $all_keywords = array(); foreach ($config as $key => $value) { if (!ctype_digit((string)$key)) { throw new Exception( pht( 'Key "%s" is not a valid priority constant. Priority constants '. 'must be nonnegative integers.', $key)); } if (!is_array($value)) { throw new Exception( pht( 'Value for key "%s" should be a dictionary.', $key)); } PhutilTypeSpec::checkMap( $value, array( 'name' => 'string', 'keywords' => 'list', 'short' => 'optional string', 'color' => 'optional 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')); } if (isset($all_keywords[$keyword])) { throw new Exception( pht( 'Two different task priorities ("%s" and "%s") have the same '. 'keyword ("%s"). Keywords must uniquely identify priorities.', $value['name'], $all_keywords[$keyword], $keyword)); } $all_keywords[$keyword] = $value['name']; } } } }