@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 243 lines 6.5 kB view raw
1<?php 2 3 4final class PhabricatorAuthContactNumber 5 extends PhabricatorAuthDAO 6 implements 7 PhabricatorApplicationTransactionInterface, 8 PhabricatorPolicyInterface, 9 PhabricatorDestructibleInterface, 10 PhabricatorEditEngineMFAInterface { 11 12 protected $objectPHID; 13 protected $contactNumber; 14 protected $uniqueKey; 15 protected $status; 16 protected $isPrimary; 17 protected $properties = array(); 18 19 const STATUS_ACTIVE = 'active'; 20 const STATUS_DISABLED = 'disabled'; 21 22 protected function getConfiguration() { 23 return array( 24 self::CONFIG_SERIALIZATION => array( 25 'properties' => self::SERIALIZATION_JSON, 26 ), 27 self::CONFIG_AUX_PHID => true, 28 self::CONFIG_COLUMN_SCHEMA => array( 29 'contactNumber' => 'text255', 30 'status' => 'text32', 31 'uniqueKey' => 'bytes12?', 32 'isPrimary' => 'bool', 33 ), 34 self::CONFIG_KEY_SCHEMA => array( 35 'key_object' => array( 36 'columns' => array('objectPHID'), 37 ), 38 'key_unique' => array( 39 'columns' => array('uniqueKey'), 40 'unique' => true, 41 ), 42 ), 43 ) + parent::getConfiguration(); 44 } 45 46 public static function initializeNewContactNumber($object) { 47 return id(new self()) 48 ->setStatus(self::STATUS_ACTIVE) 49 ->setObjectPHID($object->getPHID()) 50 ->setIsPrimary(0); 51 } 52 53 public function getPHIDType() { 54 return PhabricatorAuthContactNumberPHIDType::TYPECONST; 55 } 56 57 public function getURI() { 58 return urisprintf('/auth/contact/%s/', $this->getID()); 59 } 60 61 public function getObjectName() { 62 return pht('Contact Number %d', $this->getID()); 63 } 64 65 public function getDisplayName() { 66 return $this->getContactNumber(); 67 } 68 69 public function isDisabled() { 70 return ($this->getStatus() === self::STATUS_DISABLED); 71 } 72 73 public function newIconView() { 74 if ($this->isDisabled()) { 75 return id(new PHUIIconView()) 76 ->setIcon('fa-ban', 'grey') 77 ->setTooltip(pht('Disabled')); 78 } 79 80 if ($this->getIsPrimary()) { 81 return id(new PHUIIconView()) 82 ->setIcon('fa-certificate', 'blue') 83 ->setTooltip(pht('Primary Number')); 84 } 85 86 return id(new PHUIIconView()) 87 ->setIcon('fa-hashtag', 'bluegrey') 88 ->setTooltip(pht('Active Phone Number')); 89 } 90 91 public function newUniqueKey() { 92 $parts = array( 93 // This is future-proofing for a world where we have multiple types 94 // of contact numbers, so we might be able to avoid re-hashing 95 // everything. 96 'phone', 97 $this->getContactNumber(), 98 ); 99 100 $parts = implode("\0", $parts); 101 102 return PhabricatorHash::digestForIndex($parts); 103 } 104 105 public function save() { 106 // We require that active contact numbers be unique, but it's okay to 107 // disable a number and then reuse it somewhere else. 108 if ($this->isDisabled()) { 109 $this->uniqueKey = null; 110 } else { 111 $this->uniqueKey = $this->newUniqueKey(); 112 } 113 114 parent::save(); 115 116 return $this->updatePrimaryContactNumber(); 117 } 118 119 private function updatePrimaryContactNumber() { 120 // Update the "isPrimary" column so that at most one number is primary for 121 // each user, and no disabled number is primary. 122 123 $conn = $this->establishConnection('w'); 124 $this_id = (int)$this->getID(); 125 126 if ($this->getIsPrimary() && !$this->isDisabled()) { 127 // If we're trying to make this number primary and it's active, great: 128 // make this number the primary number. 129 $primary_id = $this_id; 130 } else { 131 // If we aren't trying to make this number primary or it is disabled, 132 // pick another number to make primary if we can. A number must be active 133 // to become primary. 134 135 // If there are multiple active numbers, pick the oldest one currently 136 // marked primary (usually, this should mean that we just keep the 137 // current primary number as primary). 138 139 // If none are marked primary, just pick the oldest one. 140 $primary_row = queryfx_one( 141 $conn, 142 'SELECT id FROM %R 143 WHERE objectPHID = %s AND status = %s 144 ORDER BY isPrimary DESC, id ASC 145 LIMIT 1', 146 $this, 147 $this->getObjectPHID(), 148 self::STATUS_ACTIVE); 149 if ($primary_row) { 150 $primary_id = (int)$primary_row['id']; 151 } else { 152 $primary_id = -1; 153 } 154 } 155 156 // Set the chosen number to primary, and all other numbers to nonprimary. 157 158 queryfx( 159 $conn, 160 'UPDATE %R SET isPrimary = IF(id = %d, 1, 0) 161 WHERE objectPHID = %s', 162 $this, 163 $primary_id, 164 $this->getObjectPHID()); 165 166 $this->setIsPrimary((int)($primary_id === $this_id)); 167 168 return $this; 169 } 170 171 public static function getStatusNameMap() { 172 return ipull(self::getStatusPropertyMap(), 'name'); 173 } 174 175 private static function getStatusPropertyMap() { 176 return array( 177 self::STATUS_ACTIVE => array( 178 'name' => pht('Active'), 179 ), 180 self::STATUS_DISABLED => array( 181 'name' => pht('Disabled'), 182 ), 183 ); 184 } 185 186 public function getSortVector() { 187 // Sort the primary number first, then active numbers, then disabled 188 // numbers. In each group, sort from oldest to newest. 189 return id(new PhutilSortVector()) 190 ->addInt($this->getIsPrimary() ? 0 : 1) 191 ->addInt($this->isDisabled() ? 1 : 0) 192 ->addInt($this->getID()); 193 } 194 195 196/* -( PhabricatorPolicyInterface )----------------------------------------- */ 197 198 199 public function getCapabilities() { 200 return array( 201 PhabricatorPolicyCapability::CAN_VIEW, 202 PhabricatorPolicyCapability::CAN_EDIT, 203 ); 204 } 205 206 public function getPolicy($capability) { 207 return $this->getObjectPHID(); 208 } 209 210 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 211 return false; 212 } 213 214 215/* -( PhabricatorDestructibleInterface )----------------------------------- */ 216 217 218 public function destroyObjectPermanently( 219 PhabricatorDestructionEngine $engine) { 220 $this->delete(); 221 } 222 223 224/* -( PhabricatorApplicationTransactionInterface )------------------------- */ 225 226 227 public function getApplicationTransactionEditor() { 228 return new PhabricatorAuthContactNumberEditor(); 229 } 230 231 public function getApplicationTransactionTemplate() { 232 return new PhabricatorAuthContactNumberTransaction(); 233 } 234 235 236/* -( PhabricatorEditEngineMFAInterface )---------------------------------- */ 237 238 239 public function newEditEngineMFAEngine() { 240 return new PhabricatorAuthContactNumberMFAEngine(); 241 } 242 243}