1
0
mirror of https://github.com/moodle/moodle.git synced 2025-04-24 18:04:43 +02:00

MDL-31989 search: get_config method to search areas

Also content_to_text moved to weblib.
This commit is contained in:
David Monllao 2016-02-23 10:44:20 +08:00 committed by Dan Poltawski
parent f900b2b6c9
commit 69d66020ce
25 changed files with 110 additions and 107 deletions

@ -489,7 +489,7 @@ $temp->add(new admin_setting_heading('searchareasheading', new lang_string('avai
$searchareas = \core_search\manager::get_search_areas_list();
foreach ($searchareas as $areaid => $searcharea) {
list($componentname, $varname) = $searcharea->get_config_var_name();
$temp->add(new admin_setting_configcheckbox($componentname . '/enable' . $varname, $searcharea->get_visible_name(true),
$temp->add(new admin_setting_configcheckbox($componentname . '/' . $varname . '_enabled', $searcharea->get_visible_name(true),
'', 1, 1, 0));
}
$ADMIN->add('searchplugins', $temp);

@ -345,6 +345,7 @@ $string['role:switchroles'] = 'Switch to other roles';
$string['roletoassign'] = 'Role to assign';
$string['roletooverride'] = 'Role to override';
$string['safeoverridenotice'] = 'Note: Capabilities with higher risks are locked because you are only allowed to override safe capabilities.';
$string['search:query'] = 'Perform site-wide searches';
$string['selectanotheruser'] = 'Select another user';
$string['selectauser'] = 'Select a user';
$string['selectrole'] = 'Select a role';

@ -1458,7 +1458,11 @@ class admin_settingpage implements part_of_admin_tree {
return false;
}
$this->settings->{$setting->name} = $setting;
$name = $setting->name;
if ($setting->plugin) {
$name = $setting->plugin . $name;
}
$this->settings->{$name} = $setting;
return true;
}
@ -9333,7 +9337,7 @@ class admin_setting_searchsetupinfo extends admin_setting {
foreach ($searchareas as $areaid => $searcharea) {
list($componentname, $varname) = $searcharea->get_config_var_name();
if (!$anyenabled) {
$anyenabled = get_config($componentname, 'enable' . $varname);
$anyenabled = get_config($componentname, $varname . '_enabled');
}
if (!$anyindexed) {
$anyindexed = get_config($componentname, $varname . '_indexingstart');
@ -9383,7 +9387,7 @@ class admin_setting_searchsetupinfo extends admin_setting {
// Available areas.
$row = array();
$url = new moodle_url('/admin/settings.php?section=manageglobalsearch#id_s_mod_assign_enablesearch_activity');
$url = new moodle_url('/admin/settings.php?section=manageglobalsearch#admin-searchengine');
$row[0] = '3. ' . html_writer::tag('a', get_string('enablesearchareas', 'admin'),
array('href' => $url));

@ -1 +1 @@
define(["jquery"],function(a){var b=null,c=function(a){b.hasClass("expanded")?e():d(a)},d=function(c){var d=a(document).width();return 767>=d&&("click"===c.type||"keydown"===c.type)?void f():void(767>=d||("keydown"===c.type&&c.preventDefault(),b.addClass("expanded"),b.find("form").addClass("expanded"),b.find("input").focus()))},e=function(){b.removeClass("expanded"),b.find("form").removeClass("expanded")},f=function(){b.find("form").submit()};return{init:function(d){b=a("#"+d),b.on("click mouseover keydown","div",c)}}});
define(["jquery"],function(a){var b=null,c=function(a){b.hasClass("expanded")?e():d(a)},d=function(c){var d=a(document).width();if("keydown"!==c.type||13===c.keyCode||32===c.keyCode)return 767>=d&&("click"===c.type||"keydown"===c.type)?void f():void(767>=d||("keydown"===c.type&&c.preventDefault(),b.addClass("expanded"),b.find("form").addClass("expanded"),b.find("input").focus()))},e=function(){b.removeClass("expanded"),b.find("form").removeClass("expanded")},f=function(){b.find("form").submit()};return{init:function(d){b=a("#"+d),b.on("click mouseover keydown","div",c)}}});

@ -59,6 +59,11 @@ define(['jquery'], function($) {
var windowWidth = $(document).width();
// We are only interested in enter and space keys (accessibility).
if (ev.type === 'keydown' && ev.keyCode !== 13 && ev.keyCode !== 32) {
return;
}
if (windowWidth <= 767 && (ev.type === 'click' || ev.type === 'keydown')) {
// Move to the search page when using small window sizes as the input requires too much space.
submitForm();

@ -2057,5 +2057,20 @@ $capabilities = array(
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
)
),
// Perform site-wide search queries through the search API.
'moodle/search:query' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'guest' => CAP_ALLOW,
'user' => CAP_ALLOW,
'student' => CAP_ALLOW,
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
)
);

@ -169,27 +169,6 @@ function editors_head_setup() {
}
}
/**
* Converts editor text input in different formats to plain text.
*
* @param string $content The text as entered by the user
* @param int $contentformat FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN or FORMAT_MARKDOWN
* @return string Plain text.
*/
function editor_input_to_text($content, $contentformat) {
switch ($contentformat) {
case FORMAT_PLAIN:
return $content;
case FORMAT_MARKDOWN:
$html = markdown_to_html($content);
return html_to_text($html, 75, false);
default:
// FORMAT_HTML and FORMAT_MOODLE.
return html_to_text($content, 75, false);
}
}
/**
* Base abstract text editor class.
*

@ -2644,7 +2644,7 @@ class global_navigation extends navigation_node {
}
// Search.
if (!empty($CFG->enableglobalsearch)) {
if (!empty($CFG->enableglobalsearch) && has_capability('moodle/search:query', $sitecontext)) {
$node = $coursenode->add(get_string('search', 'search'), new moodle_url('/search/index.php'),
self::TYPE_SETTING, null, 'search');
}

@ -3133,7 +3133,7 @@ EOD;
// Accessing $CFG directly as using \core_search::is_global_search_enabled would
// result in an extra included file for each site, even the ones where global search
// is disabled.
if (empty($CFG->enableglobalsearch)) {
if (empty($CFG->enableglobalsearch) || !has_capability('moodle/search:query', context_system::instance())) {
return '';
}
@ -3153,7 +3153,7 @@ EOD;
$inputattrs = array('type' => 'text', 'name' => 'q', 'placeholder' => get_string('search', 'search'),
'size' => 13, 'tabindex' => -1, 'id' => 'id_q_' . $id);
$contents = html_writer::tag('label', get_string('search', 'search'),
$contents = html_writer::tag('label', get_string('enteryoursearchquery', 'search'),
array('for' => 'id_q_' . $id, 'class' => 'accesshide')) . html_writer::tag('input', '', $inputattrs);
$searchinput = html_writer::tag('form', $contents, $formattrs);

@ -1914,6 +1914,27 @@ function html_to_text($html, $width = 75, $dolinks = true) {
return $result;
}
/**
* Converts content introduced in an editor to plain text.
*
* @param string $content The text as entered by the user
* @param int $contentformat The text format: FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN or FORMAT_MARKDOWN
* @return string Plain text.
*/
function content_to_text($content, $contentformat) {
switch ($contentformat) {
case FORMAT_PLAIN:
return $content;
case FORMAT_MARKDOWN:
$html = markdown_to_html($content);
return html_to_text($html, 75, false);
default:
// FORMAT_HTML and FORMAT_MOODLE.
return html_to_text($content, 75, false);
}
}
/**
* This function will highlight search words in a given string
*

@ -94,7 +94,7 @@ class post extends \core_search\area\base_mod {
// Prepare associative array with data from DB.
$doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname);
$doc->set('title', $record->subject);
$doc->set('content', editor_input_to_text($record->message, $record->messageformat));
$doc->set('content', content_to_text($record->message, $record->messageformat));
$doc->set('contextid', $context->id);
$doc->set('type', \core_search\manager::TYPE_TEXT);
$doc->set('courseid', $record->courseid);

@ -68,10 +68,10 @@ class mod_forum_search_testcase extends advanced_testcase {
// Enabled by default once global search is enabled.
$this->assertTrue($searcharea->is_enabled());
set_config('enable' . $varname, false, $componentname);
set_config($varname . '_enabled', false, $componentname);
$this->assertFalse($searcharea->is_enabled());
set_config('enable' . $varname, true, $componentname);
set_config($varname . '_enabled', true, $componentname);
$this->assertTrue($searcharea->is_enabled());
}

@ -90,7 +90,7 @@ class entry extends \core_search\area\base_mod {
// Prepare associative array with data from DB.
$doc = \core_search\document_factory::instance($entry->id, $this->componentname, $this->areaname);
$doc->set('title', $entry->concept);
$doc->set('content', editor_input_to_text($entry->definition, $entry->definitionformat));
$doc->set('content', content_to_text($entry->definition, $entry->definitionformat));
$doc->set('contextid', $context->id);
$doc->set('type', \core_search\manager::TYPE_TEXT);
$doc->set('courseid', $entry->course);

@ -67,10 +67,10 @@ class mod_glossary_search_testcase extends advanced_testcase {
// Enabled by default once global search is enabled.
$this->assertTrue($searcharea->is_enabled());
set_config('enable' . $varname, false, $componentname);
set_config($varname . '_enabled', false, $componentname);
$this->assertFalse($searcharea->is_enabled());
set_config('enable' . $varname, true, $componentname);
set_config($varname . '_enabled', true, $componentname);
$this->assertTrue($searcharea->is_enabled());
}

@ -64,12 +64,12 @@ class activity extends \core_search\area\base_activity {
// Prepare associative array with data from DB.
$doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname);
$doc->set('title', $record->name);
$doc->set('content', editor_input_to_text($record->content, $record->contentformat));
$doc->set('content', content_to_text($record->content, $record->contentformat));
$doc->set('contextid', $context->id);
$doc->set('type', \core_search\manager::TYPE_TEXT);
$doc->set('courseid', $record->course);
$doc->set('modified', $record->timemodified);
$doc->set('description1', editor_input_to_text($record->intro, $record->introformat));
$doc->set('description1', content_to_text($record->intro, $record->introformat));
return $doc;
}

@ -144,6 +144,7 @@ abstract class base {
*
* It depends on whether it is a moodle subsystem or a plugin as plugin-related config should remain in their own scope.
*
* @access private
* @return string Config var path including the plugin (or component) and the varname
*/
public function get_config_var_name() {
@ -157,6 +158,23 @@ abstract class base {
return array($this->componentname, 'search_' . $this->areaname);
}
/**
* Returns all the search area configuration.
*
* @return array
*/
public function get_config() {
list($componentname, $varname) = $this->get_config_var_name();
$config = [];
$settingnames = array('_enabled', '_indexingstart', '_indexingend', '_lastindexrun', '_docsignored', '_docsprocessed', '_recordsprocessed');
foreach ($settingnames as $name) {
$config[$varname . $name] = get_config($componentname, $varname . $name);
}
return $config;
}
/**
* Is the search component enabled by the system administrator?
*
@ -164,7 +182,7 @@ abstract class base {
*/
public function is_enabled() {
list($componentname, $varname) = $this->get_config_var_name();
return (bool)get_config($componentname, 'enable' . $varname);
return (bool)get_config($componentname, $varname . '_enabled');
}
/**
@ -193,7 +211,7 @@ abstract class base {
* Internally it should use \core_search\document to standarise the documents before sending them to the search engine.
*
* Search areas should send plain text to the search engine, use the following function to convert any user
* input data to plain text: {@link editor_input_to_text}
* input data to plain text: {@link content_to_text}
*
* @param \stdClass $record A record containing, at least, the indexed document id and a modified timestamp
* @return \core_search\document

@ -89,7 +89,7 @@ abstract class base_activity extends base_mod {
// Prepare associative array with data from DB.
$doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname);
$doc->set('title', $record->name);
$doc->set('content', editor_input_to_text($record->intro, $record->introformat));
$doc->set('content', content_to_text($record->intro, $record->introformat));
$doc->set('contextid', $context->id);
$doc->set('type', \core_search\manager::TYPE_TEXT);
$doc->set('courseid', $record->course);

@ -209,7 +209,8 @@ class document implements \renderable, \templatable {
if ($fielddata['type'] === 'int' || $fielddata['type'] === 'tdate') {
$this->data[$fieldname] = intval($value);
} else {
$this->data[$fieldname] = trim($value, "\r\n");
// Clean up line breaks and extra spaces.
$this->data[$fieldname] = preg_replace("/\s+/", ' ', trim($value, "\r\n"));
}
return $this->data[$fieldname];

@ -299,6 +299,9 @@ abstract class engine {
/**
* Executes the query on the engine.
*
* Implementations of this function should check user context array to limit the results to contexts where the
* user have access.
*
* @param stdClass $filters Query and filters to apply.
* @param array $usercontexts Contexts where the user has access. True if the user can access all contexts.
* @return \core_search\document[] Results or false if no results

@ -347,9 +347,7 @@ class manager {
// Get the courses where the current user has access.
$courses = enrol_get_my_courses(array('id', 'cacherev'));
if (isloggedin() || (isguestuser() && !$CFG->forcelogin)) {
$courses[SITEID] = get_course(SITEID);
}
$courses[SITEID] = get_course(SITEID);
$site = \course_modinfo::instance(SITEID);
foreach ($courses as $course) {
@ -391,6 +389,9 @@ class manager {
/**
* Returns documents from the engine based on the data provided.
*
* This function does not perform any kind of security checking, the caller code
* should check that the current user have moodle/search:query capability.
*
* It might return the results from the cache instead.
*
* @param stdClass $formdata
@ -579,15 +580,15 @@ class manager {
}
foreach ($searchareas as $searcharea) {
list($componentname, $varname) = $searcharea->get_config_var_name();
$config = $searcharea->get_config();
list($areaid, $varname) = $searcharea->get_config_var_name();
set_config($varname . '_indexingstart', 0, $areaid);
set_config($varname . '_indexingend', 0, $areaid);
set_config($varname . '_lastindexrun', 0, $areaid);
set_config($varname . '_docsignored', 0, $areaid);
set_config($varname . '_docsprocessed', 0, $areaid);
set_config($varname . '_recordsprocessed', 0, $areaid);
foreach ($config as $key => $value) {
// We reset them all but the enable/disabled one.
if ($key !== $varname . '_enabled') {
set_config($key, 0, $componentname);
}
}
}
}

@ -1,48 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Adds moodle fields to solr schema.
*
* Schema REST API write actions are only available from Solr 4.4 onwards.
*
* The schema should be managed and mutable to allow this script
* to add new fields to the schema.
*
* @link https://cwiki.apache.org/confluence/display/solr/Managed+Schema+Definition+in+SolrConfig
* @package search_solr
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require_once(__DIR__ . '/../../../../config.php');
echo get_string('addingfields', 'search_solr') . "\n";
if (!\core_search\manager::is_global_search_enabled()) {
throw new moodle_exception('globalsearchdisabled', 'search');
}
if ($CFG->searchengine !== 'solr') {
throw new moodle_exception('solrnotselected', 'search_solr');
}
$schema = new \search_solr\schema();
$schema->setup();
echo get_string('setupok', 'search_solr') . "\n";

@ -22,7 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['addingfields'] = 'Adding Moodle fields to the schema';
$string['connectionerror'] = 'The specified Solr server is not available or the specified index does not exist';
$string['errorcreatingschema'] = 'Error creating the Solr schema: {$a}';
$string['errorvalidatingschema'] = 'Error validating Solr schema, field {$a->fieldname} does not exist. Please <a href="{$a->setupurl}">follow this link</a> to setup the fields required by Moodle.';

@ -31,6 +31,7 @@
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_login(null, false);
require_capability('moodle/site:config', context_system::instance());
if (!\core_search\manager::is_global_search_enabled()) {
@ -44,5 +45,5 @@ if ($CFG->searchengine !== 'solr') {
$schema = new \search_solr\schema();
$schema->setup();
$url = new moodle_url('/admin/settings.php', array('section' => 'searchsolr'));
$url = new moodle_url('/admin/settings.php', array('section' => 'manageglobalsearch'));
redirect($url, get_string('setupok', 'search_solr'), 4);

@ -30,8 +30,9 @@ $title = optional_param('title', '', PARAM_NOTAGS);
$areaid = optional_param('areaid', false, PARAM_ALPHANUMEXT);
// Moving timestart and timeend further down as they might come as an array if they come from the form.
$context = context_system::instance();
$pagetitle = get_string('globalsearch', 'search');
$PAGE->set_context(context_system::instance());
$PAGE->set_context($context);
$PAGE->set_pagelayout('standard');
$PAGE->set_title($pagetitle);
$PAGE->set_heading($pagetitle);
@ -40,6 +41,8 @@ if (!empty($CFG->forcelogin)) {
require_login();
}
require_capability('moodle/search:query', $context);
$searchrenderer = $PAGE->get_renderer('core_search');
if (\core_search\manager::is_global_search_enabled() === false) {

@ -78,12 +78,12 @@ class search_manager_testcase extends advanced_testcase {
$this->assertArrayHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list(true));
list($componentname, $varname) = $searcharea->get_config_var_name();
set_config('enable' . $varname, false, $componentname);
set_config($varname . '_enabled', false, $componentname);
\core_search\manager::clear_static();
$this->assertArrayNotHasKey('mod_forum', \core_search\manager::get_search_areas_list(true));
set_config('enable' . $varname, true, $componentname);
set_config($varname . '_enabled', true, $componentname);
// Although the result is wrong, we want to check that \core_search\manager::get_search_areas_list returns cached results.
$this->assertArrayNotHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list(true));
@ -122,11 +122,12 @@ class search_manager_testcase extends advanced_testcase {
$this->assertContains($fakeareaid . ' search area is not available.', $ex->getMessage());
}
// We clean it all but enabled components.
$search->reset_config($this->forumpostareaid);
$this->assertEquals(1, get_config($componentname, $varname . '_enabled'));
$this->assertEquals(0, get_config($componentname, $varname . '_indexingstart'));
$this->assertEquals(0, get_config($componentname, $varname . '_indexingend'));
$this->assertEquals(0, get_config($componentname, $varname . '_lastindexrun'));
// No caching.
$configs = $search->get_areas_config(array($this->forumpostareaid => $searcharea));
$this->assertEquals(0, $configs[$this->forumpostareaid]->indexingstart);
@ -140,7 +141,6 @@ class search_manager_testcase extends advanced_testcase {
$this->assertEquals(0, get_config($componentname, $varname . '_indexingstart'));
$this->assertEquals(0, get_config($componentname, $varname . '_indexingend'));
$this->assertEquals(0, get_config($componentname, $varname . '_lastindexrun'));
// No caching.
$configs = $search->get_areas_config(array($this->forumpostareaid => $searcharea));
$this->assertEquals(0, $configs[$this->forumpostareaid]->indexingstart);