Sindbad~EG File Manager
<?php
/**
* Class LP_Question_CURD
*
* @author ThimPress
* @package LearnPress/Classes/CURD
* @since 3.0.0
*/
/**
* Prevent loading this file directly
*/
defined( 'ABSPATH' ) || exit();
if ( ! class_exists( 'LP_Question_CURD' ) ) {
/**
* Class LP_Question_CURD
*/
class LP_Question_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
/**
* LP_Question_CURD constructor.
*/
public function __construct() {
$this->_error_messages = array(
'QUESTION_NOT_EXISTS' => __( 'The question does not exist.', 'learnpress' ),
);
}
/**
* Create question and can add to quiz.
*
* @param $args
*
* @return bool|int|LP_Question|WP_Error
*/
public function create( &$args ) {
$args = wp_parse_args(
$args,
array(
'quiz_id' => 0,
'order' => - 1,
'id' => '',
'status' => 'publish',
'type' => 'true_or_false',
'title' => __( 'New Question', 'learnpress' ),
'content' => '',
'create_answers' => true,
)
);
// set question author for author of quiz
if ( ! empty( $args['quiz_id'] ) ) {
$user_id = get_post_field( 'post_author', $args['quiz_id'] );
} else {
$user_id = learn_press_get_current_user_id();
}
$question_id = wp_insert_post(
array(
'ID' => $args['id'],
'post_author' => $user_id,
'post_type' => LP_QUESTION_CPT,
'post_status' => $args['status'],
'post_title' => $args['title'],
'post_content' => $args['content'],
)
);
if ( $question_id ) {
// add default meta for new lesson
$default_meta = LP_Question::get_default_meta();
if ( is_array( $default_meta ) ) {
foreach ( $default_meta as $key => $value ) {
update_post_meta( $question_id, '_lp_' . $key, $value );
}
}
update_post_meta( $question_id, '_lp_type', $args['type'] );
// update user memory question types
get_user_meta( $user_id, '_learn_press_memorize_question_types', $args['type'] );
$question = LP_Question::get_question( $question_id, array( 'type' => $args['type'] ) );
$question->set_type( $args['type'] );
// add question to quiz
if ( ! empty( $args['quiz_id'] ) ) {
$quiz_curd = new LP_Quiz_CURD();
$quiz_curd->add_question( $args['quiz_id'], $question_id, $args['order'] );
}
if ( $args['create_answers'] ) {
$question->create_default_answers();
}
do_action( 'learn-press/after-create-question', $question );
return $question;
}
return $question_id;
}
public function update( &$question ) {
return $question;
// TODO: Implement update() method.
}
/**
* Delete all question's related data before run wp_delete_post(), hook to before delete question hook.
*
* @since 3.0.0
*
* @param object $question_id
*/
public function delete( &$question_id ) {
// remove all answer of question from {$wpdb->prefix}learnpress_question_answers table
$this->clear( $question_id );
// quiz curd
$curd = new LP_Quiz_CURD();
// allow hook
do_action( 'learn-press/before-delete-question', $question_id );
// get the quizzes that a question is assigned to, return WP Post
$quiz = $this->get_quiz( $question_id );
// remove question from quiz
if ( $quiz ) {
$curd->remove_questions( $quiz->ID, $question_id );
}
}
/**
* Duplicate question.
*
* @since 3.0.0
*
* @param $question_id
* @param array $args
*
* @return mixed|WP_Error
*/
public function duplicate( &$question_id, $args = array() ) {
if ( ! $question_id ) {
return new WP_Error( 'lp/question/curd/duplicate/err', 'Oops! ID not found' );
}
if ( learn_press_get_post_type( $question_id ) != LP_QUESTION_CPT ) {
return new WP_Error( 'lp/question/curd/duplicate/err', 'Op! The question does not exist' );
}
// ensure that user can create question
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'lp/question/curd/duplicate/err', 'Sorry! You do not have permission to duplicate this question' );
}
// origin question
$question = LP_Question::get_question( $question_id );
// duplicate question
$new_question_id = learn_press_duplicate_post( $question_id, array( 'post_status' => 'publish' ) );
if ( ! $new_question_id || is_wp_error( $new_question_id ) ) {
return new WP_Error( 'lp/question/curd/duplicate/err', 'Sorry! Failed to duplicate the question!' );
} else {
// init new question
$new_question = LP_Question::get_question( $new_question_id );
// set data
$new_question->set_type( $question->get_type() );
$new_question->set_data( 'answer_options', $question->get_data( 'answer_options' ) );
// trigger change user memorize question types
$user_id = get_current_user_id();
update_user_meta( $user_id, '_learn_press_memorize_question_types', $new_question->get_type() );
// duplicate answer
$this->duplicate_answer( $question_id, $new_question_id );
do_action( 'learn-press/item/after-duplicate', $question_id, $new_question_id, $args );
return $new_question_id;
}
}
/**
* Duplicate answer question.
*
* @param $question_id | origin question
* @param $question_id_clone | new question
* @version 3.0.1
* @since 1.0.1
*/
public function duplicate_answer( $question_id, $question_id_clone ) {
$lp_db = LP_Database::getInstance();
$lp_question_answers_db = LP_Question_Answers_DB::getInstance();
try {
// Get all answer of question
$filter_get_answer_options = new LP_Question_Answers_Filter();
$filter_get_answer_options->question_ids = [ $question_id ];
$answer_options = $lp_question_answers_db->get_question_asnwers( $filter_get_answer_options );
if ( $answer_options ) {
foreach ( $answer_options as $answer_option ) {
$question_answer_id = $answer_option->question_answer_id;
// Insert new question_answer
$insert_question_answer_rs = $lp_db->wpdb->insert(
$lp_db->tb_lp_question_answers,
array(
'question_id' => $question_id_clone,
'title' => ! empty( $answer_option->title ) ? $answer_option->title : '',
'value' => ! empty( $answer_option->value ) ? $answer_option->value : '',
'is_true' => ! empty( $answer_option->is_true ) ? $answer_option->is_true : '',
'order' => $answer_option->order,
),
array( '%d', '%s', '%s', '%s', '%s' )
);
if ( ! $insert_question_answer_rs ) {
throw new Exception( __( 'Failed to duplicate answer', 'learnpress' ) );
}
// Get question_answer_id have just inserted
$filter_question_answer_id = new LP_Question_Answers_Filter();
$filter_question_answer_id->only_fields = [ 'MAX(question_answer_id)' ];
$filter_question_answer_id->question_ids = [ $question_id_clone ];
$filter_question_answer_id->return_string_query = true;
$question_answer_id_query = $lp_question_answers_db->get_question_asnwers( $filter_question_answer_id );
$question_answer_id_new = (int) $lp_question_answers_db->wpdb->get_var( $question_answer_id_query );
if ( ! $question_answer_id_new ) {
throw new Exception( __( 'Failed to duplicate answer', 'learnpress' ) );
}
// Duplicate answer meta
// Get answer meta by question_answer_id
$filter_get = new LP_Question_Answermeta_Filter();
$filter_get->collection = $lp_db->tb_lp_question_answermeta;
$filter_get->collection_alias = 'qam';
$filter_get->field_count = 'meta_id';
$filter_get->limit = -1;
$filter_get->where[] = $lp_db->wpdb->prepare( 'AND qam.learnpress_question_answer_id = %d', $question_answer_id );
$filter_get->fields = $lp_db->get_cols_of_table( $lp_db->tb_lp_question_answermeta );
$question_answermeta_rs = $lp_db->execute( $filter_get );
foreach ( $question_answermeta_rs as $question_answermeta ) {
$lp_db->wpdb->insert(
$lp_db->tb_lp_question_answermeta,
array(
'learnpress_question_answer_id' => $question_answer_id_new,
'meta_key' => $question_answermeta->meta_key,
'meta_value' => $question_answermeta->meta_value,
),
array( '%d', '%s', '%s' )
);
}
}
}
} catch ( Throwable $e ) {
error_log( $e->getMessage() );
}
}
/**
* @param LP_Question $question
*
* @return bool
* @throws Exception
*/
public function load( &$question ) {
// question id
$id = $question->get_id();
if ( ! $id || ! in_array( learn_press_get_post_type( $id ), array( 'revision', LP_QUESTION_CPT ) ) ) {
throw new Exception( sprintf( __( 'Invalid question with ID "%d".', 'learnpress' ), $id ) );
}
$question->set_data_via_methods(
array(
'explanation' => get_post_meta( $id, '_lp_explanation', true ),
'hint' => get_post_meta( $id, '_lp_hint', true ),
)
);
// $this->_load_answer_options( $question );
$this->_load_meta( $question );
return true;
}
/**
* @param $question | LP_Question
*/
protected function _load_meta( &$question ) {
$type = get_post_meta( $question->get_id(), '_lp_type', true );
if ( ! learn_press_is_support_question_type( $type ) ) {
$type = 'true_or_false';
}
// $question->set_type( $type );
$mark = $this->_get_question_mark( $question->get_id() );
$question->set_data_via_methods(
array(
'mark' => $mark,
)
);
}
public function _get_question_mark( $question_id ) {
// Recheck _lp_mark @tungnx
$mark = get_post_meta( $question_id, '_lp_mark', true ) ? get_post_meta( $question_id, '_lp_mark', true ) : 0;
$mark = abs( $mark );
if ( ! $mark ) {
$mark = apply_filters( 'learn-press/question/default-mark', 1, $question_id );
update_post_meta( $question_id, '_lp_mark', $mark );
}
return $mark;
}
/**
* Get the quizzes that a question is assigned to.
*
* @since 3.0.0
*
* @param $question_id
*
* @return null|object WP_Post
*/
public function get_quiz( $question_id ) {
global $wpdb;
$query = $wpdb->prepare(
"
SELECT post.* FROM {$wpdb->posts} post
INNER JOIN {$wpdb->prefix}learnpress_quiz_questions quiz ON post.ID = quiz.quiz_id
WHERE quiz.question_id = %d
",
$question_id
);
// get single row
return $wpdb->get_row( $query );
}
/**
* Change question type.
*
* @param $question LP_Question
* @param $new_type
*
* @return false|void
* @since 3.0.0
* @version 1.0.1
*/
public function change_question_type( &$question, $new_type ) {
if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
return false;
}
$question_id = $question->get_id();
// If not new Question or not change type return
$old_type = get_post_meta( $question_id, '_lp_type', true );
if ( ! empty( $old_type ) && $old_type === $new_type ) {
return;
}
$answer_options = $question->get_data( 'answer_options' );
update_post_meta( $question_id, '_lp_type', $new_type );
$question->set_type( $new_type );
$new_question = LP_Question::get_question( $question_id, array( 'force' => true ) );
if ( $new_question ) {
$user_id = get_current_user_id();
update_user_meta( $user_id, '_learn_press_memorize_question_types', $new_type );
if ( $old_type == 'multi_choice' && $new_type == 'single_choice' ) {
$func = '_convert_answers_multi_choice_to_single_choice';
} elseif ( ( $old_type == 'multi_choice' || $old_type == 'single_choice' ) && 'true_or_false' == $new_type ) {
$func = '_convert_answers_to_true_or_false';
} else {
// for rest, clear answer data and create default
$func = '_convert_default_answers';
}
if ( is_callable( array( $this, $func ) ) ) {
$answer_options = call_user_func_array(
array( $this, $func ),
array(
$question,
$new_question,
$answer_options,
)
);
}
LP_Object_Cache::set( 'answer-options-' . $question_id, $answer_options, 'learn-press/questions' );
$new_question->set_data( 'answer_options', $answer_options );
$question = $new_question;
}
}
/**
* Update answer title
*
* @param $question_id
* @param $answer
*
* @return bool|false|int
*/
public function update_answer_title( $question_id, $answer ) {
if ( get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
return false;
}
global $wpdb;
// question data
$data = array(
'data' => apply_filters(
'learn-press/question/update-answer-data',
array(
'title' => $answer['title'],
'value' => $answer['value'] ?? '',
'is_true' => $answer['is_true'] ?? '',
)
),
'where' => array(
'question_answer_id' => $answer['question_answer_id'],
'question_id' => $question_id,
),
);
$update = $wpdb->update(
$wpdb->learnpress_question_answers,
$data['data'],
$data['where'],
array( '%s', '%s', '%s' ),
array( '%d', '%d' )
);
// Update for Fill in Blanks.
if ( ! empty( $answer['blanks'] ) ) {
$blanks = $answer['blanks'];
/*if ( is_array( $blanks ) ) {
$question = LP_Question::get_question( $question_id );
foreach ( $blanks as $id => $blank ) {
$question->_blanks[ $blank['id'] ] = $blank;
}
}*/
learn_press_update_question_answer_meta( $answer['question_answer_id'], '_blanks', $blanks );
}
return $update;
}
/**
* Update correct answer.
*
* @param $question LP_Question
* @param $correct
*
* @return bool | LP_Question
*/
public function change_correct_answer( $question, $correct ) {
if ( learn_press_get_post_type( $question->get_id() ) != LP_QUESTION_CPT ) {
return false;
}
global $wpdb;
$question_id = $question->get_id();
$question_type = $question->get_type();
$question_answers = $question->get_data( 'answer_options' );
$db_args = $answers = array();
foreach ( $question_answers as $index => $answer ) {
$answer_data = array(
'title' => $answer['title'],
'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
'is_true' => isset( $answer['is_true'] ) ? $answer['is_true'] : '',
);
// update correct for select answer
if ( $answer['question_answer_id'] == $correct['question_answer_id'] ) {
$answer_data['is_true'] = $correct['is_true'];
} else {
// untrue all rest answer with True or false and Single choice question
if ( in_array( $question_type, array( 'true_or_false', 'single_choice' ) ) ) {
$answer_data['is_true'] = '';
}
}
// question answers data to set cache
$answers[ $index ] = array(
'question_answer_id' => $answer['question_answer_id'],
'question_id' => $question_id,
'order' => $answer['order'],
'title' => $answer_data['title'],
'value' => $answer_data['value'],
'is_true' => $answer_data['is_true'],
);
// new answers data
$db_args[ $index ] = array(
'data' => array(
'title' => $answer_data['title'],
'value' => $answer_data['value'],
'is_true' => $answer_data['is_true'],
),
'where' => array(
'question_answer_id' => $answer['question_answer_id'],
'question_id' => $question_id,
'order' => $answer['order'],
),
);
}
// update db
foreach ( $db_args as $id => $arg ) {
$wpdb->update(
$wpdb->learnpress_question_answers,
$arg['data'],
$arg['where'],
array( '%s', '%s', '%s' ),
array( '%d', '%d', '%d' )
);
}
// set question answer data
$question->set_data( 'answer_options', $answers );
return $question;
}
/**
* Sort answers.
*
* @since 3.0.0
*
* @param $question_id
* @param array $order
*
* @return bool|LP_Question
*/
public function sort_answers( $question_id, $order = array() ) {
if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
return false;
}
if ( $order ) {
$question = LP_Question::get_question( $question_id );
$answers = $question->get_data( 'answer_options' );
global $wpdb;
$new_answers = array();
foreach ( $order as $index => $answer_id ) {
$wpdb->update(
$wpdb->learnpress_question_answers,
array( 'order' => $index + 1 ),
array( 'question_answer_id' => $answer_id )
);
$new_answers[ $answer_id ] = $answers[ $answer_id ];
}
$question->set_data( 'answer_options', $new_answers );
return $question;
}
return false;
}
/**
* Delete question answer.
*
* @param $question_id
* @param $answer_id
* @param $force
*
* @return bool|false|int
*/
public function delete_answer( $question_id, $answer_id, $force = false ) {
if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
return false;
}
$question = LP_Question::get_question( $question_id );
// exist answer options
$answers = $question->get_data( 'answer_options' );
global $wpdb;
// Delete answer meta
$wpdb->delete(
$wpdb->learnpress_question_answermeta,
array( 'learnpress_question_answer_id' => $answer_id )
);
$delete = $wpdb->delete(
$wpdb->learnpress_question_answers,
array( 'question_answer_id' => $answer_id )
);
if ( $delete ) {
unset( $answers[ $answer_id ] );
$question->set_data( 'answer_options', $answers );
$this->sort_answers( $question_id, array_keys( $answers ) );
}
return $delete;
}
/**
* Add new answer.
*
* @param $question_id
* @param $new_answer
*
* @return bool|false|int
*/
public function new_answer( $question_id, $new_answer ) {
if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT ) {
return false;
}
$question = LP_Question::get_question( $question_id );
// exist answer options
$answers = $question->get_data( 'answer_options' );
// number answer options
$number = count( $answers );
if ( $question->get_type() === 'sorting_choice' ) {
$new_answer['is_true'] = 'yes';
}
global $wpdb;
$new_answer = wp_parse_args(
$new_answer,
array(
'question_id' => $question_id,
'title' => '',
'value' => learn_press_random_value(),
'is_true' => '',
'order' => $number + 1,
)
);
$insert = $wpdb->insert(
$wpdb->learnpress_question_answers,
$new_answer,
learn_press_map_columns_format(
$new_answer,
array(
'question_id' => '%d',
'title' => '%s',
'value' => '%s',
'is_true' => '%s',
'order' => '%d',
)
)
);
if ( $insert ) {
$new_answer['question_answer_id'] = $wpdb->insert_id;
if ( is_array( $answers ) ) {
$answers = array_merge( $answers, array( $new_answer ) );
} else {
$answers = array( $new_answer );
}
$question->set_data( 'answer_options', $answers );
}
return $wpdb->insert_id;
}
/**
* Convert answers to true or false question.
*
* @since 3.0.0
*
* @param $question
* @param $new_question
* @param $answers
*
* @return mixed
*/
protected function _convert_answers_to_true_or_false( $question, $new_question, $answers ) {
if ( is_array( $answers ) ) {
// array answer ids
$answer_ids = array_keys( $answers );
if ( sizeof( $answers ) > 2 ) {
global $wpdb;
foreach ( $answers as $key => $answer ) {
if ( array_search( $key, $answer_ids ) > 1 ) {
$wpdb->delete(
$wpdb->learnpress_question_answers,
array( 'question_answer_id' => $answer['question_answer_id'] )
);
}
}
$answers = array_slice( $answers, 0, 2, true );
}
$correct = 0;
foreach ( $answers as $key => $answer ) {
if ( $answer['is_true'] == 'yes' ) {
$correct += 1;
}
}
if ( ! $correct ) {
// for single choice deletes all correct, set first option is correct
$answers[ $answer_ids[0] ]['is_true'] = 'yes';
} elseif ( $correct == 2 ) {
// for multiple choice keeps all correct, remove all correct and keep first option
$answers[ $answer_ids[1] ]['is_true'] = 'no';
}
}
return $answers;
}
/**
*
* Convert answers for multi choice to single choice question.
*
* @since 3.0.0
*
* @param $question
* @param $new_question
* @param $answers
*
* @return array
*/
protected function _convert_answers_multi_choice_to_single_choice( $question, $new_question, $answers ) {
if ( is_array( $answers ) ) {
// array answer ids
$answer_ids = array_keys( $answers );
$correct = 0;
foreach ( $answers as $key => $answer ) {
if ( $answer['is_true'] == 'yes' ) {
$correct += 1;
}
}
if ( ! $correct ) {
$answers[ $answer_ids[0] ]['is_true'] = 'yes';
} elseif ( $correct > 1 ) {
// remove all correct and keep first option
$answers[ $answer_ids[0] ]['is_true'] = 'no';
}
}
return $answers;
}
/**
* Convert default answers.
*
* @param $question LP_Question
* @param $new_question LP_Question
* @param $answers
*
* @return array
*/
protected function _convert_default_answers( $question, $new_question, $answers ) {
$question_id = $question->get_id();
// clear all exists answer
$this->clear( $question_id );
// set default answer
$answer_options = $new_question->get_default_answers();
if ( is_array( $answer_options ) ) {
foreach ( $answer_options as $index => $answer ) {
$insert = array(
'question_id' => $question_id,
'title' => $answer['title'],
'value' => isset( $answer['value'] ) ? stripslashes( $answer['value'] ) : '',
'is_true' => ( $answer['is_true'] == 'yes' ) ? $answer['is_true'] : '',
'order' => $index + 1,
);
$new_answers[] = $this->add_answer( $new_question->get_type(), $insert );
};
return $new_answers;
}
return $answers;
}
/**
* Add question answer.
*
* @since 3.0.0
*
* @param string $question_type
* @param array $args
*
* @return array|bool
*/
public function add_answer( $question_type = '', $args = array() ) {
global $wpdb;
$question = LP_Question::get_question( $args['question_id'], array( 'type' => $question_type ) );
$wpdb->insert(
$wpdb->learnpress_question_answers,
array(
'question_id' => $args['question_id'],
'title' => $args['title'],
'value' => $args['value'],
'is_true' => $args['is_true'],
'order' => $args['order'],
),
array( '%d', '%s', '%s', '%s', '%d' )
);
$question_answer_id = $wpdb->insert_id;
if ( $question_answer_id ) {
// update question answer option data
$answer_options = $question->get_data( 'answer_options' ) ? $question->get_data( 'answer_options' ) : array();
$new_answer_option_data = array(
'question_answer_id' => $question_answer_id,
'question_id' => $args['question_id'],
'order' => $args['order'],
'title' => $args['title'],
'value' => $args['value'],
'is_true' => $args['is_true'],
);
if ( ! $answer_options ) {
$question->set_data( 'answer_options', array( $new_answer_option_data ) );
} else {
$answer_options[] = $new_answer_option_data;
$question->set_data( 'answer_options', $answer_options );
}
return $new_answer_option_data;
} else {
return false;
}
}
/**
* Delete question answer.
*
* @since 3.0.0
*
* @param $question_id
* @param $answer_id
*
* @return bool|false|int
*/
public function delete_question_answer( $question_id, $answer_id ) {
if ( learn_press_get_post_type( $question_id ) !== LP_QUESTION_CPT || ! $answer_id ) {
return false;
}
global $wpdb;
$result = $wpdb->delete(
$wpdb->learnpress_question_answers,
array( 'question_answer_id' => $answer_id )
);
return $result;
}
/**
* Delete all question answers.
*
* @param $question_id
*
* @return bool|WP_Error
*/
public function clear( $question_id ) {
if ( ! learn_press_get_question( $question_id ) ) {
return $this->get_error( 'QUESTION_NOT_EXISTS' );
}
do_action( 'learn-press/before-clear-question', $question_id );
global $wpdb;
$wpdb->delete( $wpdb->learnpress_question_answers, array( 'question_id' => $question_id ) );
return true;
}
/**
* Load answer options for the question from database.
* Load from cache if data is already loaded into cache.
* Otherwise, load from database and put to cache.
*
* @param int $question_id
*
* @return array
*/
protected function _read_answers( $question_id ) {
global $wpdb;
$query = $wpdb->prepare(
"
SELECT question_answer_id, title, value, is_true
FROM {$wpdb->prefix}learnpress_question_answers
WHERE question_id = %d
ORDER BY `order` ASC
",
$question_id
);
$answer_options = array();
$results = $wpdb->get_results( $query );
if ( $results ) {
foreach ( $results as $k => $v ) {
$answer_option = array(
'question_answer_id' => absint( $v->question_answer_id ),
'title' => $v->title,
'value' => $v->value,
'is_true' => $v->is_true,
'order' => $k + 1, // Need???
);
$answer_options[ $v->question_answer_id ] = $answer_option;
}
}
return $answer_options;
}
/**
* Load question answers
*
* @updated 3.1.0
*
* @param array|int $question_id
*
* @return array|bool
*/
public function load_answer_options( $question_id ) {
global $wpdb;
$return_id = 0;
if ( is_array( $question_id ) ) {
foreach ( $question_id as $q_id ) {
$this->load_answer_options( $q_id );
if ( ! $return_id ) {
$return_id = $q_id;
}
}
$question_id = $return_id;
}
$answer_options = LP_Object_Cache::get( 'question-' . $question_id, 'question-answers' );
if ( false === $answer_options ) {
$answer_options = $this->_read_answers( $question_id );
LP_Object_Cache::set( 'question-' . $question_id, $answer_options, 'question-answers' );
}
return $answer_options;
}
}
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists