@@ -12,6 +12,7 @@ final class PhabricatorAuthContactNumber
12
12
protected $ contactNumber ;
13
13
protected $ uniqueKey ;
14
14
protected $ status ;
15
+ protected $ isPrimary ;
15
16
protected $ properties = array ();
16
17
17
18
const STATUS_ACTIVE = 'active ' ;
@@ -27,6 +28,7 @@ protected function getConfiguration() {
27
28
'contactNumber ' => 'text255 ' ,
28
29
'status ' => 'text32 ' ,
29
30
'uniqueKey ' => 'bytes12? ' ,
31
+ 'isPrimary ' => 'bool ' ,
30
32
),
31
33
self ::CONFIG_KEY_SCHEMA => array (
32
34
'key_object ' => array (
@@ -43,7 +45,8 @@ protected function getConfiguration() {
43
45
public static function initializeNewContactNumber ($ object ) {
44
46
return id (new self ())
45
47
->setStatus (self ::STATUS_ACTIVE )
46
- ->setObjectPHID ($ object ->getPHID ());
48
+ ->setObjectPHID ($ object ->getPHID ())
49
+ ->setIsPrimary (0 );
47
50
}
48
51
49
52
public function getPHIDType () {
@@ -73,8 +76,14 @@ public function newIconView() {
73
76
->setTooltip (pht ('Disabled ' ));
74
77
}
75
78
79
+ if ($ this ->getIsPrimary ()) {
80
+ return id (new PHUIIconView ())
81
+ ->setIcon ('fa-certificate ' , 'blue ' )
82
+ ->setTooltip (pht ('Primary Number ' ));
83
+ }
84
+
76
85
return id (new PHUIIconView ())
77
- ->setIcon ('fa-mobile ' , 'green ' )
86
+ ->setIcon ('fa-hashtag ' , 'bluegrey ' )
78
87
->setTooltip (pht ('Active Phone Number ' ));
79
88
}
80
89
@@ -101,7 +110,61 @@ public function save() {
101
110
$ this ->uniqueKey = $ this ->newUniqueKey ();
102
111
}
103
112
104
- return parent ::save ();
113
+ parent ::save ();
114
+
115
+ return $ this ->updatePrimaryContactNumber ();
116
+ }
117
+
118
+ private function updatePrimaryContactNumber () {
119
+ // Update the "isPrimary" column so that at most one number is primary for
120
+ // each user, and no disabled number is primary.
121
+
122
+ $ conn = $ this ->establishConnection ('w ' );
123
+ $ this_id = (int )$ this ->getID ();
124
+
125
+ if ($ this ->getIsPrimary () && !$ this ->isDisabled ()) {
126
+ // If we're trying to make this number primary and it's active, great:
127
+ // make this number the primary number.
128
+ $ primary_id = $ this_id ;
129
+ } else {
130
+ // If we aren't trying to make this number primary or it is disabled,
131
+ // pick another number to make primary if we can. A number must be active
132
+ // to become primary.
133
+
134
+ // If there are multiple active numbers, pick the oldest one currently
135
+ // marked primary (usually, this should mean that we just keep the
136
+ // current primary number as primary).
137
+
138
+ // If none are marked primary, just pick the oldest one.
139
+ $ primary_row = queryfx_one (
140
+ $ conn ,
141
+ 'SELECT id FROM %R
142
+ WHERE objectPHID = %s AND status = %s
143
+ ORDER BY isPrimary DESC, id ASC
144
+ LIMIT 1 ' ,
145
+ $ this ,
146
+ $ this ->getObjectPHID (),
147
+ self ::STATUS_ACTIVE );
148
+ if ($ primary_row ) {
149
+ $ primary_id = (int )$ primary_row ['id ' ];
150
+ } else {
151
+ $ primary_id = -1 ;
152
+ }
153
+ }
154
+
155
+ // Set the chosen number to primary, and all other numbers to nonprimary.
156
+
157
+ queryfx (
158
+ $ conn ,
159
+ 'UPDATE %R SET isPrimary = IF(id = %d, 1, 0)
160
+ WHERE objectPHID = %s ' ,
161
+ $ this ,
162
+ $ primary_id ,
163
+ $ this ->getObjectPHID ());
164
+
165
+ $ this ->setIsPrimary ((int )($ primary_id === $ this_id ));
166
+
167
+ return $ this ;
105
168
}
106
169
107
170
public static function getStatusNameMap () {
@@ -119,6 +182,15 @@ private static function getStatusPropertyMap() {
119
182
);
120
183
}
121
184
185
+ public function getSortVector () {
186
+ // Sort the primary number first, then active numbers, then disabled
187
+ // numbers. In each group, sort from oldest to newest.
188
+ return id (new PhutilSortVector ())
189
+ ->addInt ($ this ->getIsPrimary () ? 0 : 1 )
190
+ ->addInt ($ this ->isDisabled () ? 1 : 0 )
191
+ ->addInt ($ this ->getID ());
192
+ }
193
+
122
194
123
195
/* -( PhabricatorPolicyInterface )----------------------------------------- */
124
196
0 commit comments