Статьи

Интеграция тестов с несколькими вариантами ответов в WordPress: создание интерфейса

Это вторая часть серии статей о разработке плагина викторины с множественным выбором для WordPress. В первой части мы создали бэкэнд нашего плагина для сбора необходимых данных для хранения в базе данных.

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

Следующие темы будут рассмотрены в этой части завершения нашего плагина:

  • Создать шорткод для отображения викторины
  • Интеграция jQuery Slider для отображения вопросов и навигации
  • Завершение викторины и получение результатов
  • Создание таймера викторины

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

Итак, начнем.


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

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

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

1
add_shortcode( ‘wpq_show_quiz’, array( $this, ‘wpq_show_quiz’ ) );

Теперь давайте посмотрим на реализацию шорткода путем извлечения доступных категорий тестов из базы данных.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function wpq_show_quiz( $atts ) {
 
    global $post;
 
    $html = ‘<div id=»quiz_panel»><form action=»» method=»POST»>’;
 
    $html .= ‘<div class=»toolbar»>’;
 
    $html .= ‘<div class=»toolbar_item»><select name=»quiz_category» id=»quiz_category»>’;
 
    // Retrive the quiz categories from database
 
    $quiz_categories = get_terms( ‘quiz_categories’, ‘hide_empty=1’ );
 
    foreach ( $quiz_categories as $quiz_category ) {
 
        $html .= ‘<option value=»‘ . $quiz_category->term_id . ‘»>’ .
 
    }
 
    $html .= ‘</select></div>’;
 
    $html .= ‘<input type=»hidden» value=»select_quiz_cat» name=»wpq_action» />’;
 
    $html .= ‘<div class=»toolbar_item»><input type=»submit» value=»Select Quiz Category» /></div>’;
 
    $html .= ‘</form>’;
 
    $html .= ‘<div class=»complete toolbar_item» ><input type=»button» id=»completeQuiz» value=»Get Results» /></div>’;
 
    // Implementation of Form Submission
 
    // Displaying the Quiz as unorderd list
 
    return $html;
 
}

Наш шорткод сгенерирует форму HTML и необходимые элементы управления, используемые для теста. Мы извлекаем список доступных категорий викторины в раскрывающееся поле, чтобы пользователь мог выбрать предпочитаемую категорию. Мы можем использовать функцию get_terms с hide_empty=1 чтобы получить категории hide_empty=1 в которых есть хотя бы один вопрос.

Скрытое поле wpq_action используется для проверки значений $_POST после отправки.

После того, как вы вставите шорткод в страницу или сообщение, вывод будет выглядеть следующим образом.

Снимок экрана-204

Теперь пользователь может выбрать категорию теста и отправить форму, чтобы получить тест. Итак, мы собираемся обработать отправку формы внутри короткого кода, чтобы получить выбранную категорию и получить случайные вопросы для викторин.

Следующий код содержит реализацию извлечения вопросов из выбранной категории.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$questions_str = «»;
 
if ( isset( $_POST[‘wpq_action’] ) && ‘select_quiz_cat’ == $_POST[‘wpq_action’] ) {
 
    $html .= ‘<div id=»timer» style=»display: block;»></div>’;
    $html .= ‘<div style=»clear: both;»></div></div>’;
 
    $quiz_category_id = $_POST[‘quiz_category’];
    $quiz_num = get_option( ‘wpq_num_questions’ );
    $args = array(
        ‘post_type’ => ‘wptuts_quiz’,
        ‘tax_query’ => array(
            array(
                ‘taxonomy’ => ‘quiz_categories’,
                ‘field’ => ‘id’,
                ‘terms’ => $quiz_category_id
            )
        ),
        ‘orderby’ => ‘rand’,
        ‘post_status’ => ‘publish’,
        ‘posts_per_page’ => $quiz_num
    );
 
    $query = new WP_Query( $args );
 
    $quiz_index = 1;
    while ( $query->have_posts() ) : $query->the_post();
 
        // Generating the HTML for Questions
 
    endwhile;
    wp_reset_query();
 
    // Embedding Slider
}
else {
    $html .= ‘<div id=»timer» style=»display: none;»></div>’;
    $html .= ‘<div style=»clear: both;»></div></div>’;
}

Данный код должен быть включен в раздел « Реализация формы представления » предыдущего кода.

После отправки формы мы проверяем, содержит ли форма требуемое действие, используя скрытое поле, которое мы создали ранее. Затем мы получаем выбранную категорию викторины из массива $_POST .

Затем мы запрашиваем в базе данных сообщения wptuts_quiz с выбранной категорией теста.

Важно установить orderby как rand чтобы генерировать случайные вопросы для тестов, которые в противном случае будут генерировать один и тот же набор вопросов каждый раз. Кроме того, обязательно установите posts_per_page чтобы задать максимальное количество вопросов на каждый заданный тест.

Как только результаты будут сгенерированы, нам нужно добавить вопросы в необходимые элементы HTML, и мы будем реализовывать их в следующем разделе.


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

Создание этой функциональности с нуля может быть трудоемкой задачей, а также изобретать велосипед. Слайдер jQuery будет идеальным решением в этой ситуации, и я буду использовать RhinoSlider , так как он мой любимый, поэтому возьмите его с собой.

Внутри загруженной папки вы увидите три папки с именами img , js и css . Скопируйте папки img и css в наш плагин и скопируйте файлы из папки js в существующую папку js, которая есть в нашем плагине для викторины. Теперь мы можем начать с включения необходимых скриптов и стилей для слайдера.

В первой части мы создали необходимые скрипты для бэкэнда. В этой части мы собираемся включить необходимые скрипты для RhinoSlider, а также quiz.js для пользовательских функций.

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

Рассмотрим следующий код для включения скриптов и необходимых данных конфигурации.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function wpq_frontend_scripts() {
 
    wp_register_script( ‘rhino’, plugins_url( ‘js/rhinoslider-1.05.min.js’, __FILE__ ), array( ‘jquery’ ) );
 
    wp_register_script( ‘rhino-mousewheel’, plugins_url( ‘js/mousewheel.js’, __FILE__ ), array( ‘jquery’ ) );
 
    wp_register_script( ‘rhino-easing’, plugins_url( ‘js/easing.js’, __FILE__ ), array( ‘jquery’ ) );
 
    wp_register_script( ‘quiz’, plugins_url( ‘js/quiz.js’, __FILE__ ), array( ‘jquery’, ‘rhino’, ‘rhino-mousewheel’, ‘rhino-easing’ ) );
 
    wp_enqueue_script( ‘quiz’ );
 
    $quiz_duration = get_option( ‘wpq_duration’ );
 
    $quiz_duration = ( ! empty( $quiz_duration ) ) ?
 
    $config_array = array(
 
        ‘ajaxURL’ => admin_url( ‘admin-ajax.php’ ),
 
        ‘quizNonce’ => wp_create_nonce( ‘quiz-nonce’ ),
 
        ‘quizDuration’ => $quiz_duration,
 
        ‘plugin_url’ => $this->plugin_url
 
    );
 
    wp_localize_script( ‘quiz’, ‘quiz’, $config_array );
 
}

Здесь у нас есть три файла JavaScript, используемых для RhinoSlider, и файл quiz.js для пользовательских функций. В предыдущей части мы настраивали продолжительность викторины. Мы можем получить продолжительность, используя функцию get_option и назначить ее для массива $config . Кроме того, мы должны включить общие конфигурации в массив конфигурации.

Наконец, мы можем использовать функцию wp_localize_script чтобы назначить данные конфигурации в файле quiz.js.

Точно так же мы можем включить CSS-файлы, необходимые для Rhino Slider, используя следующий код.

1
2
3
4
5
6
7
function wpq_frontend_styles() {
 
    wp_register_style( ‘rhino-base’, plugins_url( ‘css/rhinoslider-1.05.css’, __FILE__ ) );
 
    wp_enqueue_style( ‘rhino-base’ );
 
}

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

1
2
3
add_action( ‘wp_enqueue_scripts’, array( $this, ‘wpq_frontend_scripts’ ) );
 
add_action( ‘wp_enqueue_scripts’, array( $this, ‘wpq_frontend_styles’ ) );

Все готово для интеграции слайдера с вопросами в шорткод, который мы создали ранее. Давайте двигаться вперед.

В настоящее время у нас есть два комментария внутри функции шорткода, упоминающие «Генерация HTML для вопросов» и «Слайдер внедрения». Эти разделы должны быть обновлены с соответствующим кодом для создания слайдера. Сначала нам нужно обновить цикл while следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
while ( $query->have_posts() ) : $query->the_post();
 
    $question_id = get_the_ID();
 
    $question = the_title( », », FALSE ) .
 
    $question_answers = json_decode( get_post_meta( $question_id, ‘_question_answers’, true ) );
 
    $questions_str .= ‘<li>’;
 
    $questions_str .= ‘<div class=»ques_title»><span class=»quiz_num»>’ .
 
    $questions_str .= ‘<div class=»ques_answers» data-quiz-id=»‘ . $question_id . ‘»>’;
 
    $quiestion_index = 1;
 
    foreach ( $question_answers as $key => $value ) {
 
        if ( » != $value ) {
 
            $questions_str .= $quiestion_index .
 
        }
 
        $quiestion_index++;
 
    }
 
    $questions_str .= ‘</div></li>’;
 
    $quiz_index++;
 
endwhile;

Код Объяснение

  • Внутри цикла сначала мы получаем вопрос, объединяя поля заголовка и содержимого для вопросов.
  • Затем мы получаем ответы на каждый вопрос с помощью функции get_post_meta .
  • Внутри цикла foreach все ответы будут назначены переключателям с необходимыми значениями.
  • Необходимые элементы списка будут назначены внутри цикла, включая атрибуты данных HTML, которые пригодятся в следующем разделе.
  • Конечным результатом цикла while будет строковая переменная, которая содержит список вопросов и их ответов, встроенных в HTML.

Далее нам нужно создать контейнеры для слайдера в разделе, который прокомментирован как «Внедрение слайдера». Следующий код содержит HTML-код для создания контейнеров.

1
2
3
4
5
6
7
$html .= ‘<ul id=»slider»>’ .
 
$html .= ‘<li id=»quiz_result_page»><div class=»ques_title»>Quiz Results <span id=»score»>
 
$html .= ‘<div id=»quiz_result»></div>’;
 
$html .= ‘</li></ul></div>’;

В качестве контейнера для Rhino Slider мы будем использовать неупорядоченный список с именем slider . Изначально мы включаем набор вопросов и ответов, сгенерированных внутри цикла, используя $questions_str . Он будет содержать коллекцию элементов списка.

Затем мы должны вручную создать еще один элемент списка, чтобы показать результаты теста и оценки.

Теперь все данные и слайды, необходимые для приложения викторины, настроены. Мы можем инициализировать Rhino Slider в quiz.js, чтобы увидеть тест в действии.

Я использовал несколько пользовательских стилей CSS для улучшения внешнего вида. Вы можете найти все модифицированные CSS в разделе wp_quiz файла rhinoslider-1.05.css . Теперь у вас должно быть что-то вроде следующего изображения.

Screenshot-206

Как только тест загружен, вы можете использовать элементы навигации для перемещения между вопросами и выбора ответов. Вы должны нажать кнопку «Получить результаты», как только ответы на все вопросы. Теперь нам нужно создать результаты теста, используя запрос AJAX.

Давайте реализуем код jQuery для выполнения запроса AJAX.

После нажатия кнопки «Получить результаты» мы вызываем функцию wpq_quiz_results используя jQuery. Каждый вопрос был добавлен в слайдер с помощью специального класса CSS под названием ques_answers .

ques_answers каждый элемент с ques_answers класса ques_answers , мы получаем идентификатор вопроса, используя атрибут data-quiz-id HTML с именем data-quiz-id а выбранный переключатель — с помощью jQuery.

Наконец, мы назначаем все вопросы и выбранные ответы в массив с именем selected_answers для передачи в запрос AJAX.

Взгляните на следующий код для реализации запроса AJAX.

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

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

1
2
3
add_action( ‘wp_ajax_nopriv_get_quiz_results’, array( $this, ‘get_quiz_results’ ) );
 
add_action( ‘wp_ajax_get_quiz_results’, array( $this, ‘get_quiz_results’ ) );

Затем мы можем перейти к реализации функции get_quiz_results как показано в следующем коде.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function get_quiz_results() {
 
    $score = 0;
 
    $question_answers = $_POST[«data»];
 
    $question_results = array();
 
    foreach ( $question_answers as $ques_id => $answer ) {
 
        $question_id = trim( str_replace( ‘qid_’, », $ques_id ) ) .
 
        $correct_answer = get_post_meta( $question_id, ‘_question_correct_answer’, true );
 
        if ( $answer == $correct_answer ) {
 
            $score++;
 
            $question_results[«$question_id»] = array( «answer» => $answer, «correct_answer» => $correct_answer, «mark» => «correct» );
 
        }
        else {
 
            $question_results[«$question_id»] = array( «answer» => $answer, «correct_answer» => $correct_answer, «mark» => «incorrect» );
 
        }
 
    }
 
    $total_questions = count( $question_answers );
 
    $quiz_result_data = array(
 
        «total_questions» => $total_questions,
 
        «score» => $score,
 
        «result» => $question_results
 
    );
 
    echo json_encode( $quiz_result_data );
 
    exit;
 
}

Код Объяснение

  • Выбранные ответы на все вопросы будут получены с использованием параметра data внутри массива $_POST .
  • Затем мы получаем идентификатор вопроса для каждого вопроса, заменяя префикс qid_ .
  • Далее мы получаем правильный ответ на каждый вопрос из базы данных, используя функцию get_post_meta .
  • Затем мы проверяем, соответствует ли предоставленный ответ правильному ответу, и создаем $question_results на основе состояния результата.
  • При проверке ответов нам нужно обновить оценку теста, используя переменную $score .
  • Наконец, мы присваиваем результаты и оценки $quiz_result_data массиву $quiz_result_data который будет отправлен в качестве ответа.

До сих пор мы создавали запрос AJAX и реализовывали ответ на стороне сервера. В следующем разделе мы собираемся завершить процесс генерации результатов теста, обрабатывая ответ AJAX.

В части обработки ответов у нас довольно много задач, включая отображение результатов и результатов тестов. Итак, я собираюсь разделить код на несколько разделов, чтобы пояснить это объяснение. Рассмотрим следующий код, который содержит полный запрос AJAX.

Пояснение к разделу 1

Сначала мы получаем общие вопросы теста из ответа, полученного с сервера. Затем мы используем next функцию Rhino Slider, чтобы перенаправить пользователя на слайд с результатами. Затем мы устанавливаем оценку пользователя с помощью общих вопросов внутри контейнера #score .

Пояснение к разделу 2

Начальная часть этого кода генерирует таблицу HTML с необходимыми заголовками для отображения результатов. Затем мы присваиваем вопросы таблице внутри each цикла jQuery. Мы использовали два изображения, чтобы отобразить статус вопроса об успехе или неудаче.

Пояснение к разделу 3

Первоначально мы должны разрешить прокрутку на странице результатов, так как она может быть довольно длинной для тестов с большим количеством вопросов. Атрибут CSS overflow-y используется для разрешения прокрутки. Наконец, мы устанавливаем таблицу результатов #quiz_result контейнер #quiz_result и скрываем таймер, который мы будем реализовывать в следующем разделе.

После завершения теста ваш экран должен выглядеть примерно так, как показано на следующем рисунке.

Screenshot-207

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

Давайте сосредоточимся на динамически меняющемся таймере с использованием кода jQuery, как показано ниже.

Продолжительность wp_localize_script определяется с использованием массива конфигурации, переданного с wp_localize_script функции wp_localize_script . Длительность затем конвертируется в секунды путем умножения на 60 .

Затем мы создаем функцию setTimeout для запуска таймера. Внутри функции мы сокращаем продолжительность на 1 и присваиваем контейнеру #timer . Когда время уменьшается до нуля, мы вызываем функцию wpq_quiz_results чтобы автоматически завершить тест и сгенерировать результаты.

Наконец, мы вызываем функцию setTimeout для обновления оставшегося времени. Мы завершили реализацию таймера, и ваш тест должен выглядеть следующим образом с таймером.

Screenshot-205

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

  • Создайте способ присваивать вопросы викторинам вместо создания случайных викторин.
  • Сохраните результаты теста для зарегистрированных пользователей.
  • Создать конкурс викторины между пользователями.

Дайте мне знать ваши предложения и как это происходит с процессом расширения плагина.

С нетерпением жду Вашего ответа.