'\core_course\analytics\indicator\potential_social_breadth',
'\core\analytics\indicator\any_access_after_end',
'\core\analytics\indicator\any_access_before_start',
- '\core\analytics\indicator\any_write_action',
+ '\core\analytics\indicator\any_write_action_in_course',
'\core\analytics\indicator\read_actions',
);
$indicators = array();
$string['indicator:accessesbeforestart_help'] = 'This indicator reflects if the student accessed the course before the course start date.';
$string['indicator:anywrite'] = 'Any write action';
$string['indicator:anywrite_help'] = 'This indicator represents any write (submit) action taken by the student.';
+$string['indicator:anywriteincourse'] = 'Any write action in the course';
+$string['indicator:anywriteincourse_help'] = 'This indicator represents any write (submit) action taken by the student in any course activity.';
$string['indicator:completeduserprofile'] = 'User profile is completed';
$string['indicator:completeduserprofile_help'] = 'This indicator represents that the student has completed their user profile.';
$string['indicator:completionenabled'] = 'Completion tracking enabled';
--- /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/>.
+
+/**
+ * Write actions in a course indicator.
+ *
+ * @package core
+ * @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core\analytics\indicator;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Write actions in a course indicator.
+ *
+ * @package core
+ * @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class any_write_action_in_course extends \core_analytics\local\indicator\binary {
+
+ /**
+ * Returns the name.
+ *
+ * If there is a corresponding '_help' string this will be shown as well.
+ *
+ * @return \lang_string
+ */
+ public static function get_name() : \lang_string {
+ return new \lang_string('indicator:anywriteincourse');
+ }
+
+ /**
+ * required_sample_data
+ *
+ * @return string[]
+ */
+ public static function required_sample_data() {
+ // User is not required, calculate_sample can handle its absence.
+ return array('course');
+ }
+
+ /**
+ * calculate_sample
+ *
+ * @param int $sampleid
+ * @param string $sampleorigin
+ * @param int $starttime
+ * @param int $endtime
+ * @return float
+ */
+ protected function calculate_sample($sampleid, $sampleorigin, $starttime = false, $endtime = false) {
+ global $DB;
+
+ if (!$logstore = \core_analytics\manager::get_analytics_logstore()) {
+ throw new \coding_exception('No available log stores');
+ }
+
+ // Filter by context to use the logstore_standard_log db table index.
+ $course = $this->retrieve('course', $sampleid);
+ $select = "courseid = :courseid AND anonymous = :anonymous AND (crud = 'c' OR crud = 'u')";
+ $params = array('courseid' => $course->id, 'anonymous' => '0');
+
+ if ($user = $this->retrieve('user', $sampleid)) {
+ $select .= " AND userid = :userid";
+ $params['userid'] = $user->id;
+ }
+
+ if ($starttime) {
+ $select .= " AND timecreated > :starttime";
+ $params['starttime'] = $starttime;
+ }
+ if ($endtime) {
+ $select .= " AND timecreated <= :endtime";
+ $params['endtime'] = $endtime;
+ }
+
+ $nlogs = $logstore->get_events_select_count($select, $params);
+ if ($nlogs) {
+ return self::get_max_value();
+ } else {
+ return self::get_min_value();
+ }
+ }
+}
$this->assertEquals($indicator::get_max_value(), $values[$course1->id][0]);
$this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
+ // Test any write action in the course.
+ $course1 = $this->getDataGenerator()->create_course();
+ $coursecontext1 = \context_course::instance($course1->id);
+ $activity1 = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id));
+ $activity1context = \context_module::instance($activity1->cmid);
+ $course2 = $this->getDataGenerator()->create_course();
+ $coursecontext2 = \context_course::instance($course2->id);
+ $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
+
+ $indicator = new \core\analytics\indicator\any_write_action_in_course();
+
+ $sampleids = array($user1->id => $user1->id, $user2->id => $user2->id);
+ $data = array($user1->id => array(
+ 'context' => $coursecontext1,
+ 'course' => $course1,
+ 'user' => $user1
+ ));
+ $data[$user2->id] = $data[$user1->id];
+ $data[$user2->id]['user'] = $user2;
+ $indicator->add_sample_data($data);
+
+ list($values, $unused) = $indicator->calculate($sampleids, 'user');
+ $this->assertEquals($indicator::get_min_value(), $values[$user1->id][0]);
+ $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
+
+ $beforecourseeventcreate = time();
+ sleep(1);
+
+ \logstore_standard\event\unittest_executed::create(
+ array('context' => $activity1context, 'userid' => $user1->id))->trigger();
+ list($values, $unused) = $indicator->calculate($sampleids, 'user');
+ $this->assertEquals($indicator::get_max_value(), $values[$user1->id][0]);
+ $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
+
+ // Now try with course-level samples where user is not available.
+ $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id);
+ $data = array(
+ $course1->id => array(
+ 'context' => $coursecontext1,
+ 'course' => $course1,
+ ),
+ $course2->id => array(
+ 'context' => $coursecontext2,
+ 'course' => $course2,
+ )
+ );
+ $indicator->clear_sample_data();
+ $indicator->add_sample_data($data);
+
+ // Limited by time to avoid previous logs interfering as other logs
+ // have been generated by the system.
+ list($values, $unused) = $indicator->calculate($sampleids, 'course', $beforecourseeventcreate);
+ $this->assertEquals($indicator::get_max_value(), $values[$course1->id][0]);
+ $this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
+
// Test read actions.
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);