Установить право unfiltered_html для пользователей определённой роли в WordPress в режиме Multisite
Внезапно выяснилось, что в режиме Multisite привилегия unfiltered_html есть только у суперадмина. Мне необходимо вернуть её админам и редакторам.
Следующий код помог решить эту задачу:
<php
$role_object = get_role('administrator');
$role_object->add_cap('unfiltered_html', true);
$role_object = get_role('editor');
$role_object->add_cap('unfiltered_html', true);
?>
Но у пользователей с ролью админов и редакторов возможность не появилась. Получается интересное: у роли возможность установлена, но ни вновь создаваемые пользователи с этой ролью, ни уже существующие привилегией не обладают.
Вот что я получаю, выполняя следующий код:
<?php
$args = array(
'role' => 'editor',
'orderby' => 'user_nicename',
'order' => 'ASC'
);
$users = get_users($args);
$editor_caps = get_role('editor')->capabilities;
foreach ($editor_caps as $cap => $val) {
if ($cap == 'unfiltered_html' && $val) {
echo '<p>Для роли editor установлена возможность <strong>' . $cap . '</strong></p>';
}
}
?>
<h4>Список всех пользователей с правом editor</h4>
<ul>
<?php
foreach ($users as $user) {
$user_id = $user->ID;
$user_can = user_can($user_id, 'unfiltered_html');
?>
<li>
<?php echo esc_html($user->display_name) . '[' . esc_html($user->user_email) . '] - '; ?>
<?php echo $user_can ? 'право unfiltered_html <span style="color:green;">включено</span>' : 'право unfiltered_html <span style="color:red;">отсутствует</span>'; ?>
</li>
<?php
}
?>
</ul>
<?php
Два последних пользователя были созданы уже после обновления прав у ролей editor и administrator. Хотелось бы понимать, по какой причине это происходит и можно ли как-то решить эту задачу в целом для роли, а не для пользователей по отдельности?
Ответы (1 шт):
Магия происходит в map_meta_cap():
case 'unfiltered_html':
// Disallow unfiltered_html for all users, even admins and super admins.
if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
$caps[] = 'do_not_allow';
} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
$caps[] = 'do_not_allow';
} else {
$caps[] = 'unfiltered_html';
}
break;
Но в конце этой функции есть фильтр
/**
* Filters a user's capabilities depending on specific context and/or privilege.
*
* @since 2.8.0
*
* @param string[] $caps Array of the user's capabilities.
* @param string $cap Capability name.
* @param int $user_id The user ID.
* @param array $args Adds the context to the cap. Typically the object ID.
*/
return apply_filters( 'map_meta_cap', $caps, $cap, $user_id, $args );
Думаю, что такого кода будет достаточно для решения проблемы.
/**
* @param string[] $caps Array of the user's capabilities.
* @param string $cap Capability name.
* @param int $user_id The user ID.
* @param array $args Adds the context to the cap. Typically the object ID.
*/
function my_map_meta_cap( $caps, $cap, $user_id, $args ) {
if (
'unfiltered_html' === $cap &&
is_multisite() &&
( user_can( $user_id, 'editor' ) || user_can( $user_id, 'administrator' ) )
) {
return [ 'unfiltered_html' ];
}
return $caps;
}
add_filter( 'map_meta_cap', 'my_map_meta_cap', 10, 4 );
