prefix . 'kdocs_' . $name; } /** * Event types accepted on this site. * * @return string[] */ public static function types() { return Features::is_pro() ? array_merge( self::FREE_TYPES, self::PRO_TYPES ) : self::FREE_TYPES; } /** * Writes events. * * @param array[] $events Events: type, kb_id, article_id, session, search_id, label, n1, n2, ref. * @return int Number written. */ public static function insert( array $events ) { global $wpdb; if ( ! $events ) { return 0; } $now = current_time( 'mysql' ); $day = substr( $now, 0, 10 ); $visitor = Identity::visitor(); $device = Identity::device(); $country = Identity::country(); $member = Identity::member(); $rows = array(); $values = array(); foreach ( $events as $event ) { $rows[] = '(%s,%s,%s,%d,%d,%s,%s,%s,%s,%d,%d,%s,%s,%s,%s)'; array_push( $values, $now, $day, $event['type'], (int) ( $event['kb_id'] ?? 0 ), (int) ( $event['article_id'] ?? 0 ), $visitor, (string) ( $event['session'] ?? '' ), (string) ( $event['search_id'] ?? '' ), mb_substr( (string) ( $event['label'] ?? '' ), 0, 191 ), (int) ( $event['n1'] ?? 0 ), (int) ( $event['n2'] ?? 0 ), $device, (string) ( $event['ref'] ?? '' ), $country, $member ); } $table = esc_sql( self::table( 'events' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare,PluginCheck.Security.DirectDB.UnescapedDBParameter -- Placeholders are built above. $done = $wpdb->query( $wpdb->prepare( "INSERT INTO {$table} (ts, day, type, kb_id, article_id, visitor, session, search_id, label, n1, n2, device, ref, country, member) VALUES " . implode( ',', $rows ), $values ) ); return (int) $done; } /** * Writes one server-side event (feedback, AI questions) for the current reader. * * @param string $type Type. * @param array $event Fields (see insert()). */ public static function log( $type, array $event = array() ) { if ( ! in_array( $type, self::types(), true ) || ! Identity::countable() ) { return; } $event['type'] = $type; self::insert( array( $event ) ); } }