Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions GDPR/Controllers/UserConsent.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ public function render_consent_logs_column( $value, $column_name, $user_id ) {
return $value;
}

$value = '<button type="button" class="tutor-btn tutor-btn-outline-primary tutor-btn-sm" data-tutor-modal-target="tutor-consent-logs-modal" data-consent-logs-trigger data-user-id="' . esc_attr( $user_id ) . '" data-user-name="' . esc_attr( $user->display_name ) . '" data-user-joined="' . esc_attr( $user->user_registered ) . '" data-user-email="' . esc_attr( $user->user_email ) . '" data-user-login="' . esc_attr( $user->user_login ) . '" data-avatar-src="' . esc_url( tutor_utils()->get_user_avatar_url( $user_id ) ) . '"><i class="tutor-icon-eye-line tutor-mr-8" aria-hidden="true"></i>' . esc_html__( 'View Logs', 'tutor' ) . '</button>';
$user_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( $user->display_name ?? '', ENT_QUOTES ) ) );
$value = '<button type="button" class="tutor-btn tutor-btn-outline-primary tutor-btn-sm" data-tutor-modal-target="tutor-consent-logs-modal" data-consent-logs-trigger data-user-id="' . esc_attr( $user_id ) . '" data-user-name="' . esc_attr( $user_name ) . '" data-user-joined="' . esc_attr( $user->user_registered ) . '" data-user-email="' . esc_attr( $user->user_email ) . '" data-user-login="' . esc_attr( $user->user_login ) . '" data-avatar-src="' . esc_url( tutor_utils()->get_user_avatar_url( $user_id ) ) . '"><i class="tutor-icon-eye-line tutor-mr-8" aria-hidden="true"></i>' . esc_html__( 'View Logs', 'tutor' ) . '</button>';

return $value;
}
Expand Down Expand Up @@ -387,7 +388,7 @@ public function render_consent_logs_button( $user_data ): void {
return;
}

$user_name = $user_data->display_name ?? '';
$user_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( $user_data->display_name ?? '', ENT_QUOTES ) ) );
$user_joined = $user_data->user_registered ?? '';
$user_email = $user_data->user_email ?? '';
$user_login = $user_data->user_login ?? '';
Expand Down
10 changes: 7 additions & 3 deletions assets/src/js/admin-dashboard/segments/consent-logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,17 +114,21 @@ const fetchAndRender = (userId, userName, userJoined, avatarSrc, userEmail, user
}
const userCard = `
<div class="tutor-consent-user-card">
${avatarSrc ? `<img src="${avatarSrc}" alt="${userName}" />` : ''}
${avatarSrc ? `<img class="tutor-consent-user-card-avatar" src="${avatarSrc}" alt="" />` : ''}
<div class="tutor-consent-user-card-info">
<span class="tutor-consent-user-card-name">${userName}</span>
<span class="tutor-consent-user-card-joined">${userJoined ? `${__('Joined', 'tutor')} ${userJoined}` : ''}</span>
<span class="tutor-consent-user-card-name"></span>
<span class="tutor-consent-user-card-joined"></span>
</div>
</div>
`;
modalBody.innerHTML = `
<div class="tutor-consent-timeline">${renderTimeline(logs)}</div>
${userCard}
`;
const cardNameEl = modalBody.querySelector('.tutor-consent-user-card-name');
if (cardNameEl) cardNameEl.textContent = userName;
const cardJoinedEl = modalBody.querySelector('.tutor-consent-user-card-joined');
if (cardJoinedEl && userJoined) cardJoinedEl.textContent = `${__('Joined', 'tutor')} ${userJoined}`;
if (downloadBtn) downloadBtn.style.display = '';
})
.catch(() => showEmpty());
Expand Down
10 changes: 7 additions & 3 deletions assets/src/js/admin-dashboard/segments/students.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,21 @@ const fetchAndRender = (userId, userName, userJoined, avatarSrc, userEmail, user
}
const userCard = `
<div class="tutor-consent-user-card">
${avatarSrc ? `<img src="${avatarSrc}" alt="${userName}" />` : ''}
${avatarSrc ? `<img class="tutor-consent-user-card-avatar" src="${avatarSrc}" alt="" />` : ''}
<div class="tutor-consent-user-card-info">
<span class="tutor-consent-user-card-name">${userName}</span>
<span class="tutor-consent-user-card-joined">${userJoined ? `${__('Joined', 'tutor')} ${userJoined}` : ''}</span>
<span class="tutor-consent-user-card-name"></span>
<span class="tutor-consent-user-card-joined"></span>
</div>
</div>
`;
modalBody.innerHTML = `
<div class="tutor-consent-timeline">${renderTimeline(logs)}</div>
${userCard}
`;
const cardNameEl = modalBody.querySelector('.tutor-consent-user-card-name');
if (cardNameEl) cardNameEl.textContent = userName;
const cardJoinedEl = modalBody.querySelector('.tutor-consent-user-card-joined');
if (cardJoinedEl && userJoined) cardJoinedEl.textContent = `${__('Joined', 'tutor')} ${userJoined}`;
})
.catch(() => showEmpty());
};
Expand Down
59 changes: 45 additions & 14 deletions classes/QuizBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@
$errors['ID'][] = __( 'Invalid quiz id provided', 'tutor' );
}

if ( $quiz && ! current_user_can( 'edit_post', $quiz_id ) ) {
if ( $quiz && ( ! current_user_can( 'edit_post', $quiz_id ) || ! tutor_utils()->can_user_manage( 'quiz', $quiz_id ) ) ) {
$success = false;
$errors['permission'][] = __( 'You do not have permission to edit this quiz', 'tutor' );
}
Expand Down Expand Up @@ -405,8 +405,11 @@
$errors = array_merge( $errors, $validation->errors );
}

if ( ! empty( $questions ) ) {
if ( $quiz_id ) {
$this->set_current_quiz_questions_answer_ids( $quiz_id );
}

if ( ! empty( $questions ) ) {
try {
$this->is_valid_quiz_question_answer_payload( $questions );
} catch ( \Throwable $th ) {
Expand Down Expand Up @@ -482,17 +485,45 @@
* @param array $deleted_question_ids question ids.
* @param array $deleted_answer_ids answer ids.
* @param array $deleted_temp_mask_values unsaved draw/pin/puzzle mask values.
* @param int $quiz_id optional quiz id to scope deletions.
*
* @return void
*/
public function handle_delete( $deleted_question_ids = array(), $deleted_answer_ids = array(), $deleted_temp_mask_values = array() ) {
public function handle_delete( $deleted_question_ids = array(), $deleted_answer_ids = array(), $deleted_temp_mask_values = array(), $quiz_id = 0 ) {
global $wpdb;
$deleted_question_ids = array_filter( $deleted_question_ids, 'is_numeric' );
$deleted_answer_ids = array_filter( $deleted_answer_ids, 'is_numeric' );
$deleted_temp_mask_values = is_array( $deleted_temp_mask_values ) ? array_values( array_filter( array_map( 'strval', $deleted_temp_mask_values ) ) ) : array();
$question_file_paths = array();
$mask_question_ids = array();

$quiz_id = (int) $quiz_id;
if ( $quiz_id > 0 ) {
if ( count( $deleted_question_ids ) ) {
$in_clause = QueryHelper::prepare_in_clause( $deleted_question_ids );
//phpcs:ignore -- sanitized $in_clause.
$valid_question_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT question_id FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = %d AND question_id IN ({$in_clause})",

Check failure on line 507 in classes/QuizBuilder.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable {$in_clause} at &quot;SELECT question_id FROM {$wpdb-&gt;prefix}tutor_quiz_questions WHERE quiz_id = %d AND question_id IN ({$in_clause})&quot;
$quiz_id
)
);
$deleted_question_ids = ! empty( $valid_question_ids ) ? array_map( 'intval', $valid_question_ids ) : array();
}

if ( count( $deleted_answer_ids ) ) {
$in_clause = QueryHelper::prepare_in_clause( $deleted_answer_ids );
//phpcs:ignore -- sanitized $in_clause.
$valid_answer_ids = $wpdb->get_col(
$wpdb->prepare(
"SELECT a.answer_id FROM {$wpdb->prefix}tutor_quiz_question_answers a INNER JOIN {$wpdb->prefix}tutor_quiz_questions q ON a.belongs_question_id = q.question_id WHERE q.quiz_id = %d AND a.answer_id IN ({$in_clause})",

Check failure on line 519 in classes/QuizBuilder.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable {$in_clause} at &quot;SELECT a.answer_id FROM {$wpdb-&gt;prefix}tutor_quiz_question_answers a INNER JOIN {$wpdb-&gt;prefix}tutor_quiz_questions q ON a.belongs_question_id = q.question_id WHERE q.quiz_id = %d AND a.answer_id IN ({$in_clause})&quot;
$quiz_id
)
);
$deleted_answer_ids = ! empty( $valid_answer_ids ) ? array_map( 'intval', $valid_answer_ids ) : array();
}
}

if ( count( $deleted_question_ids ) ) {
$mask_question_ids = $this->get_deletable_mask_question_ids( $deleted_question_ids );

Expand Down Expand Up @@ -840,7 +871,7 @@
$deleted_answer_ids = Input::post( 'deleted_answer_ids', array(), Input::TYPE_ARRAY );
$deleted_temp_mask_values = Input::post( 'deleted_temp_mask_values', array(), Input::TYPE_ARRAY );

$this->handle_delete( $deleted_question_ids, $deleted_answer_ids, $deleted_temp_mask_values );
$this->handle_delete( $deleted_question_ids, $deleted_answer_ids, $deleted_temp_mask_values, $quiz_id );

$wpdb->query( 'COMMIT' );

Expand Down Expand Up @@ -902,6 +933,8 @@
*/
private function set_current_quiz_questions_answer_ids( int $quiz_id ) {
if ( ! $quiz_id ) {
$this->current_quiz_question_ids = array();
$this->current_quiz_answer_ids = array();
return;
}

Expand All @@ -912,18 +945,16 @@
}
}

if ( is_null( $this->current_quiz_question_ids ) && $this->current_quiz ) {
$questions = $this->current_quiz->questions;
if ( $questions ) {
$this->current_quiz_question_ids = wp_list_pluck( $questions, 'question_id' );
}
if ( is_null( $this->current_quiz_question_ids ) ) {
$questions = $this->current_quiz ? ( $this->current_quiz->questions ?? array() ) : array();
$this->current_quiz_question_ids = ! empty( $questions ) ? wp_list_pluck( $questions, 'question_id' ) : array();
}

if ( is_null( $this->current_quiz_answer_ids ) && $this->current_quiz ) {
$quiz_details = $this->current_quiz->questions;

$quiz_question_answer = wp_list_pluck( $quiz_details, 'question_answers' );
$this->current_quiz_answer_ids = wp_list_pluck( array_merge( ...$quiz_question_answer ), 'answer_id' );
if ( is_null( $this->current_quiz_answer_ids ) ) {
$questions = $this->current_quiz ? ( $this->current_quiz->questions ?? array() ) : array();
$quiz_question_answers = ! empty( $questions ) ? wp_list_pluck( $questions, 'question_answers' ) : array();
$flattened = ! empty( $quiz_question_answers ) ? array_merge( ...$quiz_question_answers ) : array();
$this->current_quiz_answer_ids = ! empty( $flattened ) ? wp_list_pluck( $flattened, 'answer_id' ) : array();
}
}

Expand Down
10 changes: 5 additions & 5 deletions classes/Student.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
}

// @since 4.0.0 legal consent added.
$validate_consent = LegalConsent::validate_consent( LegalConsent::DISPLAY_ON_STD_REG, $_POST );

Check failure on line 90 in classes/Student.php

View workflow job for this annotation

GitHub Actions / WPCS

Processing form data without nonce verification.
if ( is_wp_error( $validate_consent ) ) {
$validation_errors[ $validate_consent->get_error_code() ] = $validate_consent->get_error_message();
}
Expand All @@ -106,8 +106,8 @@
return;
}

$first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
$last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
$first_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( tutor_utils()->input_old( 'first_name' ), ENT_QUOTES ) ) );
$last_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( tutor_utils()->input_old( 'last_name' ), ENT_QUOTES ) ) );
$email = sanitize_text_field( tutor_utils()->input_old( 'email' ) );
$user_login = sanitize_text_field( tutor_utils()->input_old( 'user_login' ) );
$password = sanitize_text_field( tutor_utils()->input_old( 'password' ) );
Expand Down Expand Up @@ -198,14 +198,14 @@
$user_id = get_current_user_id();
do_action( 'tutor_profile_update_before', $user_id );

$first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
$last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
$first_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( tutor_utils()->input_old( 'first_name' ), ENT_QUOTES ) ) );
$last_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( tutor_utils()->input_old( 'last_name' ), ENT_QUOTES ) ) );
$phone_number = sanitize_text_field( tutor_utils()->input_old( 'phone_number' ) );
$tutor_profile_bio = wp_kses( Input::post( 'tutor_profile_bio', '', Input::TYPE_KSES_POST ), tutor_utils()->allowed_profile_bio_tags() );
$tutor_profile_job_title = sanitize_text_field( tutor_utils()->input_old( 'tutor_profile_job_title' ) );
$timezone = Input::post( 'timezone', '' );

$display_name = sanitize_text_field( tutor_utils()->input_old( 'display_name' ) );
$display_name = sanitize_text_field( wp_strip_all_tags( wp_specialchars_decode( tutor_utils()->input_old( 'display_name' ), ENT_QUOTES ) ) );

$userdata = array(
'ID' => $user_id,
Expand Down
Loading