AutorÃa | Ultima modificación | Ver Log |
<?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/>.namespace core_ai\privacy;use core_privacy\local\metadata\collection;use core_privacy\local\request\approved_contextlist;use core_privacy\local\request\approved_userlist;use core_privacy\local\request\contextlist;use core_privacy\local\request\transform;use core_privacy\local\request\userlist;use core_privacy\local\request\writer;/*** Privacy Subsystem for core_ai implementing null_provider.** @package core_ai* @copyright 2024 Matt Porritt <matt.porritt@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class provider implements\core_privacy\local\metadata\provider,\core_privacy\local\request\subsystem\provider,\core_privacy\local\request\core_userlist_provider {/*** Returns meta data about this system.** @param collection $collection The initialised collection to add items to.* @return collection A listing of user data stored through this system.*/public static function get_metadata(collection $collection): collection {$collection->add_database_table('ai_policy_register', ['userid' => 'privacy:metadata:ai_policy_register:userid','contextid' => 'privacy:metadata:ai_policy_register:contextid','timeaccepted' => 'privacy:metadata:ai_policy_register:timeaccepted',], 'privacy:metadata:ai_policy_register');$collection->add_database_table('ai_action_register', ['actionname' => 'privacy:metadata:ai_action_register:actionname','actionid' => 'privacy:metadata:ai_action_register:actionid','success' => 'privacy:metadata:ai_action_register:success','userid' => 'privacy:metadata:ai_action_register:userid','provider' => 'privacy:metadata:ai_action_register:provider','timecreated' => 'privacy:metadata:ai_action_register:timecreated','timecompleted' => 'privacy:metadata:ai_action_register:timecompleted','model' => 'privacy:metadata:ai_action_register:model',], 'privacy:metadata:ai_action_register');$collection->add_database_table('ai_action_generate_image', ['prompt' => 'privacy:metadata:ai_action_generate_image:prompt','numberimages' => 'privacy:metadata:ai_action_generate_image:numberimages','quality' => 'privacy:metadata:ai_action_generate_image:quality','aspectratio' => 'privacy:metadata:ai_action_generate_image:aspectratio','style' => 'privacy:metadata:ai_action_generate_image:style','sourceurl' => 'privacy:metadata:ai_action_generate_image:sourceurl','revisedprompt' => 'privacy:metadata:ai_action_generate_image:revisedprompt',], 'privacy:metadata:ai_action_generate_image');$collection->add_database_table('ai_action_generate_text', ['prompt' => 'privacy:metadata:ai_action_generate_text:prompt','responseid' => 'privacy:metadata:ai_action_generate_text:responseid','fingerprint' => 'privacy:metadata:ai_action_generate_text:fingerprint','generatedcontent' => 'privacy:metadata:ai_action_generate_text:generatedcontent','prompttokens' => 'privacy:metadata:ai_action_generate_text:prompttokens','completiontoken' => 'privacy:metadata:ai_action_generate_text:completiontoken',], 'privacy:metadata:ai_action_generate_text');$collection->add_database_table('ai_action_summarise_text', ['prompt' => 'privacy:metadata:ai_action_summarise_text:prompt','responseid' => 'privacy:metadata:ai_action_summarise_text:responseid','fingerprint' => 'privacy:metadata:ai_action_summarise_text:fingerprint','generatedcontent' => 'privacy:metadata:ai_action_summarise_text:generatedcontent','prompttokens' => 'privacy:metadata:ai_action_summarise_text:prompttokens','completiontoken' => 'privacy:metadata:ai_action_summarise_text:completiontoken',], 'privacy:metadata:ai_action_summarise_text');$collection->add_database_table('ai_action_explain_text', ['prompt' => 'privacy:metadata:ai_action_explain_text:prompt','responseid' => 'privacy:metadata:ai_action_explain_text:responseid','fingerprint' => 'privacy:metadata:ai_action_explain_text:fingerprint','generatedcontent' => 'privacy:metadata:ai_action_explain_text:generatedcontent','prompttokens' => 'privacy:metadata:ai_action_explain_text:prompttokens','completiontoken' => 'privacy:metadata:ai_action_explain_text:completiontoken',], 'privacy:metadata:ai_action_explain_text');return $collection;}/*** Get the list of contexts that contain user information for the specified user.** @param int $userid The user to search.* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.*/public static function get_contexts_for_userid(int $userid): contextlist {$contextlist = new contextlist();// AI policy.$sql = 'SELECT DISTINCT ctx.idFROM {context} ctxJOIN {ai_policy_register} aprON apr.contextid = ctx.idWHERE apr.userid = :userid';$contextlist->add_from_sql($sql, ['userid' => $userid]);// AI action generate text.$sql = "SELECT DISTINCT ctx.idFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_generate_text} aagtON aagt.id = aar.actionidWHERE aar.actionname = 'generate_text'AND aar.userid = :userid";$contextlist->add_from_sql($sql, ['userid' => $userid]);// AI action generate image.$sql = "SELECT DISTINCT ctx.idFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_generate_image} aagiON aagi.id = aar.actionidWHERE aar.actionname = 'generate_image'AND aar.userid = :userid";$contextlist->add_from_sql($sql, ['userid' => $userid]);// AI action summarise text.$sql = "SELECT DISTINCT ctx.idFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_summarise_text} aastON aast.id = aar.actionidWHERE aar.actionname = 'summarise_text'AND aar.userid = :userid";$contextlist->add_from_sql($sql, ['userid' => $userid]);// AI action explain text.$sql = "SELECT DISTINCT ctx.idFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_explain_text} aaetON aaet.id = aar.actionidWHERE aar.actionname = 'explain_text'AND aar.userid = :userid";$contextlist->add_from_sql($sql, ['userid' => $userid]);return $contextlist;}/*** Export all user data for the specified user, in the specified contexts.** @param approved_contextlist $contextlist The approved contexts to export information for.*/public static function export_user_data(approved_contextlist $contextlist): void {global $DB;// AI policy.$userid = $contextlist->get_user()->id;[$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);$sql = 'SELECT apr.timeaccepted, ctx.id AS contextidFROM {context} ctxJOIN {ai_policy_register} aprON apr.contextid = ctx.idWHERE apr.userid = :useridAND ctx.id ' . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$policydetails = $DB->get_recordset_sql($sql, $params);foreach ($policydetails as $policydetail) {$subcontexts = [get_string('ai', 'core_ai'),];$name = 'policy';$details = (object) ['contextid' => $policydetail->contextid,'timeaccepted' => transform::datetime($policydetail->timeaccepted),];$context = \context::instance_by_id($policydetail->contextid);writer::with_context($context)->export_related_data($subcontexts, $name, $details);}$policydetails->close();// AI action generate text.$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,aagt.prompt, aagt.responseid, aagt.fingerprint, aagt.generatedcontent,aagt.prompttokens, aagt.completiontoken, aar.modelFROM {ai_action_register} aarJOIN {ai_action_generate_text} aagtON aar.actionid = aagt.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$textgeneratedetails = $DB->get_recordset_sql($sql, $params);foreach ($textgeneratedetails as $textgeneratedetail) {$subcontexts = [get_string('ai', 'core_ai'),get_string('action_generate_text', 'core_ai'),date('c', $textgeneratedetail->timecreated),];$details = (object) ['actionname' => $textgeneratedetail->actionname,'contextid' => $textgeneratedetail->contextid,'prompt' => $textgeneratedetail->prompt,'responseid' => $textgeneratedetail->responseid,'fingerprint' => $textgeneratedetail->fingerprint,'generatedcontent' => $textgeneratedetail->generatedcontent,'prompttokens' => $textgeneratedetail->prompttokens,'completiontoken' => $textgeneratedetail->completiontoken,'model' => $textgeneratedetail->model,'success' => transform::yesno($textgeneratedetail->success),'provider' => $textgeneratedetail->provider,'timecreated' => transform::datetime($textgeneratedetail->timecreated),'timecompleted' => transform::datetime($textgeneratedetail->timecompleted),];$name = 'action_generate_text';$context = \context::instance_by_id($textgeneratedetail->contextid);writer::with_context($context)->export_related_data($subcontexts, $name, $details);}$textgeneratedetails->close();// AI action generate image.$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,aagi.prompt, aagi.numberimages, aagi.quality, aagi.aspectratio, aagi.style, aagi.sourceurl,aagi.revisedprompt, aar.modelFROM {ai_action_register} aarJOIN {ai_action_generate_image} aagiON aar.actionid = aagi.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_image'AND aar.userid = :useridAND ctx.id " . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$imagegeneratedetails = $DB->get_recordset_sql($sql, $params);foreach ($imagegeneratedetails as $imagegeneratedetail) {$subcontexts = [get_string('ai', 'core_ai'),get_string('action_generate_image', 'core_ai'),date('c', $imagegeneratedetail->timecreated),];$details = (object) ['actionname' => $imagegeneratedetail->actionname,'contextid' => $imagegeneratedetail->contextid,'prompt' => $imagegeneratedetail->prompt,'numberimages' => $imagegeneratedetail->numberimages,'quality' => $imagegeneratedetail->quality,'aspectratio' => $imagegeneratedetail->aspectratio,'style' => $imagegeneratedetail->style,'sourceurl' => $imagegeneratedetail->sourceurl,'revisedprompt' => $imagegeneratedetail->revisedprompt,'model' => $imagegeneratedetail->model,'success' => transform::yesno($imagegeneratedetail->success),'provider' => $imagegeneratedetail->provider,'timecreated' => transform::datetime($imagegeneratedetail->timecreated),'timecompleted' => transform::datetime($imagegeneratedetail->timecompleted),];$name = 'action_generate_image';$context = \context::instance_by_id($imagegeneratedetail->contextid);writer::with_context($context)->export_related_data($subcontexts, $name, $details);}$imagegeneratedetails->close();// AI action summarise text.$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,aast.prompt, aast.responseid, aast.fingerprint, aast.generatedcontent,aast.prompttokens, aast.completiontoken, aar.modelFROM {ai_action_register} aarJOIN {ai_action_summarise_text} aastON aar.actionid = aast.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'summarise_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$textsummarisedetails = $DB->get_recordset_sql($sql, $params);foreach ($textsummarisedetails as $textsummarisedetail) {$subcontexts = [get_string('ai', 'core_ai'),get_string('action_summarise_text', 'core_ai'),date('c', $textsummarisedetail->timecreated),];$details = (object) ['actionname' => $textsummarisedetail->actionname,'contextid' => $textsummarisedetail->contextid,'prompt' => $textsummarisedetail->prompt,'responseid' => $textsummarisedetail->responseid,'fingerprint' => $textsummarisedetail->fingerprint,'generatedcontent' => $textsummarisedetail->generatedcontent,'prompttokens' => $textsummarisedetail->prompttokens,'completiontoken' => $textsummarisedetail->completiontoken,'model' => $textsummarisedetail->model,'success' => transform::yesno($textsummarisedetail->success),'provider' => $textsummarisedetail->provider,'timecreated' => transform::datetime($textsummarisedetail->timecreated),'timecompleted' => transform::datetime($textsummarisedetail->timecompleted),];$name = 'action_summarise_text';$context = \context::instance_by_id($textsummarisedetail->contextid);writer::with_context($context)->export_related_data($subcontexts, $name, $details);}$textsummarisedetails->close();// AI action explain text.$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,aaet.prompt, aaet.responseid, aaet.fingerprint, aaet.generatedcontent,aaet.prompttokens, aaet.completiontoken, aar.modelFROM {ai_action_register} aarJOIN {ai_action_explain_text} aaetON aar.actionid = aaet.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'explain_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$textexplaindetails = $DB->get_recordset_sql($sql, $params);foreach ($textexplaindetails as $textexplaindetail) {$subcontexts = [get_string('ai', 'core_ai'),get_string('action_explain_text', 'core_ai'),date('c', $textexplaindetail->timecreated),];$details = (object) ['actionname' => $textexplaindetail->actionname,'contextid' => $textexplaindetail->contextid,'prompt' => $textexplaindetail->prompt,'responseid' => $textexplaindetail->responseid,'fingerprint' => $textexplaindetail->fingerprint,'generatedcontent' => $textexplaindetail->generatedcontent,'prompttokens' => $textexplaindetail->prompttokens,'completiontoken' => $textexplaindetail->completiontoken,'model' => $textexplaindetail->model,'success' => transform::yesno($textexplaindetail->success),'provider' => $textexplaindetail->provider,'timecreated' => transform::datetime($textexplaindetail->timecreated),'timecompleted' => transform::datetime($textexplaindetail->timecompleted),];$name = 'action_explain_text';$context = \context::instance_by_id($textexplaindetail->contextid);writer::with_context($context)->export_related_data($subcontexts, $name, $details);}$textexplaindetails->close();}/*** Delete all data for all users in the specified context.** @param \context $context The specific context to delete data for.*/public static function delete_data_for_all_users_in_context(\context $context): void {global $DB;// Policy.$sql = 'SELECT DISTINCT apr.idFROM {ai_policy_register} aprJOIN {context} ctxON apr.contextid = ctx.idWHERE ctx.id = :contextid';$params = ['contextid' => $context->id,];$policydetails = $DB->get_records_sql($sql, $params);if ($policydetails) {$DB->delete_records_list('ai_policy_register', 'id', array_keys($policydetails));}// AI action generate text.$sql = "SELECT DISTINCT aagt.idFROM {ai_action_register} aarJOIN {ai_action_generate_text} aagtON aar.actionid = aagt.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_text'AND ctx.id = :contextid";$params = ['contextid' => $context->id,];$aagtids = $DB->get_records_sql_menu($sql, $params);if ($aagtids) {[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal(array_keys($aagtids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aagtidsql;$DB->execute($sql, $aagtidparams);}// AI action generate image.$sql = "SELECT DISTINCT aagi.idFROM {ai_action_register} aarJOIN {ai_action_generate_image} aagiON aar.actionid = aagi.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_image'AND ctx.id = :contextid";$params = ['contextid' => $context->id,];$aagiids = $DB->get_records_sql_menu($sql, $params);if ($aagiids) {[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal(array_keys($aagiids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_image}SET prompt = '',sourceurl = '',revisedprompt = ''WHERE id " . $aagiidsql;$DB->execute($sql, $aagiidparams);}// AI action summarise text.$sql = "SELECT DISTINCT aast.idFROM {ai_action_register} aarJOIN {ai_action_summarise_text} aastON aar.actionid = aast.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'summarise_text'AND ctx.id = :contextid";$params = ['contextid' => $context->id,];$aastids = $DB->get_records_sql_menu($sql, $params);if ($aastids) {[$aastidsql, $aastidparams] = $DB->get_in_or_equal(array_keys($aastids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_summarise_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aastidsql;$DB->execute($sql, $aastidparams);}// AI action explain text.$sql = "SELECT DISTINCT aaet.idFROM {ai_action_register} aarJOIN {ai_action_explain_text} aaetON aar.actionid = aaet.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'explain_text'AND ctx.id = :contextid";$params = ['contextid' => $context->id,];$aaetids = $DB->get_records_sql_menu($sql, $params);if ($aaetids) {[$aaetidsql, $aaetidparams] = $DB->get_in_or_equal(array_keys($aaetids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_explain_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aaetidsql;$DB->execute($sql, $aaetidparams);}}/*** Delete all user data for the specified user, in the specified contexts.** @param approved_contextlist $contextlist The approved contexts and user information to delete information for.*/public static function delete_data_for_user(approved_contextlist $contextlist): void {global $DB;// Policy.$userid = $contextlist->get_user()->id;[$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);$sql = "SELECT DISTINCT apr.id AS policyidFROM {context} ctxJOIN {ai_policy_register} aprON apr.contextid = ctx.idWHERE apr.userid = :useridAND ctx.id " . $contextsql;$params = ['userid' => $userid,];$params += $contextparams;$policydetails = $DB->get_recordset_sql($sql, $params);$policyids = [];foreach ($policydetails as $policydetail) {$policyids[] = $policydetail->policyid;}$policydetails->close();$DB->delete_records_list('ai_policy_register', 'id', $policyids);// AI action generate text.$sql = "SELECT DISTINCT aagt.id AS textgenerateidFROM {ai_action_register} aarJOIN {ai_action_generate_text} aagtON aar.actionid = aagt.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$textgeneratedetails = $DB->get_recordset_sql($sql, $params);$aagtids = [];foreach ($textgeneratedetails as $textgeneratedetail) {$aagtids[] = $textgeneratedetail->textgenerateid;}$textgeneratedetails->close();if ($aagtids) {[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal($aagtids, SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aagtidsql;$DB->execute($sql, $aagtidparams);}// AI action generate image.$sql = "SELECT DISTINCT aagi.id AS imagegenerateidFROM {ai_action_register} aarJOIN {ai_action_generate_image} aagiON aar.actionid = aagi.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_image'AND aar.userid = :useridAND ctx.id " . $contextsql;$imagegeneratedetails = $DB->get_recordset_sql($sql, $params);$aagiids = [];foreach ($imagegeneratedetails as $imagegeneratedetail) {$aagiids[] = $imagegeneratedetail->imagegenerateid;}$imagegeneratedetails->close();if ($aagiids) {[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal($aagiids, SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_image}SET prompt = '',sourceurl = '',revisedprompt = ''WHERE id " . $aagiidsql;$DB->execute($sql, $aagiidparams);}// AI action summarise text.$sql = "SELECT DISTINCT aast.id AS textsummariseidFROM {ai_action_register} aarJOIN {ai_action_summarise_text} aastON aar.actionid = aast.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'summarise_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$textsummarisedetails = $DB->get_recordset_sql($sql, $params);$aastids = [];foreach ($textsummarisedetails as $textsummarisedetail) {$aastids[] = $textsummarisedetail->textsummariseid;}$textsummarisedetails->close();if ($aastids) {[$aastidsql, $aastidparams] = $DB->get_in_or_equal($aastids, SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_summarise_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aastidsql;$DB->execute($sql, $aastidparams);}// AI action explain text.$sql = "SELECT DISTINCT aaet.id AS textexplainidFROM {ai_action_register} aarJOIN {ai_action_explain_text} aaetON aar.actionid = aaet.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'explain_text'AND aar.userid = :useridAND ctx.id " . $contextsql;$textexplaindetails = $DB->get_recordset_sql($sql, $params);$aaetids = [];foreach ($textexplaindetails as $textexplaindetail) {$aaetids[] = $textexplaindetail->textexplainid;}$textexplaindetails->close();if ($aaetids) {[$aaetidsql, $aaetidparams] = $DB->get_in_or_equal($aaetids, SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_explain_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aaetidsql;$DB->execute($sql, $aaetidparams);}}/*** Get the list of users who have data within a context.** @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.*/public static function get_users_in_context(userlist $userlist): void {$context = $userlist->get_context();// AI policy.$sql = 'SELECT DISTINCT apr.useridFROM {context} ctxJOIN {ai_policy_register} aprON apr.contextid = ctx.idWHERE apr.contextid = :contextid';$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);// AI action generate text.$sql = "SELECT DISTINCT aar.useridFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_generate_text} aagtON aagt.id = aar.actionidWHERE aar.actionname = 'generate_text'AND aar.contextid = :contextid";$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);// AI action generate image.$sql = "SELECT DISTINCT aar.useridFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_generate_image} aagiON aagi.id = aar.actionidWHERE aar.actionname = 'generate_image'AND aar.contextid = :contextid";$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);// AI action summarise text.$sql = "SELECT DISTINCT aar.useridFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_summarise_text} aastON aast.id = aar.actionidWHERE aar.actionname = 'summarise_text'AND aar.contextid = :contextid";$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);// AI action explain text.$sql = "SELECT DISTINCT aar.useridFROM {context} ctxJOIN {ai_action_register} aarON aar.contextid = ctx.idJOIN {ai_action_explain_text} aaetON aaet.id = aar.actionidWHERE aar.actionname = 'explain_text'AND aar.contextid = :contextid";$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);}/*** Delete multiple users within a single context.** @param approved_userlist $userlist The approved context and user information to delete information for.*/public static function delete_data_for_users(approved_userlist $userlist) {global $DB;$context = $userlist->get_context();$userids = $userlist->get_userids();[$useridssql, $useridsparams] = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);$params = ['contextid' => $context->id,];$params += $useridsparams;// Policy.$sql = "SELECT DISTINCT apr.idFROM {ai_policy_register} aprJOIN {context} ctxON apr.contextid = ctx.idWHERE ctx.id = :contextidAND apr.userid " . $useridssql;$policydetails = $DB->get_records_sql($sql, $params);if ($policydetails) {$DB->delete_records_list('ai_policy_register', 'id', array_keys($policydetails));}// AI action generate text.$sql = "SELECT DISTINCT aagt.idFROM {ai_action_register} aarJOIN {ai_action_generate_text} aagtON aar.actionid = aagt.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_text'AND ctx.id = :contextidAND aar.userid " . $useridssql;$aagtids = $DB->get_records_sql_menu($sql, $params);if ($aagtids) {[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal(array_keys($aagtids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aagtidsql;$DB->execute($sql, $aagtidparams);}// AI action generate image.$sql = "SELECT DISTINCT aagi.idFROM {ai_action_register} aarJOIN {ai_action_generate_image} aagiON aar.actionid = aagi.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'generate_image'AND ctx.id = :contextidAND aar.userid " . $useridssql;$aagiids = $DB->get_records_sql_menu($sql, $params);if ($aagiids) {[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal(array_keys($aagiids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_generate_image}SET prompt = '',sourceurl = '',revisedprompt = ''WHERE id " . $aagiidsql;$DB->execute($sql, $aagiidparams);}// AI action summarise text.$sql = "SELECT DISTINCT aast.idFROM {ai_action_register} aarJOIN {ai_action_summarise_text} aastON aar.actionid = aast.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'summarise_text'AND ctx.id = :contextidAND aar.userid " . $useridssql;$aastids = $DB->get_records_sql_menu($sql, $params);if ($aastids) {[$aastidsql, $aastidparams] = $DB->get_in_or_equal(array_keys($aastids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_summarise_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aastidsql;$DB->execute($sql, $aastidparams);}// AI action explain text.$sql = "SELECT DISTINCT aaet.idFROM {ai_action_register} aarJOIN {ai_action_explain_text} aaetON aar.actionid = aaet.idJOIN {context} ctxON aar.contextid = ctx.idWHERE aar.actionname = 'explain_text'AND ctx.id = :contextidAND aar.userid " . $useridssql;$aaetids = $DB->get_records_sql_menu($sql, $params);if ($aaetids) {[$aaetidsql, $aaetidparams] = $DB->get_in_or_equal(array_keys($aaetids), SQL_PARAMS_NAMED);$sql = "UPDATE {ai_action_explain_text}SET prompt = '',responseid = '',fingerprint = '',generatedcontent = ''WHERE id " . $aaetidsql;$DB->execute($sql, $aaetidparams);}}}