/** * 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 }
/** * Handle exporting the XML for all of the questions. * * @param String The XML for the quiz in this unit. */ function export_content_handleQuestionsAndTags() { $xml = false; if (empty($this->questionList)) { return $xml; } // Copied so we can update the master list only without adding to the work that this loop does. $questionIDListForExpanding = $this->questionList; // ### Expand Random Questions - If we have any random questions - we need all questions that they use. foreach ($questionIDListForExpanding as $questionID => $singleQuestionDetails) { // We've got a random selection, so we need to get all questions that fall into this // particular selection, and remove this random selection before it's exported. if ('random_selection' == $singleQuestionDetails->question_type) { // Expand the tags into an array. $decodedTags = WPCW_quiz_RandomSelection::decodeTagSelection($singleQuestionDetails->question_question); if (!empty($decodedTags)) { // Got any questions for these tags? $questionsForTag = WPCW_quiz_RandomSelection::questionSelection_getAllQuestionsFromTags($decodedTags); // Yep, so add them to the list, ignoring duplicates. if (!empty($questionsForTag)) { $this->questionList = $this->questionList + $questionsForTag; } // If we have a whole pool flag, then we need to get all questions that exist. But this code // doesn't check for the whole pool flag, as this export is an expensive process anyway, so // for simplicity, we're not checking for the single exception. } // Now remove this question, as it's a random question that can't be exported. unset($this->questionList[$questionID]); } // end if random selection check } global $fieldsToProcess_quizzes, $fieldsToProcess_quiz_questions; $questionParentPath = '/questions'; $newQuestionIndex = 1; foreach ($this->questionList as $questionID => $singleQuestionDetails) { // Check question is valid - just in case. $questionDetails = WPCW_questions_getQuestionDetails($questionID, true); if (!$questionDetails) { continue; } // Create a new hash for this question ID for the XML file so that we can map // questions to quizzes. Intentionally using odd numbers only, to help with spotting // any potential errors with import. $this->questionList[$questionID]->question_hash = $questionDetails->question_hash = 'wpcwqid_' . $newQuestionIndex; $newQuestionIndex += 2; // Increment by 2, to allow us to spot issues. // ### Question - Start $xml .= $this->export_objectToXML('question', false, $questionDetails, $fieldsToProcess_quiz_questions, $questionParentPath, false); // Debug - check we have all the right fields for this question //$this->debug_courseCheckFieldsWeHave($questionDetails, $fieldsToProcess_quiz_questions); // ### Questions - question_data_answers // Handle the serialized 'question_data_answers' field e.g. /* [question_data_answers] => Array ( [1] => Array ( [answer] => RHJpenpsZQ== ) [2] => Array ( [answer] => RHJpcA== ) [3] => Array ( [answer] => Q2xvdWRidXJzdA== ) [4] => Array ( [answer] => Q2F0cyAmIERvZ3M= ) ) */ $questionDetails->question_data_answers = maybe_unserialize($questionDetails->question_data_answers); // Use this to numerically order the answers $questionidx = 1; if (!empty($questionDetails->question_data_answers) && is_array($questionDetails->question_data_answers)) { $dataToBeExported = array(); foreach ($questionDetails->question_data_answers as $idx => $details) { $dataToBeExported['possible_answer_' . $questionidx] = $details['answer']; // Do we have an image for this answer? If so, then add it with it's own tag for simplcity. if (isset($details['image'])) { $dataToBeExported['possible_answer_' . $questionidx . '_image'] = $details['image']; } $questionidx++; } $xml .= $this->export_arrayToXML('question_data_answers', false, $dataToBeExported, false, $questionParentPath . '/question', '/question_data_answers'); } // ###ÊQuestion - Tags - Start if (!empty($questionDetails->tags)) { $tagParentPath = $questionParentPath . '/question'; $xml .= $this->export_startBlock($tagParentPath, 'tags'); // Render tags as question->tags->tag foreach ($questionDetails->tags as $singleTag) { $xml .= $this->export_textData('tag', $singleTag->question_tag_name, $tagParentPath . '/tags/'); } // ###ÊQuestion - Tags - End $xml .= $this->export_endBlock($questionParentPath . '/question', 'tags'); } // ### Question - End $xml .= $this->export_endBlock($questionParentPath, 'question'); flush(); } return $xml; }
/** * Function called when a new question tag is added. */ function WPCW_AJAX_handleQuestionNewTag() { $ajaxResults = array('success' => true, 'errormsg' => __('Unfortunately there was a problem adding the tag.', 'wp_courseware'), 'html' => false); // Assume that we may have multiple tags, separated by commas. $potentialTagList = explode(',', WPCW_arrays_getValue($_POST, 'tagtext')); $cleanTagList = array(); // Check if question is expected to have been saved. $hasQuestionBeenSaved = 'yes' == WPCW_arrays_getValue($_POST, 'isquestionsaved'); // Got potential tags if (!empty($potentialTagList)) { // Clean up each tag, and add to a list. foreach ($potentialTagList as $potentialTag) { $cleanTagList[] = sanitize_text_field(stripslashes($potentialTag)); } // Check that cleaned tags are ok too if (!empty($cleanTagList)) { // Do this if the question exists and we're adding tags. if ($hasQuestionBeenSaved) { // Get the ID of the question we're adding this tag to. $questionID = intval(WPCW_arrays_getValue($_POST, 'questionid')); // Validate that the question exists before we tag it. $questionDetails = WPCW_questions_getQuestionDetails($questionID); if (!$questionDetails) { $ajaxResults['errormsg'] = __('Unfortunately that question could not be found, so the tag could not be added.', 'wp_courseware'); $ajaxResults['success'] = false; } else { // Add the tag to the database, get a list of the tag details now that they have been added. $tagDetailList = WPCW_questions_tags_addTags($questionID, $cleanTagList); foreach ($tagDetailList as $tagAddedID => $tagAddedText) { // Create the HTML to show the new tag. $ajaxResults['html'] .= sprintf('<span><a data-questionid="%d" data-tagid="%d" class="ntdelbutton">X</a> %s</span>', $questionID, $tagAddedID, $tagAddedText); } } // else question found } else { $tagDetailList = WPCW_questions_tags_addTags_withoutQuestion($cleanTagList); // For a new question, the ID is a string, not a value. $questionIDStr = WPCW_arrays_getValue($_POST, 'questionid'); // Create a hidden form entry plus the little tag, so that we can add the tag to the question when we save. foreach ($tagDetailList as $tagAddedID => $tagAddedText) { // Create the HTML to show the new tag. We'll add the full string to the hidden field so that we can // add the tags later. $ajaxResults['html'] .= sprintf(' <span> <a data-questionid="%d" data-tagid="%d" class="ntdelbutton">X</a> %s <input type="hidden" name="tags_to_add%s[]" value="%s" /> </span> ', 0, $tagAddedID, $tagAddedText, $questionIDStr, addslashes($tagAddedText)); } // end foreach } } } header('Content-Type: application/json'); echo json_encode($ajaxResults); die; }
/** * 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> ', admin_url('admin.php'), __('« 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(); }
function wpcw_tag_cleanup() { global $wpdb, $wpcwdb; $wpcwdb = new WPCW_Database(); $tags = array(); $SQL = "SELECT *\n\t\t\tFROM {$wpcwdb->question_tag_mapping}"; $tags = $wpdb->get_results($SQL); foreach ($tags as $tag) { $questionDetails = WPCW_questions_getQuestionDetails($tag->question_id); if (!$questionDetails) { WPCW_questions_tags_removeTag($tag->question_id, $tag->tag_id); } WPCW_questions_tags_updatePopularity($tag->tag_id); } }