table = $db->prefix . 'us_group_access'; } public function insert( GroupAccess $access ): int { $this->db->insert( $this->table, [ 'offering_id' => $access->offeringId, 'student_id' => $access->studentId, 'email' => $access->email, 'invite_id' => $access->inviteId, 'status' => $access->status, 'invited_by' => $access->invitedBy, 'created_at' => current_time( 'mysql' ), ], [ '%d', '%d', '%s', '%d', '%s', '%d', '%s' ] ); return $this->db->insert_id; } /** * Whether a student holds a live (invited or enrolled) grant for an offering. */ public function hasGrant( int $offeringId, int $studentId ): bool { $count = (int) $this->db->get_var( $this->db->prepare( 'SELECT COUNT(*) FROM %i WHERE offering_id = %d AND student_id = %d AND status IN ( %s, %s )', $this->table, $offeringId, $studentId, GroupAccess::STATUS_INVITED, GroupAccess::STATUS_ENROLLED ) ); return $count > 0; } /** * The offering ids a student holds a live grant for — the invite-only classes * to fold into their catalogue view. * * @return list */ public function findGrantedOfferingIds( int $studentId ): array { $rows = $this->db->get_col( $this->db->prepare( 'SELECT DISTINCT offering_id FROM %i WHERE student_id = %d AND status IN ( %s, %s )', $this->table, $studentId, GroupAccess::STATUS_INVITED, GroupAccess::STATUS_ENROLLED ) ); return array_values( array_map( \Unsupervised\Schedular\Val::int( ... ), $rows ) ); } /** * All grants for an offering, newest first. * * @return list */ public function findByOffering( int $offeringId ): array { $rows = $this->db->get_results( $this->db->prepare( 'SELECT * FROM %i WHERE offering_id = %d ORDER BY id DESC', $this->table, $offeringId ) ); return array_map( GroupAccess::fromRow( ... ), $rows ?? [] ); } /** * Point email-invite grants for an address at the account created when the * invitation was accepted, so the granted class unlocks for the new student. * Only grants still awaiting an account (`student_id` NULL) are linked. */ public function linkStudentByEmail( string $email, int $studentId ): bool { if ( '' === $email ) { return false; } $sql = $this->db->prepare( 'UPDATE %i SET student_id = %d WHERE email = %s AND student_id IS NULL', $this->table, $studentId, $email ); return null !== $sql && false !== $this->db->query( $sql ); } /** * Flip a student's live grant for an offering to enrolled. */ public function markEnrolled( int $offeringId, int $studentId ): bool { return false !== $this->db->update( $this->table, [ 'status' => GroupAccess::STATUS_ENROLLED ], [ 'offering_id' => $offeringId, 'student_id' => $studentId, ], [ '%s' ], [ '%d', '%d' ] ); } public function revoke( int $id ): bool { return false !== $this->db->update( $this->table, [ 'status' => GroupAccess::STATUS_REVOKED ], [ 'id' => $id ], [ '%s' ], [ '%d' ] ); } }