Фильтровать медиа-библиотеку по пользовательскому постмета

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

Я использую плагин ACF.

Я создал поле выбора custom_select в ACF, которое включается в каждое вложение.

ACF записывает эти значения в таблицу postmeta.

Теперь я хочу отфильтровать свои вложения в библиотеке медиа по этому полю custom_select.

Я нашел много статей о включении таксономий, но ни одной по postmeta.

Мне пришлось реализовать следующее:

  1. Изменить интерфейс администратора, чтобы включить мои пользовательские фильтры
add_action('wp_enqueue_media', function () {
    wp_enqueue_script('media-library-taxonomy-filter', get_stylesheet_directory_uri() . '/assets/js/custom-media-filter.js', array('media-editor', 'media-views'));
});
  1. В custom-media-filter.js я добавляю HTML для пользовательского выбора, и каждый раз, когда мой пользовательский выбор изменяется, добавляю параметры запроса в URL и перенаправляю с этим параметром и значением
jQuery(document).ready(function () {
    jQuery('.filter-items').append('<select class="form-select" aria-label="Пользовательский фильтр document_category" id="page-document_category"><option>-Выбрать-</option><option value="document">Документ</option><option value="template">Шаблон</option></select>');
    jQuery('#page-document_category').change(function (e) {
        insertParam('document_category', this.value)
    });
    // вставить и перенаправить с новым значением
    function insertParam(key, value) {
        key = encodeURIComponent(key);
        value = encodeURIComponent(value);
        // удалить все остальные параметры
        var kvp = [];
        kvp.push(key + '=' + value);
        document.location.search = params;
    }

});
 
  1. Добавить действие в мой functions.php, связанное с pre_get_posts
add_action('pre_get_posts', 'my_custom_filter');

и создать мою пользовательскую функцию my_custom_filter, которая изменяет мета-запрос только тогда, когда мои пользовательские фильтры отправляются в URL

if (!function_exists('my_custom_filter')) {
    function my_custom_filter($wp_query_obj)
    {
        $url_query  = explode('&', $_SERVER['QUERY_STRING']);
        $params = array();
        foreach ($url_query as $param) {
            if (isset($param) && $param[0] !== '') {
                // предотвращает уведомление об explode(), если $param не содержит '='
                if (strpos($param, '=') === false) $param += '=';

                list($name, $value) = explode('=', $param, 2);
                $params[urldecode($name)][] = urldecode($value);
                urldecode_deep($params);
            }
        }
        $found = false;
        if (isset($params['document_category'])) {
            $meta_key = 'document_category';
            $meta_value = $params['document_category'][0];
            $found = true;
        }

        // здесь я могу добавить больше фильтров

        // else if ($params['document_type']) {
        //    $meta_key = 'document_type';
        //    $meta_value = $params['document_type'][0];
        //    $found = true;
        // }
 
        if ($found) {
            $meta_query = array(
                array(
                    'key'     => $meta_key,
                    'value'   => $meta_value,
                    'compare' => '=',
                ),
            );
            $wp_query_obj->set('meta_query', $meta_query);
            $wp_query_obj->set('orderby',    'meta_value_num');
            $wp_query_obj->set('order',      'ASC');
        }
        return;
    }
}

.

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

Фильтрация медиатеки по пользовательским полям постов (postmeta) с использованием ACF

Если вы используете плагин ACF (Advanced Custom Fields) и хотите реализовать возможность фильтрации вложений в медиатеке WordPress по пользовательскому полю custom_select, вам предстоит выполнить несколько шагов, чтобы существенно улучшить функциональность вашей медиатеки. Этот процесс включает в себя изменение интерфейса администратора, добавление JavaScript для управления фильтрами и настройку PHP-кода для модификации запроса. Посмотрим на все шаги подробно.

1. Изменение интерфейса администратора с помощью wp_enqueue_media

Первый шаг — подключить пользовательский JavaScript, который будет добавлять HTML-код для вашего фильтра. Это можно сделать с помощью хука wp_enqueue_media. В файле functions.php вашей темы добавьте следующий код:

add_action('wp_enqueue_media', function () {
    wp_enqueue_script('media-library-taxonomy-filter', get_stylesheet_directory_uri() . '/assets/js/custom-media-filter.js', array('media-editor', 'media-views'));
});

Этот код подключает ваш JavaScript-файл custom-media-filter.js, в котором будет реализована логика фильтрации элементов.

2. Реализация логики фильтрации на стороне клиента

В файле custom-media-filter.js реализуйте логику для отображения выпадающего списка и управления его изменениями. Вот пример кода:

jQuery(document).ready(function () {
    jQuery('.filter-items').append('<select class="form-select" aria-label="Custom filter document_category" id="page-document_category"><option>-Choose-</option><option value="document">Document</option><option value="template">Template</option></select>');

    jQuery('#page-document_category').change(function (e) {
        insertParam('document_category', this.value);
    });

    function insertParam(key, value) {
        key = encodeURIComponent(key);
        value = encodeURIComponent(value);
        var params = key + '=' + value;
        document.location.search = params;
    }
});

Этот код добавляет выпадающий список в интерфейс медиатеки и перенаправляет пользователя на страницу с обновленными параметрами URL при выборе элемента.

3. Изменение запроса с помощью pre_get_posts

Последний шаг — это изменение WP-запроса с помощью хука pre_get_posts. Добавьте следующий код в ваш файл functions.php:

add_action('pre_get_posts', 'my_custom_filter');

if (!function_exists('my_custom_filter')) {
    function my_custom_filter($wp_query_obj) {
        $url_query  = explode('&', $_SERVER['QUERY_STRING']);
        $params = array();

        foreach ($url_query as $param) {
            if (isset($param) && $param[0] !== '') {
                if (strpos($param, '=') === false) $param .= '=';
                list($name, $value) = explode('=', $param, 2);
                $params[urldecode($name)][] = urldecode($value);
            }
        }

        $found = false;
        if (isset($params['document_category'])) {
            $meta_key = 'document_category';
            $meta_value = $params['document_category'][0];
            $found = true;
        }

        if ($found) {
            $meta_query = array(
                array(
                    'key'     => $meta_key,
                    'value'   => $meta_value,
                    'compare' => '=',
                ),
            );
            $wp_query_obj->set('meta_query', $meta_query);
            $wp_query_obj->set('orderby', 'meta_value_num');
            $wp_query_obj->set('order', 'ASC');
        }
        return;
    }
}

Этот код проверяет наличие параметров URL и, если они присутствуют, изменяет запрос, добавляя соответствующий фильтр по мета-данным.

Заключение

С помощью приведенных выше шагов вы сможете успешно фильтровать ваши вложения в медиатеке WordPress по пользовательскому полю, определенному с помощью ACF. Реализация этого функционала не только улучшает пользовательский интерфейс, но и позволяет эффективно управлять ресурсами вашего сайта.

Не забывайте тестировать изменения на различных этапах, чтобы убедиться, что ваша фильтрация работает корректно. Таким образом, вы сможете экспериментировать с различными значениями и расширять функциональность при необходимости.

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

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