33Q: What is going on with the regex for email validation in
44 validate::validate_row()?
55A: The regex is intending to match an email address as
6+ 1. An empty string. Obviously not a real email address, but we are allowing
7+ enrollments in the database with "inactive" or "pending" email addresses.
8+ -- OR --
69 1. Address recipient may not contain characters (),:;<>@\"[]
710 2. Address recipient may not start or end with characters !#$%'*+-/=?^_`{|
811 3. Address recipient and hostname must be delimited with @ character
1316 8. The entire email address is case insensitive
1417
1518 Peter Bailie, Oct 29 2021
19+ Last Updated May 12, 2022 by Peter Bailie
1620----------------------------------------------------------------------------- */
1721
1822namespace ssaf ;
@@ -48,24 +52,24 @@ public static function validate_row($row, $row_num) : bool {
4852 case is_null (EXPECTED_TERM_CODE ) ? true : $ row [COLUMN_TERM_CODE ] === EXPECTED_TERM_CODE :
4953 self ::$ error = "Row {$ row_num } failed validation for unexpected term code \"{$ row [COLUMN_TERM_CODE ]}\". " ;
5054 return false ;
51- // User ID must contain only lowercase alpha, numbers, underscore, and hyphen
52- case boolval (preg_match ("/^[a-z0-9_\-]+$/ " , $ row [COLUMN_USER_ID ])):
55+ // User ID must contain only alpha characters , numbers, underscore, hyphen, and period.
56+ case boolval (preg_match ("/^[a-z0-9_\-\. ]+$/i " , $ row [COLUMN_USER_ID ])):
5357 self ::$ error = "Row {$ row_num } failed user ID validation \"{$ row [COLUMN_USER_ID ]}\". " ;
5458 return false ;
5559 // First name must be alpha characters, white-space, or certain punctuation.
56- case boolval (preg_match ("/^[a-zA-Z '`\-\. ]+$/ " , $ row [COLUMN_FIRSTNAME ])):
60+ case boolval (preg_match ("/^[a-z '`\-\. ]+$/i " , $ row [COLUMN_FIRSTNAME ])):
5761 self ::$ error = "Row {$ row_num } failed validation for student first name \"{$ row [COLUMN_FIRSTNAME ]}\". " ;
5862 return false ;
5963 // Last name must be alpha characters, white-space, or certain punctuation.
60- case boolval (preg_match ("/^[a-zA-Z '`\-\. ]+$/ " , $ row [COLUMN_LASTNAME ])):
64+ case boolval (preg_match ("/^[a-z '`\-\. ]+$/i " , $ row [COLUMN_LASTNAME ])):
6165 self ::$ error = "Row {$ row_num } failed validation for student last name \"{$ row [COLUMN_LASTNAME ]}\". " ;
6266 return false ;
6367 // Student registration section must be alphanumeric, '_', or '-'.
64- case boolval (preg_match ("/^[a-zA-Z0- 9_\-]+$/ " , $ row [COLUMN_SECTION ])):
68+ case boolval (preg_match ("/^[a-z0- 9_\-]+$/i " , $ row [COLUMN_SECTION ])):
6569 self ::$ error = "Row {$ row_num } failed validation for student section \"{$ row [COLUMN_SECTION ]}\". " ;
6670 return false ;
67- // Check email address is properly formed.
68- case boolval (preg_match ("/^(?![!#$%'*+\-\/=?^_`{|])[^(),:;<>@ \\\"\[\]]+(?<![!#$%'*+\-\/=?^_`{|])@(?:(?!\-)[a-z0-9\-]+(?<!\-)\.)+[a-z]{2,}$/i " , $ row [COLUMN_EMAIL ])):
71+ // Check email address is properly formed. Blank email addresses are also accepted.
72+ case boolval (preg_match ("/^$|^ (?![!#$%'*+\-\/=?^_`{|])[^(),:;<>@ \\\"\[\]]+(?<![!#$%'*+\-\/=?^_`{|])@(?:(?!\-)[a-z0-9\-]+(?<!\-)\.)+[a-z]{2,}$/i " , $ row [COLUMN_EMAIL ])):
6973 self ::$ error = "Row {$ row_num } failed validation for student email \"{$ row [COLUMN_EMAIL ]}\". " ;
7074 return false ;
7175 }
@@ -85,24 +89,34 @@ public static function validate_row($row, $row_num) : bool {
8589 * False, as in error found, otherwise. $user_ids is filled when return
8690 * is FALSE.
8791 *
88- * @param array $rows Data rows to check (presumably an entire couse)
89- * @param string[] &$user_id Duplicated user ID, when found
92+ * @param array $rows Data rows to check (presumably an entire couse).
93+ * @param string[] &$user_id Duplicated user ID, when found.
94+ * @param string[] &$d_rows Rows containing duplicate user IDs, indexed by user ID.
9095 * @return bool TRUE when all user IDs are unique, FALSE otherwise.
9196 */
92- public static function check_for_duplicate_user_ids (array $ rows , &$ user_ids ) : bool {
97+ public static function check_for_duplicate_user_ids (array $ rows , &$ user_ids, & $ d_rows ) : bool {
9398 usort ($ rows , function ($ a , $ b ) { return $ a [COLUMN_USER_ID ] <=> $ b [COLUMN_USER_ID ]; });
9499
95100 $ user_ids = array ();
101+ $ d_rows = array ();
96102 $ are_all_unique = true ; // Unless proven FALSE
97103 $ length = count ($ rows );
98104 for ($ i = 1 ; $ i < $ length ; $ i ++) {
99105 $ j = $ i - 1 ;
100106 if ($ rows [$ i ][COLUMN_USER_ID ] === $ rows [$ j ][COLUMN_USER_ID ]) {
101107 $ are_all_unique = false ;
102- $ user_ids [] = $ rows [$ i ][COLUMN_USER_ID ];
108+ $ user_id = $ rows [$ i ][COLUMN_USER_ID ];
109+ $ user_ids [] = $ user_id ;
110+ $ d_rows [$ user_id ][] = $ j ;
111+ $ d_rows [$ user_id ][] = $ i ;
103112 }
104113 }
105114
115+ foreach ($ d_rows as &$ d_row ) {
116+ array_unique ($ d_row , SORT_REGULAR );
117+ }
118+ unset($ d_row );
119+
106120 return $ are_all_unique ;
107121 }
108122
0 commit comments