/**
 * Handle the question deletion from the question pool page.
 * @param PageBuilder $page The page rendering object.
 */
function WPCW_quizzes_handleQuestionDeletion($page)
{
    global $wpcwdb, $wpdb;
    $wpdb->show_errors();
    // Check that the question exists and deletion has been requested
    if (isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['question_id'])) {
        $questionID = $_GET['question_id'];
        $questionDetails = WPCW_questions_getQuestionDetails($questionID);
        // Only do deletion if question details are valid.
        if ($questionDetails) {
            // Get tags for questions
            $question_tags = WPCW_questions_getQuestionDetails($questionID, $getTagsToo = true);
            // Remove tags for each question
            foreach ($question_tags->tags as $question_tag) {
                WPCW_questions_tags_removeTag($questionID, $question_tag->question_tag_id);
            }
            // Delete question from question map
            $wpdb->query($wpdb->prepare("\n\t\t\t\tDELETE FROM {$wpcwdb->quiz_qs_mapping}\n\t\t\t\tWHERE question_id = %d\n\t\t\t", $questionDetails->question_id));
            // Finally delete question itself
            $wpdb->query($wpdb->prepare("\n\t\t\t\tDELETE FROM {$wpcwdb->quiz_qs} \n\t\t\t\tWHERE question_id = %d\n\t\t\t", $questionDetails->question_id));
            $page->showMessage(sprintf(__('The question \'%s\' was successfully deleted.', 'wp_courseware'), $questionDetails->question_question));
        }
        // end of if $questionDetails
    }
    // end of check for deletion action
}
/**
 * Shows the settings page for the plugin.
 */
function WPCW_showPage_Settings_load()
{
    $page = new PageBuilder(true);
    $page->showPageHeader(__('Training Courses - Settings', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
    // Check for update flag
    if (isset($_POST['update']) && $_POST['update'] == 'tables_force_upgrade') {
        $page->showMessage(__('Upgrading WP Courseware Tables...', 'wp_courseware'));
        flush();
        $installed_ver = get_option(WPCW_DATABASE_KEY) + 0;
        WPCW_database_upgradeTables($installed_ver, true, true);
        $page->showMessage(sprintf(__('%s tables have successfully been upgraded.', 'wp_courseware'), 'WP Courseware'));
    }
    $settingsFields = array('section_access_key' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML(__('Licence Key Settings', 'wp_courseware'))), 'licence_key' => array('label' => __('Licence Key', 'wp_courseware'), 'type' => 'text', 'desc' => __('Your licence key for the WP Courseware plugin.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 32, 'minlen' => 32, 'regexp' => '/^[A-Za-z0-9]+$/', 'error' => __('Please enter your 32 character licence key, which contains only letters and numbers.', 'wp_courseware'))), 'license_activation' => array('label' => __('Licence Activation', 'wp_courseware'), 'type' => 'radio', 'required' => 'true', 'data' => array('activate_license' => sprintf('<b>%s</b>', __('Activate', 'wp_courseware')), 'deactivate_license' => sprintf('<b>%s</b>', __('Deactivate', 'wp_courseware'))), 'desc' => __('If you want to receive updates to this plugin, select "Activate". Otherwise, select "Deactivate" to deactivate license. Selecting "Deactivate" will disable any future updates. Deactivating your license allows you to move your plugin to another site.', 'wp_courseware')), 'section_default_css' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML(__('Style &amp; Design Settings', 'wp_courseware'))), 'use_default_css' => array('label' => __('Use Default CSS?', 'wp_courseware'), 'type' => 'radio', 'required' => 'true', 'data' => array('show_css' => sprintf('<b>%s</b> - %s', __('Yes', 'wp_courseware'), __('Use default stylesheet for the frontend of the website.', 'wp_courseware')), 'hide_css' => sprintf('<b>%s</b> - %s', __('No', 'wp_courseware'), __('Don\'t use the default stylesheet for the frontend of the website (you\'ll write your own CSS)', 'wp_courseware'))), 'desc' => __('If you want to style your training course material yourself, you can disable the default stylesheet. If in doubt, select <b>Yes</b>.', 'wp_courseware')), 'section_link' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML(__('Powered By Link', 'wp_courseware'))), 'show_powered_by' => array('label' => __('Show Powered By Link?', 'wp_courseware'), 'type' => 'radio', 'required' => 'true', 'data' => array('show_link' => sprintf('<b>%s</b> - %s', __('Yes', 'wp_courseware'), __('Show the <em>\'Powered By WP Courseware\'</em> link.', 'wp_courseware')), 'hide_link' => sprintf('<b>%s</b> - %s', __('No', 'wp_courseware'), __('Don\'t show any powered-by links.', 'wp_courseware'))), 'desc' => __("Do you want to show a 'Powered By WP Courseware' link at the bottom of course outlines?", 'wp_courseware')), 'affiliate_id' => array('label' => __('Your Affiliate ID', 'wp_courseware'), 'type' => 'text', 'desc' => __("(Optional) Earn some money by providing your Affiliate ID, which will turn the <b>Powered By WP Courseware</b> into an affiliate link that earns you a percentage of every sale! If you are not an affiliate, login to the member portal to register and get your ID.", 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 15, 'minlen' => 1, 'regexp' => '/^[A-Za-z0-9\\-_]+$/', 'error' => __('Please enter your Affiliate ID, which is only a number..', 'wp_courseware'))));
    // Remove licence key for child multi-sites
    if (!WPCW_plugin_hasAdminRights()) {
        unset($settingsFields['section_access_key']);
        unset($settingsFields['licence_key']);
    }
    $settings = new SettingsForm($settingsFields, WPCW_DATABASE_SETTINGS_KEY, 'wpcw_form_settings_general');
    $settings->setSaveButtonLabel(__('Save ALL Settings', 'wp_courseware'));
    // Update messages for translation
    $settings->msg_settingsSaved = __('Settings successfully saved.', 'wp_courseware');
    $settings->msg_settingsProblem = __('There was a problem saving the settings.', 'wp_courseware');
    $settings->customFormErrorMsg = __('Sorry, but unfortunately there were some errors saving the course details. Please fix the errors and try again.', 'wp_courseware');
    $settings->setAllTranslationStrings(WPCW_forms_getTranslationStrings());
    // Form event handlers - processes the saved settings in some way
    $settings->afterSaveFunction = 'WPCW_showPage_Settings_afterSave';
    $settings->afterSaveFunction = 'edd_activate_license_WPCW';
    $settings->show();
    // Create little form to force upgrading tables if something went wrong during update.
    echo WPCW_forms_createBreakHTML(__("Upgrade Tables", 'wp_courseware'), false, true, 'wpcw_upgrade_tables');
    ?>
	
	<p><?php 
    _e("If you're getting any errors with WP Courseware relating to database tables when you've updated, you can force an upgrade of the database tables using the button below.", 'wp_courseware');
    ?>
</p>
	<?php 
    $form = new FormBuilder('tables_force_upgrade');
    $form->setSubmitLabel(__('Force Table Upgrade', 'wp_courseware'));
    echo $form->toString();
    // RHS Support Information
    $page->showPageMiddle('23%');
    WPCW_docs_showSupportInfo($page);
    WPCW_docs_showSupportInfo_News($page);
    WPCW_docs_showSupportInfo_Affiliate($page);
    $page->showPageFooter();
}
/**
 * Convert page/post to a course unit 
 */
function WPCW_showPage_ConvertPage_load()
{
    $page = new PageBuilder(false);
    $page->showPageHeader(__('Convert Page/Post to Course Unit', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
    // Future Feature - Check user can edit other people's pages - use edit_others_pages or custom capability.
    if (!current_user_can('manage_options')) {
        $page->showMessage(__('Sorry, but you are not allowed to edit this page/post.', 'wp_courseware'), true);
        $page->showPageFooter();
        return false;
    }
    // Check that post ID is valid
    $postID = WPCW_arrays_getValue($_GET, 'postid') + 0;
    $convertPost = get_post($postID);
    if (!$convertPost) {
        $page->showMessage(__('Sorry, but the specified page/post does not appear to exist.', 'wp_courseware'), true);
        $page->showPageFooter();
        return false;
    }
    // Check that post isn't already a course unit before trying change.
    // This is where the conversion takes place.
    if ('course_unit' != $convertPost->post_type) {
        // Confirm we want to do the conversion
        if (!isset($_GET['confirm'])) {
            $message = sprintf(__('Are you sure you wish to convert the <em>%s</em> to a course unit?', 'wp_courseware'), $convertPost->post_type);
            $message .= '<br/><br/>';
            // Yes Button
            $message .= sprintf('<a href="%s&postid=%d&confirm=yes" class="button-primary">%s</a>', admin_url('admin.php?page=WPCW_showPage_ConvertPage'), $postID, __('Yes, convert it', 'wp_courseware'));
            // Cancel
            $message .= sprintf('&nbsp;&nbsp;<a href="%s&postid=%d&confirm=no" class="button-secondary">%s</a>', admin_url('admin.php?page=WPCW_showPage_ConvertPage'), $postID, __('No, don\'t convert it', 'wp_courseware'));
            $page->showMessage($message);
            $page->showPageFooter();
            return false;
        } else {
            // Confirmed conversion
            if ($_GET['confirm'] == 'yes') {
                $postDetails = array();
                $postDetails['ID'] = $postID;
                $postDetails['post_type'] = 'course_unit';
                // Update the post into the database
                wp_update_post($postDetails);
            }
            // Cancelled conversion
            if ($_GET['confirm'] != 'yes') {
                $page->showMessage(__('Conversion to a course unit cancelled.', 'wp_courseware'), false);
                $page->showPageFooter();
                return false;
            }
        }
    }
    // Check conversion happened
    $convertedPost = get_post($postID);
    if ('course_unit' == $convertedPost->post_type) {
        $page->showMessage(sprintf(__('The page/post was successfully converted to a course unit. You can <a href="%s">now edit the course unit</a>.', 'wp_courseware'), admin_url(sprintf('post.php?post=%d&action=edit', $postID))));
    } else {
        $page->showMessage(__('Unfortunately, there was an error trying to convert the page/post to a course unit. Perhaps you could try again?', 'wp_courseware'), true);
    }
    $page->showPageFooter();
}
/**
 * Function that allows a quiz to be created or edited.
 */
function WPCW_showPage_ModifyQuiz_load()
{
    // Thickbox needed for random and quiz windows.
    add_thickbox();
    $page = new PageBuilder(true);
    $quizDetails = false;
    $adding = false;
    $quizID = false;
    // Check POST and GET
    if (isset($_GET['quiz_id'])) {
        $quizID = $_GET['quiz_id'] + 0;
    } else {
        if (isset($_POST['quiz_id'])) {
            $quizID = $_POST['quiz_id'] + 0;
        }
    }
    // Trying to edit a quiz
    if ($quizDetails = WPCW_quizzes_getQuizDetails($quizID, false, false, false)) {
        // Abort if quiz not found.
        if (!$quizDetails) {
            $page->showPageHeader(__('Edit Quiz/Survey', 'wp_courseware'), '70%', WPCW_icon_getPageIconURL());
            $page->showMessage(__('Sorry, but that quiz/survey could not be found.', 'wp_courseware'), true);
            $page->showPageFooter();
            return;
        } else {
            // Start form prolog - with quiz ID
            printf('<form method="POST" action="%s&quiz_id=%d" name="wpcw_quiz_details_modify" id="wpcw_quiz_details_modify">', admin_url('admin.php?page=WPCW_showPage_ModifyQuiz'), $quizDetails->quiz_id);
            $page->showPageHeader(__('Edit Quiz/Survey', 'wp_courseware'), '70%', WPCW_icon_getPageIconURL());
        }
    } else {
        // Start form prolog - no quiz ID
        printf('<form method="POST" action="%s" name="wpcw_quiz_details_modify" id="wpcw_quiz_details_modify">', admin_url('admin.php?page=WPCW_showPage_ModifyQuiz'));
        $page->showPageHeader(__('Add Quiz/Survey', 'wp_courseware'), '70%', WPCW_icon_getPageIconURL());
        $adding = true;
    }
    // Generate the tabs.
    $tabList = array('wpcw_section_break_quiz_general' => array('label' => __('General Settings', 'wp_courseware')), 'wpcw_section_break_quiz_logic' => array('label' => __('Quiz Behaviour Settings', 'wp_courseware')), 'wpcw_section_break_quiz_results' => array('label' => __('Result Settings', 'wp_courseware')), 'wpcw_section_break_quiz_custom_feedback' => array('label' => __('Custom Feedback', 'wp_courseware'), 'cssclass' => 'wpcw_quiz_only_tab'), 'wpcw_section_break_quiz_questions' => array('label' => __('Manage Questions', 'wp_courseware')));
    global $wpcwdb;
    $formDetails = array('wpcw_section_break_quiz_general' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab(false)), 'quiz_title' => array('label' => __('Quiz Title', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_quiz_title', 'desc' => __('The title of your quiz or survey. Your trainees will be able to see this quiz title.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 150, 'minlen' => 1, 'regexp' => '/^[^<>]+$/', 'error' => __('Please specify a name for your quiz or survey, up to a maximum of 150 characters, just no angled brackets (&lt; or &gt;).', 'wp_courseware'))), 'quiz_desc' => array('label' => __('Quiz/Survey Description', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_quiz_desc', 'rows' => 2, 'desc' => __('(Optional) The description of this quiz. Your trainees won\'t see this description. It\'s just for your reference.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the description of your quiz to 5000 characters.', 'wp_courseware'))), 'quiz_type' => array('label' => __('Quiz Type', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_quiz_type wpcw_quiz_type_hide_pass', 'data' => array('survey' => __('<b>Survey Mode</b> - No correct answers, just collect information.', 'wp_courseware'), 'quiz_block' => __('<b>Quiz Mode - Blocking</b> - require trainee to correctly answer questions before proceeding. Trainee must achieve <b>minimum pass mark</b> to progress to the next unit.', 'wp_courseware'), 'quiz_noblock' => __('<b>Quiz Mode - Non-blocking</b> - require trainee to answer a number of questions before proceeding, but allow them to progress to the next unit <b>regardless of their pass mark</b>.', 'wp_courseware'))), 'wpcw_section_break_quiz_logic' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab(false)), 'quiz_pass_mark' => array('label' => __('Pass Mark', 'wp_courseware'), 'type' => 'select', 'required' => true, 'cssclass' => 'wpcw_quiz_block_only wpcw_quiz_only', 'data' => WPCW_quizzes_getPercentageList(__('-- Select a pass mark --', 'wp_courseware')), 'desc' => __('The minimum pass mark that your trainees need to achieve to progress on to the next unit.', 'wp_courseware')), 'quiz_attempts_allowed' => array('label' => __('Number of Attempts Allowed?', 'wp_courseware'), 'type' => 'select', 'required' => true, 'cssclass' => 'wpcw_quiz_block_only wpcw_quiz_only', 'data' => WPCW_quizzes_getAttemptList(), 'desc' => __('The maximum number of attempts that a trainee is given to complete a quiz for blocking quizzes.', 'wp_courseware')), 'quiz_show_survey_responses' => array('label' => __('Show Survey Responses?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_survey_only', 'data' => array('show_responses' => __('<b>Show Responses</b> - Show the trainee their survey responses.', 'wp_courseware'), 'no_responses' => __('<b>No Responses</b> - Don\'t show the trainee their survey responses.', 'wp_courseware')), 'desc' => __('This setting allows you to choose whether or not you want students to be able to review their past survey responses when they return to units.', 'wp_courseware')), 'quiz_paginate_questions' => array('label' => __('Paginate Questions?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_quiz_paginate_questions', 'data' => array('use_paging' => __('<b>Use Paging</b> - This setting will display quiz questions one at a time allowing students to progress through questions individually within a frame in your unit page.', 'wp_courseware'), 'no_paging' => __('<b>No Paging</b> - Don\'t use any paging. Show all quiz questions at once on the unit page.', 'wp_courseware')), 'suffix_subitems' => array('use_paging' => array('quiz_paginate_questions_settings' => array('type' => 'checkboxlist', 'required' => false, 'cssclass' => 'wpcw_quiz_paginate_questions_group', 'data' => array('allow_review_before_submission' => '<b>' . __('Allow Review Before Final Submission', 'wp_courseware') . '</b> - ' . __('If selected, students will be presented with an opportunity to review an editable list of all answers before final submission.', 'wp_courseware'), 'allow_students_to_answer_later' => '<b>' . __('Allow Students to Answer Later', 'wp_courseware') . '</b> - ' . __('If selected, the student will be able to click the "Answer Later" button and progress to the next question without answering. The question will be presented again at the end of the quiz.', 'wp_courseware'), 'allow_nav_previous_questions' => '<b>' . __('Allow Navigation to Previous Questions', 'wp_courseware') . '</b> - ' . __('If selected, a "Previous Question" button will be displayed, allowing students to freely navigate backwards and forwards through questions.', 'wp_courseware')))))), 'quiz_timer_mode' => array('label' => __('Set Time Limit for Quiz?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_quiz_timer_mode wpcw_quiz_block_only', 'data' => array('use_timer' => __('<b>Specify a Quiz Time Limit</b> - Give the trainee a fixed amount of time to complete the quiz.', 'wp_courseware'), 'no_timer' => __('<b>No Time Limit</b> - the trainee can take as long as they wish to complete the quiz.', 'wp_courseware'))), 'quiz_timer_mode_limit' => array('label' => __('Time Limit (in minutes)', 'wp_courseware'), 'type' => 'text', 'required' => false, 'cssclass' => 'wpcw_quiz_timer_mode_limit wpcw_quiz_timer_mode_active_only wpcw_quiz_block_only', 'extrahtml' => __('Minutes', 'wp_courseware'), 'validate' => array('type' => 'number', 'max' => 1000, 'min' => 1, 'error' => 'Please choose time limit between 1 and 1000 minutes.')), 'wpcw_section_break_quiz_results' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab(false)), 'quiz_show_answers' => array('label' => __('Show Answers?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_quiz_show_answers wpcw_quiz_only', 'data' => array('show_answers' => __('<b>Show Answers</b> - Show the trainee the correct answers before they progress.', 'wp_courseware'), 'no_answers' => __('<b>No Answers</b> - Don\'t show the trainee any answers before they progress.', 'wp_courseware')), 'extrahtml' => '<div class="wpcw_msg_info wpcw_msg wpcw_msg_in_form wpcw_msg_error_no_answers_selected" style="display: none">' . __('If this option is selected, students will not be able to view correct or incorrect answers.', 'wp_courseware') . '</div>', 'suffix_subitems' => array('show_answers' => array('show_answers_settings' => array('type' => 'checkboxlist', 'required' => false, 'cssclass' => '', 'errormsg' => __('Please choose at least one option when showing correct answers.', 'wp_courseware'), 'data' => array('show_correct_answer' => '<b>' . __('Show correct answer', 'wp_courseware') . '</b> - ' . __('Show the trainee the correct answers before they progress.', 'wp_courseware'), 'show_user_answer' => '<b>' . __('Show user\'s answer', 'wp_courseware') . '</b> - ' . __('Show the trainee the answer they submitted before they progress.', 'wp_courseware'), 'show_explanation' => '<b>' . __('Show explanation', 'wp_courseware') . '</b> - ' . __('Show the trainee an explanation for the correct answer (if there is one).', 'wp_courseware'), 'mark_answers' => '<b>' . __('Mark Answers', 'wp_courseware') . '</b> - ' . __('This option will show correct answers with a green check mark, and incorrect answers with a red "X".', 'wp_courseware'), 'show_results_later' => '<b>' . __('Leave quiz results available for later viewing?', 'wp_courseware') . '</b> - ' . __('This setting allows you to choose whether or not you want students to be able to review their past quiz answers when they return to units.', 'wp_courseware')), 'extrahtml' => '<div class="wpcw_msg_error wpcw_msg wpcw_msg_in_form wpcw_msg_error_show_answers_none_selected" style="display: none">' . __('To make use of this showing answers setting, at least one of the above settings should be ticked. Otherwise, no answers are actually shown.', 'wp_courseware') . '</div>')))), 'quiz_results_by_tag' => array('label' => __('Show Results by Tag?', 'wp_courseware'), 'type' => 'checkbox', 'required' => false, 'extralabel' => __('<b>Display results by question tag</b> - In addition to the overall score, indicate a breakdown of the results for each question tag.', 'wp_courseware')), 'quiz_results_by_timer' => array('label' => __('Show Completion Time?', 'wp_courseware'), 'type' => 'checkbox', 'required' => false, 'cssclass' => 'wpcw_quiz_timer_mode_active_only wpcw_quiz_block_only', 'extralabel' => __('<b>Display completion time for timed quiz</b> - If the quiz has been timed, this option will display the student\'s total time used for completing the quiz.', 'wp_courseware')));
    $form = new RecordsForm($formDetails, $wpcwdb->quiz, 'quiz_id', false, 'wpcw_quiz_details_modify');
    $form->customFormErrorMsg = __('Sorry, but unfortunately there were some errors saving the quiz details. Please fix the errors and try again.', 'wp_courseware');
    $form->setAllTranslationStrings(WPCW_forms_getTranslationStrings());
    // Got to summary of quizzes
    $directionMsg = '<br/></br>' . sprintf(__('Do you want to return to the <a href="%s">quiz summary page</a>?', 'wp_courseware'), admin_url('admin.php?page=WPCW_showPage_QuizSummary'));
    // Override success messages
    $form->msg_record_created = __('Quiz details successfully created.', 'wp_courseware') . $directionMsg;
    $form->msg_record_updated = __('Quiz details successfully updated.', 'wp_courseware') . $directionMsg;
    $form->setPrimaryKeyValue($quizID);
    $form->setSaveButtonLabel(__('Save All Quiz Settings &amp; Questions', 'wp_courseware'));
    // Do default checking based on quiz type.
    $form->filterBeforeSaveFunction = 'WPCW_actions_quizzes_beforeQuizSaved';
    $form->afterSaveFunction = 'WPCW_actions_quizzes_afterQuizSaved';
    // Set defaults when creating a new one
    if ($adding) {
        $form->loadDefaults(array('quiz_pass_mark' => 50, 'quiz_type' => 'quiz_noblock', 'quiz_show_survey_responses' => 'no_responses', 'quiz_show_answers' => 'show_answers', 'show_answers_settings' => array('show_correct_answer' => 'on', 'show_user_answer' => 'on', 'show_explanation' => 'on', 'mark_answers' => 'on', 'show_results_later' => 'on'), 'quiz_paginate_questions' => 'no_paging', 'quiz_paginate_questions_settings' => array('allow_review_before_submission' => 'on', 'allow_students_to_answer_later' => 'on', 'allow_nav_previous_questions' => 'on'), 'quiz_timer_mode' => 'no_timer', 'quiz_timer_mode_limit' => '15', 'quiz_results_by_tag' => 'on', 'quiz_results_by_timer' => 'on'));
    }
    // Get the rendered form, extract the start and finish form tags so that
    // we can use the form across multiple panes, and submit other data such
    // as questions along with the quiz itself. We're doing this because the RecordsForm
    // object actually does a really good job, so we don't want to refactor to remove it.
    $formHTML = $form->getHTML();
    $formHTML = preg_replace('/^(\\s*?)(<form(.*?>))/', '', $formHTML);
    $formHTML = preg_replace('/<\\/form>(\\s*?)$/', '', $formHTML);
    // Need to move the submit button to before the closing form tag to allow it
    // to render on the page as expected after the questions drag-n-drop section.
    // Don't bother if we're not showing any questions yet though.
    $buttonHTML = false;
    if ($form->primaryKeyValue > 0) {
        $pattern = '/<p class="submit">(\\C*?)<\\/p>/';
        if (preg_match($pattern, $formHTML, $matches)) {
            // Found it, so add to variable to show later, and strip
            // it from the HTML so far.
            $buttonHTML = $matches[0];
            $formHTML = str_replace($buttonHTML, false, $formHTML);
        }
    }
    // Not got any questions to show yet, so hide questions tab.
    if ($form->primaryKeyValue <= 0) {
        unset($tabList['wpcw_section_break_quiz_questions']);
        unset($tabList['wpcw_section_break_quiz_custom_feedback']);
    }
    // Show a placeholder for an error message that may occur within tabs.
    printf('<div class="wpcw_msg wpcw_msg_error wpcw_section_error_within_tabs">%s</div>', __('Unfortunately, there are a few missing details that need to be added before this quiz can be saved. Please resolve them and try again.', 'wp_courseware'));
    // Render the tabs
    echo WPCW_tabs_generateTabHeader($tabList, 'wpcw_quizzes_tabs');
    // The main quiz settings
    echo $formHTML;
    // Try to see if we've got an ID having saved the form from a first add
    // or we're editing the form
    if ($form->primaryKeyValue > 0) {
        $quizID = $form->primaryKeyValue;
        // Top for jumps.
        printf('<a name="top"></a>');
        // ### 1) Custom Feedback Messages
        printf('<div class="wpcw_form_break_tab"></div>');
        printf('<div class="form-table" id="wpcw_section_break_quiz_custom_feedback">');
        WPCW_showPage_customFeedback_showEditForms($quizID, $page);
        printf('</div>');
        // ### 2) Question Settings
        printf('<div class="wpcw_form_break_tab"></div>');
        printf('<div class="form-table" id="wpcw_section_break_quiz_questions">');
        WPCW_showPage_ModifyQuiz_showQuestionEntryForms($quizID, $page);
        printf('</div>');
    }
    // Reshow the button here
    echo $buttonHTML;
    // The closing form tag
    echo '</form>';
    // .wpcw_tab_wrapper
    echo '</div>';
    // The thickboxes for the page
    WPCW_showPage_thickbox_questionPool();
    WPCW_showPage_thickbox_randomQuestion();
    $page->showPageFooter();
}
/**
 * Shows a detailed summary of the user's quiz or survey answers.
 */
function WPCW_showPage_UserProgess_quizAnswers_load()
{
    global $wpcwdb, $wpdb;
    $wpdb->show_errors();
    $page = new PageBuilder(false);
    $page->showPageHeader(__('Detailed User Quiz/Survey Results', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
    $userID = WPCW_arrays_getValue($_GET, 'user_id') + 0;
    $unitID = WPCW_arrays_getValue($_GET, 'unit_id') + 0;
    $quizID = WPCW_arrays_getValue($_GET, 'quiz_id') + 0;
    // Create a link back to the detailed user progress, and back to all users.
    printf('<div class="wpcw_button_group">');
    // Link back to all user summary
    printf('<a href="%s" class="button-secondary">%s</a>&nbsp;&nbsp;', admin_url('users.php'), __('&laquo; Return to User Summary', 'wp_courseware'));
    if ($userDetails = get_userdata($userID)) {
        // Link back to user's personal summary
        printf('<a href="%s&user_id=%d" class="button-secondary">%s</a>&nbsp;&nbsp;', admin_url('users.php?page=WPCW_showPage_UserProgess'), $userDetails->ID, sprintf(__('&laquo; Return to <b>%s\'s</b> Progress Report', 'wp_courseware'), $userDetails->display_name));
    }
    // Try to get the full detailed results.
    $results = WPCW_quizzes_getUserResultsForQuiz($userID, $unitID, $quizID);
    // No results, so abort.
    if (!$results) {
        // Close the button wrapper for above early
        printf('</div>');
        // .wpcw_button_group
        $page->showMessage(__('Sorry, but no results could be found.', 'wp_courseware'), true);
        $page->showPageFooter();
        return;
    }
    // Could potentially have an issue where the quiz has been deleted
    // but the data exists.. small chance though.
    $quizDetails = WPCW_quizzes_getQuizDetails($quizID, true, true, $userID);
    // Extra button - return to gradebook
    printf('<a href="%s&course_id=%d" class="button-secondary">%s</a>&nbsp;&nbsp;', admin_url('admin.php?page=WPCW_showPage_GradeBook'), $quizDetails->parent_course_id, __("&laquo; Return to Gradebook", 'wp_courseware'));
    printf('</div>');
    // .wpcw_button_group
    // #### 1 - Handle grades being updated
    $results = WPCW_showPage_UserProgess_quizAnswers_handingGrading($quizDetails, $results, $page, $userID, $unitID);
    // #### 2A - Check if next action for user has been triggered by the admin.
    $results = WPCW_showPage_UserProgess_quizAnswers_whatsNext_savePreferences($quizDetails, $results, $page, $userID, $unitID);
    // #### 2B - Handle telling admin what's next
    WPCW_showPage_UserProgess_quizAnswers_whatsNext($quizDetails, $results, $page, $userID, $unitID);
    //Ê#### 3 - Handle sending emails if something has changed.
    if (isset($results->sendOutEmails) && $results->sendOutEmails) {
        $extraDetail = isset($results->extraEmailDetail) ? $results->extraEmailDetail : '';
        // Only called if the quiz was graded.
        if (isset($results->quiz_has_just_been_graded) && $results->quiz_has_just_been_graded) {
            // Need to call the action anyway, but any functions hanging off this
            // should check if the admin wants users to have notifications or not.
            do_action('wpcw_quiz_graded', $userID, $quizDetails, number_format($results->quiz_grade, 1), $extraDetail);
        }
        $courseDetails = WPCW_courses_getCourseDetails($quizDetails->parent_course_id);
        if ($courseDetails->email_quiz_grade_option == 'send_email') {
            // Message is only if quiz has been graded.
            if (isset($results->quiz_has_just_been_graded) && $results->quiz_has_just_been_graded) {
                $page->showMessage(__('The user has been sent an email with their grade for this course.', 'wp_courseware'));
            }
        }
    }
    // #### - Table 1 - Overview
    printf('<h3>%s</h3>', __('Quiz/Survey Overview', 'wp_courseware'));
    $tbl = new TableBuilder();
    $tbl->attributes = array('id' => 'wpcw_tbl_progress_quiz_info', 'class' => 'widefat wpcw_tbl');
    $tblCol = new TableColumn(false, 'quiz_label');
    $tblCol->cellClass = 'wpcw_tbl_label';
    $tbl->addColumn($tblCol);
    $tblCol = new TableColumn(false, 'quiz_detail');
    $tbl->addColumn($tblCol);
    // These are the base details for the quiz to show.
    $summaryData = array(__('Quiz Title', 'wp_courseware') => $quizDetails->quiz_title, __('Quiz Description', 'wp_courseware') => $quizDetails->quiz_desc, __('Quiz Type', 'wp_courseware') => WPCW_quizzes_getQuizTypeName($quizDetails->quiz_type), __('No. of Questions', 'wp_courseware') => $results->quiz_question_total, __('Completed Date', 'wp_courseware') => __('About', 'wp_courseware') . ' ' . human_time_diff($results->quiz_completed_date_ts) . ' ' . __('ago', 'wp_courseware') . '<br/><small>(' . date('D jS M Y \\a\\t H:i:s', $results->quiz_completed_date_ts) . ')</small>', __('Number of Quiz Attempts', 'wp_courseware') => $results->attempt_count, __('Permitted Quiz Attempts', 'wp_courseware') => -1 == $quizDetails->quiz_attempts_allowed ? __('Unlimited', 'wp_courseware') : $quizDetails->quiz_attempts_allowed);
    // Quiz details relating to score, etc.
    if ('survey' != $quizDetails->quiz_type) {
        $summaryData[__('Pass Mark', 'wp_courseware')] = $quizDetails->quiz_pass_mark . '%';
        // Still got items to grade
        if ($results->quiz_needs_marking > 0) {
            $summaryData[__('No. of Questions to Grade', 'wp_courseware')] = '<span class="wpcw_status_info wpcw_icon_pending">' . $results->quiz_needs_marking . '</span>';
            $summaryData[__('Overall Grade', 'wp_courseware')] = '<span class="wpcw_status_info wpcw_icon_pending">' . __('Awaiting Final Grading', 'wp_courseware') . '</span>';
        } else {
            $summaryData[__('No. of Question to Grade', 'wp_courseware')] = '-';
            // Show if PASSED or FAILED with the overall grade.
            $gradeData = false;
            if ($results->quiz_grade >= $quizDetails->quiz_pass_mark) {
                $gradeData = sprintf('<span class="wpcw_tbl_progress_quiz_overall wpcw_question_yesno_status wpcw_question_yes">%s%% %s</span>', number_format($results->quiz_grade, 1), __('Passed', 'wp_courseware'));
            } else {
                $gradeData = sprintf('<span class="wpcw_tbl_progress_quiz_overall wpcw_question_yesno_status wpcw_question_no">%s%% %s</span>', number_format($results->quiz_grade, 1), __('Failed', 'wp_courseware'));
            }
            $summaryData[__('Overall Grade', 'wp_courseware')] = $gradeData;
        }
    }
    foreach ($summaryData as $label => $data) {
        $tbl->addRow(array('quiz_label' => $label . ':', 'quiz_detail' => $data));
    }
    echo $tbl->toString();
    // ### 4 - Form Code - to allow instructor to send data back to
    printf('<form method="POST" id="wpcw_tbl_progress_quiz_grading_form">');
    printf('<input type="hidden" name="grade_answers_submitted" value="true">');
    // ### 5 - Table 2 - Each Specific Quiz
    $questionNumber = 0;
    if ($results->quiz_data && count($results->quiz_data) > 0) {
        foreach ($results->quiz_data as $questionID => $answer) {
            $data = $answer;
            // Get the question type
            if (isset($quizDetails->questions[$questionID])) {
                // Store as object for easy reference.
                $quObj = $quizDetails->questions[$questionID];
                // Render the question as a table.
                printf('<h3>%s #%d - %s</h3>', __('Question', 'wp_courseware'), ++$questionNumber, $quObj->question_question);
                $tbl = new TableBuilder();
                $tbl->attributes = array('id' => 'wpcw_tbl_progress_quiz_info', 'class' => 'widefat wpcw_tbl wpcw_tbl_progress_quiz_answers_' . $quObj->question_type);
                $tblCol = new TableColumn(false, 'quiz_label');
                $tblCol->cellClass = 'wpcw_tbl_label';
                $tbl->addColumn($tblCol);
                $tblCol = new TableColumn(false, 'quiz_detail');
                $tbl->addColumn($tblCol);
                $theirAnswer = false;
                switch ($quObj->question_type) {
                    case 'truefalse':
                    case 'multi':
                        $theirAnswer = $answer['their_answer'];
                        break;
                        // File Upload - create a download link
                    // File Upload - create a download link
                    case 'upload':
                        $theirAnswer = sprintf('<a href="%s%s" target="_blank" class="button-primary">%s .%s %s (%s)</a>', WP_CONTENT_URL, $answer['their_answer'], __('Open', 'wp_courseware'), pathinfo($answer['their_answer'], PATHINFO_EXTENSION), __('File', 'wp_courseware'), WPCW_files_getFileSize_human($answer['their_answer']));
                        break;
                        // Open Ended - Wrap in span tags, to cap the size of the field, and format new lines.
                    // Open Ended - Wrap in span tags, to cap the size of the field, and format new lines.
                    case 'open':
                        $theirAnswer = '<span class="wpcw_q_answer_open_wrap"><textarea readonly>' . $data['their_answer'] . '</textarea></span>';
                        break;
                }
                // end of $theirAnswer check
                $summaryData = array(__('Type', 'wp_courseware') => array('data' => WPCW_quizzes_getQuestionTypeName($quObj->question_type), 'cssclass' => ''), __('Their Answer', 'wp_courseware') => array('data' => $theirAnswer, 'cssclass' => ''));
                // Just for quizzes - show answers/grade
                if ('survey' != $quizDetails->quiz_type) {
                    switch ($quObj->question_type) {
                        case 'truefalse':
                        case 'multi':
                            // The right answer...
                            $summaryData[__('Correct Answer', 'wp_courseware')] = array('data' => $answer['correct'], 'cssclass' => '');
                            // Did they get it right?
                            $getItRight = sprintf('<span class="wpcw_question_yesno_status wpcw_question_%s">%s</span>', $answer['got_right'], 'yes' == $answer['got_right'] ? __('Yes', 'wp_courseware') : __('No', 'wp_courseware'));
                            $summaryData[__('Did they get it right?', 'wp_courseware')] = array('data' => $getItRight, 'cssclass' => '');
                            break;
                        case 'upload':
                        case 'open':
                            $gradeHTML = false;
                            $theirGrade = WPCW_arrays_getValue($answer, 'their_grade');
                            // Not graded - show select box.
                            if ($theirGrade == 0) {
                                $cssClass = 'wpcw_grade_needs_grading';
                            } else {
                                $cssClass = 'wpcw_grade_already_graded';
                                $gradeHTML = sprintf('<span class="wpcw_grade_view">%d%% <a href="#">(%s)</a></span>', $theirGrade, __('Click to edit', 'wp_courseware'));
                            }
                            // Not graded yet, allow admin to grade the quiz, or change
                            // the grading later if they want to.
                            $gradeHTML .= WPCW_forms_createDropdown('grade_quiz_' . $quObj->question_id, WPCW_quizzes_getPercentageList(__('-- Select a grade --', 'wp_courseware')), $theirGrade, false, 'wpcw_tbl_progress_quiz_answers_grade');
                            $summaryData[__('Their Grade', 'wp_courseware')] = array('data' => $gradeHTML, 'cssclass' => $cssClass);
                            break;
                    }
                }
                // Check of showing the right answer.
                foreach ($summaryData as $label => $data) {
                    $tbl->addRow(array('quiz_label' => $label . ':', 'quiz_detail' => $data['data']), $data['cssclass']);
                }
                echo $tbl->toString();
            }
            // end if (isset($quizDetails->questions[$questionID]))
        }
        // foreach ($results->quiz_data as $questionID => $answer)
    }
    printf('</form>');
    // Shows a bar that pops up, allowing the user to easily save all grades that have changed.
    ?>
	<div id="wpcw_sticky_bar" style="display: none">
		<div id="wpcw_sticky_bar_inner">
			<a href="#" id="wpcw_tbl_progress_quiz_grading_updated" class="button-primary"><?php 
    _e('Save Changes to Grades', 'wp_courseware');
    ?>
</a>
			<span id="wpcw_sticky_bar_status" title="<?php 
    _e('Grades have been changed. Ready to save changes?', 'wp_courseware');
    ?>
"></span>
		</div>
	</div>
	<br/><br/><br/><br/>
	<?php 
    $page->showPageFooter();
}
/** 
 * Page where the site owner can choose which courses a user is allowed to access.
 */
function WPCW_showPage_UserCourseAccess_load()
{
    global $wpcwdb, $wpdb;
    $wpdb->show_errors();
    $page = new PageBuilder(false);
    $page->showPageHeader(__('Update User Course Access Permissions', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
    // Check passed user ID is valid
    $userID = WPCW_arrays_getValue($_GET, 'user_id');
    $userDetails = get_userdata($userID);
    if (!$userDetails) {
        $page->showMessage(__('Sorry, but that user could not be found.', 'wp_courseware'), true);
        $page->showPageFooter();
        return false;
    }
    printf(__('<p>Here you can change which courses the user <b>%s</b> (Username: <b>%s</b>) can access.</p>', 'wp_courseware'), $userDetails->data->display_name, $userDetails->data->user_login);
    // Check to see if anything has been submitted?
    if (isset($_POST['wpcw_course_user_access'])) {
        $subUserID = WPCW_arrays_getValue($_POST, 'user_id') + 0;
        $userSubDetails = get_userdata($subUserID);
        // Check that user ID is valid, and that it matches user we're editing.
        if (!$userSubDetails || $subUserID != $userID) {
            $page->showMessage(__('Sorry, but that user could not be found. The changes were not saved.', 'wp_courseware'), true);
        } else {
            // Get list of courses that user is allowed to access from the submitted values.
            $courseAccessIDs = array();
            foreach ($_POST as $key => $value) {
                // Check for course ID selection
                if (preg_match('/^wpcw_course_(\\d+)$/', $key, $matches)) {
                    $courseAccessIDs[] = $matches[1];
                }
            }
            // Sync courses that the user is allowed to access
            WPCW_courses_syncUserAccess($subUserID, $courseAccessIDs, 'sync');
            // Final success message
            $message = sprintf(__('The courses for user <em>%s</em> have now been updated.', 'wp_courseware'), $userDetails->data->display_name);
            $page->showMessage($message, false);
        }
    }
    $SQL = "SELECT * \n\t\t\tFROM {$wpcwdb->courses}\n\t\t\tORDER BY course_title ASC \n\t\t\t";
    $courses = $wpdb->get_results($SQL);
    if ($courses) {
        $tbl = new TableBuilder();
        $tbl->attributes = array('id' => 'wpcw_tbl_course_access_summary', 'class' => 'widefat wpcw_tbl');
        $tblCol = new TableColumn(__('Allowed Access', 'wp_courseware'), 'allowed_access');
        $tblCol->cellClass = "allowed_access";
        $tbl->addColumn($tblCol);
        $tblCol = new TableColumn(__('Course Title', 'wp_courseware'), 'course_title');
        $tblCol->cellClass = "course_title";
        $tbl->addColumn($tblCol);
        $tblCol = new TableColumn(__('Description', 'wp_courseware'), 'course_desc');
        $tblCol->cellClass = "course_desc";
        $tbl->addColumn($tblCol);
        // Format row data and show it.
        $odd = false;
        foreach ($courses as $course) {
            $data = array();
            // Basic details
            $data['course_desc'] = $course->course_desc;
            $editURL = admin_url('admin.php?page=WPCW_showPage_ModifyCourse&course_id=' . $course->course_id);
            $data['course_title'] = sprintf('<a href="%s">%s</a>', $editURL, $course->course_title);
            // Checkbox if enabled or not
            $userAccess = WPCW_courses_canUserAccessCourse($course->course_id, $userID);
            $checkedHTML = $userAccess ? 'checked="checked"' : '';
            $data['allowed_access'] = sprintf('<input type="checkbox" name="wpcw_course_%d" %s/>', $course->course_id, $checkedHTML);
            // Odd/Even row colouring.
            $odd = !$odd;
            $tbl->addRow($data, $odd ? 'alternate' : '');
        }
        // Create a form so user can update access.
        ?>
		<form action="<?php 
        str_replace('%7E', '~', $_SERVER['REQUEST_URI']);
        ?>
" method="post">
			<?php 
        // Finally show table
        echo $tbl->toString();
        ?>
			<input type="hidden" name="user_id" value="<?php 
        echo $userID;
        ?>
"> 
			<input type="submit" class="button-primary" name="wpcw_course_user_access" value="<?php 
        _e('Save Changes', 'wp_courseware');
        ?>
" />
		</form>
		<?php 
    } else {
        printf('<p>%s</p>', __('There are currently no courses to show. Why not create one?', 'wp_courseware'));
    }
    $page->showPageFooter();
}
 /**
  * Page that shows the overview of mapping for the levels to courses.
  * @param PageBuilder $page The current page object.
  */
 private function showMembershipMappingLevels_overview($page)
 {
     // Handle the detection of the membership plugin before doing anything else.
     if (!$this->found_membershipTool()) {
         $page->showPageFooter();
         return;
     }
     // Try to show the level data
     $levelData = $this->getMembershipLevels_cached();
     if ($levelData) {
         // Create the table to show the data
         $table = new TableBuilder();
         $table->attributes = array('class' => 'wpcw_tbl widefat', 'id' => 'wpcw_members_tbl');
         $col = new TableColumn(__('Level ID', 'wp_courseware'), 'wpcw_members_id');
         $table->addColumn($col);
         $col = new TableColumn(__('Level Name', 'wp_courseware'), 'wpcw_members_name');
         $table->addColumn($col);
         $col = new TableColumn(__('Users at this level can access:', 'wp_courseware'), 'wpcw_members_levels');
         $table->addColumn($col);
         $col = new TableColumn(__('Actions', 'wp_courseware'), 'wpcw_members_actions');
         $table->addColumn($col);
         $odd = false;
         // Work out the base URL for the overview page
         $baseURL = admin_url('admin.php?page=' . $this->extensionID);
         // The list of courses that are currently on the system.
         $courses = WPCW_courses_getCourseList(false);
         // Add actual level data
         foreach ($levelData as $id => $levelDatum) {
             $data = array();
             $data['wpcw_members_id'] = $levelDatum['id'];
             $data['wpcw_members_name'] = $levelDatum['name'];
             // Get list of courses already associated with level.
             $courseListInDB = $this->getCourseAccessListForLevel($levelDatum['id']);
             if ($courses) {
                 $data['wpcw_members_levels'] = '<ul class="wpcw_tickitems">';
                 // Show which courses will be added to users created at this level.
                 foreach ($courses as $courseID => $courseName) {
                     $data['wpcw_members_levels'] .= sprintf('<li class="wpcw_%s">%s</li>', isset($courseListInDB[$courseID]) ? 'enabled' : 'disabled', $courseName);
                 }
                 $data['wpcw_members_levels'] .= '</ul>';
             } else {
                 $data['wpcw_members_levels'] = __('There are no courses yet.', 'wp_courseware');
             }
             // Buttons to edit the permissions
             $data['wpcw_members_actions'] = sprintf('<a href="%s&level_id=%s" class="button-secondary">%s</a>', $baseURL, $levelDatum['id'], __('Edit Course Access Settings', 'wp_courseware'));
             $odd = !$odd;
             $table->addRow($data, $odd ? 'alternate' : '');
         }
         echo $table->toString();
     } else {
         $page->showMessage(sprintf(__('No membership levels were found for %s.', 'wp_courseware'), $this->extensionName), true);
     }
 }
/**
 * Function that allows a question to be edited.
 */
function WPCW_showPage_ModifyQuestion_load()
{
    $page = new PageBuilder(true);
    $page->showPageHeader(__('Edit Single Question', 'wp_courseware'), '70%', WPCW_icon_getPageIconURL());
    $questionID = false;
    // Check POST and GET
    if (isset($_GET['question_id'])) {
        $questionID = $_GET['question_id'] + 0;
    } else {
        if (isset($_POST['question_id'])) {
            $questionID = $_POST['question_id'] + 0;
        }
    }
    // Trying to edit a question
    $questionDetails = WPCW_questions_getQuestionDetails($questionID, true);
    // Abort if question not found.
    if (!$questionDetails) {
        $page->showMessage(__('Sorry, but that question could not be found.', 'wp_courseware'), true);
        $page->showPageFooter();
        return;
    }
    // See if the question has been submitted for saving.
    if ('true' == WPCW_arrays_getValue($_POST, 'question_save_mode')) {
        WPCW_handler_questions_processSave(false, true);
        $page->showMessage(__('Question successfully updated.', 'wp_courseware'));
        // Assume save has happened, so reload the settings.
        $questionDetails = WPCW_questions_getQuestionDetails($questionID, true);
    }
    // Manually set the order to zero, as not needed for ordering in this context.
    $questionDetails->question_order = 0;
    switch ($questionDetails->question_type) {
        case 'multi':
            $quizObj = new WPCW_quiz_MultipleChoice($questionDetails);
            break;
        case 'truefalse':
            $quizObj = new WPCW_quiz_TrueFalse($questionDetails);
            break;
        case 'open':
            $quizObj = new WPCW_quiz_OpenEntry($questionDetails);
            break;
        case 'upload':
            $quizObj = new WPCW_quiz_FileUpload($questionDetails);
            break;
        default:
            die(__('Unknown quiz type: ', 'wp_courseware') . $questionDetails->question_type);
            break;
    }
    $quizObj->showErrors = true;
    $quizObj->needCorrectAnswers = true;
    $quizObj->hideDragActions = true;
    // #wpcw_quiz_details_questions = needed for media uploader
    // .wpcw_question_holder_static = needed for wrapping the question using existing HTML.
    printf('<div id="wpcw_quiz_details_questions"><ul class="wpcw_question_holder_static">');
    // Create form wrapper, so that we can save this question.
    printf('<form method="POST" action="%s?page=WPCW_showPage_ModifyQuestion&question_id=%d" />', admin_url('admin.php'), $questionDetails->question_id);
    // Question hidden fields
    printf('<input name="question_id" type="hidden" value="%d" />', $questionDetails->question_id);
    printf('<input name="question_save_mode" type="hidden" value="true" />');
    // Show the quiz so that it can be edited. We're re-using the code we have for editing questions,
    // to save creating any special form edit code.
    echo $quizObj->editForm_toString();
    // Save and return buttons.
    printf('<div class="wpcw_button_group"><br/>');
    printf('<a href="%s?page=WPCW_showPage_QuestionPool" class="button-secondary">%s</a>&nbsp;&nbsp;', admin_url('admin.php'), __('&laquo; Return to Question Pool', 'wp_courseware'));
    printf('<input type="submit" class="button-primary" value="%s" />', __('Save Question Details', 'wp_courseware'));
    printf('</div>');
    printf('</form>');
    printf('</ul></div>');
    $page->showPageFooter();
}
Exemple #9
0
/**
 * Shows the page where the caching settings and information is shown.
 */
function STWWT_showPage_ErrorLogs()
{
    // To add at some point - shows if the cache directory is writeable.
    //$cachePath = STWWT_plugin_getCacheDirectory();
    //echo $isWriteable = (file_exists($cachePath) && is_dir($cachePath) && is_writable($cachePath));
    global $wpdb;
    $wpdb->show_errors();
    $error_log = $wpdb->prefix . STWWT_TABLE_ERRORS;
    $page = new PageBuilder(false);
    $page->showPageHeader(__('Shrink The Web - Website Thumbnails - Error Logs', 'stwwt'), '70%');
    // Check for clear of logs
    if (isset($_POST['stwwt-clear-logs'])) {
        // Delete error thumbnails
        STWWT_cache_emptyCache(true);
        $SQL = "TRUNCATE {$error_log}";
        $wpdb->query($SQL);
        $page->showMessage("Debug logs have successfully been emptied.");
    }
    // Refresh and Clear Buttons
    ?>
		<form class="stwwt-button-right" method="post" action="<?php 
    echo str_replace('%7E', '~', $_SERVER['REQUEST_URI']);
    ?>
">
			<input type="submit" name="stwwt-refresh-logs" value="Refresh Logs" class="button-primary" />
			<input type="submit" name="stwwt-clear-logs" value="Clear Logs" class="button-secondary" />
			<div class="stwwt-clear"></div>
		</form>	
	<?php 
    $SQL = "SELECT *, UNIX_TIMESTAMP(request_date) AS request_date_ts\r\n\t\t\t\tFROM {$error_log}\r\n\t\t\t\tORDER BY request_date DESC\r\n\t\t\t\tLIMIT 50\r\n\t\t\t\t";
    $wpdb->show_errors();
    $logMsgs = $wpdb->get_results($SQL, OBJECT);
    if ($logMsgs) {
        printf('<div id="stwwt_error_count">Showing a total of <b>%d</b> log messages.</div>', $wpdb->num_rows);
        ?>
			<p>All <b>errors are cached for 12 hours</b> so that your thumbnail allowance with STW does not get used up if you have persistent errors. 
			If you've <b>had errors</b>, and you've <b>now fixed them</b>, you can click on the '<b>Clear Logs</b>' button on the right 
			to <b>flush the error cache</b> and re-attempt to fetch a thumbnail.</p>
			<?php 
        $table = new TableBuilder();
        $table->attributes = array("id" => "stwwt_error_log");
        $column = new TableColumn("ID", "id");
        $column->cellClass = "stwwt_id";
        $table->addColumn($column);
        $column = new TableColumn("Result", "request_result");
        $column->cellClass = "stwwt_result";
        $table->addColumn($column);
        $column = new TableColumn("Requested URL", "request_url");
        $column->cellClass = "stwwt_url";
        $table->addColumn($column);
        $column = new TableColumn("Type", "request_type");
        $column->cellClass = "stwwt_type";
        $table->addColumn($column);
        $column = new TableColumn("Request Date", "request_date");
        $column->cellClass = "stwwt_request-date";
        $table->addColumn($column);
        $column = new TableColumn("Detail", "request_detail");
        $column->cellClass = "stwwt_detail";
        $table->addColumn($column);
        foreach ($logMsgs as $logDetail) {
            $rowdata = array();
            $rowdata['id'] = $logDetail->logid;
            $rowdata['request_url'] = $logDetail->request_url;
            $rowdata['request_type'] = $logDetail->request_type;
            $rowdata['request_result'] = '<span>' . ($logDetail->request_result == 1 ? 'Success' : 'Error') . '</span>';
            $rowdata['request_date'] = $logDetail->request_date . '<br/>' . 'about ' . human_time_diff($logDetail->request_date_ts) . ' ago';
            // Show arguments and details
            $rowdata['request_detail'] = sprintf('<span class="stwwt_debug_header">Error Message</span>
					  									   <span class="stwwt_debug_info">%s</span>', $logDetail->request_error_msg);
            $rowdata['request_detail'] .= sprintf('<span class="stwwt_debug_header">Request Arguments</span>
					  									   <span class="stwwt_debug_info">%s</span>', STWWT_debug_formatArray(unserialize($logDetail->request_args)));
            if ($logDetail->request_detail) {
                $rowdata['request_detail'] .= sprintf('<span class="stwwt_debug_header">Raw STW Response</span>
					  									   <textarea class="stwwt_debug_raw" readonly="readonly">%s</textarea>', htmlentities($logDetail->request_detail));
            }
            $table->addRow($rowdata, $logDetail->request_result == 1 ? 'stwwt_success' : 'stwwt_error');
        }
        // Finally show table
        echo $table->toString();
        echo "<br/>";
    } else {
        printf('<div class="stwwt_clear"></div>');
        $page->showMessage("There are currently no debug logs to show.", true);
    }
    $page->showPageFooter();
}
/**
 * Page where the modules of a course can be ordered.
 */
function WPCW_showPage_CourseOrdering_load()
{
    $page = new PageBuilder(false);
    $page->showPageHeader(__('Order Course Modules &amp; Units', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
    $courseDetails = false;
    $courseID = false;
    // Trying to edit a course
    if (isset($_GET['course_id'])) {
        $courseID = $_GET['course_id'] + 0;
        $courseDetails = WPCW_courses_getCourseDetails($courseID);
    }
    // Abort if course not found.
    if (!$courseDetails) {
        $page->showMessage(__('Sorry, but that course could not be found.', 'wp_courseware'), true);
        $page->showPageFooter();
        return;
    }
    // ###ÊGenerate URLs for editing
    $modifyURL_quiz = admin_url('admin.php?page=WPCW_showPage_ModifyQuiz');
    $modifyURL_module = admin_url('admin.php?page=WPCW_showPage_ModifyModule');
    $modifyURL_unit = admin_url('post.php?action=edit');
    // Title of course being editied
    printf('<div id="wpcw_page_course_title"><span>%s</span> %s</div>', __('Editing Course:', 'wp_courseware'), $courseDetails->course_title);
    // Overall wrapper
    printf('<div id="wpcw_dragable_wrapper">');
    printf('<div id="wpcw_unassigned_wrapper" class="wpcw_floating_menu">');
    // ### Show a list of units that are not currently assigned to a module
    printf('<div id="wpcw_unassigned_units" class="wpcw_unassigned">');
    printf('<div class="wpcw_unassigned_title">%s</div>', __('Unassigned Units', 'wp_courseware'));
    printf('<ol class="wpcw_dragable_units_connected">');
    // Render each unit so that it can be dragged to a module. Still render <ol> list
    // even if there are no units to show so that we can drag units into unassociated list.
    $units = WPCW_units_getListOfUnits(0);
    if ($units) {
        foreach ($units as $unassUnit) {
            // Has unit got any existing quizzes?
            $existingQuiz = false;
            $quizObj = WPCW_quizzes_getAssociatedQuizForUnit($unassUnit->ID, false, false);
            if ($quizObj) {
                $existingQuiz = sprintf('<li id="wpcw_quiz_%d" class="wpcw_dragable_quiz_item">
								<div><a href="%s&quiz_id=%d" target="_blank" title="%s">%s (ID: %d)</a></div>
								<div class="wpcw_quiz_des">%s</div>
							</li>', $quizObj->quiz_id, $modifyURL_quiz, $quizObj->quiz_id, __('Edit this quiz...', 'wp_courseware'), $quizObj->quiz_title, $quizObj->quiz_id, $quizObj->quiz_desc);
            }
            printf('<li id="wpcw_unit_%d" class="wpcw_dragable_unit_item">						
						<div><a href="%s&post=%d" target="_blank" title="%s">%s (ID: %d)</a></div>
						<div class="wpcw_dragable_quiz_holder"><ol class="wpcw_dragable_quizzes_connected wpcw_one_only">%s</ol></div>
					</li>', $unassUnit->ID, $modifyURL_unit, $unassUnit->ID, __('Edit this unit...', 'wp_courseware'), $unassUnit->post_title, $unassUnit->ID, $existingQuiz);
        }
    }
    printf('</ol>');
    printf('</div>');
    // ### Show a list of quizzes that are not currently assigned to units
    printf('<div id="wpcw_unassigned_quizzes" class="wpcw_unassigned">');
    printf('<div class="wpcw_unassigned_title">%s</div>', __('Unassigned Quizzes', 'wp_courseware'));
    printf('<ol class="wpcw_dragable_quizzes_connected">');
    // Render each unit so that it can be dragged to a module. Still render <ol> list
    // even if there are no units to show so that we can drag units into unassociated list.
    $quizzes = WPCW_quizzes_getListOfQuizzes(0);
    if ($quizzes) {
        foreach ($quizzes as $quizObj) {
            printf('<li id="wpcw_quiz_%d" class="wpcw_dragable_quiz_item">
								<div><a href="%s&quiz_id=%d" target="_blank" title="%s">%s (ID: %d)</a></div>
								<div class="wpcw_quiz_des">%s</div>
							</li>', $quizObj->quiz_id, $modifyURL_quiz, $quizObj->quiz_id, __('Edit this quiz...', 'wp_courseware'), $quizObj->quiz_title, $quizObj->quiz_id, $quizObj->quiz_desc);
        }
    }
    printf('</ol>');
    printf('</div>');
    printf('</div>');
    // end of printf('<div class="wpcw_unassigned_wrapper">');
    // ### Show list of modules and current units
    $moduleList = WPCW_courses_getModuleDetailsList($courseID);
    if ($moduleList) {
        printf('<ol class="wpcw_dragable_modules">');
        foreach ($moduleList as $item_id => $moduleObj) {
            // Module
            printf('<li id="wpcw_mod_%d" class="wpcw_dragable_module_item">
						<div>
							<a href="%s&module_id=%d" target="_blank" title="%s"><b>%s %d - %s (ID: %d)</b></a>
						</div>', $item_id, $modifyURL_module, $item_id, __('Edit this module...', 'wp_courseware'), __('Module', 'wp_courseware'), $moduleObj->module_number, $moduleObj->module_title, $item_id);
            // Test Associated Units
            printf('<ol class="wpcw_dragable_units_connected">');
            $units = WPCW_units_getListOfUnits($item_id);
            if ($units) {
                foreach ($units as $unassUnit) {
                    $existingQuiz = false;
                    // Has unit got any existing quizzes?
                    $quizObj = WPCW_quizzes_getAssociatedQuizForUnit($unassUnit->ID, false, false);
                    $existingQuiz = false;
                    if ($quizObj) {
                        $existingQuiz = sprintf('<li id="wpcw_quiz_%d" class="wpcw_dragable_quiz_item">
								<div><a href="%s&quiz_id=%d" target="_blank" title="%s">%s (ID: %d)</a></div>
								<div class="wpcw_quiz_des">%s</div>
							</li>', $quizObj->quiz_id, $modifyURL_quiz, $quizObj->quiz_id, __('Edit this quiz...', 'wp_courseware'), $quizObj->quiz_title, $quizObj->quiz_id, $quizObj->quiz_desc);
                    }
                    printf('<li id="wpcw_unit_%d" class="wpcw_dragable_unit_item">						
						<div><a href="%s&post=%d" target="_blank" title="%s">%s (ID: %d)</a></div>
						<div class="wpcw_dragable_quiz_holder"><ol class="wpcw_dragable_quizzes_connected wpcw_one_only">%s</ol></div>
					</li>', $unassUnit->ID, $modifyURL_unit, $unassUnit->ID, __('Edit this unit...', 'wp_courseware'), $unassUnit->post_title, $unassUnit->ID, $existingQuiz);
                }
            }
            printf('</ol></li>');
        }
        printf('</ol>');
    } else {
        _e('No modules yet.', 'wp_courseware');
    }
    ?>
	<div id="wpcw_sticky_bar" style="display: none">
		<div id="wpcw_sticky_bar_inner">
			<a href="#" id="wpcw_dragable_modules_save" class="button-primary"><?php 
    _e('Save Changes to Ordering', 'wp_courseware');
    ?>
</a>
			<span id="wpcw_sticky_bar_status" title="<?php 
    _e('Ordering has changed. Ready to save changes?', 'wp_courseware');
    ?>
"></span>
		</div>
	</div>
	<?php 
    // Close overall wrapper
    printf('</div>');
    $page->showPageFooter();
}
 /**
  * Assign selected courses to members of a paticular level.
  * @param Level ID in which members will get courses enrollment adjusted.
  */
 protected function retroactive_assignment($level_ID)
 {
     global $wpdb;
     $page = new PageBuilder(false);
     // $levelID = substr($level_ID, strpos($level_ID, "_") + 1);
     // $level_ID = 'S2member_level' . $levelID;
     $results = get_users(array('role' => $level_ID));
     if ($results) {
         // Get user's assigned products and enroll them into courses accordingly
         foreach ($results as $result) {
             $id = $result->ID;
             $s2member_access_level = 's2member_level' . get_user_field("s2member_access_level", $id);
             parent::handle_courseSync($id, array($s2member_access_level));
         }
         $page->showMessage(__('All members were successfully retroactively enrolled into the selected courses.', 'wp_courseware'));
         return;
     } else {
         $page->showMessage(__('No existing customers found for the specified product.', 'wp_courseware'));
     }
 }
Exemple #12
0
/**
 * Handle sending out emails to users when they have completed the course and we're sending them their final grade.
 * 
 * @param Object $courseDetails The details of the course that we're sending details out for.
 * @param PageBuilder $page The page that's rendering the page structure.
 */
function WPCW_showPage_GradeBook_handleFinalGradesEmail($courseDetails, $page)
{
    // This could take a long time, hence setting time limit to unlimited.
    set_time_limit(0);
    global $wpdb, $wpcwdb;
    $wpdb->show_errors();
    // Get users to email final grades to
    $usersNeedGrades_SQL = $wpdb->prepare("\n\t\tSELECT * \n\t\tFROM {$wpcwdb->user_courses} uc\t\t\t\t\t\t\t\t\t\n\t\tLEFT JOIN {$wpdb->users} u ON u.ID = uc.user_id\n\t\tWHERE uc.course_id = %d\n\t\t  AND u.ID IS NOT NULL\n\t\t  AND uc.course_progress = 100\n\t\t  AND uc.course_final_grade_sent != 'sent'\n\t\t", $courseDetails->course_id);
    // Allow the list of users to email to be customised.
    $usersNeedGrades = $wpdb->get_results(apply_filters("wpcw_back_query_filter_gradebook_users_final_grades_email", $usersNeedGrades_SQL, $courseDetails));
    // Abort if there's nothing to do, showing a useful error message to the user.
    if (empty($usersNeedGrades)) {
        $page->showMessage(__('There are currently no users that are eligible to receive their final grade.', 'wp_courseware') . ' ' . __('No emails have been sent.', 'wp_courseware'), true);
        return;
    }
    $totalUserCount = count($usersNeedGrades);
    //WPCW_debug_showArray($courseDetails);
    // ### Email Template - Construct the from part of the email
    $headers = false;
    if ($courseDetails->course_from_email) {
        $headers = sprintf('From: %s <%s>' . "\r\n", $courseDetails->course_from_name, $courseDetails->course_from_email);
    }
    // Start the status pane to wrap the updates.
    printf('<div id="wpcw_gradebook_email_progress">');
    // Little summary of how many users there are.
    printf('<h3>%s <b>%d %s</b>...</h3>', __('Sending final grade emails to', 'wp_courseware'), $totalUserCount, _n('user', 'users', $totalUserCount, 'wp_courseware'));
    // Get all the quizzes for this course
    $quizIDList = array();
    $quizIDListForSQL = false;
    $quizzesForCourse = WPCW_quizzes_getAllQuizzesForCourse($courseDetails->course_id);
    // Create a simple list of IDs to use in SQL queries
    if ($quizzesForCourse) {
        foreach ($quizzesForCourse as $singleQuiz) {
            $quizIDList[$singleQuiz->quiz_id] = $singleQuiz;
        }
        // Convert list of IDs into an SQL list
        $quizIDListForSQL = '(' . implode(',', array_keys($quizIDList)) . ')';
    }
    // Run through each user, and generate their details.
    $userCount = 1;
    foreach ($usersNeedGrades as $aSingleUser) {
        printf('<p>%s (%s) - <b>%d%% %s</b></p>', $aSingleUser->display_name, $aSingleUser->user_email, number_format($userCount / $totalUserCount * 100, 1), __('complete', 'wp_courseware'));
        // Work out what tags we have to replace in the body and subject and replace
        // the generic ones.
        $messageBody = $courseDetails->email_complete_course_grade_summary_body;
        $tagList_Body = WPCW_email_getTagList($messageBody);
        $messageBody = WPCW_email_replaceTags_generic($courseDetails, $aSingleUser, $tagList_Body, $messageBody);
        $messageSubject = $courseDetails->email_complete_course_grade_summary_subject;
        $tagList_Subject = WPCW_email_getTagList($messageSubject);
        $messageSubject = WPCW_email_replaceTags_generic($courseDetails, $aSingleUser, $tagList_Subject, $messageSubject);
        // Generate the data for all of the quizzes, and add it to the email.
        $quizGradeMessage = "\n";
        // Only add quiz summary if we have one!
        if (!empty($quizIDList)) {
            // Get quiz results for this user
            $quizResults = WPCW_quizzes_getQuizResultsForUser($aSingleUser->ID, $quizIDListForSQL);
            // Track cumulative data
            $quizScoresSoFar = 0;
            $quizScoresSoFar_count = 0;
            // ### Now render results for each quiz
            foreach ($quizIDList as $aQuizID => $singleQuiz) {
                // Got progress data, process the result
                if (isset($quizResults[$aQuizID])) {
                    // Extract results and unserialise the data array.
                    $theResults = $quizResults[$aQuizID];
                    $theResults->quiz_data = maybe_unserialize($theResults->quiz_data);
                    // We've got something that needs grading.
                    if ($theResults->quiz_needs_marking == 0) {
                        // Calculate score, and use for cumulative.
                        $score = number_format($theResults->quiz_grade);
                        $quizScoresSoFar += $score;
                        $quizScoresSoFar_count++;
                        // Add to string with the quiz name and each grade.
                        $quizGradeMessage .= sprintf("%s #%d - %s\n%s: %s%%\n\n", __('Quiz', 'wp_courseware'), $quizScoresSoFar_count, $singleQuiz->quiz_title, __('Grade', 'wp_courseware'), $score);
                    }
                }
                // end of quiz result check.
            }
        }
        // end of check for quizzes for course
        // Calculate the cumulative grade
        $cumulativeGrade = $quizScoresSoFar_count > 0 ? number_format($quizScoresSoFar / $quizScoresSoFar_count, 1) . '%' : __('n/a', 'wp_courseware');
        // Now replace the cumulative grades.
        $messageBody = str_ireplace('{QUIZ_SUMMARY}', trim($quizGradeMessage), $messageBody);
        $messageBody = str_ireplace('{CUMULATIVE_GRADE}', $cumulativeGrade, $messageBody);
        // Set up the target email address
        $targetEmail = $aSingleUser->user_email;
        // Send the actual email
        if (!wp_mail($targetEmail, $messageSubject, $messageBody, $headers)) {
            error_log('WPCW_email_sendEmail() - email did not send.');
        }
        // Update the user record to mark as being sent
        $wpdb->query($wpdb->prepare("\n\t\t    \tUPDATE {$wpcwdb->user_courses}\n\t\t    \t   SET course_final_grade_sent = 'sent'\n\t\t    \tWHERE user_id = %d\n\t\t    \t  AND course_id = %d\n\t\t    ", $aSingleUser->ID, $courseDetails->course_id));
        flush();
        $userCount++;
    }
    // Tell the user we're complete.
    printf('<h3>%s</h3>', __('All done.', 'wp_courseware'));
    printf('</div>');
}
 /**
  * Assign selected courses to members of a paticular level.
  * @param Level ID in which members will get courses enrollment adjusted.
  */
 protected function retroactive_assignment($level_ID)
 {
     //Get all transactions from EDD
     $logging = new EDD_Logging();
     $transactions = $logging->get_logs($level_ID);
     $payment_ids = array();
     $customer_ids = array();
     //Convert log entries into payment IDs
     if ($transactions) {
         foreach ($transactions as $key => $transaction) {
             $payment_ids[] = get_post_meta($transaction->ID, '_edd_log_payment_id', true);
         }
     }
     //Get IDs that are member of membership level
     if (count($payment_ids) > 0) {
         foreach ($payment_ids as $key => $payment_id) {
             $customer_ids[$key] = get_post_meta($payment_id, '_edd_payment_user_id', true);
         }
     }
     //clean up duplicate IDs
     $customer_ids = array_unique($customer_ids);
     $page = new PageBuilder(false);
     //Enroll members of level
     if (count($customer_ids) > 0) {
         foreach ($customer_ids as $customer_id) {
             $memberLevels = edd_get_users_purchased_products($customer_id);
             $userLevels = array();
             foreach ($memberLevels as $key => $memberLevel) {
                 $userLevels[$key] = $memberLevel->ID;
             }
             // Over to the parent class to handle the sync of data.
             parent::handle_courseSync($customer_id, $userLevels);
             $page->showMessage(__('All members were successfully retroactively enrolled into the selected courses.', 'wp_courseware'));
         }
         return;
     } else {
         $page->showMessage(__('No existing members found for the specified level.', 'wp_courseware'));
     }
 }
/**
 * Function that allows a module to be created or edited.
 */
function WPCW_showPage_ModifyModule_load()
{
    $page = new PageBuilder(true);
    $moduleDetails = false;
    $moduleID = false;
    $adding = false;
    // Trying to edit a course
    if (isset($_GET['module_id'])) {
        $moduleID = $_GET['module_id'] + 0;
        $moduleDetails = WPCW_modules_getModuleDetails($moduleID);
        // Abort if module not found.
        if (!$moduleDetails) {
            $page->showPageHeader(__('Edit Module', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
            $page->showMessage(__('Sorry, but that module could not be found.', 'wp_courseware'), true);
            $page->showPageFooter();
            return;
        } else {
            $page->showPageHeader(__('Edit Module', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
        }
    } else {
        $page->showPageHeader(__('Add Module', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
        $adding = true;
    }
    global $wpcwdb;
    $formDetails = array('module_title' => array('label' => __('Module Title', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_module_title', 'desc' => __('The title of your module. You <b>do not need to number the modules</b> - this is done automatically based on the order that they are arranged.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 150, 'minlen' => 1, 'regexp' => '/^[^<>]+$/', 'error' => __('Please specify a name for your module, up to a maximum of 150 characters, just no angled brackets (&lt; or &gt;). Your trainees will be able to see this module title.', 'wp_courseware'))), 'parent_course_id' => array('label' => __('Associated Course', 'wp_courseware'), 'type' => 'select', 'required' => true, 'cssclass' => 'wpcw_associated_course', 'desc' => __('The associated training course that this module belongs to.', 'wp_courseware'), 'data' => WPCW_courses_getCourseList(__('-- Select a Training Course --', 'wp_courseware'))), 'module_desc' => array('label' => __('Module Description', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_module_desc', 'desc' => __('The description of this module. Your trainees will be able to see this module description.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the description of your module to 5000 characters.', 'wp_courseware'))));
    $form = new RecordsForm($formDetails, $wpcwdb->modules, 'module_id');
    $form->customFormErrorMsg = __('Sorry, but unfortunately there were some errors saving the module details. Please fix the errors and try again.', 'wp_courseware');
    $form->setAllTranslationStrings(WPCW_forms_getTranslationStrings());
    // Useful place to go
    $directionMsg = '<br/></br>' . sprintf(__('Do you want to return to the <a href="%s">course summary page</a>?', 'wp_courseware'), admin_url('admin.php?page=WPCW_wp_courseware'));
    // Override success messages
    $form->msg_record_created = __('Module details successfully created.', 'wp_courseware') . $directionMsg;
    $form->msg_record_updated = __('Module details successfully updated.', 'wp_courseware') . $directionMsg;
    $form->setPrimaryKeyValue($moduleID);
    $form->setSaveButtonLabel(__('Save ALL Details', 'wp_courseware'));
    // See if we have a course ID to pre-set.
    if ($adding && ($courseID = WPCW_arrays_getValue($_GET, 'course_id'))) {
        $form->loadDefaults(array('parent_course_id' => $courseID));
    }
    // Call to re-order modules once they've been created
    $form->afterSaveFunction = 'WPCW_actions_modules_afterModuleSaved_formHook';
    $form->show();
    $page->showPageMiddle('20%');
    // Editing a module?
    if ($moduleDetails) {
        // ### Include a link to delete the module
        $page->openPane('wpcw-deletion-module', __('Delete Module?', 'wp_courseware'));
        printf('<a href="%s&action=delete_module&module_id=%d" class="wpcw_delete_item" title="%s">%s</a>', admin_url('admin.php?page=WPCW_wp_courseware'), $moduleID, __("Are you sure you want to delete the this module?\n\nThis CANNOT be undone!", 'wp_courseware'), __('Delete this Module', 'wp_courseware'));
        printf('<p>%s</p>', __('Units will <b>not</b> be deleted, they will <b>just be disassociated</b> from this module.', 'wp_courseware'));
        $page->closePane();
        // #### Show a list of all sub-units
        $page->openPane('wpcw-units-module', __('Units in this Module', 'wp_courseware'));
        $unitList = WPCW_units_getListOfUnits($moduleID);
        if ($unitList) {
            printf('<ul class="wpcw_unit_list">');
            foreach ($unitList as $unitID => $unitObj) {
                printf('<li>%s %d - %s</li>', __('Unit', 'wp_courseware'), $unitObj->unit_meta->unit_number, $unitObj->post_title);
            }
            printf('</ul>');
        } else {
            printf('<p>%s</p>', __('There are currently no units in this module.', 'wp_courseware'));
        }
    }
    $page->showPageFooter();
}
/**
 * Handle the quiz deletion from the summary page.
 * @param PageBuilder $page The page rendering object.
 */
function WPCW_quizzes_handleQuizDeletion($page)
{
    global $wpcwdb, $wpdb;
    $wpdb->show_errors();
    // Check that the quiz exists and deletion has been requested
    if (isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['quiz_id'])) {
        $quizID = $_GET['quiz_id'];
        $quizDetails = WPCW_quizzes_getQuizDetails($quizID, false, false, false);
        // Only do deletion if quiz details are valid.
        if ($quizDetails) {
            // Delete quiz questions from question map
            $wpdb->query($wpdb->prepare("\n\t\t\t\tDELETE FROM {$wpcwdb->quiz_qs_mapping}\n\t\t\t\tWHERE parent_quiz_id = %d\n\t\t\t", $quizDetails->quiz_id));
            // Delete user progress
            $wpdb->query($wpdb->prepare("\n\t\t\t\tDELETE FROM {$wpcwdb->user_progress_quiz} \n\t\t\t\tWHERE quiz_id = %d\n\t\t\t", $quizDetails->quiz_id));
            // Finally delete quiz itself
            $wpdb->query($wpdb->prepare("\n\t\t\t\tDELETE FROM {$wpcwdb->quiz} \n\t\t\t\tWHERE quiz_id = %d\n\t\t\t", $quizDetails->quiz_id));
            $page->showMessage(sprintf(__('The quiz \'%s\' was successfully deleted.', 'wp_courseware'), $quizDetails->quiz_title));
        }
        // end of if $quizDetails
    }
    // end of check for deletion action
}
/**
 * Function that allows a course to be created or edited.
 */
function WPCW_showPage_ModifyCourse_load()
{
    $page = new PageBuilder(true);
    $courseDetails = false;
    $courseID = false;
    // Trying to edit a course
    if (isset($_GET['course_id'])) {
        $courseID = $_GET['course_id'] + 0;
        $courseDetails = WPCW_courses_getCourseDetails($courseID);
        // Abort if course not found.
        if (!$courseDetails) {
            $page->showPageHeader(__('Edit Course', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
            $page->showMessage(__('Sorry, but that course could not be found.', 'wp_courseware'), true);
            $page->showPageFooter();
            return;
        } else {
            $page->showPageHeader(__('Edit Course', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
            // Check user is allowed to edit this course.
            $canEditCourse = apply_filters('wpcw_back_permissions_user_can_edit_course', true, get_current_user_id(), $courseDetails);
            if (!$canEditCourse) {
                $page->showMessage(apply_filters('wpcw_back_msg_permissions_user_can_edit_course', __('You are currently not permitted to edit this course.', 'wp_courseware'), get_current_user_id(), $courseDetails), true);
                $page->showPageFooter();
                return;
            }
        }
    } else {
        $page->showPageHeader(__('Add Course', 'wp_courseware'), '75%', WPCW_icon_getPageIconURL());
        // Check user is allowed to add another course.
        $canAddCourse = apply_filters('wpcw_back_permissions_user_can_add_course', true, get_current_user_id());
        if (!$canAddCourse) {
            $page->showMessage(apply_filters('wpcw_back_msg_permissions_user_can_add_course', __('You are currently not permitted to add a new course.', 'wp_courseware'), get_current_user_id()), true);
            $page->showPageFooter();
            return;
        }
    }
    // We've requested a course tool. Do the checks here...
    if ($courseDetails && ($action = WPCW_arrays_getValue($_GET, 'action'))) {
        switch ($action) {
            // Tool - reset progress for all users.
            case 'reset_course_progress':
                // Get a list of all users on this course.
                global $wpdb, $wpcwdb;
                $userList = $wpdb->get_col($wpdb->prepare("\n\t\t\t\t\t\tSELECT user_id \n\t\t\t\t\t\tFROM {$wpcwdb->user_courses}\n\t\t\t\t\t\tWHERE course_id = %d \n\t\t\t\t\t", $courseDetails->course_id));
                $unitList = false;
                // Get all units for a course
                $courseMap = new WPCW_CourseMap();
                $courseMap->loadDetails_byCourseID($courseDetails->course_id);
                $unitList = $courseMap->getUnitIDList_forCourse();
                // Reset all users for this course.
                WPCW_users_resetProgress($userList, $unitList, $courseDetails, $courseMap->getUnitCount());
                // Confirm it's complete.
                $page->showMessage(__('User progress for this course has been reset.', 'wp_courseware'));
                break;
                // Access changes
            // Access changes
            case 'grant_access_users_all':
            case 'grant_access_users_admins':
                WPCW_showPage_ModifyCourse_courseAccess_runAccessChanges($page, $action, $courseDetails);
                break;
        }
        // Add a link back to editing, as we've hidden that panel.
        printf('<p><a href="%s?page=WPCW_showPage_ModifyCourse&course_id=%d" class="button button-secondary">%s</a></p>', admin_url('admin.php'), $courseDetails->course_id, __('&laquo; Go back to editing the course settings', 'wp_courseware'));
    } else {
        global $wpcwdb;
        $formDetails = array('break_course_general' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab(false)), 'course_title' => array('label' => __('Course Title', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_course_title', 'desc' => __('The title of your course.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 150, 'minlen' => 1, 'regexp' => '/^[^<>]+$/', 'error' => __('Please specify a name for your course, up to a maximum of 150 characters, just no angled brackets (&lt; or &gt;). Your trainees will be able to see this course title.', 'wp_courseware'))), 'course_desc' => array('label' => __('Course Description', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_desc', 'desc' => __('The description of this course. Your trainees will be able to see this course description.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the description of your course to 5000 characters.', 'wp_courseware'))), 'course_opt_completion_wall' => array('label' => __('When do users see the next unit on the course?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'desc' => __('Can a user see all possible course units? Or must they complete previous units before seeing the next unit?', 'wp_courseware'), 'data' => array('all_visible' => __('<b>All Units Visible</b> - All units are visible regardless of completion progress.', 'wp_courseware'), 'completion_wall' => __('<b>Only Completed/Next Units Visible</b> - Only show units that have been completed, plus the next unit that the user can start.', 'wp_courseware'))), 'break_course_access' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'course_opt_user_access' => array('label' => __('Granting users access to this course', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'desc' => __('This setting allows you to set how users can access this course. They can either be given access automatically as soon as the user is created, or you can manually give them access. You can always manually remove access if you wish.', 'wp_courseware'), 'data' => array('default_show' => __('<b>Automatic</b> - All newly created users will be given access this course.', 'wp_courseware'), 'default_hide' => __('<b>Manual</b> - Users can only access course if you grant them access.', 'wp_courseware'))), 'break_course_messages' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'course_message_unit_complete' => array('label' => __('Message - Unit Complete', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee once they\'ve <b>completed a unit</b>, which is displayed at the bottom of the unit page. HTML is OK.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_course_complete' => array('label' => __('Message - Course Complete', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee once they\'ve <b>completed the whole course</b>, which is displayed at the bottom of the unit page. HTML is OK.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_unit_pending' => array('label' => __('Message - Unit Pending', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee when they\'ve <b>yet to complete a unit</b>. This message is displayed at the bottom of the unit page, along with a button that says "<b>Mark as completed</b>". HTML is OK.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_unit_no_access' => array('label' => __('Message - Access Denied', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee they are <b>not allowed to access a unit</b>, because they are not allowed to <b>access the whole course</b>.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_unit_not_yet' => array('label' => __('Message - Not Yet Available', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee they are <b>not allowed to access a unit yet</b>, because they need to complete a previous unit.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_unit_not_logged_in' => array('label' => __('Message - Not Logged In', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee they are <b>not logged in</b>, and therefore cannot access the unit.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_quiz_open_grading_blocking' => array('label' => __('Message - Open-Question Submitted - Blocking Mode', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee they have submitted an answer to an <b>open-ended or upload question</b>, and you need to grade their answer <b>before they continue</b>.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'course_message_quiz_open_grading_non_blocking' => array('label' => __('Message - Open-Question Submitted - Non-Blocking Mode', 'wp_courseware'), 'type' => 'textarea', 'required' => true, 'cssclass' => 'wpcw_course_message', 'desc' => __('The message shown to a trainee they have submitted an answer to an <b>open-ended or upload question</b>, and you need to grade their answer, but they can <b>continue anyway</b>.', 'wp_courseware'), 'rows' => 2, 'validate' => array('type' => 'string', 'maxlen' => 500, 'minlen' => 1, 'error' => __('Please limit message to 500 characters.', 'wp_courseware'))), 'break_course_notifications_from_details' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'course_from_email' => array('label' => __('Email From Address', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_course_email', 'desc' => __('The email address that the email notifications should be from.<br/>Depending on your server\'s spam-protection set up, this may not appear in the outgoing emails.', 'wp_courseware'), 'validate' => array('type' => 'email', 'maxlen' => 150, 'minlen' => 1, 'error' => __('Please enter a valid email address.', 'wp_courseware'))), 'course_from_name' => array('label' => __('Email From Name', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_course_email', 'desc' => __('The name used on the email notifications, which are sent to you and your trainees. <br/>Depending on your server\'s spam-protection set up, this may not appear in the outgoing emails.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 150, 'minlen' => 1, 'regexp' => '/^[^<>]+$/', 'error' => __('Please specify a from name, up to a maximum of 150 characters, just no angled brackets (&lt; or &gt;).', 'wp_courseware'))), 'course_to_email' => array('label' => __('Admin Notify Email Address', 'wp_courseware'), 'type' => 'text', 'required' => true, 'cssclass' => 'wpcw_course_email', 'desc' => __('The email address to send admin notifications to.', 'wp_courseware'), 'validate' => array('type' => 'email', 'maxlen' => 150, 'minlen' => 1, 'error' => __('Please enter a valid email address.', 'wp_courseware'))), 'break_course_notifications_user_module' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'email_complete_module_option_admin' => array('label' => __('Module Complete - Notify You?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_course_email_template_option', 'data' => array('send_email' => __('<b>Send me an email</b> - when one of your trainees has completed a module.', 'wp_courseware'), 'no_email' => __('<b>Don\'t send me an email</b> - when one of your trainees has completed a module.', 'wp_courseware'))), 'email_complete_module_option' => array('label' => __('Module Complete - Notify User?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_course_email_template_option', 'data' => array('send_email' => __('<b>Send Email</b> - to user when module has been completed.', 'wp_courseware'), 'no_email' => __('<b>Don\'t Send Email</b> - to user when module has been completed.', 'wp_courseware'))), 'email_complete_module_subject' => array('label' => __('Module Complete - Email Subject', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template_subject', 'rows' => 2, 'desc' => __('The <b>subject line</b> for the email sent to a user when they complete a <b>module</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 300, 'minlen' => 1, 'error' => __('Please limit the email subject to 300 characters.', 'wp_courseware'))), 'email_complete_module_body' => array('label' => __('Module Complete - Email Body', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template', 'desc' => __('The <b>template body</b> for the email sent to a user when they complete a <b>module</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the email body to 5000 characters.', 'wp_courseware'))), 'break_course_notifications_user_course' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'email_complete_course_option_admin' => array('label' => __('Course Complete - Notify You?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_course_email_template_option', 'data' => array('send_email' => __('<b>Send me an email</b> - when one of your trainees has completed the whole course.', 'wp_courseware'), 'no_email' => __('<b>Don\'t send me an email</b> - when one of your trainees has completed the whole course.', 'wp_courseware'))), 'email_complete_course_option' => array('label' => __('Course Complete - Notify User?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_course_email_template_option', 'data' => array('send_email' => __('<b>Send Email</b> - to user when the whole course has been completed.', 'wp_courseware'), 'no_email' => __('<b>Don\'t Send Email</b> - to user when the whole course has been completed.', 'wp_courseware'))), 'email_complete_course_subject' => array('label' => __('Course Complete - Email Subject', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template_subject', 'rows' => 2, 'desc' => __('The <b>subject line</b> for the email sent to a user when they complete <b>the whole course</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 300, 'minlen' => 1, 'error' => __('Please limit the email subject to 300 characters.', 'wp_courseware'))), 'email_complete_course_body' => array('label' => __('Course Complete - Email Body', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template', 'desc' => __('The <b>template body</b> for the email sent to a user when they complete <b>the whole course</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the email body to 5000 characters.', 'wp_courseware'))), 'break_course_notifications_user_grades' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'email_quiz_grade_option' => array('label' => __('Quiz Grade - Notify User?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'cssclass' => 'wpcw_course_email_template_option', 'data' => array('send_email' => __('<b>Send Email</b> - to user after a quiz is graded (automatically or by the instructor).', 'wp_courseware'), 'no_email' => __('<b>Don\'t Send Email</b> - to user when a quiz is graded.', 'wp_courseware'))), 'email_quiz_grade_subject' => array('label' => __('Quiz Graded - Email Subject', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template_subject', 'rows' => 2, 'desc' => __('The <b>subject line</b> for the email sent to a user when they receive a <b>grade for a quiz</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 300, 'minlen' => 1, 'error' => __('Please limit the email subject to 300 characters.', 'wp_courseware'))), 'email_quiz_grade_body' => array('label' => __('Quiz Graded - Email Body', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template', 'desc' => __('The <b>template body</b> for the email sent to a user when they receive a <b>grade for a quiz</b>.', 'wp_courseware'), 'rows' => 20, 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the email body to 5000 characters.', 'wp_courseware'))), 'break_course_notifications_user_final' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'email_complete_course_grade_summary_subject' => array('label' => __('Final Summary - Email Subject', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'cssclass' => 'wpcw_course_email_template_subject', 'rows' => 2, 'desc' => __('The <b>subject line</b> for the email sent to a user when they receive their <b>grade summary at the end of the course</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 300, 'minlen' => 1, 'error' => __('Please limit the email subject to 300 characters.', 'wp_courseware'))), 'email_complete_course_grade_summary_body' => array('label' => __('Final Summary - Email Body', 'wp_courseware'), 'type' => 'textarea', 'required' => false, 'rows' => 20, 'cssclass' => 'wpcw_course_email_template', 'desc' => __('The <b>template body</b> for the email sent to a user when they receive their <b>grade summary at the end of the course</b>.', 'wp_courseware'), 'validate' => array('type' => 'string', 'maxlen' => 5000, 'minlen' => 1, 'error' => __('Please limit the email body to 5000 characters.', 'wp_courseware'))), 'break_course_certificates_user_course' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'course_opt_use_certificate' => array('label' => __('Enable certificates?', 'wp_courseware'), 'type' => 'radio', 'required' => true, 'data' => array('use_certs' => __('<b>Yes</b> - generate a PDF certificate when user completes this course.', 'wp_courseware'), 'no_certs' => __('<b>No</b> - don\'t generate a PDF certificate when user completes this course.', 'wp_courseware'))), 'break_course_certificates_user_tools' => array('type' => 'break', 'html' => WPCW_forms_createBreakHTML_tab()), 'course_tools_reset_all_users' => array('label' => __('Reset User Progess for this Course?', 'wp_courseware'), 'type' => 'custom', 'html' => sprintf('<a href="%s?page=WPCW_showPage_ModifyCourse&course_id=%d&action=reset_course_progress" class="button-primary" id="wpcw_course_btn_progress_reset_whole_course">%s</a><p>%s</p>', admin_url('admin.php'), $courseID, __('Reset All Users on this Course to the start', 'wp_courseware'), __('This button will reset all users who can access this course back to the beginning of the course. This deletes all grade data too.', 'wp_courseware'))), 'course_tools_user_access' => array('label' => __('Bulk-grant access to this course?', 'wp_courseware'), 'type' => 'custom', 'html' => sprintf('<a href="%s?page=WPCW_showPage_ModifyCourse&course_id=%d&action=grant_access_users_all" class="button-primary" id="wpcw_course_btn_access_all_existing_users">%s</a>&nbsp;&nbsp;
										    <a href="%s?page=WPCW_showPage_ModifyCourse&course_id=%d&action=grant_access_users_admins" class="button-primary" id="wpcw_course_btn_access_all_existing_admins">%s</a> 
										    <p>%s</p>', admin_url('admin.php'), $courseID, __('All Existing Users (including Administrators)', 'wp_courseware'), admin_url('admin.php'), $courseID, __('Only All Existing Administrators', 'wp_courseware'), __('You can use the buttons above to grant all users access to this course. Depending on how many users you have, this may be a slow process.', 'wp_courseware'))));
        // Generate the tabs.
        $tabList = array('break_course_general' => array('label' => __('General Course Details', 'wp_courseware')), 'break_course_access' => array('label' => __('User Access', 'wp_courseware')), 'break_course_messages' => array('label' => __('User Messages', 'wp_courseware')), 'break_course_notifications_from_details' => array('label' => __('Email Address Details', 'wp_courseware')), 'break_course_notifications_user_module' => array('label' => __('Email Notifications - Module', 'wp_courseware')), 'break_course_notifications_user_course' => array('label' => __('Email Notifications - Course', 'wp_courseware')), 'break_course_notifications_user_grades' => array('label' => __('Email Notifications - Quiz Grades', 'wp_courseware')), 'break_course_notifications_user_final' => array('label' => __('Email Notifications - Final Summary', 'wp_courseware')), 'break_course_certificates_user_course' => array('label' => __('Certificates', 'wp_courseware')), 'break_course_certificates_user_tools' => array('label' => __('Course Access Tools', 'wp_courseware')));
        // Remove reset fields if not appropriate.
        if (!$courseDetails) {
            // The tab
            unset($tabList['break_course_certificates_user_tools']);
            // The tool
            unset($formDetails['break_course_certificates_user_tools']);
            unset($formDetails['course_tools_reset_all_users']);
        }
        $form = new RecordsForm($formDetails, $wpcwdb->courses, 'course_id', false, 'wpcw_course_settings');
        $form->customFormErrorMsg = __('Sorry, but unfortunately there were some errors saving the course details. Please fix the errors and try again.', 'wp_courseware');
        $form->setAllTranslationStrings(WPCW_forms_getTranslationStrings());
        // Set defaults if adding a new course
        if (!$courseDetails) {
            $form->loadDefaults(array('email_complete_module_subject' => EMAIL_TEMPLATE_COMPLETE_MODULE_SUBJECT, 'email_complete_course_subject' => EMAIL_TEMPLATE_COMPLETE_COURSE_SUBJECT, 'email_quiz_grade_subject' => EMAIL_TEMPLATE_QUIZ_GRADE_SUBJECT, 'email_complete_course_grade_summary_subject' => EMAIL_TEMPLATE_COURSE_SUMMARY_WITH_GRADE_SUBJECT, 'email_complete_module_body' => EMAIL_TEMPLATE_COMPLETE_MODULE_BODY, 'email_complete_course_body' => EMAIL_TEMPLATE_COMPLETE_COURSE_BODY, 'email_quiz_grade_body' => EMAIL_TEMPLATE_QUIZ_GRADE_BODY, 'email_complete_course_grade_summary_body' => EMAIL_TEMPLATE_COURSE_SUMMARY_WITH_GRADE_BODY, 'course_from_name' => get_bloginfo('name'), 'course_from_email' => get_bloginfo('admin_email'), 'course_to_email' => get_bloginfo('admin_email'), 'course_opt_completion_wall' => 'completion_wall', 'course_opt_user_access' => 'default_show', 'email_complete_course_option_admin' => 'send_email', 'email_complete_course_option' => 'send_email', 'email_complete_module_option_admin' => 'send_email', 'email_complete_module_option' => 'send_email', 'email_quiz_grade_option' => 'send_email', 'course_opt_use_certificate' => 'no_certs', 'course_message_unit_not_yet' => __("You need to complete the previous unit first.", 'wp_courseware'), 'course_message_unit_pending' => __("Have you completed this unit? Then mark this unit as completed.", 'wp_courseware'), 'course_message_unit_complete' => __("You have now completed this unit.", 'wp_courseware'), 'course_message_course_complete' => __("You have now completed the whole course. Congratulations!", 'wp_courseware'), 'course_message_unit_no_access' => __("Sorry, but you're not allowed to access this course.", 'wp_courseware'), 'course_message_unit_not_logged_in' => __('You cannot view this unit as you\'re not logged in yet.', 'wp_courseware'), 'course_message_quiz_open_grading_blocking' => __('Your quiz has been submitted for grading by the course instructor. Once your grade has been entered, you will be able access the next unit.', 'wp_courseware'), 'course_message_quiz_open_grading_non_blocking' => __('Your quiz has been submitted for grading by the course instructor. You have now completed this unit.', 'wp_courseware')));
        }
        // Useful place to go
        $directionMsg = '<br/></br>' . sprintf(__('Do you want to return to the <a href="%s">course summary page</a>?', 'wp_courseware'), admin_url('admin.php?page=WPCW_wp_courseware'));
        // Override success messages
        $form->msg_record_created = __('Course details successfully created. ', 'wp_courseware') . $directionMsg;
        $form->msg_record_updated = __('Course details successfully updated. ', 'wp_courseware') . $directionMsg;
        $form->setPrimaryKeyValue($courseID);
        $form->setSaveButtonLabel(__('Save ALL Details', 'wp_courseware'));
        // Process form
        $formHTML = $form->getHTML();
        // Show message about this course having quizzes that require a pass mark.
        // Need updated details for this.
        $courseDetails = WPCW_courses_getCourseDetails($courseID);
        if ($courseDetails && $courseDetails->course_opt_completion_wall == 'all_visible') {
            $quizzes = WPCW_quizzes_getAllBlockingQuizzesForCourse($courseDetails->course_id);
            // Count how many blocking quizzes there are.
            if ($quizzes && count($quizzes) > 0) {
                $quizCountMessage = sprintf(__('Currently <b>%d of your quizzes</b> are blocking process based on a percentage score <b>in this course</b>.', 'wp_courseware'), count($quizzes));
            } else {
                $quizCountMessage = __('You do not currently have any blocking quizzes for this course.', 'wp_courseware');
            }
            printf('<div id="message" class="wpcw_msg_info wpcw_msg"><b>%s</b> - %s<br/><br/>
					%s				
					</div>', __('Important Note', 'wp_courseware'), __('You have selected <b>All Units Visible</b>. If you create a quiz blocking progress based on a percentage score, students will have access to the entire course regardless of quiz score.', 'wp_courseware'), $quizCountMessage);
        }
        // Generate the tabs
        echo WPCW_tabs_generateTabHeader($tabList, 'wpcw_courses_tabs', false);
        // Show the form
        echo $formHTML;
        echo '</div>';
        // .wpcw_tab_wrapper
    }
    // end if not doing a tool manipulation.
    $page->showPageMiddle('20%');
    // Include a link to delete the course
    if ($courseDetails) {
        $page->openPane('wpcw-deletion-course', __('Delete Course?', 'wp_courseware'));
        WPCW_showPage_ModifyCourse_deleteCourseButton($courseDetails);
        $page->closePane();
    }
    // Email template tags here...
    $page->openPane('wpcw_docs_email_tags', __('Email Template Tags', 'wp_courseware'));
    printf('<h4 class="wpcw_docs_side_mini_hdr">%s</h4>', __('All Email Notifications', 'wp_courseware'));
    printf('<dl class="wpcw_email_tags">');
    printf('<dt>{USER_NAME}</dt><dd>%s</dd>', __('The display name of the user.', 'wp_courseware'));
    printf('<dt>{SITE_NAME}</dt><dd>%s</dd>', __('The name of the website.', 'wp_courseware'));
    printf('<dt>{SITE_URL}</dt><dd>%s</dd>', __('The URL of the website.', 'wp_courseware'));
    printf('<dt>{COURSE_TITLE}</dt><dd>%s</dd>', __('The title of the course for the unit that\'s just been completed.', 'wp_courseware'));
    printf('<dt>{MODULE_TITLE}</dt><dd>%s</dd>', __('The title of the module for the unit that\'s just been completed.', 'wp_courseware'));
    printf('<dt>{MODULE_NUMBER}</dt><dd>%s</dd>', __('The number of the module for the unit that\'s just been completed.', 'wp_courseware'));
    printf('<dt>{CERTIFICATE_LINK}</dt><dd>%s</dd>', __('If the course has PDF certificates enabled, this is the link of the PDF certficate. (If there is no certificate or certificates are not enabled, this is simply blank)', 'wp_courseware'));
    printf('</dl>');
    printf('<h4 class="wpcw_docs_side_mini_hdr">%s</h4>', __('Quiz Email Notifications Only', 'wp_courseware'));
    printf('<dl class="wpcw_email_tags">');
    printf('<dt>{QUIZ_TITLE}</dt><dd>%s</dd>', __('The title of the quiz that has been graded.', 'wp_courseware'));
    printf('<dt>{QUIZ_GRADE}</dt><dd>%s</dd>', __('The overall percentage grade for a quiz.', 'wp_courseware'));
    printf('<dt>{QUIZ_GRADES_BY_TAG}</dt><dd>%s</dd>', __('Includes a breakdown of scores by tag if available.', 'wp_courseware'));
    printf('<dt>{QUIZ_TIME}</dt><dd>%s</dd>', __('If the quiz was timed, displays the time used to complete the quiz.', 'wp_courseware'));
    printf('<dt>{QUIZ_ATTEMPTS}</dt><dd>%s</dd>', __('Indicates the number of attempts for the quiz.', 'wp_courseware'));
    printf('<dt>{CUSTOM_FEEDBACK}</dt><dd>%s</dd>', __('Includes any custom feedback messages that have been triggered based on the user\'s specific results in the quiz.', 'wp_courseware'));
    printf('<dt>{QUIZ_RESULT_DETAIL}</dt><dd>%s</dd>', __('Any optional information relating to the result of the quiz, e.g. information about retaking the quiz.', 'wp_courseware'));
    printf('<dt>{UNIT_TITLE}</dt><dd>%s</dd>', __('The title of the unit that is associated with the quiz.', 'wp_courseware'));
    printf('<dt>{UNIT_URL}</dt><dd>%s</dd>', __('The URL of the unit that is associated with the quiz.', 'wp_courseware'));
    printf('</dl>');
    printf('<h4 class="wpcw_docs_side_mini_hdr">%s</h4>', __('Final Summary Notifications Only', 'wp_courseware'));
    printf('<dl class="wpcw_email_tags">');
    printf('<dt>{CUMULATIVE_GRADE}</dt><dd>%s</dd>', __('The overall cumulative grade that the user has scored from completing all quizzes on the course.', 'wp_courseware'));
    printf('<dt>{QUIZ_SUMMARY}</dt><dd>%s</dd>', __('The summary of each quiz, and what the user scored on each.', 'wp_courseware'));
    printf('</dl>');
    $page->showPageFooter();
}