/** * Show the forms where the quiz answers can be edited. * * @param Integer $quizID the ID of the quiz to be edited. * @param Object $page The associated page object for showing messages. */ function WPCW_showPage_ModifyQuiz_showQuestionEntryForms($quizID, $page) { global $wpdb, $wpcwdb; $wpdb->show_errors(); // Work out if we need correct answers or not. And what the pass mark is. $quizDetails = WPCW_quizzes_getQuizDetails($quizID, true, false, false); $needCorrectAnswers = 'survey' != $quizDetails->quiz_type; // Show the existing quiz questions as a series of forms. $quizItems = WPCW_quizzes_getListOfQuestions($quizID); // Show the number of correct answers the user must get in order to pass. if ('quiz_block' == $quizDetails->quiz_type) { $totalQs = WPCW_quizzes_calculateActualQuestionCount($quizID); $passQs = ceil($quizDetails->quiz_pass_mark / 100 * $totalQs); printf('<div class="wpcw_msg wpcw_msg_info">'); printf(__('The trainee will be required to correctly answer at least <b>%d of the %d</b> following questions (<b>at least %d%%</b>) to progress.', 'wp_courseware'), $passQs, $totalQs, $quizDetails->quiz_pass_mark); printf('</div>'); } // Got a quiz, and trainer is requiring to show answers. Tell them we can't show answers // as this quiz contains open-ended questions that need grading. if ($needCorrectAnswers && 'show_answers' == $quizDetails->quiz_show_answers && WPCW_quizzes_containsQuestionsNeedingManualGrading($quizItems)) { printf('<div class="wpcw_msg wpcw_msg_error">'); printf(__('This quiz contains questions that need <b>manual grading</b>, and you\'ve selected \'<b>Show Answers</b>\' when the user completes this quiz. ', 'wp_courseware') . '<br/><br/>' . __('Since answers cannot be shown to the user because they are not known at that stage, <b>answers cannot be shown</b>. To hide this message, select \'<b>No Answers</b>\' above.', 'wp_courseware')); printf('</div>'); } $errorCount = 0; global $errorCount; // Wrapper for questions printf('<ol class="wpcw_dragable_question_holder">'); if ($quizItems) { // Render edit form for each of the quizzes that already exist foreach ($quizItems as $quizItem) { switch ($quizItem->question_type) { case 'multi': $quizObj = new WPCW_quiz_MultipleChoice($quizItem); break; case 'truefalse': $quizObj = new WPCW_quiz_TrueFalse($quizItem); break; case 'open': $quizObj = new WPCW_quiz_OpenEntry($quizItem); break; case 'upload': $quizObj = new WPCW_quiz_FileUpload($quizItem); break; case 'random_selection': $quizObj = new WPCW_quiz_RandomSelection($quizItem); break; default: die(__('Unknown quiz type: ', 'wp_courseware') . $quizItem->question_type); break; } $quizObj->showErrors = true; $quizObj->needCorrectAnswers = $needCorrectAnswers; // Keep track of errors if ($quizObj && $quizObj->gotError) { $errorCount++; } echo $quizObj->editForm_toString(); } } printf('</ol>'); // Do any of the questions have residual errors? Tell the user. if ($errorCount > 0) { $page->showMessage(sprintf(__('%d of the questions below have errors. Please make corrections and then save the changes.', 'wp_courseware'), $errorCount), true); } $page->showPageMiddle('35%'); // Show the menu for saving and adding new items. WPCW_showPage_ModifyQuiz_FloatMenu($page); // Flag to indicate that questions have been updated. printf('<input type="hidden" name="survey_updated" value="survey_updated" />'); printf('<a name="new_question"></a>'); // The empty forms for adding a new question $quizItemDummy = new stdClass(); $quizItemDummy->question_question = ''; $quizItemDummy->question_correct_answer = false; $quizItemDummy->question_order = 0; $quizItemDummy->question_answer_type = false; $quizItemDummy->question_answer_hint = false; $quizItemDummy->question_answer_explanation = false; $quizItemDummy->question_answer_file_types = 'doc, pdf, jpg, png, jpeg, gif'; $quizItemDummy->question_image = false; $quizItemDummy->question_usage_count = 0; $quizItemDummy->question_multi_random_enable = 0; $quizItemDummy->question_multi_random_count = 5; // Create some dummy answers. $quizItemDummy->question_data_answers = serialize(array(1 => array('answer' => ''), 2 => array('answer' => ''), 3 => array('answer' => ''))); $quizFormsToCreate = array('new_multi' => 'WPCW_quiz_MultipleChoice', 'new_tf' => 'WPCW_quiz_TrueFalse', 'new_open' => 'WPCW_quiz_OpenEntry', 'new_upload' => 'WPCW_quiz_FileUpload', 'new_random_selection' => 'WPCW_quiz_RandomSelection'); // Create the dummy quiz objects foreach ($quizFormsToCreate as $dummyid => $objClass) { // Set placeholder class $quizItemDummy->question_id = $dummyid; // Create new object and set it up with defaults $quizObj = new $objClass($quizItemDummy); $quizObj->cssClasses .= ' wpcw_question_template'; $quizObj->showErrors = false; $quizObj->needCorrectAnswers = $needCorrectAnswers; $quizObj->editForm_questionNotSavedYet = true; echo $quizObj->editForm_toString(); } }
/** * Function that show a summary of the quizzes. */ function WPCW_showPage_QuizSummary_load() { global $wpcwdb, $wpdb; $wpdb->show_errors(); // Get the requested page number $paging_pageWanted = WPCW_arrays_getValue($_GET, 'pagenum') + 0; if ($paging_pageWanted == 0) { $paging_pageWanted = 1; } // Title for page with page number $titlePage = false; if ($paging_pageWanted > 1) { $titlePage = sprintf(' - %s %s', __('Page', 'wp_courseware'), $paging_pageWanted); } $page = new PageBuilder(false); $page->showPageHeader(__('Quiz & Survey Summary', 'wp_courseware') . $titlePage, '75%', WPCW_icon_getPageIconURL()); // Handle the quiz deletion before showing remaining quizzes... WPCW_quizzes_handleQuizDeletion($page); // Handle the sorting and filtering $orderBy = WPCW_arrays_getValue($_GET, 'orderby'); $ordering = WPCW_arrays_getValue($_GET, 'order'); // Validate ordering switch ($orderBy) { case 'quiz_title': case 'quiz_id': break; default: $orderBy = 'quiz_id'; break; } // Create opposite ordering for reversing it. $ordering_opposite = false; switch ($ordering) { case 'desc': $ordering_opposite = 'asc'; break; case 'asc': $ordering_opposite = 'desc'; break; default: $ordering = 'desc'; $ordering_opposite = 'asc'; break; } // Was a search string specified? Or a specific item? $searchString = WPCW_arrays_getValue($_GET, 's'); // Create WHERE string based search - Title or Description of Quiz $stringWHERE = false; if ($searchString) { $stringWHERE = $wpdb->prepare(" WHERE quiz_title LIKE %s OR quiz_desc LIKE %s ", '%' . $searchString . '%', '%' . $searchString . '%'); } $summaryPageURL = admin_url('admin.php?page=WPCW_showPage_QuizSummary'); // Show the form for searching ?> <form id="wpcw_quizzes_search_box" method="get" action="<?php echo $summaryPageURL; ?> "> <p class="search-box"> <label class="screen-reader-text" for="wpcw_quizzes_search_input"><?php _e('Search Quizzes', 'wp_courseware'); ?> </label> <input id="wpcw_quizzes_search_input" type="text" value="<?php echo $searchString; ?> " name="s"/> <input class="button" type="submit" value="<?php _e('Search Quizzes', 'wp_courseware'); ?> "/> <input type="hidden" name="page" value="WPCW_showPage_QuizSummary" /> </p> </form> <br/><br/> <?php $SQL_PAGING = "\n\t\t\tSELECT COUNT(*) as quiz_count \n\t\t\tFROM {$wpcwdb->quiz}\t\t\t\n\t\t\t{$stringWHERE}\n\t\t\tORDER BY quiz_id DESC \n\t\t"; $paging_resultsPerPage = 50; $paging_totalCount = $wpdb->get_var($SQL_PAGING); $paging_recordStart = ($paging_pageWanted - 1) * $paging_resultsPerPage + 1; $paging_recordEnd = $paging_pageWanted * $paging_resultsPerPage; $paging_pageCount = ceil($paging_totalCount / $paging_resultsPerPage); $paging_sqlStart = $paging_recordStart - 1; // Show search message - that a search has been tried. if ($searchString) { printf('<div class="wpcw_search_count">%s "%s" (%s %s) (<a href="%s">%s</a>)</div>', __('Search results for', 'wp_courseware'), htmlentities($searchString), $paging_totalCount, _n('result', 'results', $paging_totalCount, 'wp_courseware'), $summaryPageURL, __('reset', 'wp_courseware')); } // Do main query $SQL = "SELECT * \n\t\t\tFROM {$wpcwdb->quiz}\t\t\t\n\t\t\t{$stringWHERE}\n\t\t\tORDER BY {$orderBy} {$ordering}\n\t\t\tLIMIT {$paging_sqlStart}, {$paging_resultsPerPage}\t\t\t \n\t\t\t"; // These are already checked, so they are safe, hence no prepare() // Generate paging code $baseURL = WPCW_urls_getURLWithParams($summaryPageURL, 'pagenum') . "&pagenum="; $paging = WPCW_tables_showPagination($baseURL, $paging_pageWanted, $paging_pageCount, $paging_totalCount, $paging_recordStart, $paging_recordEnd); $quizzes = $wpdb->get_results($SQL); if ($quizzes) { $tbl = new TableBuilder(); $tbl->attributes = array('id' => 'wpcw_tbl_quiz_summary', 'class' => 'widefat wpcw_tbl'); // ID - sortable $sortableLink = sprintf('<a href="%s&order=%s&orderby=quiz_id"><span>%s</span><span class="sorting-indicator"></span></a>', $baseURL, 'quiz_id' == $orderBy ? $ordering_opposite : 'asc', __('ID', 'wp_courseware')); // ID - render $tblCol = new TableColumn($sortableLink, 'quiz_id'); $tblCol->headerClass = 'quiz_id' == $orderBy ? 'sorted ' . $ordering : 'sortable'; $tblCol->cellClass = "quiz_id"; $tbl->addColumn($tblCol); // Title - sortable $sortableLink = sprintf('<a href="%s&order=%s&orderby=quiz_title"><span>%s</span><span class="sorting-indicator"></span></a>', $baseURL, 'quiz_title' == $orderBy ? $ordering_opposite : 'asc', __('Quiz Title', 'wp_courseware')); // Title - render $tblCol = new TableColumn($sortableLink, 'quiz_title'); $tblCol->headerClass = 'quiz_title' == $orderBy ? 'sorted ' . $ordering : 'sortable'; $tblCol->cellClass = "quiz_title"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Associated Unit', 'wp_courseware'), 'associated_unit'); $tblCol->cellClass = "associated_unit"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Quiz Type', 'wp_courseware'), 'quiz_type'); $tblCol->cellClass = "quiz_type"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Show Answers', 'wp_courseware'), 'quiz_show_answers'); $tblCol->cellClass = "quiz_type wpcw_center"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Paging', 'wp_courseware'), 'quiz_use_paging'); $tblCol->cellClass = "quiz_type wpcw_center"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Questions', 'wp_courseware'), 'total_questions'); $tblCol->cellClass = "total_questions wpcw_center"; $tbl->addColumn($tblCol); $tblCol = new TableColumn(__('Actions', 'wp_courseware'), 'actions'); $tblCol->cellClass = "actions"; $tbl->addColumn($tblCol); // Stores course details in a mini cache to save lots of MySQL lookups. $miniCourseDetailCache = array(); // Format row data and show it. $odd = false; foreach ($quizzes as $quiz) { $data = array(); // URLs $editURL = admin_url('admin.php?page=WPCW_showPage_ModifyQuiz&quiz_id=' . $quiz->quiz_id); $surveyExportURL = admin_url('admin.php?page=WPCW_showPage_QuizSummary&wpcw_export=csv_export_survey_data&quiz_id=' . $quiz->quiz_id); // Maintain paging where possible. $deleteURL = $baseURL . '&action=delete&quiz_id=' . $quiz->quiz_id; // Basic Details $data['quiz_id'] = $quiz->quiz_id; // Quiz Title $data['quiz_title'] = sprintf('<b><a href="%s">%s</a></b>', $editURL, $quiz->quiz_title); if ($quiz->quiz_desc) { $data['quiz_title'] .= '<span class="wpcw_quiz_desc">' . $quiz->quiz_desc . '</span>'; } // Associated Unit if ($quiz->parent_unit_id > 0 && ($unitDetails = get_post($quiz->parent_unit_id))) { $data['associated_unit'] = sprintf('<span class="associated_unit_unit"><b>%s</b>: <a href="%s" target="_blank" title="%s \'%s\'...">%s</a></span>', __('Unit', 'wp_courseware'), get_permalink($unitDetails->ID), __('View ', 'wp_courseware'), $unitDetails->post_title, $unitDetails->post_title); // Also add associated course if (isset($miniCourseDetailCache[$quiz->parent_course_id])) { $courseDetails = $miniCourseDetailCache[$quiz->parent_course_id]; } else { // Save course details to cache (as likely to use it again). $courseDetails = $miniCourseDetailCache[$quiz->parent_course_id] = WPCW_courses_getCourseDetails($quiz->parent_course_id); } // Might not have course details. if ($courseDetails) { $data['associated_unit'] .= sprintf('<span class="associated_unit_course"><b>%s:</b> <a href="admin.php?page=WPCW_showPage_ModifyCourse&course_id=%d" title="%s \'%s\'...">%s</a></span>', __('Course', 'wp_courseware'), $courseDetails->course_id, __('Edit ', 'wp_courseware'), $courseDetails->course_title, $courseDetails->course_title); } } else { $data['associated_unit'] = 'n/a'; } // Showing Answers or paging? $data['quiz_show_answers'] = 'show_answers' == $quiz->quiz_show_answers ? '<span class="wpcw_tick"></span>' : '-'; $data['quiz_use_paging'] = 'use_paging' == $quiz->quiz_paginate_questions ? '<span class="wpcw_tick"></span>' : '-'; // Type of quiz $data['quiz_type'] = WPCW_quizzes_getQuizTypeName($quiz->quiz_type); // Show passmark for blocking quizzes. if ('quiz_block' == $quiz->quiz_type) { $data['quiz_type'] .= '<span class="wpcw_quiz_pass_info">' . sprintf(__('Min. Pass Mark of %d%%', 'wp_courseware'), $quiz->quiz_pass_mark) . '</span>'; } // Total number of questions $data['total_questions'] = WPCW_quizzes_calculateActualQuestionCount($quiz->quiz_id); // Actions $data['actions'] = '<ul class="wpcw_action_link_list">'; $data['actions'] .= sprintf('<li><a href="%s" class="button-primary">%s</a></li>', $editURL, __('Edit', 'wp_courseware')); $data['actions'] .= sprintf('<li><a href="%s" class="button-secondary wpcw_action_link_delete_quiz wpcw_action_link_delete" rel="%s">%s</a></li>', $deleteURL, __('Are you sure you wish to delete this quiz?', 'wp_courseware'), __('Delete', 'wp_courseware')); // Add export button for surveys if ('survey' == $quiz->quiz_type) { $data['actions'] .= sprintf('<li class="wpcw_action_item_newline"><a href="%s" class="button-secondary">%s</a></li>', $surveyExportURL, __('Export Responses', 'wp_courseware')); } $data['actions'] .= '</ul>'; // Odd/Even row colouring. $odd = !$odd; $tbl->addRow($data, $odd ? 'alternate' : ''); } // Finally show table echo $paging; echo $tbl->toString(); echo $paging; } else { printf('<p>%s</p>', __('There are currently no quizzes to show. Why not create one?', 'wp_courseware')); } $page->showPageFooter(); }