[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * @task validate Configuration Validation 5 */ 6 final class ManiphestTaskStatus extends ManiphestConstants { 7 8 const STATUS_OPEN = 'open'; 9 const STATUS_CLOSED_RESOLVED = 'resolved'; 10 const STATUS_CLOSED_WONTFIX = 'wontfix'; 11 const STATUS_CLOSED_INVALID = 'invalid'; 12 const STATUS_CLOSED_DUPLICATE = 'duplicate'; 13 const STATUS_CLOSED_SPITE = 'spite'; 14 15 const SPECIAL_DEFAULT = 'default'; 16 const SPECIAL_CLOSED = 'closed'; 17 const SPECIAL_DUPLICATE = 'duplicate'; 18 19 private static function getStatusConfig() { 20 return PhabricatorEnv::getEnvConfig('maniphest.statuses'); 21 } 22 23 private static function getEnabledStatusMap() { 24 $spec = self::getStatusConfig(); 25 26 $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); 27 foreach ($spec as $const => $status) { 28 if ($is_serious && !empty($status['silly'])) { 29 unset($spec[$const]); 30 continue; 31 } 32 } 33 34 return $spec; 35 } 36 37 public static function getTaskStatusMap() { 38 return ipull(self::getEnabledStatusMap(), 'name'); 39 } 40 41 public static function getTaskStatusName($status) { 42 return self::getStatusAttribute($status, 'name', pht('Unknown Status')); 43 } 44 45 public static function getTaskStatusFullName($status) { 46 $name = self::getStatusAttribute($status, 'name.full'); 47 if ($name !== null) { 48 return $name; 49 } 50 51 return self::getStatusAttribute($status, 'name', pht('Unknown Status')); 52 } 53 54 public static function renderFullDescription($status) { 55 if (self::isOpenStatus($status)) { 56 $color = 'status'; 57 $icon = 'fa-square-o bluegrey'; 58 } else { 59 $color = 'status-dark'; 60 $icon = 'fa-check-square-o'; 61 } 62 63 $img = id(new PHUIIconView()) 64 ->setIconFont($icon); 65 66 $tag = phutil_tag( 67 'span', 68 array( 69 'class' => 'phui-header-'.$color.' plr', 70 ), 71 array( 72 $img, 73 self::getTaskStatusFullName($status), 74 )); 75 76 return $tag; 77 } 78 79 private static function getSpecialStatus($special) { 80 foreach (self::getStatusConfig() as $const => $status) { 81 if (idx($status, 'special') == $special) { 82 return $const; 83 } 84 } 85 return null; 86 } 87 88 public static function getDefaultStatus() { 89 return self::getSpecialStatus(self::SPECIAL_DEFAULT); 90 } 91 92 public static function getDefaultClosedStatus() { 93 return self::getSpecialStatus(self::SPECIAL_CLOSED); 94 } 95 96 public static function getDuplicateStatus() { 97 return self::getSpecialStatus(self::SPECIAL_DUPLICATE); 98 } 99 100 public static function getOpenStatusConstants() { 101 $result = array(); 102 foreach (self::getEnabledStatusMap() as $const => $status) { 103 if (empty($status['closed'])) { 104 $result[] = $const; 105 } 106 } 107 return $result; 108 } 109 110 public static function getClosedStatusConstants() { 111 $all = array_keys(self::getTaskStatusMap()); 112 $open = self::getOpenStatusConstants(); 113 return array_diff($all, $open); 114 } 115 116 public static function isOpenStatus($status) { 117 foreach (self::getOpenStatusConstants() as $constant) { 118 if ($status == $constant) { 119 return true; 120 } 121 } 122 return false; 123 } 124 125 public static function isClosedStatus($status) { 126 return !self::isOpenStatus($status); 127 } 128 129 public static function getStatusActionName($status) { 130 return self::getStatusAttribute($status, 'name.action'); 131 } 132 133 public static function getStatusColor($status) { 134 return self::getStatusAttribute($status, 'transaction.color'); 135 } 136 137 public static function getStatusIcon($status) { 138 return self::getStatusAttribute($status, 'transaction.icon'); 139 } 140 141 public static function getStatusPrefixMap() { 142 $map = array(); 143 foreach (self::getEnabledStatusMap() as $const => $status) { 144 foreach (idx($status, 'prefixes', array()) as $prefix) { 145 $map[$prefix] = $const; 146 } 147 } 148 149 $map += array( 150 'ref' => null, 151 'refs' => null, 152 'references' => null, 153 'cf.' => null, 154 ); 155 156 return $map; 157 } 158 159 public static function getStatusSuffixMap() { 160 $map = array(); 161 foreach (self::getEnabledStatusMap() as $const => $status) { 162 foreach (idx($status, 'suffixes', array()) as $prefix) { 163 $map[$prefix] = $const; 164 } 165 } 166 return $map; 167 } 168 169 private static function getStatusAttribute($status, $key, $default = null) { 170 $config = self::getStatusConfig(); 171 172 $spec = idx($config, $status); 173 if ($spec) { 174 return idx($spec, $key, $default); 175 } 176 177 return $default; 178 } 179 180 181 /* -( Configuration Validation )------------------------------------------- */ 182 183 184 /** 185 * @task validate 186 */ 187 public static function isValidStatusConstant($constant) { 188 if (strlen($constant) > 12) { 189 return false; 190 } 191 if (!preg_match('/^[a-z0-9]+\z/', $constant)) { 192 return false; 193 } 194 return true; 195 } 196 197 198 /** 199 * @task validate 200 */ 201 public static function validateConfiguration(array $config) { 202 foreach ($config as $key => $value) { 203 if (!self::isValidStatusConstant($key)) { 204 throw new Exception( 205 pht( 206 'Key "%s" is not a valid status constant. Status constants must '. 207 'be 1-12 characters long and contain only lowercase letters (a-z) '. 208 'and digits (0-9). For example, "%s" or "%s" are reasonable '. 209 'choices.', 210 $key, 211 'open', 212 'closed')); 213 } 214 if (!is_array($value)) { 215 throw new Exception( 216 pht( 217 'Value for key "%s" should be a dictionary.', 218 $key)); 219 } 220 221 PhutilTypeSpec::checkMap( 222 $value, 223 array( 224 'name' => 'string', 225 'name.full' => 'optional string', 226 'name.action' => 'optional string', 227 'closed' => 'optional bool', 228 'special' => 'optional string', 229 'transaction.icon' => 'optional string', 230 'transaction.color' => 'optional string', 231 'silly' => 'optional bool', 232 'prefixes' => 'optional list<string>', 233 'suffixes' => 'optional list<string>', 234 )); 235 } 236 237 $special_map = array(); 238 foreach ($config as $key => $value) { 239 $special = idx($value, 'special'); 240 if (!$special) { 241 continue; 242 } 243 244 if (isset($special_map[$special])) { 245 throw new Exception( 246 pht( 247 'Configuration has two statuses both marked with the special '. 248 'attribute "%s" ("%s" and "%s"). There should be only one.', 249 $special, 250 $special_map[$special], 251 $key)); 252 } 253 254 switch ($special) { 255 case self::SPECIAL_DEFAULT: 256 if (!empty($value['closed'])) { 257 throw new Exception( 258 pht( 259 'Status "%s" is marked as default, but it is a closed '. 260 'status. The default status should be an open status.', 261 $key)); 262 } 263 break; 264 case self::SPECIAL_CLOSED: 265 if (empty($value['closed'])) { 266 throw new Exception( 267 pht( 268 'Status "%s" is marked as the default status for closing '. 269 'tasks, but is not a closed status. It should be a closed '. 270 'status.', 271 $key)); 272 } 273 break; 274 case self::SPECIAL_DUPLICATE: 275 if (empty($value['closed'])) { 276 throw new Exception( 277 pht( 278 'Status "%s" is marked as the status for closing tasks as '. 279 'duplicates, but it is not a closed status. It should '. 280 'be a closed status.', 281 $key)); 282 } 283 break; 284 } 285 286 $special_map[$special] = $key; 287 } 288 289 // NOTE: We're not explicitly validating that we have at least one open 290 // and one closed status, because the DEFAULT and CLOSED specials imply 291 // that to be true. If those change in the future, that might become a 292 // reasonable thing to validate. 293 294 $required = array( 295 self::SPECIAL_DEFAULT, 296 self::SPECIAL_CLOSED, 297 self::SPECIAL_DUPLICATE, 298 ); 299 300 foreach ($required as $required_special) { 301 if (!isset($special_map[$required_special])) { 302 throw new Exception( 303 pht( 304 'Configuration defines no task status with special attribute '. 305 '"%s", but you must specify a status which fills this special '. 306 'role.', 307 $required_special)); 308 } 309 } 310 } 311 312 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |