Fixed search and updated collations of various fields to more appropriate ones.

This commit is contained in:
flash 2023-08-03 12:40:30 +00:00
parent 9dd7156c79
commit b7de5acfd8
6 changed files with 212 additions and 37 deletions

View file

@ -0,0 +1,162 @@
<?php
use Index\Data\IDbConnection;
use Index\Data\Migration\IDbMigration;
final class UpdateCollationsInVariousTables_20230803_114403 implements IDbMigration {
public function migrate(IDbConnection $conn): void {
$conn->execute('
ALTER TABLE msz_audit_log
CHANGE COLUMN log_action log_action VARCHAR(50) NOT NULL COLLATE "ascii_general_ci" AFTER user_id,
CHANGE COLUMN log_country log_country CHAR(2) NOT NULL DEFAULT "XX" COLLATE "ascii_general_ci" AFTER log_ip;
');
$conn->execute('
ALTER TABLE msz_auth_tfa
CHANGE COLUMN tfa_token tfa_token CHAR(32) NOT NULL COLLATE "ascii_bin" AFTER user_id;
');
$conn->execute('
ALTER TABLE msz_changelog_changes
CHANGE COLUMN change_log change_log VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER change_created,
CHANGE COLUMN change_text change_text TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER change_log;
');
$conn->execute('
ALTER TABLE msz_changelog_tags
CHANGE COLUMN tag_name tag_name VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER tag_id,
CHANGE COLUMN tag_description tag_description TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER tag_name;
');
$conn->execute('
ALTER TABLE msz_comments_categories
CHANGE COLUMN category_name category_name VARCHAR(255) NOT NULL COLLATE "ascii_bin" AFTER category_id;
');
$conn->execute('
ALTER TABLE msz_comments_posts
CHANGE COLUMN comment_text comment_text TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER comment_reply_to;
');
$conn->execute('
ALTER TABLE msz_config
CHANGE COLUMN config_name config_name VARCHAR(100) NOT NULL COLLATE "ascii_general_ci" FIRST;
');
$conn->execute('
ALTER TABLE msz_emoticons
CHANGE COLUMN emote_url emote_url VARCHAR(255) NOT NULL COLLATE "ascii_bin" AFTER emote_hierarchy;
');
$conn->execute('
ALTER TABLE msz_emoticons_strings
CHANGE COLUMN emote_string emote_string VARCHAR(50) NOT NULL COLLATE "ascii_general_ci" AFTER emote_string_order;
');
$conn->execute('
ALTER TABLE msz_forum_categories
CHANGE COLUMN forum_name forum_name VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER forum_parent,
CHANGE COLUMN forum_description forum_description TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER forum_type,
CHANGE COLUMN forum_icon forum_icon VARCHAR(50) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER forum_description,
CHANGE COLUMN forum_link forum_link VARCHAR(255) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER forum_colour;
');
$conn->execute('
ALTER TABLE msz_forum_posts
CHANGE COLUMN post_text post_text MEDIUMTEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER post_ip;
');
$conn->execute('
ALTER TABLE msz_forum_topics
CHANGE COLUMN topic_title topic_title VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER topic_type;
');
$conn->execute('
ALTER TABLE msz_forum_topics_redirects
CHANGE COLUMN topic_redir_url topic_redir_url VARCHAR(255) NOT NULL COLLATE "ascii_bin" AFTER user_id;
');
$conn->execute('
ALTER TABLE msz_login_attempts
CHANGE COLUMN attempt_country attempt_country CHAR(2) NOT NULL DEFAULT "XX" COLLATE "ascii_general_ci" AFTER attempt_ip,
CHANGE COLUMN attempt_user_agent attempt_user_agent TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER attempt_created;
');
$conn->execute('
ALTER TABLE msz_news_categories
CHANGE COLUMN category_name category_name VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER category_id,
CHANGE COLUMN category_description category_description TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER category_name;
');
$conn->execute('
ALTER TABLE msz_news_posts
CHANGE COLUMN post_title post_title VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER post_is_featured,
CHANGE COLUMN post_text post_text TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER post_title;
');
$conn->execute('
ALTER TABLE msz_profile_fields
CHANGE COLUMN field_key field_key VARCHAR(50) NOT NULL COLLATE "ascii_general_ci" AFTER field_order,
CHANGE COLUMN field_title field_title VARCHAR(50) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER field_key,
CHANGE COLUMN field_regex field_regex VARCHAR(255) NOT NULL COLLATE "ascii_bin" AFTER field_title;
');
$conn->execute('
ALTER TABLE msz_profile_fields_formats
CHANGE COLUMN format_regex format_regex VARCHAR(255) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER field_id,
CHANGE COLUMN format_link format_link VARCHAR(255) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER format_regex,
CHANGE COLUMN format_display format_display VARCHAR(255) NOT NULL DEFAULT "%s" COLLATE "utf8mb4_unicode_520_ci" AFTER format_link;
');
$conn->execute('
ALTER TABLE msz_profile_fields_values
CHANGE COLUMN field_value field_value VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER format_id;
');
$conn->execute('
ALTER TABLE msz_roles
CHANGE COLUMN role_name role_name VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER role_hierarchy,
CHANGE COLUMN role_title role_title VARCHAR(64) NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER role_name,
CHANGE COLUMN role_description role_description TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER role_title;
');
$conn->execute('
ALTER TABLE msz_sessions
CHANGE COLUMN session_user_agent session_user_agent TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER session_ip_last,
CHANGE COLUMN session_country session_country CHAR(2) NOT NULL DEFAULT "XX" COLLATE "ascii_general_ci" AFTER session_client_info;
');
$conn->execute('
ALTER TABLE msz_users
CHANGE COLUMN username username VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER user_id,
CHANGE COLUMN password password VARCHAR(255) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER username,
CHANGE COLUMN email email VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER password,
CHANGE COLUMN user_country user_country CHAR(2) NOT NULL DEFAULT "XX" COLLATE "ascii_general_ci" AFTER user_super,
CHANGE COLUMN user_totp_key user_totp_key CHAR(26) NULL DEFAULT NULL COLLATE "ascii_bin" AFTER display_role,
CHANGE COLUMN user_about_content user_about_content TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER user_totp_key,
CHANGE COLUMN user_signature_content user_signature_content TEXT NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER user_about_parser,
CHANGE COLUMN user_title user_title VARCHAR(64) NULL DEFAULT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER user_background_settings;
');
$conn->execute('
ALTER TABLE msz_users_bans
CHANGE COLUMN ban_reason_public ban_reason_public TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER ban_severity,
CHANGE COLUMN ban_reason_private ban_reason_private TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER ban_reason_public;
');
$conn->execute('
ALTER TABLE msz_users_modnotes
CHANGE COLUMN note_title note_title VARCHAR(255) NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER note_created,
CHANGE COLUMN note_body note_body TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER note_title;
');
$conn->execute('
ALTER TABLE msz_users_password_resets
CHANGE COLUMN verification_code verification_code CHAR(12) NULL DEFAULT NULL COLLATE "ascii_general_ci" AFTER reset_requested;
');
$conn->execute('
ALTER TABLE msz_users_warnings
CHANGE COLUMN warn_body warn_body TEXT NOT NULL COLLATE "utf8mb4_unicode_520_ci" AFTER mod_id;
');
}
}

View file

@ -81,7 +81,7 @@ if(!empty($searchQuery)) {
ON r.`role_id` = u.`display_role` ON r.`role_id` = u.`display_role`
LEFT JOIN `msz_users_roles` AS ur LEFT JOIN `msz_users_roles` AS ur
ON ur.`user_id` = u.`user_id` ON ur.`user_id` = u.`user_id`
WHERE LOWER(u.`username`) LIKE CONCAT("%%", LOWER(:query), "%%") WHERE u.`username` LIKE CONCAT("%%", :query, "%%")
GROUP BY u.`user_id` GROUP BY u.`user_id`
'); ');
$findUsers->bind('query', $searchQuery); $findUsers->bind('query', $searchQuery);

View file

@ -57,7 +57,7 @@ final class HomeHandler extends Handler {
orderBy: 'random', orderBy: 'random',
); );
// can also chat here, whoa // can also cheat here, whoa
$stats['users:online:recent'] = count($onlineUserInfos); $stats['users:online:recent'] = count($onlineUserInfos);
// TODO: don't hardcode forum ids // TODO: don't hardcode forum ids

View file

@ -36,12 +36,8 @@ class User {
if(!preg_match('#^' . self::NAME_REGEX . '$#u', $name)) if(!preg_match('#^' . self::NAME_REGEX . '$#u', $name))
return 'invalid'; return 'invalid';
$userId = (int)DB::prepare( $userId = (int)DB::prepare('SELECT user_id FROM msz_users WHERE username = :username')
'SELECT `user_id`' ->bind('username', $name)->fetchColumn();
. ' FROM `msz_users`'
. ' WHERE LOWER(`username`) = LOWER(:username)'
) ->bind('username', $name)
->fetchColumn();
if($userId > 0) if($userId > 0)
return 'in-use'; return 'in-use';
@ -75,12 +71,8 @@ class User {
if(!checkdnsrr(mb_substr(mb_strstr($address, '@'), 1), 'MX')) if(!checkdnsrr(mb_substr(mb_strstr($address, '@'), 1), 'MX'))
return 'dns'; return 'dns';
$userId = (int)DB::prepare( $userId = (int)DB::prepare('SELECT user_id FROM msz_users WHERE email = :email')
'SELECT `user_id`' ->bind('email', $address)->fetchColumn();
. ' FROM `msz_users`'
. ' WHERE LOWER(`email`) = LOWER(:email)'
) ->bind('email', $address)
->fetchColumn();
if($userId > 0) if($userId > 0)
return 'in-use'; return 'in-use';

View file

@ -214,10 +214,10 @@ class Users {
++$args; ++$args;
$query .= ' WHERE user_id = ?'; $query .= ' WHERE user_id = ?';
} }
if($selectName) // change the collation for both name and email to a case insensitive one if($selectName)
$query .= sprintf(' %s LOWER(username) = LOWER(?)', ++$args > 1 ? 'OR' : 'WHERE'); $query .= sprintf(' %s username = ?', ++$args > 1 ? 'OR' : 'WHERE');
if($selectMail) if($selectMail)
$query .= sprintf(' %s LOWER(email) = LOWER(?)', ++$args > 1 ? 'OR' : 'WHERE'); $query .= sprintf(' %s email = ?', ++$args > 1 ? 'OR' : 'WHERE');
$args = 0; $args = 0;
$stmt = $this->cache->get($query); $stmt = $this->cache->get($query);

View file

@ -1,31 +1,52 @@
{% macro user_card(user) %} {% macro user_card(user) %}
{% from 'macros.twig' import avatar %} {% from 'macros.twig' import avatar %}
{% if user.info is defined %}
{% set colour = user.colour %}
{% set info = user.info %}
{% set ftopics = user.ftopics %}
{% set fposts = user.fposts %}
{% else %}
{% set colour = user.user_colour %}
{% set info = {
'id': user.user_id,
'name': user.username,
'hasTitle': user.user_title is defined and user.user_title is not empty,
'title': user.user_title|default(''),
'hasCountryCode': user.user_country is defined and user.user_country != 'XX',
'countryCode': user.user_country|default('XX'),
'hasLastActive': user.user_active is defined and user.user_active > 0,
'lastActiveTime': user.user_active,
'createdTime': user.user_created
} %}
{% set ftopics = user.user_count_topics %}
{% set fposts = user.user_count_posts %}
{% endif %}
<div class="usercard" style="--accent-colour: {{ user.colour }}"> <div class="usercard" style="--accent-colour: {{ colour }}">
<div class="usercard__background"></div> <div class="usercard__background"></div>
<a class="usercard__link" href="{{ url('user-profile', {'user': user.info.id}) }}" title="Visit {{ user.info.name }}'{{ user.info.name|last|lower == 's' ? '' : 's' }} profile"></a> <a class="usercard__link" href="{{ url('user-profile', {'user': info.id}) }}" title="Visit {{ info.name }}'{{ info.name|last|lower == 's' ? '' : 's' }} profile"></a>
<div class="usercard__avatar"> <div class="usercard__avatar">
{{ avatar(user.info.id, 50, user.info.name) }} {{ avatar(info.id, 50, info.name) }}
</div> </div>
<div class="usercard__details"> <div class="usercard__details">
<div class="usercard__details_inner"> <div class="usercard__details_inner">
<div class="usercard__details__username"> <div class="usercard__details__username">
{{ user.info.name }} {{ info.name }}
</div> </div>
{% if user.info.hasTitle %} {% if info.hasTitle %}
<div class="usercard__details__title"> <div class="usercard__details__title">
{{ user.info.title }} {{ info.title }}
</div> </div>
{% endif %} {% endif %}
{% if user.info.hasCountryCode %} {% if info.hasCountryCode %}
<div class="usercard__details__country"> <div class="usercard__details__country">
<div class="flag flag--{{ user.info.countryCode|lower }}"></div> <div class="flag flag--{{ info.countryCode|lower }}"></div>
<div class="usercard__details__country__name"> <div class="usercard__details__country__name">
{{ user.info.countryCode|country_name }} {{ info.countryCode|country_name }}
</div> </div>
</div> </div>
{% endif %} {% endif %}
@ -33,30 +54,30 @@
</div> </div>
<div class="usercard__stats"> <div class="usercard__stats">
{% if user.ftopics > 0 %} {% if ftopics > 0 %}
<a class="usercard__stat" href="{{ url('user-profile-forum-topics', {'user': user.info.id}) }}"> <a class="usercard__stat" href="{{ url('user-profile-forum-topics', {'user': info.id}) }}">
<div class="usercard__stat__name">Topics</div> <div class="usercard__stat__name">Topics</div>
<div class="usercard__stat__value">{{ user.ftopics|number_format }}</div> <div class="usercard__stat__value">{{ ftopics|number_format }}</div>
</a> </a>
{% endif %} {% endif %}
{% if user.fposts > 0 %} {% if fposts > 0 %}
<a class="usercard__stat" href="{{ url('user-profile-forum-posts', {'user': user.info.id}) }}"> <a class="usercard__stat" href="{{ url('user-profile-forum-posts', {'user': info.id}) }}">
<div class="usercard__stat__name">Posts</div> <div class="usercard__stat__name">Posts</div>
<div class="usercard__stat__value">{{ user.fposts|number_format }}</div> <div class="usercard__stat__value">{{ fposts|number_format }}</div>
</a> </a>
{% endif %} {% endif %}
{% if user.info.hasLastActive %} {% if info.hasLastActive %}
<div class="usercard__stat usercard__stat--wide" title="{{ user.info.lastActiveTime|date('r') }}"> <div class="usercard__stat usercard__stat--wide" title="{{ info.lastActiveTime|date('r') }}">
<div class="usercard__stat__name">Last seen</div> <div class="usercard__stat__name">Last seen</div>
<div class="usercard__stat__value"><time datetime="{{ user.info.lastActiveTime|date('c') }}">{{ user.info.lastActiveTime|time_format }}</time></div> <div class="usercard__stat__value"><time datetime="{{ info.lastActiveTime|date('c') }}">{{ info.lastActiveTime|time_format }}</time></div>
</div> </div>
{% endif %} {% endif %}
<div class="usercard__stat usercard__stat--wide" title="{{ user.info.createdTime|date('r') }}"> <div class="usercard__stat usercard__stat--wide" title="{{ info.createdTime|date('r') }}">
<div class="usercard__stat__name">Joined</div> <div class="usercard__stat__name">Joined</div>
<div class="usercard__stat__value"><time datetime="{{ user.info.createdTime|date('c') }}">{{ user.info.createdTime|time_format }}</time></div> <div class="usercard__stat__value"><time datetime="{{ info.createdTime|date('c') }}">{{ info.createdTime|time_format }}</time></div>
</div> </div>
</div> </div>
</div> </div>