Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questions report #6410

Open
wants to merge 4 commits into
base: trunk
Choose a base branch
from
Open
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
13 changes: 9 additions & 4 deletions includes/class-sensei-analysis-overview-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class Sensei_Analysis_Overview_List_Table extends Sensei_List_Table {
public function __construct( $type = 'users' ) {
_deprecated_function( __METHOD__, '4.3.0', 'Sensei_Reports_Overview_List_Table_Factory::create()' );

$this->type = in_array( $type, array( 'courses', 'lessons', 'users' ), true ) ? $type : 'users';
$this->type = in_array( $type, array( 'courses', 'lessons', 'users', 'questions' ), true ) ? $type : 'users';
$this->page_slug = Sensei_Analysis::PAGE_SLUG;

print_r($type);
// Load Parent token into constructor.
parent::__construct( 'analysis_overview' );

Expand Down Expand Up @@ -198,6 +198,12 @@ function get_sortable_columns() {
);
break;

case 'questions':
$columns = array(
'title' => array( 'display_name', false ),
);
break;

case 'users':
default:
$columns = array(
Expand Down Expand Up @@ -885,8 +891,7 @@ public function output_top_filters() {
?>
<form class="sensei-analysis__top-filters">
<?php Sensei_Utils::output_query_params_as_inputs( [ 'course_filter', 'start_date', 'end_date', 's' ] ); ?>

<?php if ( 'lessons' === $this->type ) : ?>
<?php if ( in_array( $this->type, [ 'lessons', 'questions' ], true ) ) : ?>
<label for="sensei-course-filter">
<?php esc_html_e( 'Course', 'sensei-lms' ); ?>:
</label>
Expand Down
1 change: 1 addition & 0 deletions includes/class-sensei-analysis.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ private function display_reports_navigation() {
'students' => __( 'Students', 'sensei-lms' ),
'courses' => __( 'Courses', 'sensei-lms' ),
'lessons' => __( 'Lessons', 'sensei-lms' ),
'questions' => __('Questions', 'sensei-lms'),
);
$current_report_key = isset( $reports[ $type ] ) ? $type : 'students';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
<?php

/**
* File containing the Sensei_Reports_Overview_Data_Provider_Questions class.
*
* @package sensei
*/

if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}

/**
* Class Sensei_Reports_Overview_Data_Provider_Questions
*
* @since 4.3.0
*/
class Sensei_Reports_Overview_Data_Provider_Questions implements Sensei_Reports_Overview_Data_Provider_Interface
{
/**
* Total number of students found with given criteria.
*
* @var int Total number of items
*/
private $last_total_items = 0;

/**
* Contains start date and time for filtering.
*
* @var string|null
*/
private $date_from;

/**
* Contains end date and time for filtering.
*
* @var string|null
*/
private $date_to;

/**
* Get the data for the overview report.
*
* @param array $filters Filters to apply to the data.
*
* @return array
*/
public function get_items(array $filters): array
{
global $wpdb;
$enrolment_prefix = $wpdb->get_blog_prefix() . \Sensei_Course_Enrolment::META_PREFIX_ENROLMENT_RESULTS;

$this->date_from = $filters['last_activity_date_from'] ?? null;
$this->date_to = $filters['last_activity_date_to'] ?? null;

$query_args = array(
'fields' => ['ID', 'user_login', 'user_email', 'user_registered', 'display_name'],
'orderby' => $filters['orderby'] ?? '',
'order' => $filters['order'] ?? 'ASC',
'meta_compare_key' => 'LIKE',
'meta_key' => $enrolment_prefix, // phpcs:ignore WordPress.DB.SlowDBQuery -- Filter enrolled users only.
);

$query_args = array_merge($query_args, $filters);
if (!empty($filters['search'])) {
$query_args['search'] = '*' . trim($filters['search'], '*') . '*';
}

/**
* Filter the WP_User_Query arguments
*
* @since 1.6.0
* @param $query_args
*/
$query_args = apply_filters('sensei_analysis_overview_filter_users', $query_args);

add_action('pre_user_query', [$this, 'group_by_users']);

if ($this->get_is_last_activity_filter_enabled()) {
add_action('pre_user_query', [$this, 'add_last_activity_to_user_query']);
add_action('pre_user_query', [$this, 'filter_users_by_last_activity']);

if (!empty($query_args['orderby']) && 'last_activity_date' === $query_args['orderby']) {
add_action('pre_user_query', [$this, 'add_orderby_custom_field_to_user_query']);
}
}

add_action('pre_user_query', [$this, 'add_pre_user_query_hook']);

$wp_user_search = new WP_User_Query($query_args);

remove_action('pre_user_query', [$this, 'add_pre_user_query_hook']);
remove_action('pre_user_query', [$this, 'add_orderby_custom_field_to_user_query']);
remove_action('pre_user_query', [$this, 'add_last_activity_to_user_query']);
remove_action('pre_user_query', [$this, 'filter_users_by_last_activity']);

$learners = $wp_user_search->get_results();
$this->last_total_items = $wp_user_search->get_total();

return $learners;
}

/**
* Check if last activity filter is enabled.
*
* @return {boolean} Whether last activity filter is enabled.
*/
public function get_is_last_activity_filter_enabled()
{
/**
* Filters if the last activity filter by date and the last activity sorting are enabled in
* the students report.
*
* @hook sensei_students_report_last_activity_filter_enabled
* @since 4.6.4
*
* @param {boolean} $enabled Whether the students last activity filter is enabled.
*
* @return {boolean} Whether the students last activity filter is enabled.
*/
return apply_filters('sensei_students_report_last_activity_filter_enabled', true);
}

/**
* Add a user query hook before querying the users.
* This allows for third parties to alter the query.
*
* @since 4.6.0
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function add_pre_user_query_hook(WP_User_Query $query)
{
/**
* Fires before the user query is executed.
*
* @hook sensei_reports_overview_students_data_provider_pre_user_query
* @since 4.6.0
*
* @param {WP_User_Query} $query The user query.
*/
do_action('sensei_reports_overview_students_data_provider_pre_user_query', $query);
}

/**
* Filter the users to ones enrolled in a course.
*
* @deprecated 4.6.4
*
* @since 4.4.1
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function only_course_enrolled_users(WP_User_Query $query)
{
_deprecated_function(__METHOD__, '4.6.4');

global $wpdb;

$query->query_from .= "
INNER JOIN {$wpdb->comments}
ON {$wpdb->comments}.user_id = {$wpdb->users}.ID
AND {$wpdb->comments}.comment_type = 'sensei_course_status'
";

$query->query_where .= " GROUP BY {$wpdb->users}.ID ";
}

/**
* Group query by users.
*
* @since 4.6.4
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function group_by_users(WP_User_Query $query)
{
global $wpdb;

$query->query_where .= " GROUP BY {$wpdb->users}.ID ";
}

/**
* Order query based on the custom field.
*
* @since 4.3.0
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function add_orderby_custom_field_to_user_query(WP_User_Query $query)
{
$query->query_orderby = 'ORDER BY ' . $query->query_vars['orderby'] . ' ' . $query->query_vars['order'];
}

/**
* Add the `last_activity` field to the user query.
*
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function add_last_activity_to_user_query(WP_User_Query $query)
{
global $wpdb;

$query->query_fields .= ", (
SELECT MAX({$wpdb->comments}.comment_date_gmt)
FROM {$wpdb->comments}
USE INDEX (sensei_comment_type_user_id)
WHERE {$wpdb->comments}.user_id = {$wpdb->users}.ID
AND {$wpdb->comments}.comment_approved IN ('complete', 'passed', 'graded')
AND {$wpdb->comments}.comment_type = 'sensei_lesson_status'
ORDER BY {$wpdb->comments}.comment_date_gmt DESC
) AS last_activity_date";
}

/**
* Filter the users by last activity start/end date.
*
* This action should be called after `Sensei_Analysis_Overview_List_Table::add_last_activity_to_user_query`.
*
* @access private
*
* @param WP_User_Query $query The user query.
*/
public function filter_users_by_last_activity(WP_User_Query $query)
{
global $wpdb;

if (!$this->date_from && !$this->date_to) {
return;
}

$query->query_where .= ' HAVING 1 = 1';

// Filter by start date.
if ($this->date_from) {
$query->query_where .= $wpdb->prepare(
' AND last_activity_date >= %s',
$this->date_from
);
}

// Filter by end date.
if ($this->date_to) {
$query->query_where .= $wpdb->prepare(
' AND last_activity_date <= %s',
$this->date_to
);
}
}

/**
* Get the total number of items found for the last query.
*
* @return int
*/
public function get_last_total_items(): int
{
return $this->last_total_items;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public function __construct( string $type, Sensei_Reports_Overview_Data_Provider
// Load Parent token into constructor.
parent::__construct( 'analysis_overview' );

var_dump($type);

$this->type = $type;
$this->data_provider = $data_provider;

Expand Down Expand Up @@ -301,7 +303,7 @@ public function output_top_filters() {
do_action( 'sensei_reports_overview_before_top_filters', $this->type );
?>

<?php if ( 'lessons' === $this->type ) : ?>
<?php if ( in_array( $this->type, [ 'lessons', 'questions' ], true ) ) : ?>
<label for="sensei-course-filter">
<?php esc_html_e( 'Course', 'sensei-lms' ); ?>:

Expand Down Expand Up @@ -395,6 +397,10 @@ public function data_table_footer() {
$report = 'lessons-overview';
break;

case 'questions':
$report = 'questions-overview';
break;

case 'users':
default:
$report = 'user-overview';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public function create( string $type ) {
Sensei()->course,
new Sensei_Reports_Overview_Data_Provider_Lessons( Sensei()->course )
);
case 'questions':
return new Sensei_Reports_Overview_List_Table_Questions(
new Sensei_Reports_Overview_Data_Provider_Questions(),
new Sensei_Reports_Overview_Service_Questions()
);
default:
throw new InvalidArgumentException( 'Unknown list table type' );
}
Expand Down
Loading