diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 8d36065667c..fd687c31e04 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -189,6 +189,11 @@ class workshop { */ protected $evaluationinstance = null; + /** + * @var array It gets initialised in init_initial_bar, and may have keys 'i_first' and 'i_last' depending on what is selected. + */ + protected $initialbarprefs = []; + /** * Initializes the workshop API instance using the data from DB * @@ -680,15 +685,24 @@ class workshop { global $DB; list($sql, $params) = $this->get_participants_sql($musthavesubmission, $groupid); + list($filteringsql, $filteringparams) = $this->get_users_with_initial_filtering_sql_where(); + $wheresql = ""; + if ($filteringsql) { + $wheresql .= $filteringsql; + $params = array_merge($params, $filteringparams); + } if (empty($sql)) { return array(); } list($sort, $sortparams) = users_order_by_sql('tmp'); - $sql = "SELECT * - FROM ($sql) tmp - ORDER BY $sort"; + $sql = "SELECT * FROM ($sql) tmp"; + + if ($wheresql) { + $sql .= " WHERE $wheresql"; + } + $sql .= " ORDER BY $sort"; return $DB->get_records_sql($sql, array_merge($params, $sortparams), $limitfrom, $limitnum); } @@ -3218,6 +3232,66 @@ class workshop { $DB->update_record('workshop_submissions', $record); } + /** + * Get the initial first name. + * + * @return string|null initial of first name we are currently filtering by. + */ + public function get_initial_first(): ?string { + if (empty($this->initialbarprefs['i_first'])) { + return null; + } + + return $this->initialbarprefs['i_first']; + } + + /** + * Get the initial last name. + * + * @return string|null initial of last name we are currently filtering by. + */ + public function get_initial_last(): ?string { + if (empty($this->initialbarprefs['i_last'])) { + return null; + } + + return $this->initialbarprefs['i_last']; + } + + /** + * Init method for initial bars. + * @return void + */ + public function init_initial_bar(): void { + global $SESSION; + if ($this->phase === self::PHASE_SETUP) { + return; + } + + $ifirst = optional_param('ifirst', null, PARAM_NOTAGS); + $ilast = optional_param('ilast', null, PARAM_NOTAGS); + + if (empty($SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id])) { + $SESSION->mod_workshop = new stdClass(); + $SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id] = []; + } + if (!empty($SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_first'])) { + $this->initialbarprefs['i_first'] = $SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_first']; + } + if (!empty($SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_last'])) { + $this->initialbarprefs['i_last'] = $SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_last']; + } + if (!is_null($ifirst)) { + $this->initialbarprefs['i_first'] = $ifirst; + $SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_first'] = $ifirst; + } + + if (!is_null($ilast)) { + $this->initialbarprefs['i_last'] = $ilast; + $SESSION->mod_workshop->initialbarprefs['id-'.$this->context->id]['i_last'] = $ilast; + } + } + //////////////////////////////////////////////////////////////////////////////// // Internal methods (implementation details) // //////////////////////////////////////////////////////////////////////////////// @@ -3430,6 +3504,28 @@ class workshop { return array($sql, $params); } + /** + * Returns SQL to fetch all enrolled users with the first name or last name. + * + * @return array + */ + protected function get_users_with_initial_filtering_sql_where(): array { + global $DB; + $conditions = []; + $params = []; + $ifirst = $this->get_initial_first(); + $ilast = $this->get_initial_last(); + if ($ifirst) { + $conditions[] = $DB->sql_like('LOWER(tmp.firstname)', ':i_first' , false, false); + $params['i_first'] = $DB->sql_like_escape($ifirst) . '%'; + } + if ($ilast) { + $conditions[] = $DB->sql_like('LOWER(tmp.lastname)', ':i_last' , false, false); + $params['i_last'] = $DB->sql_like_escape($ilast) . '%'; + } + return [implode(" AND ", $conditions), $params]; + } + /** * Returns SQL statement that can be used to fetch all actively enrolled participants in the workshop * diff --git a/mod/workshop/renderer.php b/mod/workshop/renderer.php index 4fb20c070f2..aa43c1a4ca2 100644 --- a/mod/workshop/renderer.php +++ b/mod/workshop/renderer.php @@ -431,7 +431,7 @@ class mod_workshop_renderer extends plugin_renderer_base { $userinfo = $data->userinfo; if (empty($grades)) { - return ''; + return $this->output->notification(get_string('nothingtodisplay'), 'success', false); } $table = new html_table(); @@ -821,6 +821,22 @@ class mod_workshop_renderer extends plugin_renderer_base { return $this->output->container($this->output->render($select), 'perpagewidget'); } + /** + * Render the initials bars for workshop. + * + * @param workshop $workshop the current workshop of initial bars. + * @param moodle_url $url base URL object. + * @return string HTML. + */ + public function initials_bars(workshop $workshop, moodle_url $url): string { + $ifirst = $workshop->get_initial_first(); + $ilast = $workshop->get_initial_last(); + + $html = $this->output->initials_bar($ifirst, 'firstinitial', get_string('firstname'), 'ifirst', $url); + $html .= $this->output->initials_bar($ilast, 'lastinitial', get_string('lastname'), 'ilast', $url); + return $html; + } + /** * Renders the user's final grades * diff --git a/mod/workshop/tests/behat/workshop_activity_filter.feature b/mod/workshop/tests/behat/workshop_activity_filter.feature new file mode 100644 index 00000000000..eac488a3609 --- /dev/null +++ b/mod/workshop/tests/behat/workshop_activity_filter.feature @@ -0,0 +1,86 @@ +@mod @mod_workshop +Feature: View work shop activity submissions report. + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | student1 | Vinnie | Money | student1@example.com | + | student2 | Anna | Velvet | student2@example.com | + | student3 | Anna | Moe | student3@example.com | + | teacher1 | Darrell | Teacher1 | teacher1@example.com | + And the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And the following "course enrolments" exist: + | user | course | role | + | student1 | C1 | student | + | student2 | C1 | student | + | student3 | C1 | student | + | teacher1 | C1 | editingteacher | + And the following "activities" exist: + | activity | name | intro | course | + | workshop | Music history | Test workshop description | C1 | + + Scenario Outline: Filter submissions report by surname/first name + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + When I change phase in workshop "Music history" to "" + Then ".firstinitial" "css_element" should exist + And ".lastinitial" "css_element" should exist + And "grading-report" "table" should exist + And I should see "Anna Moe" in the "grading-report" "table" + And I should see "Vinnie Money" in the "grading-report" "table" + And I should see "Anna Velvet" in the "grading-report" "table" + + Examples: + | phase | + | Submission phase | + | Assessment phase | + | Grading evaluation phase | + | Closed | + + Scenario: Filter submissions report by surname/first name is hidden in the Setup phase. + When I am on the "Music history" "workshop activity" page logged in as teacher1 + Then ".firstinitial" "css_element" should not exist + And ".lastinitial" "css_element" should not exist + And "grading-report" "table" should not exist + + Scenario: Filter submissions report by first name as a teacher. + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + And I change phase in workshop "Music history" to "Submission phase" + When I click on "A" "link" in the ".firstinitial" "css_element" + Then I should see "Anna Moe" in the "grading-report" "table" + And I should see "Anna Velvet" in the "grading-report" "table" + And I should not see "Vinnie Money" in the "grading-report" "table" + + Scenario: Filter submissions report by surname name as a teacher. + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + And I change phase in workshop "Music history" to "Submission phase" + When I click on "V" "link" in the ".lastinitial" "css_element" + Then I should see "Anna Velvet" in the "grading-report" "table" + And I should not see "Anna Moe" in the "grading-report" "table" + And I should not see "Vinnie Money" in the "grading-report" "table" + + Scenario: Filter submissions report by first name and surname as a teacher. + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + And I change phase in workshop "Music history" to "Submission phase" + When I click on "V" "link" in the ".firstinitial" "css_element" + And I click on "M" "link" in the ".lastinitial" "css_element" + Then I should see "Vinnie Money" in the "grading-report" "table" + And I should not see "Anna Moe" in the "grading-report" "table" + And I should not see "Anna Velvet" in the "grading-report" "table" + + Scenario: Filter submissions report and see nothing. + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + And I change phase in workshop "Music history" to "Submission phase" + When I click on "Z" "link" in the ".firstinitial" "css_element" + Then I should see "Nothing to display" + + Scenario: Filter submissions report using All by first name + Given I am on the "Music history" "workshop activity" page logged in as teacher1 + And I change phase in workshop "Music history" to "Submission phase" + When I click on "V" "link" in the ".firstinitial" "css_element" + And I click on "M" "link" in the ".lastinitial" "css_element" + And I click on "All" "link" in the ".firstinitial" "css_element" + Then I should see "Vinnie Money" in the "grading-report" "table" + And I should see "Anna Moe" in the "grading-report" "table" + And I should not see "Anna Velvet" in the "grading-report" "table" diff --git a/mod/workshop/tests/locallib_test.php b/mod/workshop/tests/locallib_test.php index 42cda0a853f..802163fcf58 100644 --- a/mod/workshop/tests/locallib_test.php +++ b/mod/workshop/tests/locallib_test.php @@ -778,4 +778,97 @@ class locallib_test extends \advanced_testcase { $this->assertTrue($workshop3->check_group_membership($student2->id)); $this->assertFalse($workshop3->check_group_membership($student3->id)); } + + /** + * Test init_initial_bar function. + * + * @covers \workshop::init_initial_bar + */ + public function test_init_initial_bar(): void { + global $SESSION; + $this->resetAfterTest(); + + $_GET['ifirst'] = 'A'; + $_GET['ilast'] = 'B'; + $contextid = $this->workshop->context->id; + + $this->workshop->init_initial_bar(); + $initialbarprefs = $this->get_initial_bar_prefs_property(); + + $this->assertEquals('A', $initialbarprefs['i_first']); + $this->assertEquals('B', $initialbarprefs['i_last']); + $this->assertEquals('A', $SESSION->mod_workshop->initialbarprefs['id-' . $contextid]['i_first']); + $this->assertEquals('B', $SESSION->mod_workshop->initialbarprefs['id-' . $contextid]['i_last']); + + $_GET['ifirst'] = null; + $_GET['ilast'] = null; + $SESSION->mod_workshop->initialbarprefs['id-' . $contextid]['i_first'] = 'D'; + $SESSION->mod_workshop->initialbarprefs['id-' . $contextid]['i_last'] = 'E'; + + $this->workshop->init_initial_bar(); + $initialbarprefs = $this->get_initial_bar_prefs_property(); + + $this->assertEquals('D', $initialbarprefs['i_first']); + $this->assertEquals('E', $initialbarprefs['i_last']); + } + + /** + * Test empty init_initial_bar + * + * @covers \workshop::init_initial_bar + */ + public function test_init_initial_bar_empty(): void { + $this->resetAfterTest(); + + $this->workshop->init_initial_bar(); + $initialbarprefs = $this->get_initial_bar_prefs_property(); + + $this->assertEmpty($initialbarprefs); + } + + /** + * Test get_initial_first function + * + * @covers \workshop::get_initial_first + */ + public function test_get_initial_first(): void { + $this->resetAfterTest(); + $this->workshop->init_initial_bar(); + $this->assertEquals(null, $this->workshop->get_initial_first()); + + $_GET['ifirst'] = 'D'; + $this->workshop->init_initial_bar(); + $this->assertEquals('D', $this->workshop->get_initial_first()); + } + + /** + * Test get_initial_last function + * + * @covers \workshop::get_initial_last + */ + public function test_get_initial_last(): void { + $this->resetAfterTest(); + $this->workshop->init_initial_bar(); + $this->assertEquals(null, $this->workshop->get_initial_last()); + + $_GET['ilast'] = 'D'; + $this->workshop->init_initial_bar(); + $this->assertEquals('D', $this->workshop->get_initial_last()); + } + + /** + * Get the protected propertyinitialbarprefs from workshop class. + * + * @coversNothing + * @return array initialbarspref property. eg ['i_first' => 'A', 'i_last' => 'B'] + */ + private function get_initial_bar_prefs_property(): array { + + $reflector = new \ReflectionObject($this->workshop); + $initialbarprefsprop = $reflector->getProperty('initialbarprefs'); + $initialbarprefsprop->setAccessible(true); + $initialbarprefs = $initialbarprefsprop->getValue($this->workshop); + + return $initialbarprefs; + } } diff --git a/mod/workshop/view.php b/mod/workshop/view.php index 92ab043e679..67b8bec38de 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -72,7 +72,7 @@ if ($workshop->phase == workshop::PHASE_SUBMISSION and $workshop->phaseswitchass if (!is_null($editmode) && $PAGE->user_allowed_editing()) { $USER->editing = $editmode; } - +$workshop->init_initial_bar(); $userplan = new workshop_user_plan($workshop, $USER->id); foreach ($userplan->phases as $phase) { @@ -281,7 +281,7 @@ switch ($workshop->phase) { $reportopts->showsubmissiongrade = false; $reportopts->showgradinggrade = false; $reportopts->workshopphase = $workshop->phase; - + echo $output->initials_bars($workshop, $baseurl); echo $output->render($pagingbar); echo $output->render(new workshop_grading_report($data, $reportopts)); echo $output->render($pagingbar); @@ -341,6 +341,7 @@ switch ($workshop->phase) { 'workshop-viewlet-gradereport-collapsed'); echo $output->box_start('generalbox gradesreport'); echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget'); + echo $output->initials_bars($workshop, $baseurl); echo $output->render($pagingbar); echo $output->render(new workshop_grading_report($data, $reportopts)); echo $output->render($pagingbar); @@ -498,6 +499,7 @@ switch ($workshop->phase) { 'workshop-viewlet-gradereport-collapsed'); echo $output->box_start('generalbox gradesreport'); echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget'); + echo $output->initials_bars($workshop, $baseurl); echo $output->render($pagingbar); echo $output->render(new workshop_grading_report($data, $reportopts)); echo $output->render($pagingbar); @@ -623,6 +625,7 @@ switch ($workshop->phase) { 'workshop-viewlet-gradereport-collapsed'); echo $output->box_start('generalbox gradesreport'); echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget'); + echo $output->initials_bars($workshop, $baseurl); echo $output->render($pagingbar); echo $output->render(new workshop_grading_report($data, $reportopts)); echo $output->render($pagingbar);