/** * Try to load details using a module ID. * @param Integer $moduleID The ID of the module to use to load details for this course. */ public function loadDetails_byModuleID($moduleID) { $moduleDetails = WPCW_modules_getModuleDetails($moduleID); if (!$moduleDetails) { return; } $this->courseDetails = WPCW_courses_getCourseDetails($moduleDetails->parent_course_id); $this->loadUnitsForCourse(); }
/** * Handle any deletion if any has been requested. * @param Object $page The reference to the object showing the page content */ function WPCW_handler_processDeletion($page) { // Check for deletion command if (!isset($_GET['action'])) { return; } $action = WPCW_arrays_getValue($_GET, 'action'); switch ($action) { // ### Deleting a module case 'delete_module': $module_id = WPCW_arrays_getValue($_GET, 'module_id'); $moduleDetails = WPCW_modules_getModuleDetails($module_id); if ($moduleDetails) { // Actually delete the module from the system WPCW_modules_deleteModule($moduleDetails); $page->showMessage(sprintf(__('Successfully deleted module "<em>%s</em>".', 'wp_courseware'), $moduleDetails->module_title)); } break; // ### Deleting a course // ### Deleting a course case 'delete_course': $course_id = WPCW_arrays_getValue($_GET, 'course_id'); $courseDetails = WPCW_courses_getCourseDetails($course_id); if ($courseDetails) { // What deletion method? $deleteMethod = 'complete'; if ('course_and_module' == WPCW_arrays_getValue($_POST, 'delete_course_type')) { $deleteMethod = 'course_and_module'; } // Actually delete the course from the system WPCW_modules_deleteCourse($courseDetails, $deleteMethod); $page->showMessage(sprintf(__('Successfully deleted training course "<em>%s</em>".', 'wp_courseware'), $courseDetails->course_title)); } break; } }
/** * 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; }
/** * Creates the correct URL for course units, showing module and course names. * * @param String $post_link The current permalinkf for the unit (which includes %module_number%). * @param Object $post The object of the post for which a URL is requested. */ function WPCW_units_createCorrectUnitURL($post_link, $post = 0, $leavename = FALSE) { // Only filter if found module number if (strpos('%module_number%', $post_link) === 'FALSE') { return $post_link; } // Ensure we have access to the post object if (is_object($post)) { $post_id = $post->ID; } else { $post_id = $post; $post = get_post($post_id); } // Check that we've got access to the right course unit post type if (!is_object($post) || $post->post_type != 'course_unit') { return $post_link; } // Work out the module number for the unit. $moduleID = get_post_meta($post->ID, 'wpcw_associated_module', true) + 0; // V2.2 Fix - Using module NUMBER not module ID for the URL. $moduleDetails = WPCW_modules_getModuleDetails($moduleID); // Not found the right module, so remove the prefix. if (!$moduleDetails) { return str_replace('%module_number%', 'module-unassigned', $post_link); } // Put new slug in place of %module_number% return str_replace('%module_number%', 'module-' . $moduleDetails->module_number, $post_link); }
/** * 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 (< or >). 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(); }