diff --git a/classes/helper.php b/classes/helper.php index 43e74f5b..aba6f506 100644 --- a/classes/helper.php +++ b/classes/helper.php @@ -850,6 +850,7 @@ public function set_tool_config(object|int $pageorid, string $name, string $valu // Lastupdated timestamp hast to be reset in cache. $this->clear_caches($page->id); + $this->notify_data_changed($page, 'settings'); } /** @@ -1135,8 +1136,8 @@ public function store_answer( $this->clear_caches($pageid); $this->get_answers($table, $pageid, $answercolumn); $this->get_answers_grouped($table, ['pageid' => $pageid], $answercolumn); - $this->get_page_last_update_time($pageid, true); - $this->get_page_last_update_time($pageid, false); + $this->notify_data_changed($this->get_page($pageid), 'answers', true); + $this->notify_data_changed($this->get_page($pageid), 'answers', false); return $answerids; } @@ -1161,6 +1162,7 @@ public function delete_all_answers(string $table, int $pageid): bool { $params = ['pageid' => $pageid]; $return = $DB->delete_records($table, $params); $this->clear_caches($pageid); + $this->notify_data_changed($this->get_page($pageid), 'answers'); return $return; } @@ -1197,6 +1199,7 @@ public function delete_single_answer(string $table, int $pageid, int $answerid): $params = ['pageid' => $pageid, 'id' => $answerid]; $return = $DB->delete_records($table, $params); $this->clear_caches($pageid); + $this->notify_data_changed($this->get_page($pageid), 'answers'); return $return; } @@ -1235,6 +1238,7 @@ public function delete_answers_of_user(string $table, int $pageid, int $userid): $params = ['pageid' => $pageid, $toolhelper->get_answer_userid_column() => $userid]; $return = $DB->delete_records($table, $params); $this->clear_caches($pageid); + $this->notify_data_changed($page, 'answers'); return $return; } @@ -1324,112 +1328,101 @@ public function get_answers_grouped(string $table, array $params, string $answer } /** - * Get the lastupdated timestamp. + * Notify, that data changed. This sets a new timestamp to the cache. + * Clients then knew, there is someting new, and they have to update this. * - * @param int|object $pageorid + * @param object $page + * @param string $identifier * @param bool $ignoreanswers - * @return mixed + * @return void */ - public function get_page_last_update_time(int|object $pageorid, bool $ignoreanswers = false): string|int { - global $USER; - - $page = $pageorid; - if (!is_object($page)) { - $page = $this->get_page($page); - } - - if (empty($page)) { - return 0; - } - - // We only want to deliver results if the teacher allowed to view it. - $instance = self::get_instance_by_pageid($page->id); - $cm = self::get_cm_by_instance($instance); - if ( - empty($this->get_tool_config($page->id, 'showonteacherpermission')) - && !has_capability('mod/mootimeter:moderator', \context_module::instance($cm->id)) - ) { - return 0; - } + public function notify_data_changed(object $page, string $identifier = '', bool $ignoreanswers = false): void { - $settingslastupdated = $this->get_lastupdate_tool_settings($page); - $answerslastupdated = $this->get_lastupdate_answers($page, $ignoreanswers); - - return $settingslastupdated + $answerslastupdated; + $cache = \cache::make('mod_mootimeter', 'lastupdated'); + $cachekey = 'lastupdate_' . $identifier . '_' . (int) $ignoreanswers . '_' . $page->id; + \local_debugger\performance\debugger::print_debug_backtrace('test', 'data changed_' . $identifier, time()); + $cache->set($cachekey, time()); } /** - * Get the last updated timestamp of the answers. + * Get the recent data changed timestamp * * @param object $page + * @param string $identifier * @param bool $ignoreanswers * @return int - * @throws coding_exception */ - public function get_lastupdate_answers(object $page, bool $ignoreanswers = false): int { - $classname = "\mootimetertool_" . $page->tool . "\\" . $page->tool; - if (!class_exists($classname)) { - return "Class '" . $page->tool . "' is missing in tool " . $page->tool; - } - - $toolhelper = new $classname(); - if (!method_exists($toolhelper, 'get_last_update_time')) { - return "Method 'get_last_update_time' is missing in tools helper class " . $page->tool; - } + public function get_data_changed(object $page, string $identifier = '', bool $ignoreanswers = false): int { $cache = \cache::make('mod_mootimeter', 'lastupdated'); - $cachekey = 'lastupdate_answers_' . (int) $ignoreanswers . '_' . $page->id; - $answerslastupdated = $cache->get($cachekey); - - if (empty($answerslastupdated)) { - $answerslastupdated = $toolhelper->get_last_update_time($page->id, $ignoreanswers); - $cache->set($cachekey, $answerslastupdated); - } + $cachekey = 'lastupdate_' . $identifier . '_' . (int) $ignoreanswers . '_' . $page->id; + \local_debugger\performance\debugger::print_debug_backtrace('test', 'get data changed_' . $identifier, $cache->get($cachekey)); - return $answerslastupdated; + return (int) $cache->get($cachekey); } /** - * Get the most recent timestamp of tool settings. + * Get the lastupdated timestamp. * - * @param object $page - * @return int - * @throws coding_exception + * @param int|object $pageorid + * @param bool $ignoreanswers + * @return mixed */ - public function get_lastupdate_tool_settings(object $page): int { - global $DB; + public function get_page_last_update_time( + int|object $pageorid, + string $identifier = '', + bool $ignoreanswers = false + ): string|int { - $cache = \cache::make('mod_mootimeter', 'lastupdated'); - $cachekey = 'lastupdate_settings_' . $page->id; - $mostrecenttimesettings = $cache->get($cachekey); - - if (empty($mostrecenttimesettings)) { - // Make the settings change test in the global helper class. Because its everywhere the same. - // It's important, that the default value is NOT null, but 0 instead. Otherwise GREATEST will return null anyway. - $sql = 'SELECT MAX(timemodified) as time FROM {mootimeter_tool_settings} WHERE pageid = :pageid'; - $record = $DB->get_record_sql($sql, ['pageid' => $page->id]); - - $mostrecenttimesettings = 0; - if (!empty($record)) { - $mostrecenttimesettings = $record->time; - } + if (!in_array($identifier, ['settings', 'answers', ''])) { + throw new moodle_exception( + 'generalexceptionmessage', + 'error', + '', + get_string("cacheidentifiernotallowed", "mootimeter") . " => " . $identifier + ); + } + + if (is_object($pageorid)) { + $page = $pageorid; + } else { + $page = $this->get_page($pageorid); + } - $mostrecenttimesettings = max($page->timemodified, $page->timecreated, $mostrecenttimesettings); - $cache->set($cachekey, $mostrecenttimesettings); + // We only want to deliver results if the teacher allowed to view it. + $instance = self::get_instance_by_pageid($page->id); + $cm = self::get_cm_by_instance($instance); + if ( + empty($this->get_tool_config($page->id, 'showonteacherpermission')) + && !has_capability('mod/mootimeter:moderator', \context_module::instance($cm->id)) + ) { + return 0; + } + + if (empty($identifier)) { + $lastupdatesettings = (int) $this->get_data_changed($page, 'settings'); + $lastupdateanswers = (int) $this->get_data_changed($page, 'answers', $ignoreanswers); + return max($lastupdatesettings, $lastupdateanswers); } - return $mostrecenttimesettings; + + return (int) $this->get_data_changed($page, $identifier, $ignoreanswers); } /** * Get the teacherpermission to view state. * - * @param object $page + * @param object|bool $page * @return int * @throws dml_exception * @throws coding_exception */ - public function get_teacherpermission_to_view(object $page): int { + public function get_teacherpermission_to_view(object|bool $page): int { + + // On empty page, there are no permissions needed. This is normally the case, if a new page is added. + if (empty($page)) { + return 0; + } $instance = self::get_instance_by_pageid($page->id); $cm = self::get_cm_by_instance($instance); @@ -1456,13 +1449,6 @@ public function clear_caches(int $pageid): void { $cache = \cache::make('mod_mootimeter', 'answers'); $cache->delete('answers_' . $pageid); $cache->delete('cnt_' . $pageid); - - $cache = \cache::make('mod_mootimeter', 'lastupdated'); - $cache->delete('lastupdate_settings_' . $pageid); - // Lastupdate timestamp with answers. - $cache->delete('lastupdate_answers_0_' . $pageid); - // Lastupdate timestamp without answers. - $cache->delete('lastupdate_answers_1_' . $pageid); } /** diff --git a/classes/local/pagelist.php b/classes/local/pagelist.php index 0fdfce48..3cb23922 100644 --- a/classes/local/pagelist.php +++ b/classes/local/pagelist.php @@ -100,7 +100,7 @@ public function get_pagelist_params(int $cmid, int $pageidselected, object $data 'tooltip' => mb_strimwidth($helper::get_tool_config($pagerow, 'question'), 0, 40, '...'), ]; - $pageupdatedat = $helper->get_lastupdate_tool_settings($pagerow); + $pageupdatedat = $helper->get_page_last_update_time($temppages['pageid'], 'settings'); $maxtimecreated = max($maxtimecreated, $pageupdatedat); $pagenumber++; @@ -111,9 +111,9 @@ public function get_pagelist_params(int $cmid, int $pageidselected, object $data // We have to distinguish from which page the request comes. // We differentiate between the standard content page (question page) and other pages (eg. results and overview page). if (empty($dataset->r) && empty($dataset->o)) { - $temppages['dataset']['contentchangedat'] = $helper->get_page_last_update_time($temppages['pageid'], true); + $temppages['dataset']['contentchangedat'] = $helper->get_page_last_update_time($temppages['pageid'], '', true); } else { - $temppages['dataset']['contentchangedat'] = $helper->get_page_last_update_time($temppages['pageid']); + $temppages['dataset']['contentchangedat'] = $helper->get_page_last_update_time($temppages['pageid'], ''); } \mod_mootimeter\local\mootimeterstate::add_mootimeterstate('contentchangedat', $temppages['dataset']['contentchangedat']); diff --git a/classes/toolhelper.php b/classes/toolhelper.php index 26175b6c..4858a256 100644 --- a/classes/toolhelper.php +++ b/classes/toolhelper.php @@ -70,15 +70,6 @@ public function get_answer_userid_column(): ?string { */ abstract public function insert_answer(object $page, $answer); - /** - * Get the timestamp of the last answer. - * - * @param int|object $pageorid - * @param bool $ignoreanswers - * @return int - */ - abstract public function get_last_update_time(int|object $pageorid, bool $ignoreanswers = false); - /** * Delete Page * diff --git a/lang/de/mootimeter.php b/lang/de/mootimeter.php index 0e7857f9..75119da8 100644 --- a/lang/de/mootimeter.php +++ b/lang/de/mootimeter.php @@ -31,6 +31,7 @@ $string['anonymousmode'] = 'Anonymer Modus'; $string['anonymousmode_desc'] = ' - Dieses Setting kann nicht verändert werden, sobald Antworten existieren'; $string['cachedef_answers'] = 'Enthält die Antworten für die Seiten.'; +$string['cacheidentifiernotallowed'] = 'Der verwendete Cache Identifier ist hier nicht zulässig.'; $string['cannotview'] = 'Sie haben keine Berechtigung, auf diese Seite zuzugreifen!'; $string['createnewpagesettings'] = 'Neue Seiteneinstellungen'; $string['default_new_page_visibility'] = 'Neue Seiten standardmäßig sichtbar'; diff --git a/lang/en/mootimeter.php b/lang/en/mootimeter.php index 79599aa1..7f8314c0 100644 --- a/lang/en/mootimeter.php +++ b/lang/en/mootimeter.php @@ -31,6 +31,7 @@ $string['anonymousmode'] = 'If checked, teachers can not view voters names.'; $string['anonymousmode_desc'] = 'This setting can not be changed when answers exist!'; $string['cachedef_answers'] = 'Contains the pages answers.'; +$string['cacheidentifiernotallowed'] = 'The used cache identifier is not allowed here.'; $string['cannotview'] = 'You are not allowed to access this page!'; $string['createnewpagesettings'] = 'New page settings'; $string['default_new_page_visibility'] = 'New pages visible by default'; diff --git a/tools/quiz/classes/quiz.php b/tools/quiz/classes/quiz.php index 4cb8ef5d..97e6c7f3 100644 --- a/tools/quiz/classes/quiz.php +++ b/tools/quiz/classes/quiz.php @@ -773,7 +773,7 @@ public function get_result_params_chartjs(int|object $pageorid): array { 'labels' => json_encode($labels), 'values' => json_encode($values), 'question' => self::get_tool_config($page, 'question'), - 'lastupdated' => $this->get_page_last_update_time($page->id), + 'lastupdated' => $this->get_page_last_update_time($page->id, ''), 'teacherpermissiontoview' => $this->get_teacherpermission_to_view($page), ]; @@ -827,40 +827,6 @@ public function delete_answers_tool(object $page, array $conditions): void { $this->clear_caches($page->id); } - /** - * Get the lastupdated timestamp. - * - * @param int|object $pageorid - * @param bool $ignoreanswers - * @return int - */ - public function get_last_update_time(int|object $pageorid, bool $ignoreanswers = false): int { - global $DB; - - $page = $pageorid; - if (!is_object($page)) { - $page = $this->get_page($page); - } - - $mostrecenttimeanswer = 0; - if (!$ignoreanswers) { - // It's important, that the default value is NOT null, but 0 instead. Otherwise GREATEST will return null anyway. - $sql = 'SELECT SUM(GREATEST(timecreated, timemodified)) as time FROM ' - . '{' . $this->get_answer_table() . '} WHERE pageid = :pageid'; - $queryresultanswer = $DB->get_field_sql($sql, ['pageid' => $page->id]); - $mostrecenttimeanswer = !is_null($queryresultanswer) ? $queryresultanswer : 0; - } - - // It's important, that the default value is NOT null, but 0 instead. Otherwise GREATEST will return null anyway. - $mostrecenttimeoptions = 0; - $sql = 'SELECT SUM(GREATEST(timecreated, timemodified)) as time FROM ' - . '{' . $this->get_answer_option_table() . '} WHERE pageid = :pageid'; - $queryresultoptions = $DB->get_field_sql($sql, ['pageid' => $page->id]); - $mostrecenttimeoptions = !is_null($queryresultoptions) ? $queryresultoptions : 0; - - return $mostrecenttimeanswer + $mostrecenttimeoptions; - } - /** * Get array of counted values for each answer/ option. * @param int $pageid diff --git a/tools/wordcloud/classes/external/get_answers.php b/tools/wordcloud/classes/external/get_answers.php index a69b3d1e..3d34d501 100644 --- a/tools/wordcloud/classes/external/get_answers.php +++ b/tools/wordcloud/classes/external/get_answers.php @@ -75,7 +75,7 @@ public static function execute(int $pageid, int $lastupdated): array { require_capability('mod/mootimeter:view', $cmcontext); $wordcloud = new wordcloud(); - $lastupdatednew = $wordcloud->get_page_last_update_time($pageid); + $lastupdatednew = $wordcloud->get_page_last_update_time($pageid, 'answers'); $answerlist = $wordcloud->get_answerlist_wordcloud($pageid); diff --git a/tools/wordcloud/classes/wordcloud.php b/tools/wordcloud/classes/wordcloud.php index fdf0e43f..18a4337f 100644 --- a/tools/wordcloud/classes/wordcloud.php +++ b/tools/wordcloud/classes/wordcloud.php @@ -420,35 +420,6 @@ public function get_col_settings_tool_params(object $page, array $params = []) { return $returnparams; } - /** - * Get the lastupdated timestamp. - * - * @param int|object $pageorid - * @param bool $ignoreanswers - * @return int - */ - public function get_last_update_time(int|object $pageorid, bool $ignoreanswers = false): int { - global $DB; - - $page = $pageorid; - if (!is_object($page)) { - $page = $this->get_page($page); - } - - $instance = self::get_instance_by_pageid($page->id); - $cm = self::get_cm_by_instance($instance); - - $mostrecenttimeanswer = 0; - if (!$ignoreanswers) { - $sql = 'SELECT SUM(GREATEST(timecreated, timemodified)) as time FROM ' - . '{' . self::ANSWER_TABLE . '} WHERE pageid = :pageid'; - $queryresult = $DB->get_field_sql($sql, ['pageid' => $page->id]); - $mostrecenttimeanswer = !is_null($queryresult) ? $queryresult : 0; - } - - return $mostrecenttimeanswer; - } - /** * Delete all DB entries related to a specific page. * @param object $page