diff --git a/analytics/classes/insights_generator.php b/analytics/classes/insights_generator.php new file mode 100644 index 00000000000..c8f539831ab --- /dev/null +++ b/analytics/classes/insights_generator.php @@ -0,0 +1,193 @@ +. + +/** + * Insights generator. + * + * @package core_analytics + * @copyright 2019 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_analytics; + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/lib/messagelib.php'); + +/** + * Insights generator. + * + * @package core_analytics + * @copyright 2019 David Monllao {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class insights_generator { + + /** + * @var int + */ + private $modelid; + + /** + * @var \core_analytics\local\target\base + */ + private $target; + + /** + * @var int[] + */ + private $contextcourseids; + + /** + * Constructor. + * + * @param int $modelid + * @param \core_analytics\local\target\base $target + */ + public function __construct(int $modelid, \core_analytics\local\target\base $target) { + $this->modelid = $modelid; + $this->target = $target; + } + + /** + * Generates insight notifications. + * + * @param array $samplecontexts The contexts these predictions belong to + * @param \core_analytics\prediction $predictions The prediction records + * @return null + */ + public function generate($samplecontexts, $predictions) { + + $analyserclass = $this->target->get_analyser_class(); + + if ($analyserclass::one_sample_per_analysable()) { + foreach ($predictions as $prediction) { + + $context = $samplecontexts[$prediction->get_prediction_data()->contextid]; + list($insighturl, $fullmessage, $fullmessagehtml) = $this->prediction_info($prediction); + $this->notifications($context, $insighturl, $fullmessage, $fullmessagehtml); + } + + } else { + foreach ($samplecontexts as $context) { + + $insighturl = $this->target->get_insight_context_url($this->modelid, $context); + $fullmessage = get_string('insightinfomessage', 'analytics', $insighturl->out(false)); + $fullmessagehtml = get_string('insightinfomessagehtml', 'analytics', $insighturl->out()); + $this->notifications($context, $insighturl, $fullmessage, $fullmessagehtml); + } + } + } + + /** + * Generates a insight notification for the user. + * + * @param \context $context + * @param \moodle_url $insighturl The insight URL + * @param string $fullmessage + * @param string $fullmessagehtml + * @return null + */ + private function notifications(\context $context, \moodle_url $insighturl, string $fullmessage, string $fullmessagehtml) { + $users = $this->target->get_insights_users($context); + foreach ($users as $user) { + + $subject = $this->target->get_insight_subject($this->modelid, $context); + + $message = new \core\message\message(); + $message->component = 'moodle'; + $message->name = 'insights'; + + $message->userfrom = \core_user::get_noreply_user(); + $message->userto = $user; + + $message->subject = $subject; + + // Same than the subject. + $message->contexturlname = $message->subject; + $message->courseid = $this->get_context_courseid($context); + + $message->fullmessage = $fullmessage; + $message->fullmessageformat = FORMAT_PLAIN; + $message->fullmessagehtml = $fullmessagehtml; + $message->smallmessage = $fullmessage; + $message->contexturl = $insighturl->out(false); + + message_send($message); + } + } + + /** + * Returns the course context of the provided context reading an internal cache first. + * + * @param \context $context + * @return int + */ + private function get_context_courseid(\context $context) { + + if (empty($this->contextcourseids[$context->id])) { + + $coursecontext = $context->get_course_context(false); + if (!$coursecontext) { + // Default to the frontpage course context. + $coursecontext = \context_course::instance(SITEID); + } + $this->contextcourseids[$context->id] = $coursecontext->instanceid; + } + + return $this->contextcourseids[$context->id]; + } + + /** + * Extracts info from the prediction for display purposes. + * + * @param \core_analytics\prediction $prediction + * @return array Three items array with formats [\moodle_url, string, string] + */ + private function prediction_info(\core_analytics\prediction $prediction) { + + $predictionactions = $this->target->prediction_actions($prediction, true); + + $messageactions = ''; + $messageactionshtml = ''; + $insighturl = null; + foreach ($predictionactions as $action) { + $actionurl = $action->get_url(); + if (!$actionurl->get_param('forwardurl')) { + + $actiondoneurl = new \moodle_url('/report/insights/done.php'); + // Set the forward url to the 'done' script. + $actionurl->param('forwardurl', $actiondoneurl->out(false)); + } + + $btnstyle = 'btn-default'; + 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(); + $btnstyle = 'btn-primary'; + } + $messageactions .= $action->get_text() . ': ' . $action->get_url()->out(false) . PHP_EOL; + $messageactionshtml .= '' . + $action->get_text() . ''; + } + + $fullmessage = get_string('insightinfomessageprediction', 'analytics', $messageactions); + $fullmessagehtml = get_string('insightinfomessagepredictionhtml', 'analytics', $messageactionshtml); + + return [$insighturl, $fullmessage, $fullmessagehtml]; + } +} \ No newline at end of file diff --git a/analytics/classes/local/target/base.php b/analytics/classes/local/target/base.php index 65e68b4c6dd..b59030e02c4 100644 --- a/analytics/classes/local/target/base.php +++ b/analytics/classes/local/target/base.php @@ -196,106 +196,9 @@ abstract class base extends \core_analytics\calculable { * @return void */ public function generate_insight_notifications($modelid, $samplecontexts, array $predictions = []) { - - $analyserclass = $this->get_analyser_class(); - if ($analyserclass::one_sample_per_analysable()) { - foreach ($predictions as $prediction) { - $context = $samplecontexts[$prediction->get_prediction_data()->contextid]; - - $subject = $this->get_insight_subject($modelid, $context); - $users = $this->get_insights_users($context); - - if (!$coursecontext = $context->get_course_context(false)) { - $coursecontext = \context_course::instance(SITEID); - } - - $predictionactions = $this->prediction_actions($prediction, true); - - $messageactions = ''; - $messageactionshtml = ''; - $insighturl = null; - foreach ($predictionactions as $action) { - $actionurl = $action->get_url(); - if (!$actionurl->get_param('forwardurl')) { - - $actiondoneurl = new \moodle_url('/report/insights/done.php'); - // Set the forward url to the 'done' script. - $actionurl->param('forwardurl', $actiondoneurl->out(false)); - } - if (empty($insighturl)) { - // We use the primary action url as insight url so we logged that the user followed the provided link. - $insighturl = $action->get_url(); - } - $messageactions .= $action->get_text() . ': ' . $action->get_url()->out(false) . PHP_EOL; - $messageactionshtml .= '' . - $action->get_text() . ''; - } - - $fullmessage = get_string('insightinfomessageprediction', 'analytics', $messageactions); - $fullmessagehtml = get_string('insightinfomessagepredictionhtml', 'analytics', $messageactionshtml); - - foreach ($users as $user) { - $this->generate_insight_notification($user, $subject, $insighturl, $coursecontext, - $fullmessage, $fullmessagehtml); - } - } - - } else { - - foreach ($samplecontexts as $context) { - - $subject = $this->get_insight_subject($modelid, $context); - $users = $this->get_insights_users($context); - - if (!$coursecontext = $context->get_course_context(false)) { - $coursecontext = \context_course::instance(SITEID); - } - - foreach ($users as $user) { - $insighturl = $this->get_insight_context_url($modelid, $context); - $fullmessage = get_string('insightinfomessage', 'analytics', $insighturl->out(false)); - $fullmessagehtml = get_string('insightinfomessagehtml', 'analytics', $insighturl->out()); - $this->generate_insight_notification($user, $subject, $insighturl, $coursecontext, - $fullmessage, $fullmessagehtml); - } - } - } - } - - /** - * Generates a insight notification for the user. - * - * @param \stdClass $user The user - * @param string $subject The notification subject - * @param \moodle_url $insighturl The insight URL - * @param \context $coursecontext - * @param string $fullmessage - * @param string $fullmessagehtml - * @return null - */ - protected function generate_insight_notification(\stdClass $user, string $subject, \moodle_url $insighturl, - \context $coursecontext, string $fullmessage, string $fullmessagehtml) { - - $message = new \core\message\message(); - $message->component = 'moodle'; - $message->name = 'insights'; - - $message->userfrom = \core_user::get_noreply_user(); - $message->userto = $user; - - $message->subject = $subject; - - // Same than the subject. - $message->contexturlname = $message->subject; - $message->courseid = $coursecontext->instanceid; - - $message->fullmessage = $fullmessage; - $message->fullmessageformat = FORMAT_PLAIN; - $message->fullmessagehtml = $fullmessagehtml; - $message->smallmessage = $fullmessage; - $message->contexturl = $insighturl->out(false); - - message_send($message); + // Delegate the processing of insights to the insights_generator. + $insightsgenerator = new \core_analytics\insights_generator($modelid, $this); + $insightsgenerator->generate($samplecontexts, $predictions); } /** @@ -307,7 +210,7 @@ abstract class base extends \core_analytics\calculable { * @param \context $context * @return array */ - protected function get_insights_users(\context $context) { + public function get_insights_users(\context $context) { if ($context->contextlevel === CONTEXT_USER) { $users = [$context->instanceid => \core_user::get_user($context->instanceid)]; } else if ($context->contextlevel >= CONTEXT_COURSE) { @@ -327,7 +230,7 @@ abstract class base extends \core_analytics\calculable { * @param \context $context * @return \moodle_url */ - protected function get_insight_context_url($modelid, $context) { + public function get_insight_context_url($modelid, $context) { return new \moodle_url('/report/insights/insights.php?modelid=' . $modelid . '&contextid=' . $context->id); } @@ -338,11 +241,8 @@ abstract class base extends \core_analytics\calculable { * @param \context $context * @return string */ - protected function get_insight_subject(int $modelid, \context $context) { - $insightinfo = new \stdClass(); - $insightinfo->insightname = $this->get_name(); - $insightinfo->contextname = $context->get_context_name(); - return get_string('insightmessagesubject', 'analytics', $insightinfo); + public function get_insight_subject(int $modelid, \context $context) { + return get_string('insightmessagesubject', 'analytics', $context->get_context_name()); } /** diff --git a/user/classes/analytics/target/upcoming_activities_due.php b/user/classes/analytics/target/upcoming_activities_due.php index 39383356e5a..7ee12690432 100644 --- a/user/classes/analytics/target/upcoming_activities_due.php +++ b/user/classes/analytics/target/upcoming_activities_due.php @@ -64,7 +64,7 @@ class upcoming_activities_due extends \core_analytics\local\target\binary { * @param \context $context * @return string */ - protected function get_insight_subject(int $modelid, \context $context) { + public function get_insight_subject(int $modelid, \context $context) { return get_string('youhaveupcomingactivitiesdue'); }