Как отключить profile.php для пользователей?
Я использую WordPress 4.2.2 и последнюю версию BuddyPress. Я хочу, чтобы все пользователи настраивали свои профили только через страницу профиля BuddyPress. Поэтому мне нужно отключить доступ к profile.php для пользователей. Я скрыл ссылку на профиль в панели инструментов с помощью плагина WP Admin UI Customize, но если кто-то введет URL mysite/wp-admin/profile.php напрямую, страница все равно открывается. Как полностью отключить profile.php для пользователей?

Перенаправление с profile.php
на админ-панель
Вот один из способов сделать это:
add_action( 'load-profile.php', function() {
if( ! current_user_can( 'manage_options' ) )
exit( wp_safe_redirect( admin_url() ) );
} );
где мы перенаправляем на админ-панель, если текущий пользователь не может управлять опциями.
Перенаправление с profile.php
на страницу участника
Если вы хотите перенаправить на профиль участника, можно попробовать (не тестировалось):
add_action( 'load-profile.php', function() {
if( ! current_user_can( 'manage_options' ) && function_exists( 'bp_core_get_user_domain' ) )
exit( wp_safe_redirect( bp_core_get_user_domain( get_current_user_id() ) ) );
} );
Функция bp_core_get_user_domain()
упоминалась в этом ответе несколько лет назад от @BooneGorges.
Я проверил исходный код BuddyPress, и эта функция все еще доступна в версии 2.3 (см. здесь).
Для PHP < 5.3
add_action( 'load-profile.php', 'wpse_195353_profile_redirect_to_dashboard' );
function wpse_195353_profile_redirect_to_dashboard()
{
if( ! current_user_can( 'manage_options' ) )
exit( wp_safe_redirect( admin_url() ) );
}
и
add_action( 'load-profile.php', 'wpse_195353_profile_redirect_to_member_page' );
function wpse_195353_profile_redirect_to_member_page()
{
if( ! current_user_can( 'manage_options' ) && function_exists( 'bp_core_get_user_domain' ) )
exit( wp_safe_redirect( bp_core_get_user_domain( get_current_user_id() ) ) );
}
но вам стоит рассмотреть обновление версии PHP, если это ваш случай.

Это не помогает, брат. Когда я вставляю эти два кода, появляется белый экран.

Вы используете PHP < 5.3? Если да, то анонимные функции не поддерживаются, но это легко изменить на обычные функции - пожалуйста, посмотрите обновленный ответ @azizul

Брат! Два кода для PHP<5.3 работают!! Но есть проблема - мой сервер (bluehost) cPanel показывает версию PHP 5.4.24, и я не понимаю, почему этот код работает. Могут ли возникнуть проблемы в будущем, если я буду использовать этот код?

Рад, что у вас сработало. Это странно, но обе версии кода должны быть безопасными для будущих версий PHP. Мне просто нравятся анонимные функции, добавленные в PHP 5.3 ;-) @azizul

Большое спасибо за предыдущую помощь. Мне нужна еще одна помощь! Я хочу перенаправлять admin.php?page=jetpack также и для пользователей. Как это сделать?

Следующий код* перенаправляет пользователей без прав администратора на пользовательскую страницу профиля во фронтенде, поскольку вместо отключения доступа их нужно перенаправить на вашу собственную страницу. :)
<?php
add_action ('init' , 'wpse_redirect_profile_access');
function wpse_redirect_profile_access(){
//администраторы не будут затронуты
if (current_user_can('manage_options')) return '';
//если мы находимся на странице профиля в админке
if (strpos ($_SERVER ['REQUEST_URI'] , 'wp-admin/profile.php' )) {
wp_redirect ( home_url( '/my-profile' )); // например, на страницу: example.com/my-profile/
exit();
}
}

@birgire ты прав. Я этого не заметил, большое спасибо. Теперь исправлено. :)

ps: нужно быть осторожным при использовании if
без фигурных скобок. Это работает для одного выражения, но у вас их два. В текущем варианте exit()
находится вне блока if
и будет выполняться всегда. Поэтому лучше использовать синтаксис if(){ }
, когда имеем дело с двумя или более выражениями ;-)

Мне нравится этот вариант. Вы можете добавить страницы админки в массив для их перенаправления. В примере ниже я перенаправляю на Дашборд, но вы также можете перенаправить на URL BuddyPress... Я просто не уверен, какой именно это URL, так как редко использую BP.
function no_proflie_admin_pages_redirect() {
global $pagenow;
if(!current_user_can('manage_options')) {
$admin_redirects = array(
'profile.php'
);
if(in_array($pagenow, $admin_redirects)){
wp_redirect( admin_url('/') ); exit;
}
}
}
add_action('admin_init', 'no_proflie_admin_pages_redirect');
Также вы можете скрыть любые дополнительные ссылки на profile.php с помощью простого CSS:
function hide_any_profile_links() { ?>
<style type="text/css">
a[href="http://example.com/wp-admin/profile.php"], a[href="profile.php"]{
display: none!important;
}
</style>
<?php }
add_action('admin_head', 'hide_any_profile_links', 999);
Этого же можно добиться с помощью jQuery или используя PHP и буферизацию вывода.

Боюсь, что использование current_user_can()
в глобальной области видимости не сработает, потому что wp_get_current_user()
ещё не определена.

Привет @birgire, не мог бы ты привести пример, когда это не сработает на странице профиля?

Проверка current_user_can()
должна быть внутри коллбэка no_proflie_admin_pages_redirect
, чтобы избежать ошибки undefined.

Привет, спасибо за ответ, birgire, я только что заметил. В любом случае, знаешь ли ты, когда именно это может произойти? Я использую этот подход уже пару лет и пока не сталкивался с проблемами, что удивительно, и никогда не видел сообщений об ошибках... Может ли это произойти только у определенных пользователей?

Мы не можем использовать current_user_can()
в глобальной области видимости внутри плагина. Это приводит к ошибке Fatal error: Call to undefined function wp_get_current_user()
. Но, полагаю, ты используешь это в файле functions.php
?

Ты был прав. Протестировал это в плагине, а не в functions.php
, и получил фатальную ошибку!

CSS-селектор можно упростить до a[href$="profile.php"]
, что означает совпадение с концом значения атрибута href
.

Продолжая ответ @birgire, из которого я нашел первый сниппет, который оказался самым лаконичным из виденных мною для этой задачи, хочу добавить следующее, так как считаю, что это может быть полезно для большинства пользователей, заходящих в эту ветку.
Если вы не хотите, чтобы пользователи получали доступ к своему профилю в админке, скорее всего, вы также не хотите, чтобы они могли заходить в консоль.
Типичный сценарий — когда у вас есть подписчики, которым вообще не нужен доступ к админке. По умолчанию они могут заходить в консоль и свой профиль, поэтому давайте это исправим:
function redirect_subscribers () {
if( ! current_user_can( 'edit_posts' ) {
exit( wp_safe_redirect( site_url() ) );
}
}
add_action( 'load-index.php', 'redirect_subscribers' );
add_action( 'load-profile.php', 'redirect_subscribers' );
Обратите внимание, что в данном случае я использовал capability edit_posts
, так как я ориентируюсь только на подписчиков, и это capability, которое есть у всех ролей, кроме подписчиков.
Затем я использую site_url()
для перенаправления на главную страницу, но вы также можете использовать get_permalink($page_id)
, передавая id
страницы, где вы создали раздел "Мой аккаунт".
Хук load-{$page_hook}
описан в кодексе.
