post_type !== LP_QUIZ_CPT ) {
return $r;
}
return 'html';
},
1000
);
}
/**
* Layout for edit course curriculum.
*
* @since 4.2.9
* @version 1.0.0
*/
public function edit_quiz_layout( QuizPostModel $quizPostModel ) {
wp_enqueue_style( 'lp-edit-quiz' );
wp_enqueue_script( 'lp-edit-quiz' );
$args = [
'id_url' => 'edit-quiz',
'quiz_id' => $quizPostModel->ID,
];
/**
* @uses self::render_edit_quiz
*/
$call_back = array(
'class' => self::class,
'method' => 'render_edit_quiz',
);
echo TemplateAJAX::load_content_via_ajax( $args, $call_back );
}
/**
* Allow callback for AJAX.
*
* @param array $callbacks
*
* @return array
*/
public function allow_callback( array $callbacks ): array {
$callbacks[] = get_class( $this ) . ':render_edit_quiz';
$callbacks[] = get_class( $this ) . ':render_list_items_not_assign';
return $callbacks;
}
/**
* Render edit course curriculum html.
*
* @throws Exception
* @since 4.2.9
* @version 1.0.1
*/
public static function render_edit_quiz( array $data ): stdClass {
$content = new stdClass();
try {
$quiz_id = $data['quiz_id'] ?? 0;
$quizPostModel = QuizPostModel::find( $quiz_id, true );
if ( ! $quizPostModel ) {
throw new Exception( __( 'Quiz not found', 'learnpress' ) );
}
// Check permission
$quizPostModel->check_capabilities_create_item_course();
self::instance()->quizPostModel = $quizPostModel;
$content->content = self::instance()->html_edit_quiz( $quizPostModel );
} catch ( Throwable $e ) {
$content->content = Template::print_message(
$e->getMessage(),
Response::STATUS_ERROR,
false
);
}
return $content;
}
/**
* Render html for edit quiz.
*
* @param QuizPostModel $quizPostModel
*
* @return string
* @throws Exception
*/
public function html_edit_quiz( QuizPostModel $quizPostModel ): string {
$html_questions = '';
// Get sections items
$question_ids = $quizPostModel->get_question_ids();
$count_questions = count( $question_ids );
foreach ( $question_ids as $question_id ) {
$questionPostModel = QuestionPostModel::find( $question_id, true );
$html_questions .= $this->html_edit_question( $questionPostModel );
}
$section_questions = [
'wrap' => '
',
'list-sections' => $html_questions,
'question-clone' => $this->html_edit_question(),
'wrap_end' => '
',
];
$section = [
'wrap' => '',
'heading' => '
',
'h4' => sprintf(
'
%s
',
__( 'Details', 'learnpress' )
),
'count-questions' => sprintf(
'
%s
',
$count_questions,
sprintf(
__( '
%1$d %2$s', 'learnpress' ),
$count_questions,
sprintf(
'
%s%s',
__( 'Question', 'learnpress' ),
__( 'Questions', 'learnpress' )
)
)
),
'quiz-toggle' =>
'
',
'heading_end' => '
',
'questions' => Template::combine_components( $section_questions ),
'add_new_question' => $this->html_add_new_question(),
'select_items' => $this->html_popup_items_to_select_clone( $quizPostModel ),
'wrap_end' => '
',
];
return Template::combine_components( $section );
}
/**
* HTML for edit question.
*
* @param $questionPostModel
*
* @return string
*/
public function html_edit_question( $questionPostModel = null ): string {
$is_clone = false;
$question_id = 0;
$question_title = '';
$html_edit_main = '';
if ( $questionPostModel instanceof QuestionPostModel ) {
$question_id = $questionPostModel->ID;
$question_title = $questionPostModel->post_title;
$section_edit_details = [
'wrap' => '',
'header' => sprintf(
'',
__( 'Option Details', 'learnpress' )
),
'collapse' => '
',
'point' => AdminEditQuestionTemplate::instance()->html_edit_mark( $questionPostModel ),
'hint' => AdminEditQuestionTemplate::instance()->html_edit_hint( $questionPostModel ),
'explanation' => AdminEditQuestionTemplate::instance()->html_edit_explanation( $questionPostModel ),
'collapse_end' => '
',
'wrap_end' => '
',
];
$section_edit_main = [
'wrap' => sprintf(
'',
$question_id
),
'left' => '
',
'description' => AdminEditQuestionTemplate::instance()->html_edit_question_description( $questionPostModel ),
'answers' => AdminEditQuestionTemplate::instance()->html_edit_question_by_type( $questionPostModel ),
'left_end' => '
',
'details' => Template::combine_components( $section_edit_details ),
'wrap_end' => '
',
];
$html_edit_main = Template::combine_components( $section_edit_main );
} else {
$is_clone = true;
}
$section = [
'wrap' => sprintf(
'',
esc_attr( $question_id ),
esc_attr( $is_clone ? 'clone lp-hidden' : '' ),
esc_attr( $is_clone ? '' : $questionPostModel->get_type() )
),
'head' => '
',
'drag' => sprintf(
'
',
esc_attr__( 'Drag to reorder section', 'learnpress' )
),
'loading' => '
',
'title' => AdminEditQuestionTemplate::instance()->html_input_question_title( $question_title ),
'btn-update' => sprintf(
'
',
__( 'Update' )
),
'btn-cancel' => sprintf(
'
',
__( 'Cancel' )
),
'type' => sprintf(
'
%s',
esc_html(
$questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_type_label() : ''
)
),
'btn-edit' => sprintf(
'
',
esc_attr__( 'Edit question detail', 'learnpress' ),
esc_url(
$questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_edit_link() : '#'
)
),
'btn-delete' => sprintf(
'
',
esc_attr__( 'Remove question', 'learnpress' ),
esc_attr__( 'Are you sure?', 'learnpress' ),
esc_attr__(
'This question will be removed from this quiz. The question will no longer be assigned to this quiz, but will not be permanently deleted.',
'learnpress'
)
),
'toggle' => '
',
'head_end' => '
',
'edit_main' => $html_edit_main,
'wrap_end' => '
',
];
return Template::combine_components( $section );
}
/**
* HTML for add new question.
*
* @return string
*/
public function html_add_new_question(): string {
$html_question_types = sprintf(
'',
esc_html__( 'Select question type', 'learnpress' )
);
$question_types = QuestionPostModel::get_types();
foreach ( $question_types as $type => $label ) {
$html_question_types .= sprintf(
'',
esc_attr( $type ),
esc_html( $label )
);
}
$html_question_types = Template::instance()->nest_elements(
[
sprintf(
'',
],
$html_question_types
);
$section = [
'wrap' => '',
'icon' => '',
'input' => sprintf(
'',
esc_attr__( 'Create a new question', 'learnpress' ),
esc_attr__( 'Question title is required', 'learnpress' ),
Template::convert_data_to_json(
[
'id_url' => 'create-question-add-to-quiz',
'quiz_id' => $this->quizPostModel->get_id(),
'action' => 'create_question_add_to_quiz',
]
),
),
'types' => $html_question_types,
'button' => sprintf(
'',
esc_attr__( 'Enter title question and choice type', 'learnpress' ),
__( 'Add Question', 'learnpress' )
),
'btn-select-items' => sprintf(
'',
__( 'Question Bank', 'learnpress' )
),
'wrap_end' => '
',
];
return Template::combine_components( $section );
}
/**
* HTML for popup items to select clone.
*
* @param QuizPostModel $quizPostModel
*
* @return string
*/
public function html_popup_items_to_select_clone( QuizPostModel $quizPostModel ): string {
$tabs = [
LP_QUESTION_CPT => __( 'Questions', 'learnpress' ),
];
/**
* @uses self::render_list_items_not_assign
*/
$html_items = TemplateAJAX::load_content_via_ajax(
[
'id_url' => 'list-questions-not-assign',
'enableScrollToView' => false,
'quiz_id' => $quizPostModel->ID,
'paged' => 1,
],
[
'class' => self::class,
'method' => 'render_list_items_not_assign',
]
);
$section = [
'wrap-script-template' => '',
];
return Template::combine_components( $section );
}
/**
* Render list items not assign to any quiz.
*
* @throws Exception
*
* @since 4.2.8.7
* @version 1.0.2
*/
public static function render_list_items_not_assign( $data ): stdClass {
$content = new stdClass();
try {
// Check permission
if ( ! current_user_can( UserModel::ROLE_ADMINISTRATOR ) ) {
throw new Exception( esc_html__( 'Access denied.', 'learnpress' ) );
}
$quiz_id = $data['quiz_id'] ?? 0;
$item_selecting = $data['item_selecting'] ?? [];
$search_title = $data['search_title'] ?? '';
$paged = intval( $data['paged'] ?? 1 );
$item_selecting_compare = new stdClass();
$quizPostModel = QuizPostModel::find( $quiz_id, true );
if ( ! $quizPostModel ) {
throw new Exception( __( 'Quiz not found', 'learnpress' ) );
}
$lp_posts_db = LP_Post_DB::getInstance();
$filter = new PostFilter();
$filter->only_fields = [
'DISTINCT(p.ID) AS ID',
'p.post_title',
'p.post_type',
];
$filter->post_type = LP_QUESTION_CPT;
$filter->post_status = [ 'publish' ];
$filter->order_by = 'p.ID';
$filter->page = $paged;
if ( ! empty( $search_title ) ) {
$filter->post_title = $search_title;
}
// Old logic: Get all questions not assigned to any quiz.
// New logic: Get all questions not assigned to the quiz.
$filter->where[] = $lp_posts_db->wpdb->prepare(
"AND p.ID NOT IN ( SELECT question_id FROM {$lp_posts_db->tb_lp_quiz_questions} WHERE quiz_id = %d )",
$quizPostModel->ID
);
$total_rows = 0;
$posts = $lp_posts_db->get_posts( $filter, $total_rows );
$total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
$html_lis = '';
if ( empty( $posts ) ) {
$html_lis = sprintf( '%s', __( 'No items found', 'learnpress' ) );
} else {
if ( ! empty( $item_selecting ) ) {
foreach ( $item_selecting as $item ) {
if ( ! isset( $item['id'] ) || ! isset( $item['type'] ) ) {
continue;
}
$item_selecting_compare->{$item['id']} = new stdClass();
}
}
foreach ( $posts as $post ) {
/**
* @var $questionPostModel QuestionPostModel
*/
$questionPostModel = QuestionPostModel::find( $post->ID, true );
if ( ! $questionPostModel ) {
continue;
}
$checked = '';
if ( isset( $item_selecting_compare->{$post->ID} ) ) {
$checked = ' checked="checked"';
}
$title_display = sprintf(
'%s(#%d - %s)',
esc_html( $post->post_title ),
$post->ID,
esc_html( $questionPostModel->get_type_label() )
);
$html_lis .= sprintf(
'%s%s',
sprintf(
'',
esc_attr( $post->ID ?? 0 ),
esc_attr( $questionPostModel->get_type_label() ?? '' ),
esc_attr( $questionPostModel->get_type() ?? '' ),
esc_attr( $title_display ), // For JS display on list selected.
esc_attr( $checked ),
esc_url( $questionPostModel->get_edit_link() ),
esc_attr( $questionPostModel->get_the_title() ?? '' )
),
$title_display
);
}
}
$section = [
'ul' => '',
'items' => $html_lis,
'ul_end' => '
',
'pagination' => Template::instance()->html_pagination(
[
'total_pages' => $total_pages,
'paged' => $paged,
]
),
];
$content->content = Template::combine_components( $section );
} catch ( Throwable $e ) {
$content->content = Template::print_message(
$e->getMessage(),
Response::STATUS_ERROR,
false
);
}
return $content;
}
}