prefix . 'aieo_role_log'; } public static function register() { add_action( 'add_user_role', array( __CLASS__, 'on_add' ), 10, 2 ); add_action( 'remove_user_role', array( __CLASS__, 'on_remove' ), 10, 2 ); add_action( 'deleted_user', array( __CLASS__, 'forget' ) ); add_action( 'admin_init', array( __CLASS__, 'install' ), 5 ); } public static function install() { if ( ! function_exists( 'aieo_install_schema_once' ) ) { return; } aieo_install_schema_once( self::SCHEMA_OPTION, self::SCHEMA_VERSION, static function () { global $wpdb; $table = self::table(); $collate = function_exists( 'aieo_get_charset_collate' ) ? aieo_get_charset_collate() : $wpdb->get_charset_collate(); return false !== $wpdb->query( "CREATE TABLE IF NOT EXISTS {$table} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, role varchar(191) NOT NULL DEFAULT '', action varchar(8) NOT NULL DEFAULT '', actor_id bigint(20) unsigned NOT NULL DEFAULT 0, source varchar(32) NOT NULL DEFAULT '', created_at datetime NOT NULL, PRIMARY KEY (id), KEY idx_user (user_id, id) ) {$collate}" ); } ); } private static function ready() { return (int) get_option( self::SCHEMA_OPTION, 0 ) >= self::SCHEMA_VERSION; } private static function record( $user_id, $role, $action ) { if ( (int) $user_id <= 0 || '' === (string) $role || ! self::ready() ) { return; } global $wpdb; $wpdb->insert( self::table(), array( 'user_id' => (int) $user_id, 'role' => (string) $role, 'action' => (string) $action, 'actor_id' => get_current_user_id(), 'source' => class_exists( 'AIEO_Safe_Roles' ) ? (string) AIEO_Safe_Roles::$source : '', 'created_at' => gmdate( 'Y-m-d H:i:s' ), ), array( '%d', '%s', '%s', '%d', '%s', '%s' ) ); } public static function on_add( $user_id, $role ) { self::record( (int) $user_id, (string) $role, 'add' ); } public static function on_remove( $user_id, $role ) { self::record( (int) $user_id, (string) $role, 'remove' ); } public static function forget( $user_id ) { if ( ! self::ready() ) { return; } global $wpdb; $wpdb->delete( self::table(), array( 'user_id' => (int) $user_id ), array( '%d' ) ); } public static function history( $user_id, $limit = 20 ) { if ( ! self::ready() ) { return array(); } global $wpdb; $rows = (array) $wpdb->get_results( $wpdb->prepare( 'SELECT role, action, actor_id, source, created_at FROM %i WHERE user_id = %d ORDER BY id DESC LIMIT %d', self::table(), (int) $user_id, max( 1, (int) $limit ) ), ARRAY_A ); foreach ( $rows as $i => $row ) { $rows[ $i ]['actor_id'] = (int) $row['actor_id']; } return $rows; } public static function source_label( $source ) { $labels = array( 'manual' => __( 'the Roles screen', 'ai-eshop-optimizer' ), 'profile' => __( 'the account’s profile', 'ai-eshop-optimizer' ), 'bulk' => __( 'the Users list', 'ai-eshop-optimizer' ), 'signup' => __( 'an approved application', 'ai-eshop-optimizer' ), 'loyalty' => __( 'the Bonus card’s Join', 'ai-eshop-optimizer' ), 'gravity_forms' => __( 'a Gravity Forms form', 'ai-eshop-optimizer' ), 'workflow' => __( 'a workflow', 'ai-eshop-optimizer' ), ); return $labels[ (string) $source ] ?? __( 'another plugin or WordPress', 'ai-eshop-optimizer' ); } }