Có cách nào để cho phép ký tự đặc biệt trong tên người dùng như "#" và "~" không?
Có cách nào để cho phép ký tự đặc biệt trong tên người dùng như "#" và "~" không?
Câu trả lời:
Bạn phải ghi đè user_validate_name (tên $) :
Verify the syntax of the given name.
Để làm điều đó, hãy xác định mã xác thực tên người dùng của bạn trong mô-đun tùy chỉnh của bạn
function MODULENAME_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'user_register') {
$form['#validate'] = array();
$form['#validate'][] = 'registration_username_validate';
}
}
Và bên trong hàm register_username_validate thực hiện logic của bạn để cho phép các ký tự đặc biệt của bạn.
Quan tâm về các vấn đề bảo mật gây ra bằng cách cho phép các ký tự đặc biệt trong tên người dùng và về các vấn đề hiển thị không được vệ sinh tên người dùng có thể gây ra trong các chủ đề.
user_account_form_validate
chức năng mặc định xác nhận nhiều hơn chỉ là tên người dùng. Thay thế điều này có thể cho phép tên người dùng trùng lặp! Tôi đã thêm một câu trả lời xung quanh những vấn đề này.
Thật không may, không có cách thẳng về phía trước để làm điều này. Theo mặc định user_register_form
và user_profile_form
đã user_account_form_validate
đặt làm trình xác nhận đầu tiên của họ trong $form['#validate']
. user_account_form_validate()
kiểm tra và xóa tên, email và chữ ký của một tài khoản. Là một phần của việc kiểm tra tên, nó thực hiện cuộc gọi đến user_validate_name()
. Đây là chức năng chúng tôi muốn ghi đè, không user_account_form_validate
.
Người ta sẽ hy vọng một cái móc hữu ích để ghi đè lên nó, nhưng than ôi. Nếu tôi không quan tâm đến việc xác thực email và chữ ký cũng như kiểm tra xem tên có trùng lặp hay không, tôi chỉ có thể xóa user_account_form_validate
khỏi
$form['#validate']
. Nhưng điều đó không tốt. Thay vào đó, tôi thêm một trình xác nhận bổ sung hoàn tác công việc user_validate_name()
và làm lại mọi thứ mà không cần kiểm tra ký tự đặc biệt.
<?php
function MODULENAME_form_user_register_form_alter(
array &$form, array &$form_state, $form_id)
{
MODULENAME_add_name_validator($form);
}
function MODULENAME_form_user_profile_form_alter(
array &$form, array &$form_state, $form_id)
{
MODULENAME_add_name_validator($form);
}
function MODULENAME_add_name_validator(array &$form)
{
$validate =& $form['#validate'];
# Since `validate_name()` clears out any errors for the "name" field, we
# want to put it right after the validator we want to partially override.
$acct_validate_index = array_search('user_account_form_validate', $validate);
array_splice($validate, ($acct_validate_index + 1), 0,
['MODULENAME_validate_name']
);
}
function MODULENAME_validate_name(array $form, array &$form_state)
{
# There is no blessed way of overriding the call to `user_validate_name()` in
# `user_account_form_validate()`.
$errors =& drupal_static('form_set_error', []);
# Yes, this gets the errors. `form_get_error()` uses this method so... yeah.
if (!isset($errors['name']))
# `user_validate_name()` is a superset of what is checked here. If the name
# passed that validation, no need to rerun things.
return;
# `form_set_error()` also calls `drupal_set_message()` if it finds an
# error.
$msg_index = array_search($errors['name'], $_SESSION['messages']['error']);
if ($msg_index !== false) {
unset($_SESSION['messages']['error'][$msg_index]);
if (empty($_SESSION['messages']['error']))
unset($_SESSION['messages']['error']);
}
unset($errors['name']);
$name = isset($form_state['values']['name'])
? $form_state['values']['name'] : null;
# These checks are taken from `user_validate_name()`, simply excluding the
# for characters we don't mind being in the names.
if (!$name)
$error = t('You must enter a username.');
else if (substr($name, 0, 1) == ' ')
$error = t('The username cannot begin with a space.');
else if (substr($name, -1) == ' ')
$error = t('The username cannot end with a space.');
else if (strpos($name, ' ') !== FALSE)
$error = t('The username cannot contain multiple spaces in a row.');
else if (preg_match('/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP
'\x{AD}' . // Soft-hyphen
'\x{2000}-\x{200F}' . // Various space characters
'\x{2028}-\x{202F}' . // Bidirectional text overrides
'\x{205F}-\x{206F}' . // Various text hinting characters
'\x{FEFF}' . // Byte order mark
'\x{FF01}-\x{FF60}' . // Full-width latin
'\x{FFF9}-\x{FFFD}' . // Replacement characters
'\x{0}-\x{1F}]/u', // NULL byte and control characters
$name))
$error = t('The username contains an illegal character.');
else if (drupal_strlen($name) > USERNAME_MAX_LENGTH)
$error = t('The username %name is too long: it must be %max characters '
.'or less.'
,['%name' => $name, '%max' => USERNAME_MAX_LENGTH]);
if (isset($error))
form_set_error('name', $error);
}
Vẫn còn một kiểm tra ký tự đặc biệt, tuy nhiên nó chỉ kiểm tra các ký tự sử dụng vô hình hoặc đặc biệt.
$form['#validate'] = array();
sẽ ghi đè mọi trình xử lý xác thực hiện có, bao gồm cả các trình xử lý có thể được đặt bởi các mô-đun đóng góp / tùy chỉnh khác. Tốt hơn để chọn lọc bỏ qua chức năng xác nhận bị ghi đè.