Используйте хуки или фильтры, или перезапишите эту функцию Gamipress?

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

В данный момент Gamipress позволяет вам импортировать CSV файл, который содержит имя пользователя (электронную почту или ID) и значение очков, которое нужно добавить к типу очков для этого пользователя. Для достижения этой цели используется данная функция, которая записывает в журнал gamipress.

/**
 * AJAX обработчик для инструмента импорта очков
 *
 * @since 1.6.4
 */
function gamipress_import_export_points_tool_ajax_import() {
    // Проверка безопасности, завершает работу, если безопасность не пройдена
    check_ajax_referer( 'gamipress_admin', 'nonce' );

    // Проверка прав пользователя
    if( ! current_user_can( gamipress_get_manager_capability() ) ) {
        wp_send_json_error( __( 'Вам не разрешено выполнять это действие.', 'gamipress' ) );
    }

    // Проверка полученных параметров
    if( ! isset( $_FILES['file'] ) ) {
        wp_send_json_error( __( 'Нет файла для импорта.', 'gamipress' ) );
    }

    $import_file = $_FILES['file']['tmp_name'];

    if( empty( $import_file ) ) {
        wp_send_json_error( __( 'Не удаётся получить файл для импорта, проверьте права доступа к файлам сервера.', 'gamipress' ) );
    }

    ignore_user_abort( true );

    if ( ! gamipress_is_function_disabled( 'set_time_limit' ) ) {
        set_time_limit( 0 );
    }

    // Получение содержимого файла
    $file_contents = file_get_contents( $import_file );

    if( empty( $file_contents ) ) {
        wp_send_json_error( __( 'Пустой файл, нечего импортировать.', 'gamipress' ) );
    }

    // Настройка переменных
    $points_types = gamipress_get_points_types();

    // Разделение по переносам строк
    $lines = explode( "\n", $file_contents );

    foreach( $lines as $number => $line ) {

        $columns = str_getcsv( $line );

        if( count( $columns ) >= 3 ) {

            $user = false;
            $points = 0;
            $points_type="";
            $log_description = '';
            $deduct = false;

            // Пользователь
            if( isset( $columns[0] ) && ! empty( $columns[0] ) ) {

                $user_field = 'login';

                if( filter_var( $columns[0], FILTER_VALIDATE_EMAIL ) ) {
                    $user_field = 'email';
                } else if( is_numeric( $columns[0] ) ) {
                    $user_field = 'id';
                }

                $user = get_user_by( $user_field, $columns[0] );

            }

            // Очки
            if( isset( $columns[1] ) && is_numeric( $columns[1] ) ) {

                // Если сумма очков имеет отрицательный знак, значит, пользователь хочет вычесть
                if ( substr( $columns[1], 0, 1 ) === '-') {
                    $deduct = true;
                    $columns[1] = substr( $columns[1], 1); // Удалить отрицательный знак
                }

                $points = absint( $columns[1] );

            }

            // Тип очков
            if( isset( $columns[2] ) && ! empty( $columns[2] ) && isset( $points_types[$columns[2]] ) ) {

                $points_type = $columns[2];

            }

            // Описание журнала
            if( isset( $columns[3] ) && ! empty( $columns[3] ) ) {

                $log_description = $columns[3];

            }

            // Проверка, выполнено ли всё
            if( $user && $points > 0 && ! empty( $points_type ) ) {

                // При награждении очками, передав ID администратора, нам нужно передать полную новую сумму
                $current_points = gamipress_get_user_points( $user->ID, $points_type );

                $args = array(
                    'admin_id'  => get_current_user_id(),
                    'reason'    => $log_description,
                    'log_type'  => 'points_award'
                );

                // Если описание журнала пустое, пусть GamiPress настроит его из настроек журнала
                if( empty( $log_description ) ) {
                    $args = array( 'admin_id'  => get_current_user_id() );
                }

                if( $deduct ) {
                    // Вычесть очки у пользователя
                    gamipress_deduct_points_to_user( $user->ID, $current_points - $points, $points_type, $args );
                } else {
                    // Наградить очками пользователя
                    gamipress_award_points_to_user( $user->ID, $points + $current_points, $points_type, $args );
                }

            }

        }

    }

    // Возвратить сообщение об успешном завершении
    wp_send_json_success( __( 'Баланс очков пользователя был успешно обновлён.', 'gamipress' ) );
}
add_action( 'wp_ajax_gamipress_import_export_points_tool_import', 'gamipress_import_export_points_tool_ajax_import' );

Эта функция не добавляет очки к общий счет пользователей. Она просто записывает это в журнал. У меня есть функция, которую я написал, чтобы зарегистрировать очки для пользователя. Однако она регистрирует общую сумму очков, а не добавляет значение очков – так как функция импорта передаёт очки +/- текущие очки. Я хотел бы зарегистрировать значение очков – не очки +/- текущие очки.

//Gamipress - Регистрация очков пользователя при импорте очков из CSV
function ofc_insert_user_earning_on_import_points_tool( $user_id, $points, $points_type, $args ) {

    if( ! defined( 'DOING_AJAX' ) ) return;
    if( ! DOING_AJAX ) return;
    if( ! isset( $_REQUEST['action'] ) ) return;
    if( $_REQUEST['action'] !== 'gamipress_import_export_points_tool_import' ) return;

    $points_type_obj = gamipress_get_points_type( $points_type );
    $award = ( current_filter() === 'gamipress_award_points_to_user' );

    if( ! $award ) {
        $points *= -1;
    }

    gamipress_insert_user_earning( $user_id, array(
        'title'         => ( isset( $args['reason'] ) ? $args['reason'] : '' ),
        'post_id'       => $points_type_obj['ID'],
        'post_type'     => 'points-type',
        'points'        => $points,
        'points_type'   => $points_type,
        'date'          => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
    ) );

}
add_action( 'gamipress_award_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4 );
add_action( 'gamipress_deduct_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4 );

Как мне подключиться к функции gamipress_import_export_points_tool_ajax_import, чтобы получить $points вместо общей суммы очков? (Надеюсь, это имеет смысл)

Оказывается, всё было так просто, как добавить эту строку в мою функцию:

$current_total_points = gamipress_get_user_points( $user_id, $points_type);

И затем передать $points – $current_total_points в функцию вставки заработка пользователя GamiPress.

function ofc_insert_user_earning_on_import_points_tool( $user_id, $points, $points_type, $args ) {

    if( ! defined( 'DOING_AJAX' ) ) return;
    if( ! DOING_AJAX ) return;
    if( ! isset( $_REQUEST['action'] ) ) return;
    if( $_REQUEST['action'] !== 'gamipress_import_export_points_tool_import' ) return;

    $points_type_obj = gamipress_get_points_type( $points_type );
    $award = ( current_filter() === 'gamipress_award_points_to_user' );

    //если мы вычитаем очки, то делаем очки отрицательными
    if( ! $award ) {
        $points *= -1;
    }

    $current_total_points = gamipress_get_user_points( $user_id, $points_type);

    gamipress_insert_user_earning( $user_id, array(
        'title'         => ( isset( $args['reason'] ) ? $args['reason'] : '' ),
        'post_id'       => $points_type_obj['ID'],
        'post_type'     => 'points-type',
        'points'        => $points - $current_total_points,
        'points_type'   => $points_type,
        'date'          => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
    ) );

}
add_action( 'gamipress_award_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4 );
add_action( 'gamipress_deduct_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4 );

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

Как использовать хуки или фильтры, или переписать функцию Gamipress?

В вопросе рассматривается ситуация, когда необходимо изменить поведение функции gamipress_import_export_points_tool_ajax_import, чтобы при импорте очков из CSV-файла добавлялись не общие баллы пользователя, а только значения очков, указанные в импорте. Ниже представлена подробная инструкция по решению этой задачи.

Проблема

Gamipress в своем базовом функционале лишь записывает сумму очков для пользователя в лог, без их фактического добавления к текущему балансу. Переписывание функции, как правило, не рекомендуется из-за возможных проблем с обновлениями и совместимостью с другими плагинами. Вместо этого лучше использовать хуки и фильтры.

Решение

  1. Использование хуков:
    Вам необходимо использовать хук gamipress_award_points_to_user для обработки процесса добавления очков к пользователю. Этот хук позволит вам изменить логику добавления очков в систему.

  2. Извлечение текущего количества очков:
    Чтобы правильно управлять очками, вы можете добавить следующую строку в вашу функцию:

    $current_total_points = gamipress_get_user_points($user_id, $points_type);
  3. Модификация функции:
    Теперь вам нужно изменить логику, чтобы вместо установки нового количества очков, система корректно добавляла только новые очки. Обновленная функция может выглядеть следующим образом:

    function ofc_insert_user_earning_on_import_points_tool($user_id, $points, $points_type, $args) {
       if (!defined('DOING_AJAX') || !DOING_AJAX) return;
       if (!isset($_REQUEST['action']) || $_REQUEST['action'] !== 'gamipress_import_export_points_tool_import') return;
    
       $points_type_obj = gamipress_get_points_type($points_type);
       $award = (current_filter() === 'gamipress_award_points_to_user');
    
       // Учитываем вычитание очков
       if (!$award) {
           $points *= -1;
       }
    
       // Получаем текущее количество очков
       $current_total_points = gamipress_get_user_points($user_id, $points_type);
    
       // Записываем новые очки
       gamipress_insert_user_earning($user_id, array(
           'title'         => (isset($args['reason']) ? $args['reason'] : ''),
           'post_id'       => $points_type_obj['ID'],
           'post_type'     => 'points-type',
           'points'        => $points - $current_total_points, // Изменение здесь
           'points_type'   => $points_type,
           'date'          => date('Y-m-d H:i:s', current_time('timestamp')),
       ));
    }
    add_action('gamipress_award_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4);
    add_action('gamipress_deduct_points_to_user', 'ofc_insert_user_earning_on_import_points_tool', 10, 4);

Заключение

Ваше изменение теперь будет корректно обрабатывать добавление очков для пользователя, основываясь на импорте из CSV. Вместо того чтобы переопределять основную функцию Gamipress, вы используете хуки, что обеспечивает более стабильную и совместимую реализацию. Это решение позволяет избежать трудностей с обновлениями плагина и сохраняет гибкость в дальнейшем развитии вашей функциональности.

Вопрос, как изменить поведение gamipress_import_export_points_tool_ajax_import не всегда очевиден, однако использование хуков и фильтров в WordPress предоставляет множество возможностей для кастомизации — что и продемонстрировано в этом решении.

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

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