diff --git a/analytics/classes/insights_generator.php b/analytics/classes/insights_generator.php
index 6dad5ebcba9..cb24ccdc251 100644
--- a/analytics/classes/insights_generator.php
+++ b/analytics/classes/insights_generator.php
@@ -193,19 +193,23 @@ class insights_generator {
$insighturl = null;
foreach ($predictionactions as $action) {
$actionurl = $action->get_url();
+ $opentoblank = false;
if (!$actionurl->get_param('forwardurl')) {
$params = ['actionvisiblename' => $action->get_text(), 'target' => '_blank'];
$actiondoneurl = new \moodle_url('/report/insights/done.php', $params);
// Set the forward url to the 'done' script.
$actionurl->param('forwardurl', $actiondoneurl->out(false));
+
+ $opentoblank = true;
}
if (empty($insighturl)) {
// We use the primary action url as insight url so we log that the user followed the provided link.
$insighturl = $action->get_url();
}
- $actiondata = (object)['url' => $action->get_url()->out(false), 'text' => $action->get_text()];
+ $actiondata = (object)['url' => $action->get_url()->out(false), 'text' => $action->get_text(),
+ 'opentoblank' => $opentoblank];
$fullmessageplaintext .= get_string('insightinfomessageaction', 'analytics', $actiondata) . PHP_EOL;
$messageactions[] = $actiondata;
}
diff --git a/analytics/classes/local/target/base.php b/analytics/classes/local/target/base.php
index daf27246b45..0db27aa6d40 100644
--- a/analytics/classes/local/target/base.php
+++ b/analytics/classes/local/target/base.php
@@ -105,6 +105,15 @@ abstract class base extends \core_analytics\calculable {
return true;
}
+ /**
+ * Should the insights of this model be linked from reports?
+ *
+ * @return bool
+ */
+ public function link_insights_report(): bool {
+ return true;
+ }
+
/**
* Based on facts (processed by machine learning backends) by default.
*
@@ -147,7 +156,7 @@ abstract class base extends \core_analytics\calculable {
$actions = array();
- if ($includedetailsaction) {
+ if ($this->link_insights_report() && $includedetailsaction) {
$predictionurl = new \moodle_url('/report/insights/prediction.php', array('id' => $predictionid));
$detailstext = $this->get_view_details_text();
diff --git a/analytics/classes/manager.php b/analytics/classes/manager.php
index 03b02e9399a..a5553d56197 100644
--- a/analytics/classes/manager.php
+++ b/analytics/classes/manager.php
@@ -484,6 +484,9 @@ class manager {
/**
* Returns the models with insights at the provided context.
*
+ * Note that this method is used for display purposes. It filters out models whose insights
+ * are not linked from the reports page.
+ *
* @param \context $context
* @return \core_analytics\model[]
*/
@@ -494,7 +497,7 @@ class manager {
$models = self::get_all_models(true, true, $context);
foreach ($models as $key => $model) {
// Check that it not only have predictions but also generates insights from them.
- if (!$model->uses_insights()) {
+ if (!$model->uses_insights() || !$model->get_target()->link_insights_report()) {
unset($models[$key]);
}
}
diff --git a/analytics/classes/model.php b/analytics/classes/model.php
index e5ca153c6d4..83ccb923e4d 100644
--- a/analytics/classes/model.php
+++ b/analytics/classes/model.php
@@ -963,19 +963,22 @@ class model {
$this->get_target()->generate_insight_notifications($this->model->id, $samplecontexts, $predictions);
- // Update cache.
- $cache = \cache::make('core', 'contextwithinsights');
- foreach ($samplecontexts as $context) {
- $modelids = $cache->get($context->id);
- if (!$modelids) {
- // The cache is empty, but we don't know if it is empty because there are no insights
- // in this context or because cache/s have been purged, we need to be conservative and
- // "pay" 1 db read to fill up the cache.
- $models = \core_analytics\manager::get_models_with_insights($context);
- $cache->set($context->id, array_keys($models));
- } else if (!in_array($this->get_id(), $modelids)) {
- array_push($modelids, $this->get_id());
- $cache->set($context->id, $modelids);
+ if ($this->get_target()->link_insights_report()) {
+
+ // Update cache.
+ $cache = \cache::make('core', 'contextwithinsights');
+ foreach ($samplecontexts as $context) {
+ $modelids = $cache->get($context->id);
+ if (!$modelids) {
+ // The cache is empty, but we don't know if it is empty because there are no insights
+ // in this context or because cache/s have been purged, we need to be conservative and
+ // "pay" 1 db read to fill up the cache.
+ $models = \core_analytics\manager::get_models_with_insights($context);
+ $cache->set($context->id, array_keys($models));
+ } else if (!in_array($this->get_id(), $modelids)) {
+ array_push($modelids, $this->get_id());
+ $cache->set($context->id, $modelids);
+ }
}
}
}
diff --git a/analytics/templates/insight_info_message_prediction.mustache b/analytics/templates/insight_info_message_prediction.mustache
index 9896031bf6d..7bd76de7c0d 100644
--- a/analytics/templates/insight_info_message_prediction.mustache
+++ b/analytics/templates/insight_info_message_prediction.mustache
@@ -33,7 +33,8 @@
"text": "Moodle"
}, {
"url": "https://en.wikipedia.org/wiki/Noodle",
- "text": "Noodle"
+ "text": "Noodle",
+ "opentoblank": 1
}
]
}
@@ -65,5 +66,5 @@ body:not(.dir-ltr):not(.dir-rtl) .btn-insight {
{{#actions}}
- {{text}}
+ {{text}}
{{/actions}}
diff --git a/lang/en/calendar.php b/lang/en/calendar.php
index 9a7982ef762..2e31f24bb36 100644
--- a/lang/en/calendar.php
+++ b/lang/en/calendar.php
@@ -261,6 +261,7 @@ $string['urlforical'] = 'URL for iCalendar export, for subscribing to calendar';
$string['user'] = 'User';
$string['userevent'] = 'User event';
$string['userevents'] = 'User events';
+$string['viewupcomingactivitiesdue'] = 'View the upcoming activities due';
$string['wed'] = 'Wed';
$string['wednesday'] = 'Wednesday';
$string['weekly'] = 'Weekly';
diff --git a/report/insights/insights.php b/report/insights/insights.php
index 2aaab8b05f3..5dc9dfc0361 100644
--- a/report/insights/insights.php
+++ b/report/insights/insights.php
@@ -40,10 +40,24 @@ if ($context->contextlevel < CONTEXT_COURSE) {
// Only for higher levels than course.
$PAGE->set_context($context);
}
+
\core_analytics\manager::check_can_list_insights($context);
// Get all models that are enabled, trained and have predictions at this context.
$othermodels = \core_analytics\manager::get_all_models(true, true, $context);
+array_filter($othermodels, function($model) use ($context) {
+
+ // Discard insights that are not linked unless you are a manager.
+ if (!$model->get_target()->link_insights_report()) {
+ try {
+ \core_analytics\manager::check_can_manage_models();
+ } catch (\required_capability_exception $e) {
+ return false;
+ }
+ }
+ return true;
+});
+
if (!$modelid && count($othermodels)) {
// Autoselect the only available model.
$model = reset($othermodels);
@@ -89,6 +103,12 @@ if (!$modelid) {
$model = new \core_analytics\model($modelid);
+if (!$model->get_target()->link_insights_report()) {
+
+ // Only manager access if this target does not link the insights report.
+ \core_analytics\manager::check_can_manage_models();
+}
+
$insightinfo = new stdClass();
$insightinfo->contextname = $context->get_context_name();
$insightinfo->insightname = $model->get_target()->get_name();
diff --git a/user/classes/analytics/target/upcoming_activities_due.php b/user/classes/analytics/target/upcoming_activities_due.php
index b97ecbe1d44..bd3fe9edc02 100644
--- a/user/classes/analytics/target/upcoming_activities_due.php
+++ b/user/classes/analytics/target/upcoming_activities_due.php
@@ -160,6 +160,15 @@ class upcoming_activities_due extends \core_analytics\local\target\binary {
return 0;
}
+ /**
+ * No need to link to the insights report in this case.
+ *
+ * @return bool
+ */
+ public function link_insights_report(): bool {
+ return false;
+ }
+
/**
* Adds a view upcoming events action.
*
@@ -180,9 +189,9 @@ class upcoming_activities_due extends \core_analytics\local\target\binary {
// We force a lookahead of 30 days so we are sure that the upcoming activities due are shown.
$url = new \moodle_url('/calendar/view.php', ['view' => 'upcoming', 'lookahead' => '30']);
- $pix = new \pix_icon('i/calendar', get_string('upcomingevents', 'calendar'));
+ $pix = new \pix_icon('i/calendar', get_string('viewupcomingactivitiesdue', 'calendar'));
$action = new \core_analytics\prediction_action('viewupcoming', $prediction,
- $url, $pix, get_string('upcomingevents', 'calendar'));
+ $url, $pix, get_string('viewupcomingactivitiesdue', 'calendar'));
return array_merge([$action], $parentactions);
}