Commit 7f9fb2c8 authored by sam marshall's avatar sam marshall
Browse files

MDL-60880 core_search: Allow search of specific context (front-end)

parent cfa00fc5
...@@ -78,6 +78,12 @@ class block_globalsearch extends block_base { ...@@ -78,6 +78,12 @@ class block_globalsearch extends block_base {
'type' => 'text', 'size' => '15'); 'type' => 'text', 'size' => '15');
$this->content->text .= html_writer::empty_tag('input', $inputoptions); $this->content->text .= html_writer::empty_tag('input', $inputoptions);
// Context id.
if ($this->page->context && $this->page->context->contextlevel !== CONTEXT_SYSTEM) {
$this->content->text .= html_writer::empty_tag('input', ['type' => 'hidden',
'name' => 'context', 'value' => $this->page->context->id]);
}
// Search button. // Search button.
$this->content->text .= html_writer::tag('button', get_string('search', 'search'), $this->content->text .= html_writer::tag('button', get_string('search', 'search'),
array('id' => 'searchform_button', 'type' => 'submit', 'title' => 'globalsearch', 'class' => 'btn btn-secondary')); array('id' => 'searchform_button', 'type' => 'submit', 'title' => 'globalsearch', 'class' => 'btn btn-secondary'));
......
...@@ -53,6 +53,7 @@ $string['engineserverstatus'] = 'The search engine is not available. Please cont ...@@ -53,6 +53,7 @@ $string['engineserverstatus'] = 'The search engine is not available. Please cont
$string['enteryoursearchquery'] = 'Enter your search query'; $string['enteryoursearchquery'] = 'Enter your search query';
$string['errors'] = 'Errors'; $string['errors'] = 'Errors';
$string['errorareanotavailable'] = '{$a} search area is not available.'; $string['errorareanotavailable'] = '{$a} search area is not available.';
$string['everywhere'] = 'Everywhere you can access';
$string['filesinindexdirectory'] = 'Files in index directory'; $string['filesinindexdirectory'] = 'Files in index directory';
$string['filterheader'] = 'Filter'; $string['filterheader'] = 'Filter';
$string['fromtime'] = 'Modified after'; $string['fromtime'] = 'Modified after';
...@@ -89,6 +90,7 @@ $string['searcharea'] = 'Search area'; ...@@ -89,6 +90,7 @@ $string['searcharea'] = 'Search area';
$string['searching'] = 'Searching in ...'; $string['searching'] = 'Searching in ...';
$string['searchnotpermitted'] = 'You are not allowed to do a search'; $string['searchnotpermitted'] = 'You are not allowed to do a search';
$string['searchsetupdescription'] = 'The following steps help you to set up Moodle global search.'; $string['searchsetupdescription'] = 'The following steps help you to set up Moodle global search.';
$string['searchwithin'] = 'Search within';
$string['seconds'] = 'seconds'; $string['seconds'] = 'seconds';
$string['solutions'] = 'Solutions'; $string['solutions'] = 'Solutions';
$string['statistics'] = 'Statistics'; $string['statistics'] = 'Statistics';
......
...@@ -3259,6 +3259,10 @@ EOD; ...@@ -3259,6 +3259,10 @@ EOD;
$contents = html_writer::tag('label', get_string('enteryoursearchquery', 'search'), $contents = html_writer::tag('label', get_string('enteryoursearchquery', 'search'),
array('for' => 'id_q_' . $id, 'class' => 'accesshide')) . html_writer::tag('input', '', $inputattrs); array('for' => 'id_q_' . $id, 'class' => 'accesshide')) . html_writer::tag('input', '', $inputattrs);
if ($this->page->context && $this->page->context->contextlevel !== CONTEXT_SYSTEM) {
$contents .= html_writer::empty_tag('input', ['type' => 'hidden',
'name' => 'context', 'value' => $this->page->context->id]);
}
$searchinput = html_writer::tag('form', $contents, $formattrs); $searchinput = html_writer::tag('form', $contents, $formattrs);
return html_writer::tag('div', $searchicon . $searchinput, array('class' => 'search-input-wrapper nav-link', 'id' => $id)); return html_writer::tag('div', $searchicon . $searchinput, array('class' => 'search-input-wrapper nav-link', 'id' => $id));
......
...@@ -48,6 +48,13 @@ class search extends \moodleform { ...@@ -48,6 +48,13 @@ class search extends \moodleform {
$mform->setType('q', PARAM_TEXT); $mform->setType('q', PARAM_TEXT);
$mform->addRule('q', get_string('required'), 'required', null, 'client'); $mform->addRule('q', get_string('required'), 'required', null, 'client');
// Show the 'search within' option if the user came from a particular context.
if (!empty($this->_customdata['searchwithin'])) {
$mform->addElement('select', 'searchwithin', get_string('searchwithin', 'search'),
$this->_customdata['searchwithin']);
$mform->setDefault('searchwithin', '');
}
$mform->addElement('header', 'filtersection', get_string('filterheader', 'search')); $mform->addElement('header', 'filtersection', get_string('filterheader', 'search'));
$mform->setExpanded('filtersection', false); $mform->setExpanded('filtersection', false);
...@@ -79,12 +86,21 @@ class search extends \moodleform { ...@@ -79,12 +86,21 @@ class search extends \moodleform {
$mform->addElement('course', 'courseids', get_string('courses', 'core'), $options); $mform->addElement('course', 'courseids', get_string('courses', 'core'), $options);
$mform->setType('courseids', PARAM_INT); $mform->setType('courseids', PARAM_INT);
// Course options should be hidden if we choose to search within a specific location.
if (!empty($this->_customdata['searchwithin'])) {
$mform->hideIf('courseids', 'searchwithin', 'ne', '');
}
$mform->addElement('date_time_selector', 'timestart', get_string('fromtime', 'search'), array('optional' => true)); $mform->addElement('date_time_selector', 'timestart', get_string('fromtime', 'search'), array('optional' => true));
$mform->setDefault('timestart', 0); $mform->setDefault('timestart', 0);
$mform->addElement('date_time_selector', 'timeend', get_string('totime', 'search'), array('optional' => true)); $mform->addElement('date_time_selector', 'timeend', get_string('totime', 'search'), array('optional' => true));
$mform->setDefault('timeend', 0); $mform->setDefault('timeend', 0);
// Source context i.e. the page they came from when they clicked search.
$mform->addElement('hidden', 'context');
$mform->setType('context', PARAM_INT);
$this->add_action_buttons(false, get_string('search', 'search')); $this->add_action_buttons(false, get_string('search', 'search'));
} }
} }
...@@ -27,6 +27,7 @@ require_once(__DIR__ . '/../config.php'); ...@@ -27,6 +27,7 @@ require_once(__DIR__ . '/../config.php');
$page = optional_param('page', 0, PARAM_INT); $page = optional_param('page', 0, PARAM_INT);
$q = optional_param('q', '', PARAM_NOTAGS); $q = optional_param('q', '', PARAM_NOTAGS);
$title = optional_param('title', '', PARAM_NOTAGS); $title = optional_param('title', '', PARAM_NOTAGS);
$contextid = optional_param('context', 0, PARAM_INT);
// Moving areaids, courseids, timestart, and timeend further down as they might come as an array if they come from the form. // Moving areaids, courseids, timestart, and timeend further down as they might come as an array if they come from the form.
$context = context_system::instance(); $context = context_system::instance();
...@@ -55,8 +56,23 @@ if (\core_search\manager::is_global_search_enabled() === false) { ...@@ -55,8 +56,23 @@ if (\core_search\manager::is_global_search_enabled() === false) {
$search = \core_search\manager::instance(); $search = \core_search\manager::instance();
// We first get the submitted data as we want to set it all in the page URL. // Set up custom data for form.
$mform = new \core_search\output\form\search(null, array('searchengine' => $search->get_engine()->get_plugin_name())); $customdata = ['searchengine' => $search->get_engine()->get_plugin_name()];
if ($contextid) {
// When a context is supplied, check if it's within course level. If so, show dropdown.
$context = context::instance_by_id($contextid);
$coursecontext = $context->get_course_context(false);
if ($coursecontext) {
$searchwithin = [];
$searchwithin[''] = get_string('everywhere', 'search');
$searchwithin['course'] = $coursecontext->get_context_name();
if ($context->contextlevel !== CONTEXT_COURSE) {
$searchwithin['context'] = $context->get_context_name();
}
$customdata['searchwithin'] = $searchwithin;
}
}
$mform = new \core_search\output\form\search(null, $customdata);
$data = $mform->get_data(); $data = $mform->get_data();
if (!$data && $q) { if (!$data && $q) {
...@@ -77,9 +93,25 @@ if (!$data && $q) { ...@@ -77,9 +93,25 @@ if (!$data && $q) {
} }
$data->timestart = optional_param('timestart', 0, PARAM_INT); $data->timestart = optional_param('timestart', 0, PARAM_INT);
$data->timeend = optional_param('timeend', 0, PARAM_INT); $data->timeend = optional_param('timeend', 0, PARAM_INT);
$data->context = $contextid;
$mform->set_data($data); $mform->set_data($data);
} }
// Convert the 'search within' option, if used, to course or context restrictions.
if ($data && !empty($data->searchwithin)) {
switch ($data->searchwithin) {
case 'course':
$data->courseids = [$coursecontext->instanceid];
break;
case 'context':
$data->courseids = [$coursecontext->instanceid];
$data->contextids = [$context->id];
break;
}
}
// Set the page URL. // Set the page URL.
$urlparams = array('page' => $page); $urlparams = array('page' => $page);
if ($data) { if ($data) {
......
...@@ -7,10 +7,13 @@ Feature: Use global search interface ...@@ -7,10 +7,13 @@ Feature: Use global search interface
Background: Background:
Given the following config values are set as admin: Given the following config values are set as admin:
| enableglobalsearch | 1 | | enableglobalsearch | 1 |
And the following "courses" exist:
| shortname | fullname |
| F1 | Amphibians |
And the following "activities" exist: And the following "activities" exist:
| activity | name | intro | course | idnumber | | activity | name | intro | course | idnumber |
| page | PageName1 | PageDesc1 | Acceptance test site | PAGE1 | | page | PageName1 | PageDesc1 | F1 | PAGE1 |
| forum | ForumName1 | ForumDesc1 | Acceptance test site | FORUM1 | | forum | ForumName1 | ForumDesc1 | F1 | FORUM1 |
And I log in as "admin" And I log in as "admin"
@javascript @javascript
...@@ -47,3 +50,44 @@ Feature: Use global search interface ...@@ -47,3 +50,44 @@ Feature: Use global search interface
# Check the link works. # Check the link works.
And I follow "ForumName1" And I follow "ForumName1"
And I should see "ForumName1" in the ".breadcrumb" "css_element" And I should see "ForumName1" in the ".breadcrumb" "css_element"
@javascript
Scenario: Search starting from site context (no within option)
Given global search expects the query "frogs" and will return:
| type | idnumber |
| activity | PAGE1 |
When I search for "frogs" using the header global search box
And I expand all fieldsets
Then I should not see "Search within"
And I should see "Courses"
@javascript
Scenario: Search starting from course context (within option lists course)
Given global search expects the query "frogs" and will return:
| type | idnumber |
| activity | PAGE1 |
When I am on "Amphibians" course homepage
And I search for "frogs" using the header global search box
And I expand all fieldsets
Then I should see "Search within"
And I select "Everywhere you can access" from the "Search within" singleselect
And I should see "Courses"
And I select "Course: Amphibians" from the "Search within" singleselect
And I should not see "Courses"
@javascript
Scenario: Search starting from forum context (within option lists course and forum)
Given global search expects the query "frogs" and will return:
| type | idnumber |
| activity | PAGE1 |
When I am on "Amphibians" course homepage
And I follow "ForumName1"
And I search for "frogs" using the header global search box
And I expand all fieldsets
And I should see "Search within"
And I select "Everywhere you can access" from the "Search within" singleselect
And I should see "Courses"
And I select "Course: Amphibians" from the "Search within" singleselect
And I should not see "Courses"
And I select "Forum: ForumName1" from the "Search within" singleselect
And I should not see "Courses"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment