--- /dev/null
+// 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/>.
+
+/**
+ * Potential contexts selector module.
+ *
+ * @module tool_analytics/potential-contexts
+ * @class potential-contexts
+ * @package tool_analytics
+ * @copyright 2019 David Monllao
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define(['jquery', 'core/ajax'], function($, Ajax) {
+
+ return /** @alias module:tool_analytics/potential-contexts */ {
+
+ processResults: function(selector, results) {
+ var contexts = [];
+ if ($.isArray(results)) {
+ $.each(results, function(index, context) {
+ contexts.push({
+ value: context.id,
+ label: context.name
+ });
+ });
+ return contexts;
+
+ } else {
+ return results;
+ }
+ },
+
+ transport: function(selector, query, success, failure) {
+ var promise;
+
+ let modelid = $(selector).attr('modelid') || null;
+ promise = Ajax.call([{
+ methodname: 'tool_analytics_potential_contexts',
+ args: {
+ query: query,
+ modelid: modelid
+ }
+ }]);
+
+ promise[0].then(success).fail(failure);
+ }
+
+ };
+
+});
--- /dev/null
+<?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/>.
+
+/**
+ * This is the external API for this component.
+ *
+ * @package tool_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_analytics;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once("$CFG->libdir/externallib.php");
+
+use external_api;
+use external_function_parameters;
+use external_value;
+use external_single_structure;
+use external_multiple_structure;
+
+/**
+ * This is the external API for this component.
+ *
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class external extends external_api {
+
+ const MAX_CONTEXTS_RETURNED = 100;
+
+ /**
+ * potential_contexts parameters.
+ *
+ * @since Moodle 3.8
+ * @return external_function_parameters
+ */
+ public static function potential_contexts_parameters() {
+ return new external_function_parameters(
+ array(
+ 'query' => new external_value(PARAM_NOTAGS, 'The model id', VALUE_DEFAULT),
+ 'modelid' => new external_value(PARAM_INT, 'The model id', VALUE_DEFAULT)
+ )
+ );
+ }
+
+ /**
+ * Return the contexts that match the provided query.
+ *
+ * @since Moodle 3.8
+ * @param string|null $query
+ * @param int|null $modelid
+ * @return array an array of contexts
+ */
+ public static function potential_contexts(?string $query = null, ?int $modelid = null) {
+
+ $params = self::validate_parameters(self::potential_contexts_parameters(), ['modelid' => $modelid, 'query' => $query]);
+
+ \core_analytics\manager::check_can_manage_models();
+
+ if ($params['modelid']) {
+ $model = new \core_analytics\model($params['modelid']);
+ $contexts = ($model->get_analyser(['notimesplitting' => true]))::potential_context_restrictions($params['query']);
+ } else {
+ $contexts = \core_analytics\manager::get_potential_context_restrictions(null, $params['query']);
+ }
+
+ $contextoptions = [];
+ $i = 0;
+ foreach ($contexts as $contextid => $contextname) {
+
+ if ($i === self::MAX_CONTEXTS_RETURNED) {
+ // Limited to MAX_CONTEXTS_RETURNED items.
+ break;
+ }
+
+ $contextoptions[] = ['id' => $contextid, 'name' => $contextname];
+ $i++;
+ }
+
+ return $contextoptions;
+ }
+
+ /**
+ * potential_contexts return
+ *
+ * @since Moodle 3.8
+ * @return external_description
+ */
+ public static function potential_contexts_returns() {
+ return new external_multiple_structure(
+ new external_single_structure([
+ 'id' => new external_value(PARAM_INT, 'ID of the context'),
+ 'name' => new external_value(PARAM_NOTAGS, 'The context name')
+ ])
+ );
+ }
+}
$mform->addHelpButton('timesplitting', 'timesplittingmethod', 'analytics');
// Contexts restriction.
- if (!empty($this->_customdata['contexts'])) {
+ if (!empty($this->_customdata['supportscontexts'])) {
- \core_collator::asort($this->_customdata['contexts']);
- $options = ['multiple' => true, 'noselectionstring' => get_string('all')];
- $mform->addElement('autocomplete', 'contexts', get_string('contexts', 'tool_analytics'), $this->_customdata['contexts'],
- $options);
+ $options = [
+ 'ajax' => 'tool_analytics/potential-contexts',
+ 'multiple' => true,
+ 'noselectionstring' => get_string('all')
+ ];
+
+ if (!empty($this->_customdata['id'])) {
+ $options['modelid'] = $this->_customdata['id'];
+ $contexts = $this->load_current_contexts();
+ } else {
+ // No need to preload any selected contexts.
+ $contexts = [];
+ }
+
+ $mform->addElement('autocomplete', 'contexts', get_string('contexts', 'tool_analytics'), $contexts, $options);
$mform->setType('contexts', PARAM_INT);
$mform->addHelpButton('contexts', 'contexts', 'tool_analytics');
}
return $errors;
}
+
+ /**
+ * Load the currently selected context options.
+ *
+ * @return array
+ */
+ protected function load_current_contexts() {
+ $contexts = [];
+ foreach ($this->_customdata['contexts'] as $context) {
+ $contexts[$context->id] = $context->get_context_name(true, true);
+ }
+
+ return $contexts;
+ }
}
return (!$target->based_on_assumptions());
});
+// Set 'supportscontexts' to true as at this stage we don't know if the contexts are supported by
+// the selected target.
$customdata = array(
'trainedmodel' => false,
'staticmodel' => false,
'indicators' => \core_analytics\manager::get_all_indicators(),
'timesplittings' => \core_analytics\manager::get_all_time_splittings(),
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors(),
- 'contexts' => \core_analytics\manager::get_potential_context_restrictions(),
+ 'supportscontexts' => true,
);
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
--- /dev/null
+<?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/>.
+
+/**
+ * Tool analytics webservice definitions.
+ *
+ * @package tool_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$functions = array(
+
+ 'tool_analytics_potential_contexts' => array(
+ 'classname' => 'tool_analytics\external',
+ 'methodname' => 'potential_contexts',
+ 'description' => 'Retrieve the list of potential contexts for a model.',
+ 'type' => 'read',
+ 'ajax' => true,
+ 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
+ ),
+);
+
$invalidcurrenttimesplitting = $model->invalid_timesplitting_selected();
$potentialtimesplittings = $model->get_potential_timesplittings();
+ $analyser = $model->get_analyser();
$customdata = array(
'id' => $model->get_id(),
'indicators' => $model->get_potential_indicators(),
'timesplittings' => $potentialtimesplittings,
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors(),
- 'contexts' => ($model->get_analyser())::potential_context_restrictions()
+ 'supportscontexts' => ($analyser)::context_restriction_support(),
+ 'contexts' => $model->get_contexts(),
);
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
--- /dev/null
+<?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/>.
+
+/**
+ * Tool analytics external functions tests.
+ *
+ * @package tool_analytics
+ * @category external
+ * @copyright 2019 David Monllaó {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 3.8
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+
+require_once($CFG->dirroot . '/webservice/tests/helpers.php');
+require_once(__DIR__ . '/../../../../analytics/tests/fixtures/test_indicator_max.php');
+require_once(__DIR__ . '/../../../../analytics/tests/fixtures/test_target_course_level_shortname.php');
+
+/**
+ * Tool analytics external functions tests
+ *
+ * @package tool_analytics
+ * @category external
+ * @copyright 2019 David Monllaó {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @since Moodle 3.8
+ */
+class tool_analytics_external_testcase extends externallib_advanced_testcase {
+
+ /**
+ * test_potential_contexts description
+ */
+ public function test_potential_contexts() {
+ $this->resetAfterTest();
+
+ $this->setAdminUser();
+
+ // Include the all context levels so the misc. category get included.
+ $this->assertCount(1, \tool_analytics\external::potential_contexts());
+
+ // The frontpage is not included.
+ $this->assertCount(0, \tool_analytics\external::potential_contexts('PHPUnit'));
+
+ $target = \core_analytics\manager::get_target('test_target_course_level_shortname');
+ $indicators = ['test_indicator_max' => \core_analytics\manager::get_indicator('test_indicator_max')];
+ $model = \core_analytics\model::create($target, $indicators);
+
+ $this->assertCount(1, \tool_analytics\external::potential_contexts(null, $model->get_id()));
+ }
+
+ /**
+ * test_potential_contexts description
+ *
+ * @expectedException required_capability_exception
+ */
+ public function test_potential_contexts_no_manager() {
+ $this->resetAfterTest();
+
+ $user = $this->getDataGenerator()->create_user();
+ $this->setUser($user);
+
+ $this->assertCount(2, \tool_analytics\external::potential_contexts());
+ }
+}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2019052000; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2019052002; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2019051100; // Requires this Moodle version.
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
* This generic implementation returns all the contexts in the site for the provided context level.
* Overwrite it for specific restrictions in your analyser.
*
+ * @param string|null $query Context name filter.
* @return int[]
*/
- public static function potential_context_restrictions() {
- return \core_analytics\manager::get_potential_context_restrictions(static::context_restriction_support());
+ public static function potential_context_restrictions(string $query = null) {
+ return \core_analytics\manager::get_potential_context_restrictions(static::context_restriction_support(), $query);
}
/**
*
* @throws \coding_exception
* @param array|null $contextlevels The list of context levels provided by the analyser. Null if all of them.
+ * @param string|null $query
* @return array Associative array with contextid as key and the short version of the context name as value.
*/
- public static function get_potential_context_restrictions(?array $contextlevels = null) {
+ public static function get_potential_context_restrictions(?array $contextlevels = null, string $query = null) {
global $DB;
if (empty($contextlevels) && !is_null($contextlevels)) {
$sql = "SELECT cc.id, cc.name, ctx.id AS contextid
FROM {course_categories} cc
JOIN {context} ctx ON ctx.contextlevel = :ctxlevel AND ctx.instanceid = cc.id";
- $coursecats = $DB->get_recordset_sql($sql, ['ctxlevel' => CONTEXT_COURSECAT]);
+ $params = ['ctxlevel' => CONTEXT_COURSECAT];
+
+ if ($query) {
+ $sql .= " WHERE " . $DB->sql_like('cc.name', ':query', false, false);
+ $params['query'] = '%' . $query . '%';
+ }
+
+ $coursecats = $DB->get_recordset_sql($sql, $params);
foreach ($coursecats as $record) {
$contexts[$record->contextid] = get_string('category') . ': ' .
format_string($record->name, true, array('context' => $contextsystem));
$sql = "SELECT c.id, c.shortname, ctx.id AS contextid
FROM {course} c
- JOIN {context} ctx ON ctx.contextlevel = :ctxlevel AND ctx.instanceid = c.id";
- $courses = $DB->get_recordset_sql($sql, ['ctxlevel' => CONTEXT_COURSE]);
+ JOIN {context} ctx ON ctx.contextlevel = :ctxlevel AND ctx.instanceid = c.id
+ WHERE c.id != :siteid";
+ $params = ['ctxlevel' => CONTEXT_COURSE, 'siteid' => SITEID];
+
+ if ($query) {
+ $sql .= ' AND (' . $DB->sql_like('c.fullname', ':query1', false, false) . ' OR ' .
+ $DB->sql_like('c.shortname', ':query2', false, false) . ')';
+ $params['query1'] = '%' . $query . '%';
+ $params['query2'] = '%' . $query . '%';
+ }
+
+ $courses = $DB->get_recordset_sql($sql, $params);
foreach ($courses as $record) {
$contexts[$record->contextid] = get_string('course') . ': ' .
format_string($record->shortname, true, array('context' => $contextsystem));
// No potential context restrictions.
$this->assertFalse(\core_analytics\manager::get_potential_context_restrictions([]));
- // Include the all context levels so the frontpage and the misc. category get included.
- $this->assertCount(2, \core_analytics\manager::get_potential_context_restrictions());
+ // Include the all context levels so the misc. category get included.
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions());
$this->getDataGenerator()->create_course();
$this->getDataGenerator()->create_category();
- $this->assertCount(4, \core_analytics\manager::get_potential_context_restrictions());
- $this->assertCount(4, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE, CONTEXT_COURSECAT]));
+ $this->assertCount(3, \core_analytics\manager::get_potential_context_restrictions());
+ $this->assertCount(3, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE, CONTEXT_COURSECAT]));
- $this->assertCount(2, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE]));
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE]));
$this->assertCount(2, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSECAT]));
+
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSECAT], 'Course category'));
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSECAT], 'Course category 1'));
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSECAT], 'Miscellaneous'));
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE], 'Test course 1'));
+ $this->assertCount(1, \core_analytics\manager::get_potential_context_restrictions([CONTEXT_COURSE], 'Test course'));
}
}