3 abstract class PhabricatorManagementWorkflow
extends PhutilArgumentWorkflow
{
5 public function isExecutable() {
9 public function getViewer() {
10 // Some day, we might provide a more general viewer mechanism to scripts.
11 // For now, workflows can call this method for convenience and future
13 return PhabricatorUser
::getOmnipotentUser();
16 protected function parseTimeArgument($time) {
21 $epoch = strtotime($time);
23 throw new PhutilArgumentUsageException(
24 pht('Unable to parse time "%s".', $time));
29 protected function newContentSource() {
30 return PhabricatorContentSource
::newForSource(
31 PhabricatorConsoleContentSource
::SOURCECONST
);
34 protected function logInfo($label, $message) {
37 "**<bg:blue> %s </bg>** %s\n",
42 protected function logOkay($label, $message) {
45 "**<bg:green> %s </bg>** %s\n",
50 protected function logWarn($label, $message) {
53 "**<bg:yellow> %s </bg>** %s\n",
58 protected function logFail($label, $message) {
61 "**<bg:red> %s </bg>** %s\n",
66 private function logRaw($message) {
67 fprintf(STDERR
, '%s', $message);
70 final protected function loadUsersFromArguments(array $identifiers) {
79 $user_type = PhabricatorPeopleUserPHIDType
::TYPECONST
;
81 foreach ($identifiers as $identifier) {
82 // If the value is a user PHID, treat as a PHID.
83 if (phid_get_type($identifier) === $user_type) {
84 $phids[$identifier] = $identifier;
88 // If the value is "@..." and then some text, treat it as a username.
89 if ((strlen($identifier) > 1) && ($identifier[0] == '@')) {
90 $usernames[$identifier] = substr($identifier, 1);
94 // If the value is digits, treat it as both an ID and a username.
95 // Entirely numeric usernames, like "1234", are valid.
96 if (ctype_digit($identifier)) {
97 $ids[$identifier] = $identifier;
98 $usernames[$identifier] = $identifier;
102 // Otherwise, treat it as an unescaped username.
103 $usernames[$identifier] = $identifier;
106 $viewer = $this->getViewer();
110 $users = id(new PhabricatorPeopleQuery())
114 foreach ($users as $user) {
115 $phid = $user->getPHID();
116 $results[$phid][] = $user;
121 $users = id(new PhabricatorPeopleQuery())
123 ->withUsernames($usernames)
126 $reverse_map = array();
127 foreach ($usernames as $identifier => $username) {
128 $username = phutil_utf8_strtolower($username);
129 $reverse_map[$username][] = $identifier;
132 foreach ($users as $user) {
133 $username = $user->getUsername();
134 $username = phutil_utf8_strtolower($username);
136 $reverse_identifiers = idx($reverse_map, $username, array());
138 if (count($reverse_identifiers) > 1) {
139 throw new PhutilArgumentUsageException(
141 'Multiple user identifiers (%s) correspond to the same user. '.
142 'Identify each user exactly once.',
143 implode(', ', $reverse_identifiers)));
146 foreach ($reverse_identifiers as $reverse_identifier) {
147 $results[$reverse_identifier][] = $user;
153 $users = id(new PhabricatorPeopleQuery())
158 foreach ($users as $user) {
159 $id = $user->getID();
160 $results[$id][] = $user;
165 foreach ($identifiers as $identifier) {
166 $users = idx($results, $identifier, array());
168 throw new PhutilArgumentUsageException(
170 'No user "%s" exists. Specify users by username, ID, or PHID.',
174 if (count($users) > 1) {
175 // This can happen if you have a user "@25", a user with ID 25, and
176 // specify "--user 25". You can disambiguate this by specifying
178 throw new PhutilArgumentUsageException(
180 'Identifier "%s" matches multiple users. Specify each user '.
181 'unambiguously with "@username" or by using user PHIDs.',
185 $list[] = head($users);