@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at recaptime-dev/main 210 lines 5.9 kB view raw
1<?php 2 3final class PhabricatorAuthInviteAction extends Phobject { 4 5 private $rawInput; 6 private $emailAddress; 7 private $userPHID; 8 private $issues = array(); 9 private $action; 10 11 const ACTION_SEND = 'invite.send'; 12 const ACTION_ERROR = 'invite.error'; 13 const ACTION_IGNORE = 'invite.ignore'; 14 15 const ISSUE_PARSE = 'invite.parse'; 16 const ISSUE_DUPLICATE = 'invite.duplicate'; 17 const ISSUE_UNVERIFIED = 'invite.unverified'; 18 const ISSUE_VERIFIED = 'invite.verified'; 19 const ISSUE_INVITED = 'invite.invited'; 20 const ISSUE_ACCEPTED = 'invite.accepted'; 21 22 public function getRawInput() { 23 return $this->rawInput; 24 } 25 26 public function getEmailAddress() { 27 return $this->emailAddress; 28 } 29 30 public function getUserPHID() { 31 return $this->userPHID; 32 } 33 34 public function getIssues() { 35 return $this->issues; 36 } 37 38 public function setAction($action) { 39 $this->action = $action; 40 return $this; 41 } 42 43 public function getAction() { 44 return $this->action; 45 } 46 47 public function willSend() { 48 return ($this->action == self::ACTION_SEND); 49 } 50 51 public function getShortNameForIssue($issue) { 52 $map = array( 53 self::ISSUE_PARSE => pht('Not a Valid Email Address'), 54 self::ISSUE_DUPLICATE => pht('Address Duplicated in Input'), 55 self::ISSUE_UNVERIFIED => pht('Unverified User Email'), 56 self::ISSUE_VERIFIED => pht('Verified User Email'), 57 self::ISSUE_INVITED => pht('Previously Invited'), 58 self::ISSUE_ACCEPTED => pht('Already Accepted Invite'), 59 ); 60 61 return idx($map, $issue); 62 } 63 64 public function getShortNameForAction($action) { 65 $map = array( 66 self::ACTION_SEND => pht('Will Send Invite'), 67 self::ACTION_ERROR => pht('Address Error'), 68 self::ACTION_IGNORE => pht('Will Ignore Address'), 69 ); 70 71 return idx($map, $action); 72 } 73 74 public function getIconForAction($action) { 75 switch ($action) { 76 case self::ACTION_SEND: 77 $icon = 'fa-envelope-o'; 78 $color = 'green'; 79 break; 80 case self::ACTION_IGNORE: 81 $icon = 'fa-ban'; 82 $color = 'grey'; 83 break; 84 case self::ACTION_ERROR: 85 $icon = 'fa-exclamation-triangle'; 86 $color = 'red'; 87 break; 88 } 89 90 return id(new PHUIIconView()) 91 ->setIcon("{$icon} {$color}"); 92 } 93 94 public static function newActionListFromAddresses( 95 PhabricatorUser $viewer, 96 array $addresses) { 97 98 $results = array(); 99 foreach ($addresses as $address) { 100 $result = new PhabricatorAuthInviteAction(); 101 $result->rawInput = $address; 102 103 $email = new PhutilEmailAddress($address); 104 $result->emailAddress = phutil_utf8_strtolower($email->getAddress()); 105 106 if (!preg_match('/^\S+@\S+\.\S+\z/', $result->emailAddress)) { 107 $result->issues[] = self::ISSUE_PARSE; 108 } 109 110 $results[] = $result; 111 } 112 113 // Identify duplicates. 114 $address_groups = mgroup($results, 'getEmailAddress'); 115 foreach ($address_groups as $address => $group) { 116 if (count($group) > 1) { 117 foreach ($group as $action) { 118 $action->issues[] = self::ISSUE_DUPLICATE; 119 } 120 } 121 } 122 123 // Identify addresses which are already in the system. 124 $addresses = mpull($results, 'getEmailAddress'); 125 $email_objects = id(new PhabricatorUserEmail())->loadAllWhere( 126 'address IN (%Ls)', 127 $addresses); 128 129 $email_map = array(); 130 foreach ($email_objects as $email_object) { 131 $address_key = phutil_utf8_strtolower($email_object->getAddress()); 132 $email_map[$address_key] = $email_object; 133 } 134 135 // Identify outstanding invites. 136 $invites = id(new PhabricatorAuthInviteQuery()) 137 ->setViewer($viewer) 138 ->withEmailAddresses($addresses) 139 ->execute(); 140 $invite_map = mpull($invites, null, 'getEmailAddress'); 141 142 foreach ($results as $action) { 143 $email = idx($email_map, $action->getEmailAddress()); 144 if ($email) { 145 if ($email->getUserPHID()) { 146 $action->userPHID = $email->getUserPHID(); 147 if ($email->getIsVerified()) { 148 $action->issues[] = self::ISSUE_VERIFIED; 149 } else { 150 $action->issues[] = self::ISSUE_UNVERIFIED; 151 } 152 } 153 } 154 155 $invite = idx($invite_map, $action->getEmailAddress()); 156 if ($invite) { 157 if ($invite->getAcceptedByPHID()) { 158 $action->issues[] = self::ISSUE_ACCEPTED; 159 if (!$action->userPHID) { 160 // This could be different from the user who is currently attached 161 // to the email address if the address was removed or added to a 162 // different account later. Only show it if the address was 163 // removed, since the current status is more up-to-date otherwise. 164 $action->userPHID = $invite->getAcceptedByPHID(); 165 } 166 } else { 167 $action->issues[] = self::ISSUE_INVITED; 168 } 169 } 170 } 171 172 foreach ($results as $result) { 173 foreach ($result->getIssues() as $issue) { 174 switch ($issue) { 175 case self::ISSUE_PARSE: 176 $result->action = self::ACTION_ERROR; 177 break; 178 case self::ISSUE_ACCEPTED: 179 case self::ISSUE_VERIFIED: 180 $result->action = self::ACTION_IGNORE; 181 break; 182 } 183 } 184 if (!$result->action) { 185 $result->action = self::ACTION_SEND; 186 } 187 } 188 189 return $results; 190 } 191 192 public function sendInvite(PhabricatorUser $actor, $template) { 193 if (!$this->willSend()) { 194 throw new Exception(pht('Invite action is not a send action!')); 195 } 196 197 if (!preg_match('/{\$INVITE_URI}/', $template)) { 198 throw new Exception(pht('Invite template does not include invite URI!')); 199 } 200 201 PhabricatorWorker::scheduleTask( 202 'PhabricatorAuthInviteWorker', 203 array( 204 'address' => $this->getEmailAddress(), 205 'template' => $template, 206 'authorPHID' => $actor->getPHID(), 207 )); 208 } 209 210}