%PDF- %PDF-
Direktori : /home2/vacivi36/ava/mod/data/classes/ |
Current File : //home2/vacivi36/ava/mod/data/classes/manager.php |
<?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 mod_data; use cm_info; use context_module; use completion_info; use data_field_base; use mod_data_renderer; use mod_data\event\course_module_viewed; use mod_data\event\template_viewed; use mod_data\event\template_updated; use moodle_page; use core_component; use stdClass; /** * Class manager for database activity * * @package mod_data * @copyright 2022 Ferran Recio <ferran@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class manager { /** Module name. */ const MODULE = 'data'; /** The plugin name. */ const PLUGINNAME = 'mod_data'; /** Template list with their files required to save the information of a preset. */ const TEMPLATES_LIST = [ 'listtemplate' => 'listtemplate.html', 'singletemplate' => 'singletemplate.html', 'asearchtemplate' => 'asearchtemplate.html', 'addtemplate' => 'addtemplate.html', 'rsstemplate' => 'rsstemplate.html', 'csstemplate' => 'csstemplate.css', 'jstemplate' => 'jstemplate.js', 'listtemplateheader' => 'listtemplateheader.html', 'listtemplatefooter' => 'listtemplatefooter.html', 'rsstitletemplate' => 'rsstitletemplate.html', ]; /** @var string plugin path. */ public $path; /** @var stdClass course_module record. */ private $instance; /** @var context_module the current context. */ private $context; /** @var cm_info course_modules record. */ private $cm; /** @var array the current data_fields records. * Do not access this attribute directly, use $this->get_field_records instead */ private $_fieldrecords = null; /** * Class constructor. * * @param cm_info $cm course module info object * @param stdClass $instance activity instance object. */ public function __construct(cm_info $cm, stdClass $instance) { global $CFG; $this->cm = $cm; $this->instance = $instance; $this->context = context_module::instance($cm->id); $this->instance->cmidnumber = $cm->idnumber; $this->path = $CFG->dirroot . '/mod/' . self::MODULE; } /** * Create a manager instance from an instance record. * * @param stdClass $instance an activity record * @return manager */ public static function create_from_instance(stdClass $instance): self { $cm = get_coursemodule_from_instance(self::MODULE, $instance->id); // Ensure that $this->cm is a cm_info object. $cm = cm_info::create($cm); return new self($cm, $instance); } /** * Create a manager instance from a course_modules record. * * @param stdClass|cm_info $cm an activity record * @return manager */ public static function create_from_coursemodule($cm): self { global $DB; // Ensure that $this->cm is a cm_info object. $cm = cm_info::create($cm); $instance = $DB->get_record(self::MODULE, ['id' => $cm->instance], '*', MUST_EXIST); return new self($cm, $instance); } /** * Create a manager instance from a data_record entry. * * @param stdClass $record the data_record record * @return manager */ public static function create_from_data_record($record): self { global $DB; $instance = $DB->get_record(self::MODULE, ['id' => $record->dataid], '*', MUST_EXIST); $cm = get_coursemodule_from_instance(self::MODULE, $instance->id); $cm = cm_info::create($cm); return new self($cm, $instance); } /** * Return the current context. * * @return context_module */ public function get_context(): context_module { return $this->context; } /** * Return the current instance. * * @return stdClass the instance record */ public function get_instance(): stdClass { return $this->instance; } /** * Return the current cm_info. * * @return cm_info the course module */ public function get_coursemodule(): cm_info { return $this->cm; } /** * Return the current module renderer. * * @param moodle_page|null $page the current page * @return mod_data_renderer the module renderer */ public function get_renderer(?moodle_page $page = null): mod_data_renderer { global $PAGE; $page = $page ?? $PAGE; return $page->get_renderer(self::PLUGINNAME); } /** * Trigger module viewed event and set the module viewed for completion. * * @param stdClass $course course object */ public function set_module_viewed(stdClass $course) { global $CFG; require_once($CFG->libdir . '/completionlib.php'); // Trigger module viewed event. $event = course_module_viewed::create([ 'objectid' => $this->instance->id, 'context' => $this->context, ]); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('course_modules', $this->cm); $event->add_record_snapshot(self::MODULE, $this->instance); $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($this->cm); } /** * Trigger module template viewed event. */ public function set_template_viewed() { // Trigger an event for viewing templates. $event = template_viewed::create([ 'context' => $this->context, 'courseid' => $this->cm->course, 'other' => [ 'dataid' => $this->instance->id, ], ]); $event->add_record_snapshot(self::MODULE, $this->instance); $event->trigger(); } /** * Return if the database has fields. * * @return bool true if the database has fields */ public function has_fields(): bool { global $DB; if ($this->_fieldrecords === null) { return $DB->record_exists('data_fields', ['dataid' => $this->instance->id]); } return !empty($this->_fieldrecords); } /** * Return the database fields. * * @return data_field_base[] the field instances. */ public function get_fields(): array { $result = []; $fieldrecords = $this->get_field_records(); foreach ($fieldrecords as $fieldrecord) { $result[$fieldrecord->id] = $this->get_field($fieldrecord); } return $result; } /** * Return the field records (the current data_fields records). * * @return stdClass[] an array of records */ public function get_field_records() { global $DB; if ($this->_fieldrecords === null) { $this->_fieldrecords = $DB->get_records('data_fields', ['dataid' => $this->instance->id], 'id'); } return $this->_fieldrecords; } /** * Return a specific field instance from a field record. * * @param stdClass $fieldrecord the fieldrecord to convert * @return data_field_base the data field class instance */ public function get_field(stdClass $fieldrecord): data_field_base { global $CFG; // Some old field plugins require $CFG to be in the scope. $filepath = "{$this->path}/field/{$fieldrecord->type}/field.class.php"; $classname = "data_field_{$fieldrecord->type}"; if (!file_exists($filepath)) { return new data_field_base($fieldrecord, $this->instance, $this->cm); } require_once($filepath); if (!class_exists($classname)) { return new data_field_base($fieldrecord, $this->instance, $this->cm); } $newfield = new $classname($fieldrecord, $this->instance, $this->cm); return $newfield; } /** * Return a specific template. * * NOTE: this method returns a default template if the module template is empty. * However, it won't update the template database field. * * Some possible options: * - search: string with the current searching text. * - page: integer repesenting the current pagination page numbre (if any) * - baseurl: a moodle_url object to the current page. * * @param string $templatename * @param array $options extra display options array * @return template the template instance */ public function get_template(string $templatename, array $options = []): template { if ($templatename === 'single') { $templatename = 'singletemplate'; } $instance = $this->instance; $templatecontent = $instance->{$templatename} ?? ''; if (empty($templatecontent)) { $templatecontent = data_generate_default_template($instance, $templatename, 0, false, false); } $options['templatename'] = $templatename; // Some templates have extra options. $options = array_merge($options, template::get_default_display_options($templatename)); return new template($this, $templatecontent, $options); } /** Check if the user can manage templates on the current context. * * @param int $userid the user id to check ($USER->id if null). * @return bool if the user can manage templates on current context. */ public function can_manage_templates(?int $userid = null): bool { global $USER; if (!$userid) { $userid = $USER->id; } return has_capability('mod/data:managetemplates', $this->context, $userid); } /** Check if the user can export entries on the current context. * * @param int $userid the user id to check ($USER->id if null). * @return bool if the user can export entries on current context. */ public function can_export_entries(?int $userid = null): bool { global $USER, $DB; if (!$userid) { $userid = $USER->id; } // Exportallentries and exportentry are basically the same capability. return has_capability('mod/data:exportallentries', $this->context) || has_capability('mod/data:exportentry', $this->context) || (has_capability('mod/data:exportownentry', $this->context) && $DB->record_exists('data_records', ['userid' => $userid, 'dataid' => $this->instance->id])); } /** * Update the database templates. * * @param stdClass $newtemplates an object with all the new templates * @return bool if updated successfully. */ public function update_templates(stdClass $newtemplates): bool { global $DB; $record = (object)[ 'id' => $this->instance->id, ]; foreach (self::TEMPLATES_LIST as $templatename => $templatefile) { if (!isset($newtemplates->{$templatename})) { continue; } $record->{$templatename} = $newtemplates->{$templatename}; } // The add entry form cannot repeat tags. if (isset($record->addtemplate) && !data_tags_check($this->instance->id, $record->addtemplate)) { return false; } $DB->update_record(self::MODULE, $record); $this->instance = $DB->get_record(self::MODULE, ['id' => $this->cm->instance], '*', MUST_EXIST); // Trigger an event for saving the templates. $event = template_updated::create(array( 'context' => $this->context, 'courseid' => $this->cm->course, 'other' => array( 'dataid' => $this->instance->id, ) )); $event->trigger(); return true; } /** * Reset all templates. * * @return bool if the reset is done or not */ public function reset_all_templates(): bool { $newtemplates = new stdClass(); foreach (self::TEMPLATES_LIST as $templatename => $templatefile) { $newtemplates->{$templatename} = ''; } return $this->update_templates($newtemplates); } /** * Reset all templates related to a specific template. * * @param string $templatename the template name * @return bool if the reset is done or not */ public function reset_template(string $templatename): bool { $newtemplates = new stdClass(); // Reset the template to default. $newtemplates->{$templatename} = ''; if ($templatename == 'listtemplate') { $newtemplates->listtemplateheader = ''; $newtemplates->listtemplatefooter = ''; } if ($templatename == 'rsstemplate') { $newtemplates->rsstitletemplate = ''; } return $this->update_templates($newtemplates); } /** Check if the user can view a specific preset. * * @param preset $preset the preset instance. * @param int $userid the user id to check ($USER->id if null). * @return bool if the user can view the preset. */ public function can_view_preset (preset $preset, ?int $userid = null): bool { global $USER; if (!$userid) { $userid = $USER->id; } $presetuserid = $preset->get_userid(); if ($presetuserid && $presetuserid != $userid) { return has_capability('mod/data:viewalluserpresets', $this->context, $userid); } return true; } /** * Returns an array of all the available presets. * * @return array A list with the datapreset plugins and the presets saved by users. */ public function get_available_presets(): array { // First load the datapreset plugins that exist within the modules preset dir. $pluginpresets = static::get_available_plugin_presets(); // Then find the presets that people have saved. $savedpresets = static::get_available_saved_presets(); return array_merge($pluginpresets, $savedpresets); } /** * Returns an array of all the presets that users have saved to the site. * * @return array A list with the preset saved by the users. */ public function get_available_saved_presets(): array { global $USER; $presets = []; $fs = get_file_storage(); $files = $fs->get_area_files(DATA_PRESET_CONTEXT, DATA_PRESET_COMPONENT, DATA_PRESET_FILEAREA); if (empty($files)) { return $presets; } $canviewall = has_capability('mod/data:viewalluserpresets', $this->get_context()); foreach ($files as $file) { $isnotdirectory = ($file->is_directory() && $file->get_filepath() == '/') || !$file->is_directory(); $userid = $file->get_userid(); $cannotviewfile = !$canviewall && $userid != $USER->id; if ($isnotdirectory || $cannotviewfile) { continue; } $preset = preset::create_from_storedfile($this, $file); $presets[] = $preset; } return $presets; } /** * Returns an array of all the available plugin presets. * * @return array A list with the datapreset plugins. */ public static function get_available_plugin_presets(): array { $presets = []; $dirs = core_component::get_plugin_list('datapreset'); foreach ($dirs as $dir => $fulldir) { if (preset::is_directory_a_preset($fulldir)) { $preset = preset::create_from_plugin(null, $dir); $presets[] = $preset; } } return $presets; } }