/** * Creates the object using the unit post. * @param Object $post The post object for this unit. */ function __construct($post) { $this->unitPost = $post; $this->createdAfterAJAX = false; // Initialise any raw data $this->unchecked_QuizAnswersToGrade = $this->fetch_quizzes_loadRawAnswersSoFarForThisQuiz(false); // Load parent data for this unit $this->parentData = WPCW_units_getAssociatedParentData($post->ID); // Load the user ID for the user who is logged in $this->currentUserID = get_current_user_id(); $this->extraMessagesToShow_preQuizResults = array(); // Defaults $this->userProgress = false; $this->unitQuizDetails = false; $this->unitQuizProgress = false; $this->unitQuizProgress_incompleteQs = false; $this->cached_resultsByTag = false; // Try to load the progress data for this user if ($this->parentData) { // Main user progress data $this->userProgress = new UserProgress($this->parentData->course_id, $this->currentUserID); // Quiz details (if applicable) // Get quiz details $this->unitQuizDetails = WPCW_quizzes_getAssociatedQuizForUnit($this->unitPost->ID, true, $this->currentUserID); // Get quiz progress details if ($this->check_quizzes_validQuizDetails()) { // Got the user progress, determine if it's pending marking or not. $this->unitQuizProgress = WPCW_quizzes_getUserResultsForQuiz($this->currentUserID, $this->unitPost->ID, $this->unitQuizDetails->quiz_id); // Try to work out which questions are still incomplete. $this->updateInternalVariable_quizzes_getIncompleteQuestions(); } } }
/** * Handle showing the box that allows a user to mark a unit as completed. */ function WPCW_units_processUnitContent($content) { // #### Ensure we're only showing a course unit, a single item if (!is_single() || 'course_unit' != get_post_type()) { return $content; } global $post; // #### Get associated data for this unit. No course/module data, not a unit $parentData = WPCW_units_getAssociatedParentData($post->ID); if (!$parentData) { return $content; } // #### Ensure we're logged in $user_id = get_current_user_id(); if ($user_id == 0) { // Return no access error without content return WPCW_units_createErrorMessage($parentData->course_message_unit_not_logged_in); } $userProgress = new UserProgress($parentData->course_id, $user_id); // #### User not allowed access to content, so certainly can't say they've done this unit. if (!$userProgress->canUserAccessCourse()) { // Return no access error without content return WPCW_units_createErrorMessage($parentData->course_message_unit_no_access); } // #### Is user allowed to access this unit yet? if (!$userProgress->canUserAccessUnit($post->ID)) { // Return no access error without content return WPCW_units_createErrorMessage($parentData->course_message_unit_not_yet); } // #### Determine if this unit has been completed or not. $progressDetails = WPCW_units_getUserUnitDetails($user_id, $post->ID); $completed = $progressDetails && $progressDetails->unit_completed_status == 'complete'; // #### Show completion box if ($completed) { $completionBox = WPCW_units_getCompletionBox_complete($parentData, $post->ID, $user_id); } else { $completionBox = WPCW_units_getCompletionBox_pending($parentData, $post->ID); } // #### Show the navigation box (disable the next item if not completed yet). $navigationBox = WPCW_units_getNavigationBox($parentData, $post->ID, $userProgress, !$completed); return $content . $completionBox . $navigationBox; }
/** * Function called when a user is submitting quiz answers via * the frontend form. */ function WPCW_AJAX_units_handleQuizResponse() { // Security check if (!wp_verify_nonce(WPCW_arrays_getValue($_POST, 'progress_nonce'), 'wpcw-progress-nonce')) { die(__('Security check failed!', 'wp_courseware')); } // Quiz ID and Unit ID are combined in the single CSS ID for validation. // So validate both are correct and that user is allowed to access quiz. $quizAndUnitID = WPCW_arrays_getValue($_POST, 'id'); // e.g. quiz_complete_69_1 or quiz_complete_17_2 (first ID is unit, 2nd ID is quiz) if (!preg_match('/quiz_complete_(\\d+)_(\\d+)/', $quizAndUnitID, $matches)) { echo WPCW_units_getCompletionBox_error(); die; } // Use the extracted data for further validation $unitID = $matches[1]; $quizID = $matches[2]; $user_id = get_current_user_id(); // #### Get associated data for this unit. No course/module data, not a unit $parentData = WPCW_units_getAssociatedParentData($unitID); if (!$parentData) { // No error, as not a valid unit. die; } // #### User not allowed access to content, so certainly can't say they've done this unit. if (!WPCW_courses_canUserAccessCourse($parentData->course_id, $user_id)) { // No error, as not a valid unit. die; } // #### Check that the quiz is valid and belongs to this unit $quizDetails = WPCW_quizzes_getQuizDetails($quizID, true); if (!($quizDetails && $quizDetails->parent_unit_id == $unitID)) { die; } // Validate the quiz answers... which means we might have to // send back the form to be re-filled. $canContinue = WPCW_quizzes_handleQuizRendering_canUserContinueAfterQuiz($quizDetails, $_POST, $user_id); // Check that user is allowed to progress. if ($canContinue) { WPCW_units_saveUserProgress_Complete($user_id, $unitID, 'complete'); // Unit complete, check if course/module is complete too. do_action('wpcw_user_completed_unit', $user_id, $unitID, $parentData); // Only complete if allowed to continue. echo WPCW_units_getCompletionBox_complete($parentData, $unitID, $user_id); } die; }
/** * Function called when the unit ordering is being saved via AJAX. * This function will save the order of the modules, units and any unassigned units. * */ function WPCW_AJAX_handleUnitOrderingSaving() { // Security check if (!wp_verify_nonce(WPCW_arrays_getValue($_POST, 'order_nonce'), 'wpcw-order-nonce')) { die(__('Security check failed!', 'wp_courseware')); } // Get list of modules to save, check IDs are what we expect, and abort if nothing to do. $moduleList = WPCW_arrays_getValue($_POST, 'moduleList'); if (!$moduleList || count($moduleList) < 1) { die; } global $wpdb, $wpcwdb; $wpdb->show_errors(); $parentCourseID = 0; // Save new module ordering to database $moduleOrderCount = 0; // Ordering of units is absolute to the whole course $unitOrderCount = 0; //error_log(print_r($_POST, true)); // Need a course ID for resetting the ordering. foreach ($moduleList as $moduleID) { // Validate we have an actual module if (preg_match('/^wpcw_mod_(\\d+)$/', $moduleID, $matches)) { // Get course ID from module $moduleDetails = WPCW_modules_getModuleDetails($matches[1]); if ($moduleDetails) { $parentCourseID = $moduleDetails->parent_course_id; break; } } } // If there's no associated parent course, there's an issue. if (!$parentCourseID) { error_log('WPCW_AJAX_handleUnitOrderingSaving(). No associated parent course ID, so aborting.'); die; } // 2013-05-01 - Bug with orphan modules being left in the units_meta // Fix - Clean out existing units in this course, resetting them. // Then update the ordering using the loops below. $SQL = $wpdb->prepare("\n\t\tUPDATE {$wpcwdb->units_meta}\n\t\t SET unit_order = 0, parent_module_id = 0, \n\t\t \t parent_course_id = 0, unit_number = 0\n\t\tWHERE parent_course_id = %d\n\t", $parentCourseID); $wpdb->query($SQL); foreach ($moduleList as $moduleID) { // ### Check module name matches expected format. if (preg_match('/^wpcw_mod_(\\d+)$/', $moduleID, $matches)) { $moduleOrderCount++; $moduleIDClean = $matches[1]; // Update module list with new ordering $SQL = $wpdb->prepare("\n\t\t\t\tUPDATE {$wpcwdb->modules}\n\t\t\t\t SET module_order = %d, module_number = %d\n\t\t\t\tWHERE module_id = %d\n\t\t\t", $moduleOrderCount, $moduleOrderCount, $moduleIDClean); $wpdb->query($SQL); // ### Check units associated with this module $unitList = WPCW_arrays_getValue($_POST, $moduleID); if ($unitList && count($unitList) > 0) { $unitNumber = 0; foreach ($unitList as $unitID) { $unitNumber++; // Check unit name matches expected format. if (preg_match('/^wpcw_unit_(\\d+)$/', $unitID, $matches)) { $unitOrderCount += 10; $unitIDClean = $matches[1]; // Update database with new association and ordering. $SQL = $wpdb->prepare("\n\t\t\t\t\t\t\tUPDATE {$wpcwdb->units_meta}\n\t\t\t\t\t\t\t SET unit_order = %d, parent_module_id = %d, \n\t\t\t\t\t\t\t \t parent_course_id = %d, unit_number = %d\n\t\t\t\t\t\t\tWHERE unit_id = %d\n\t\t\t\t\t\t", $unitOrderCount, $moduleIDClean, $parentCourseID, $unitNumber, $unitIDClean); $wpdb->query($SQL); // 2013-05-01 - Updated to use the module ID, rather than the module order. update_post_meta($unitIDClean, 'wpcw_associated_module', $moduleIDClean); } } // end foreach } // end of $unitList check } } // #### Check for any units that have associated quizzes foreach ($_POST as $key => $value) { // Check any post value that has a unit in it if (preg_match('/^wpcw_unit_(\\d+)$/', $key, $matches)) { $unitIDClean = $matches[1]; // Try to extract the unit ID // [wpcw_unit_71] => Array // ( // [0] => wpcw_quiz_2 //) $quizIDRaw = false; if ($value && is_array($value)) { $quizIDRaw = $value[0]; } // Got a matching quiz ID if (preg_match('/^wpcw_quiz_(\\d+)$/', $quizIDRaw, $matches)) { $quizIDClean = $matches[1]; // Grab parent course ID from unit. Can't assume all units are in same course. $parentData = WPCW_units_getAssociatedParentData($unitIDClean); $parentCourseID = $parentData->parent_course_id; // Update database with new association and ordering. $SQL = $wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpcwdb->quiz}\n\t\t\t\t\t SET parent_unit_id = %d, parent_course_id = %d\n\t\t\t\t\tWHERE quiz_id = %d\n\t\t\t\t", $unitIDClean, $parentCourseID, $quizIDClean); $wpdb->query($SQL); // Add new associated unit information to the user quiz progress, // keeping any existing quiz results. $SQL = $wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpcwdb->user_progress_quiz}\n\t\t\t\t\t SET unit_id = %d\n\t\t\t\t\tWHERE quiz_id = %d\n\t\t\t\t", $unitIDClean, $quizIDClean); $wpdb->query($SQL); } } } // #### Check for any unassigned units, and ensure they're de-associated from modules. $unitList = WPCW_arrays_getValue($_POST, 'unassunits'); if ($unitList && count($unitList) > 0) { foreach ($unitList as $unitID) { // Check unit name matches expected format. if (preg_match('/^wpcw_unit_(\\d+)$/', $unitID, $matches)) { $unitIDClean = $matches[1]; // Update database with new association and ordering. $SQL = $wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpcwdb->units_meta}\n\t\t\t\t\t SET unit_order = 0, parent_module_id = 0, parent_course_id = 0, unit_number = 0\n\t\t\t\t\tWHERE unit_id = %d\n\t\t\t\t", $unitIDClean); $wpdb->query($SQL); // Update post meta to remove associated module detail update_post_meta($unitIDClean, 'wpcw_associated_module', 0); // Remove progress for this unit, as likely to be associated with something else. $SQL = $wpdb->prepare("\n\t\t\t\t\tDELETE FROM {$wpcwdb->user_progress}\n\t\t\t\t\tWHERE unit_id = %d\n\t\t\t\t", $unitIDClean); $wpdb->query($SQL); } } // end foreach ($unitList as $unitID) } // #### Check for any unassigned quizzes, and ensure they're de-associated from units. $quizList = WPCW_arrays_getValue($_POST, 'unassquizzes'); if ($quizList && count($quizList) > 0) { foreach ($quizList as $quizID) { // Check unit name matches expected format. if (preg_match('/^wpcw_quiz_(\\d+)$/', $quizID, $matches)) { $quizIDClean = $matches[1]; // Update database with new association and ordering. $SQL = $wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpcwdb->quiz}\n\t\t\t\t\t SET parent_unit_id = 0, parent_course_id = 0\n\t\t\t\t\tWHERE quiz_id = %d\n\t\t\t\t", $quizIDClean); $wpdb->query($SQL); // Remove the associated unit information from the user quiz progress. // But keep the quiz results for now. $SQL = $wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpcwdb->user_progress_quiz}\n\t\t\t\t\t SET unit_id = 0\n\t\t\t\t\tWHERE quiz_id = %d\n\t\t\t\t", $quizIDClean); $wpdb->query($SQL); } } // end foreach ($quizList as $quizID) } // Update course details $courseDetails = WPCW_courses_getCourseDetails($parentCourseID); if ($courseDetails) { do_action('wpcw_course_details_updated', $courseDetails); } //error_log(print_r($matches, true)); die; }
/** * Handles saving what the admin wants to do for the user next. */ function WPCW_showPage_UserProgess_quizAnswers_whatsNext_savePreferences($quizDetails, $results, $page, $userID, $unitID) { // Admin wants to save the next action to this progress. if (isset($_POST['failed_quiz_next_action']) && $_POST['failed_quiz_next_action']) { global $wpdb, $wpcwdb; $wpdb->show_errors(); $userNextAction = WPCW_arrays_getValue($_POST, 'wpcw_user_continue_action'); $userRetakeMsg = filter_var(WPCW_arrays_getValue($_POST, 'wpcw_user_progress_failed_reason'), FILTER_SANITIZE_STRING); // Check action is valid. Abort if not if (!in_array($userNextAction, array('retake_quiz', 'progress_anyway'))) { return $results; } // ****** REDUNDANT SWITCH ******* // Sort out the SQL statement for what to update // switch ($userNextAction) // { // // User needs to retake the course. // case 'retake_quiz': // break; // // User is allowed to progress // case 'progress_anyway': // $userRetakeMsg = false; // // Mark the unit as completed. // WPCW_units_saveUserProgress_Complete($userID, $unitID); // // Unit complete, check if course/module is complete too. // do_action('wpcw_user_completed_unit', $userID, $unitID, WPCW_units_getAssociatedParentData($unitID)); // break; // } // Update the progress item $SQL = $wpdb->prepare("\n\t\t \tUPDATE {$wpcwdb->user_progress_quiz}\n\t\t \t SET quiz_next_step_type = '%s', \n\t\t \t quiz_next_step_msg = %s \n\t\t \tWHERE user_id = %d \n\t\t \t AND unit_id = %d \n\t\t \t AND quiz_id = %d\n\t\t \tORDER BY quiz_attempt_id DESC\n\t\t \tLIMIT 1\n\t \t\t", $userNextAction, $userRetakeMsg, $userID, $unitID, $quizDetails->quiz_id); $wpdb->query($SQL); // Need to update the results object for use later. $results->quiz_next_step_type = $userNextAction; $results->quiz_next_step_msg = $userRetakeMsg; switch ($userNextAction) { // User needs to retake the course. case 'retake_quiz': $results->extraEmailDetail = __('Since you didn\'t pass the quiz, the instructor has asked that you re-take this quiz.', 'wp_courseware'); if ($userRetakeMsg) { $results->extraEmailDetail .= "\n\n" . $userRetakeMsg; } break; // User is allowed to progress // User is allowed to progress case 'progress_anyway': $results->extraEmailDetail = __('Although you didn\'t pass the quiz, the instructor is allowing you to continue.', 'wp_courseware'); // Mark the unit as completed. WPCW_units_saveUserProgress_Complete($userID, $unitID); // Unit complete, check if course/module is complete too. do_action('wpcw_user_completed_unit', $userID, $unitID, WPCW_units_getAssociatedParentData($unitID)); break; } // Tell code to send out emails $results->sendOutEmails = true; } $results->quiz_has_just_been_graded = true; return $results; }
/** * Function called when a user is blocked on a quiz due to running out of attempts. * * @param Integer $userID The ID of the user who has run out of attempts. * @param Object $quizDetails The details of the quiz that needs grading. */ function WPCW_actions_userQuizUserNeedsUnblocking_notifyAdmin($userID, $quizDetails) { if (!$userID || !$quizDetails) { return; } $adminSubject = __("User Needs Unblocking Notification - {USER_NAME} - '{COURSE_TITLE}'", 'wp_courseware'); $adminBody = __("Hi Trainer! \n\t\t\t\t\t\t\t\nJust to let you know, {USER_NAME} has just completed a quiz ({QUIZ_TITLE}), but they have failed and run out of attempts. You can unblock their progress here:\n{QUIZ_GRADE_URL}\n\n{SITE_NAME}\n{SITE_URL}\n", 'wp_courseware'); // Generate the quiz name and URL to mark the quiz before passing for email to be sent. $quizGradeURL = sprintf('%s&user_id=%d&quiz_id=%d&unit_id=%d', admin_url('users.php?page=WPCW_showPage_UserProgess_quizAnswers'), $userID, $quizDetails->quiz_id, $quizDetails->parent_unit_id); $adminBody = str_ireplace('{QUIZ_TITLE}', $quizDetails->quiz_title, $adminBody); $adminBody = str_ireplace('{QUIZ_GRADE_URL}', $quizGradeURL, $adminBody); // User and Unit details $userDetails = get_userdata($userID); $unitParentData = WPCW_units_getAssociatedParentData($quizDetails->parent_unit_id); // Check admin email address exists before sending. if ($unitParentData->course_to_email) { WPCW_email_sendEmail($unitParentData, $userDetails, $unitParentData->course_to_email, $adminSubject, $adminBody); } // Any additional admin-level notifications? do_action("wpcw_user_quiz_user_needs_blocking_notification", $unitParentData, $userDetails, $adminSubject, $adminBody); }
/** * Function that creates a list of units. * * @param Integer $courseID The ID of the course to show. * @param Array $options The list of options to show. */ function WPCW_courses_renderCourseList($courseID, $options) { extract(shortcode_atts(array('module' => 0, 'module_desc' => false, 'show_title' => false, 'show_desc' => false, 'widget_mode' => false, 'show_toggle_col' => false, 'show_modules_previous' => 'all', 'show_modules_next' => 'all', 'toggle_modules' => 'expand_all'), $options)); // Check settings to to see if they are true $module_desc = $module_desc == 'true'; $show_title = $show_title == 'true'; $show_desc = $show_desc == 'true'; $courseDetails = false; $parentData = false; global $post; // Show course based on current location for user. Use the currently shown post // to work out which course to show using the associated parent data. if ('current' == $courseID) { $parentData = WPCW_units_getAssociatedParentData($post->ID); if ($parentData) { $courseDetails = WPCW_courses_getCourseDetails($parentData->parent_course_id); $courseID = $parentData->parent_course_id; } else { return false; } } else { // Check course ID is valid $courseDetails = WPCW_courses_getCourseDetails($courseID); if (!$courseDetails) { return __('Unrecognised course ID.', 'wp_courseware'); } // Course ID is fine, get associated parent data for // hiding aspects of the widget $parentData = WPCW_units_getAssociatedParentData($post->ID); } $moduleList = false; // Do we just want a single module? if ($module > 0) { // Get module by module number within course (not the module ID) $moduleDetailsSingle = WPCW_modules_getModuleDetails_byModuleNumber($courseDetails->course_id, $module); if (!$moduleDetailsSingle) { return __('Could not find module.', 'wp_courseware'); } // Create module list of 1 using single module $moduleList[$moduleDetailsSingle->module_id] = $moduleDetailsSingle; } else { // Check there are modules $moduleList = WPCW_courses_getModuleDetailsList($courseID); if (!$moduleList) { return __('There are no modules in this training course.', 'wp_courseware'); } } $html = false; // #### Show course title/description if ($show_title) { $html .= sprintf('<div class="wpcw_fe_course_title">%s</div>', $courseDetails->course_title); } if ($show_desc) { $html .= sprintf('<div class="wpcw_fe_course_desc">%s</div>', $courseDetails->course_desc); } $html .= '<table id="wpcw_fe_course" cellspacing="0" cellborder="0">'; $showUnitLinks = false; // If true, show links to the units $colCount = 2; // Number of columns in the table // UP Object to determine what to show to the user. $userProgress = false; // Check user is logged in, and if they can access this course $user_id = get_current_user_id(); if ($user_id != 0) { $userProgress = new UserProgress($courseID, $user_id); // Show links for user if they are allowed to access this course. if ($userProgress->canUserAccessCourse()) { // User is logged in and can do course, so show the stuff they can do. $showUnitLinks = true; // Got an extra column to show progress $colCount = 3; } } // If we're showing a widget, and we have the parent data based on the // currently viewed unit, then change what's in the widget in terms // of previous/next units. $hideList = array(); if ($widget_mode && $module == 0 && $parentData) { // Build a list of the modules before and after the current // module, so that we can more easily control what's visible, // and what's not. $modulesBefore = array(); $modulesAfter = array(); $currentList =& $modulesBefore; foreach ($moduleList as $moduleID => $moduleObj) { // Switch lists, we've found the current module if ($moduleID == $parentData->parent_module_id) { $currentList =& $modulesAfter; } else { $currentList[] = $moduleID; } } // Handle showing previous modules switch ($show_modules_previous) { // All all items in the before list to be hidden case 'none': $hideList = array_merge($hideList, $modulesBefore); break; case 'all': break; // Keep a specific number of modules to show. // Keep a specific number of modules to show. default: $show_modules_previous += 0; $modulesToPickFrom = count($modulesBefore); // Remove the modules at the start of the list, leaving the right number of // $show_modules_previous modules in the list. if ($show_modules_previous > 0 && $modulesToPickFrom > $show_modules_previous) { $hideList = array_merge($hideList, array_slice($modulesBefore, 0, $modulesToPickFrom - $show_modules_previous)); } break; } // end switch // Handle showing the next modules. switch ($show_modules_next) { // All all items in the after list to be hidden case 'none': $hideList = array_merge($hideList, $modulesAfter); break; case 'all': break; // Keep a specific number of modules to show. // Keep a specific number of modules to show. default: $show_modules_next += 0; $modulesToPickFrom = count($modulesAfter); // Remove the modules at the start of the list, leaving the right number of // $show_modules_previous modules in the list. if ($show_modules_next > 0 && $modulesToPickFrom > $show_modules_next) { $hideList = array_merge($hideList, array_slice($modulesAfter, $show_modules_next)); } break; } // end switch } // Columns for marking item as being pending or complete. $progress_Complete = '<td class="wpcw_fe_unit_progress wpcw_fe_unit_progress_complete"><span> </span></td>'; $progress_Pending = '<td class="wpcw_fe_unit_progress wpcw_fe_unit_progress_incomplete"><span> </span></td>'; $progress_Blank = '<td class="wpcw_fe_unit_progress"><span> </span></td>'; // Show modules foreach ($moduleList as $moduleID => $moduleObj) { // See if we're skipping this module if (in_array($moduleID, $hideList)) { continue; } // If $collapseTitleArea is set to true, then the module will be collapsed. So just check what to hide // based on the contents of $toggle_modules $collapseTitleArea = false; if ($widget_mode && $parentData) { switch ($toggle_modules) { case 'contract_all': $collapseTitleArea = true; break; // See if the currently visible unit module is the one being rendered. // See if the currently visible unit module is the one being rendered. case 'contract_all_but_current': $collapseTitleArea = $moduleID != $parentData->parent_module_id; break; // Default is not to collapse. } } // We're showing the toggle section, so add it. if ($show_toggle_col) { $moduleTitleArea = false; $moduleTitleArea = sprintf('<td>%s</td><td class="wpcw_fe_toggle">%s</td>', $moduleObj->module_title, $collapseTitleArea ? '+' : '-'); } else { $moduleTitleArea = sprintf('<td colspan="%d">%s</td>', $colCount - 1, $moduleObj->module_title); } // Render final title bit $html .= sprintf('<tr class="wpcw_fe_module %s" id="wpcw_fe_module_group_%d"> <td>%s %d</td> ' . $moduleTitleArea . ' </tr>', $collapseTitleArea ? 'wpcw_fe_module_toggle_hide' : '', $moduleObj->module_number, __('Module', 'wp_courseware'), $moduleObj->module_number, $moduleTitleArea); // ### Showing the module descriptions? if ($module_desc) { $html .= sprintf('<tr class="wpcw_fe_module_des"><td colspan="%d">%s</td></tr>', $colCount, $moduleObj->module_desc); } // Add the class for the row that matches the parent module ID. $moduleRowClass = ' wpcw_fe_module_group_' . $moduleObj->module_number; // ### No Units Line $units = WPCW_units_getListOfUnits($moduleID); if (!$units) { $extraColSpan = 0; if ($show_toggle_col) { $extraColSpan = 1; } $html .= sprintf('<tr class="wpcw_fe_unit wpcw_fe_unit_none %s"> <td colspan="%d">%s</td> </tr>', $moduleRowClass, $colCount + $extraColSpan, __('There are no units in this module.', 'wp_courseware')); } else { // Render each unit foreach ($units as $unit) { $progressRow = false; $progressCol = false; // Show links for units if ($showUnitLinks) { // Yes we are showing progress data... see what state we're at. if ($userProgress) { if ($userProgress->isUnitCompleted($unit->ID)) { $progressCol = $progress_Complete; $progressRow = 'wpcw_fe_unit_complete'; } else { $progressCol = $progress_Pending; $progressRow = 'wpcw_fe_unit_pending'; } //$progressCol = ($userProgress->isUnitCompleted($unit->ID) ? $progress_Complete : $progress_Pending); } // See if the user is allowed to access this unit or not. if ($userProgress->canUserAccessUnit($unit->ID)) { // Main unit title, link and unit number $html .= sprintf(' <tr class="wpcw_fe_unit ' . $progressRow . $moduleRowClass . '"> <td>%s %d</td> <td class="wpcw_fe_unit"><a href="%s">%s</a></td> ' . $progressCol . ' </tr>', __('Unit', 'wp_courseware'), $unit->unit_meta->unit_number, get_permalink($unit->ID), $unit->post_title); } else { // If we're not allowed to access the unit, then it's always marked as pending. $html .= sprintf(' <tr class="wpcw_fe_unit ' . $progressRow . $moduleRowClass . '"> <td>%s %d</td> <td class="wpcw_fe_unit">%s</td> ' . $progress_Pending . ' </tr>', __('Unit', 'wp_courseware'), $unit->unit_meta->unit_number, $unit->post_title); } } else { $colspan = 1; if ($show_toggle_col) { $colspan = 2; } $html .= sprintf(' <tr class="wpcw_fe_unit ' . $progressRow . $moduleRowClass . '"> <td>%s %d</td> <td colspan="%d" class="wpcw_fe_unit">%s</td> </tr>', __('Unit', 'wp_courseware'), $unit->unit_meta->unit_number, $colspan, $unit->post_title); } } } // end show units } $html .= '</table>'; // Add powered by link $settings = TidySettings_getSettings(WPCW_DATABASE_SETTINGS_KEY); $html .= WPCW_generatedPoweredByLink($settings); return $html; }
/** * Function called when a post is being deleted by WordPress. Want to check * if this relates to a unit, and if so, remove it from our tables. * * @param Integer $post_id The ID of the post being deleted. */ function WPCW_units_deleteUnitHandler($post_id) { global $wpdb, $wpcwdb; $wpdb->show_errors(); // See if we've got data on this unit in the meta table $SQL = $wpdb->prepare("SELECT * FROM {$wpcwdb->units_meta} WHERE unit_id = %d", $post_id); if ($unitDetails = $wpdb->get_row($SQL)) { // Right, it's one of our units, so need to delete the meta data $SQL = $wpdb->prepare("DELETE FROM {$wpcwdb->units_meta} WHERE unit_id = %d", $post_id); $wpdb->query($SQL); // Delete it from the user progress too $SQL = $wpdb->prepare("DELETE FROM {$wpcwdb->user_progress} WHERE unit_id = %d", $post_id); $wpdb->query($SQL); // Associated with a course? $parentData = WPCW_units_getAssociatedParentData($post_id); if ($unitDetails->parent_course_id > 0) { // Need to update the course unit count and progresses do_action('wpcw_course_details_updated', $unitDetails->parent_course_id); } // Quiz - Unconnect it from the quiz that it's associated with. $SQL = $wpdb->prepare("UPDATE {$wpcwdb->quiz} SET parent_unit_id = 0, parent_course_id = 0 WHERE parent_unit_id = %d", $post_id); $wpdb->query($SQL); // Quiz Progress - Unconnect it from this quiz. $SQL = $wpdb->prepare("UPDATE {$wpcwdb->user_progress_quiz} SET unit_id = 0 WHERE unit_id = %d", $post_id); $wpdb->query($SQL); } }