Требуется помощь: отфильтровать Elementor Loop Grid, чтобы показать только назначенные магазины для каждого пользователя.

Вопрос или проблема

Я работаю над порталом для внутренних операций клиента, и сталкиваюсь с проблемой фильтрации контента для конкретных пользователей. Вот детали:

Я создал пользовательский тип записи (CPT) для магазинов с использованием Advanced Custom Fields (ACF). В базе данных более 3000 магазинов.

Каждому магазину назначен конкретный торговый представитель (пользователь с ролью “sales-rep”). Я достиг этого, создав пользовательский плагин, который позволяет назначать магазины пользователям и ограничивать доступ на основе этих назначений.

Код плагина:


if (!defined('ABSPATH')) {
   exit;
}

// Регистрация метабокса для назначения пользователей-торговых представителей
add_action('add_meta_boxes', 'mkusers_add_metabox');
function mkusers_add_metabox() {
   add_meta_box(
       'mkusers_access_control',
       'Назначить торговых представителей',
       'mkusers_render_metabox',
       'customer',
       'side',
       'default'
   );
}

function mkusers_render_metabox($post) {
   $assigned_users = get_post_meta($post->ID, '_mkusers_assigned_users', true) ?: [];
   $sales_reps = get_users(['role' => 'sales-rep']);

   wp_nonce_field('mkusers_save_metabox', 'mkusers_nonce');

   echo '
'; foreach ($sales_reps as $user) { $checked = in_array($user->ID, $assigned_users) ? 'checked' : ''; echo '
'; } echo '
'; } // Сохранение данных метабокса add_action('save_post', 'mkusers_save_metabox'); function mkusers_save_metabox($post_id) { if (!isset($_POST['mkusers_nonce']) || !wp_verify_nonce($_POST['mkusers_nonce'], 'mkusers_save_metabox')) { return; } if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (isset($_POST['mkusers_assigned_users'])) { $assigned_users = array_map('intval', $_POST['mkusers_assigned_users']); update_post_meta($post_id, '_mkusers_assigned_users', $assigned_users); } else { delete_post_meta($post_id, '_mkusers_assigned_users'); } } // Добавление полей быстрой и массовой правки add_action('quick_edit_custom_box', 'mkusers_quick_edit_box', 10, 2); add_action('bulk_edit_custom_box', 'mkusers_bulk_edit_box', 10, 2); function mkusers_quick_edit_box($column_name, $post_type) { if ($post_type !== 'customer' || $column_name !== 'assigned_users') { return; } $sales_reps = get_users(['role' => 'sales-rep']); echo '
'; echo '
'; echo ''; echo '
'; echo '
'; } function mkusers_bulk_edit_box($column_name, $post_type) { if ($post_type !== 'customer') { return; } mkusers_quick_edit_box($column_name, $post_type); } // Сохранение данных быстрой и массовой правки add_action('save_post_customer', 'mkusers_save_quick_edit'); function mkusers_save_quick_edit($post_id) { if (isset($_POST['mkusers_quick_edit_assigned_users'])) { $assigned_users = array_map('intval', $_POST['mkusers_quick_edit_assigned_users']); update_post_meta($post_id, '_mkusers_assigned_users', $assigned_users); } } // Обработка данных массовой правки add_action('wp_ajax_mkusers_bulk_edit', 'mkusers_handle_bulk_edit'); function mkusers_handle_bulk_edit() { if (!isset($_POST['post_ids'], $_POST['assigned_users'])) { wp_send_json_error('Недопустимый ввод'); } $post_ids = array_map('intval', $_POST['post_ids']); $assigned_users = array_map('intval', $_POST['assigned_users']); foreach ($post_ids as $post_id) { if (!empty($assigned_users)) { update_post_meta($post_id, '_mkusers_assigned_users', $assigned_users); } else { delete_post_meta($post_id, '_mkusers_assigned_users'); } } wp_send_json_success(); } // Добавление колонки назначенных пользователей в список CPT покупателей add_filter('manage_customer_posts_columns', 'mkusers_add_assigned_users_column'); function mkusers_add_assigned_users_column($columns) { $columns['assigned_users'] = 'Назначенные торговые представители'; return $columns; } // Заполнение колонки назначенных пользователей add_action('manage_customer_posts_custom_column', 'mkusers_display_assigned_users_column', 10, 2); function mkusers_display_assigned_users_column($column_name, $post_id) { if ($column_name === 'assigned_users') { $assigned_users = get_post_meta($post_id, '_mkusers_assigned_users', true) ?: []; $user_names = array_map(function ($user_id) { $user = get_user_by('id', $user_id); return $user ? $user->display_name : ''; }, $assigned_users); echo esc_html(implode(', ', $user_names)); } } // Ограничение доступа для не назначенных пользователей add_action('template_redirect', 'mkusers_restrict_access'); function mkusers_restrict_access() { if (is_singular('customer') && !current_user_can('edit_posts')) { global $post; $assigned_users = get_post_meta($post->ID, '_mkusers_assigned_users', true) ?: []; if (!in_array(get_current_user_id(), $assigned_users) && !current_user_can('administrator')) { wp_redirect('https://mckenzieportal.com/access-restricted/'); exit; } } } // Подключение скрипта быстрой и массовой правки add_action('admin_enqueue_scripts', 'mkusers_enqueue_quick_edit_script'); function mkusers_enqueue_quick_edit_script($hook) { if ('edit.php' === $hook && get_current_screen()->post_type === 'customer') { wp_enqueue_script( 'mkusers-quick-edit', plugins_url('mkusers-quick-edit.js', __FILE__), ['jquery'], '1.4', true ); } }

Например: торговый представитель с именем пользователя 14A имеет 80 магазинов, назначенных на него. Каждый торговый представитель может просматривать только свои назначенные магазины.

Если торговый представитель попытается получить доступ к магазину, к которому он не назначен, его перенаправляют на страницу с ограниченным доступом (эта часть работает нормально).

Как отображаются магазины: Я использую виджет Loop Grid от Elementor на странице под названием Dashboard для отображения всех магазинов.

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

Что я пытался сделать: Я пытался модифицировать запрос Elementor с использованием PHP (через хуки, такие как elementor/query/*), чтобы фильтровать магазины на основе вошедшего пользователя.

Хотя логика кажется правильной, ни одно решение пока не сработало. Либо магазины не отображаются, либо возникают ошибки (например, неопределенные функции или проблемы с запросами).

Цель: На странице Dashboard:

Когда торговый представитель входит в систему, он должен видеть только магазины, назначенные ему в Loop Grid от Elementor.

Решение должно работать без проблем с системой запросов Elementor.

Я был бы очень признателен за любую помощь, предложения кода или идеи по поводу того, как это правильно реализовать. Спасибо!
введите описание изображения здесь

Ответ или решение

Для решения задачи фильтрации отображения магазинов в Elementor Loop Grid по пользователям, вам потребуется применить несколько техник, основанных на предоставленном коде и функционале WordPress. Я опишу шаги и предложу код, который поможет вам отфильтровать магазины таким образом, чтобы каждый торговый представитель видел только свои назначенные магазины.

1. Описание проблемы

Вы создали пользовательский тип записи (CPT) для магазинов и используете Advanced Custom Fields (ACF) для назначения их определенным торговым представителям. У вас уже настроен механизм, который ограничивает доступ к записям на основе назначений с помощью метаданных. Однако Elementor Loop Grid в данный момент отображает все магазины, и вам необходимо его отфильтровать, чтобы показывать только те магазины, которые назначены текущему пользователю.

2. Решение проблемы

Для начала вам нужно использовать хук elementor/query/selector для настройки запроса, который будет использоваться плагином Elementor. Комплексный код ниже добавит необходимые фильтры к запросу.

3. Код для фильтрации магазинов

Добавьте следующий код в файл functions.php вашей темы или в ваш плагин:

// Фильтрация запросов Elementor для Loop Grid
add_action('elementor/query/assigned_stores', function ($query) {
    if (!is_user_logged_in()) {
        return; // Проверка на вход пользователя
    }

    // Получение идентификатора текущего пользователя
    $current_user_id = get_current_user_id();

    // Получение магазинов, назначенных текущему пользователю
    $args = array(
        'post_type' => 'customer', // Убедитесь, что ваш CPT называется 'customer'
        'meta_query' => array(
            array(
                'key' => '_mkusers_assigned_users',
                'value' => '"' . $current_user_id . '"',
                'compare' => 'LIKE'
            )
        )
    );

    // Изменение основного запроса Elementor
    $query->set('meta_query', $args['meta_query']);
});

4. Объяснение кода

  • Проверка входа: Обеспечиваем, чтобы функция выполнялась только для вошедших пользователей.
  • Получение ID пользователя: ID текущего пользователя извлекается с помощью get_current_user_id().
  • Meta Query: Создается массив args с мета-запросом, который проверяет, есть ли текущий пользователь в массиве назначенных пользователей для каждого магазина. Это достигается с помощью LIKE для поиска в массиве.
  • Модификация запроса: Мы устанавливаем наш мета-запрос в запрос Elementor с помощью $query->set().

5. Применение в Elementor

Теперь, чтобы данный фильтр заработал, вам нужно сделать следующее в Elementor:

  1. Откройте вашу страницу с Loop Grid.
  2. В разделе "Query" выберите "Кастомный запрос" и введите название вашего запроса (например, assigned_stores).
  3. Сохраните изменения и проверьте результат.

6. Заключение

С помощью предоставленного кода вы достигнете желаемой цели, и каждый торговый представитель сможет видеть только те магазины, которые были назначены ему. Убедитесь, что ваш тип записи и метаданные настроены корректно, чтобы избежать возможных ошибок в запросах.

Если у вас возникнут вопросы или потребуется помощь с доработкой, не стесняйтесь обращаться. Успехов в реализации вашего проекта!

Оцените материал
Добавить комментарий

Капча загружается...