���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/lib.php.tar
���ѧ٧ѧ�
home3/cpr76684/public_html/Aem/lib/behat/lib.php 0000644 00000051600 15151264171 0015103 0 ustar 00 <?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/>. /** * Behat basic functions * * It does not include MOODLE_INTERNAL because is part of the bootstrap. * * This script should not be usually included, neither any of its functions * used, within mooodle code at all. It's for exclusive use of behat and * moodle setup.php. For places requiring a different/special behavior * needing to check if are being run as part of behat tests, use: * if (defined('BEHAT_SITE_RUNNING')) { ... * * @package core * @category test * @copyright 2012 David Monllaó * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__ . '/../testing/lib.php'); define('BEHAT_EXITCODE_CONFIG', 250); define('BEHAT_EXITCODE_REQUIREMENT', 251); define('BEHAT_EXITCODE_PERMISSIONS', 252); define('BEHAT_EXITCODE_REINSTALL', 253); define('BEHAT_EXITCODE_INSTALL', 254); define('BEHAT_EXITCODE_INSTALLED', 256); /** * The behat test site fullname and shortname. */ define('BEHAT_PARALLEL_SITE_NAME', "behatrun"); /** * Exits with an error code * * @param mixed $errorcode * @param string $text * @return void Stops execution with error code */ function behat_error($errorcode, $text = '') { // Adding error prefixes. switch ($errorcode) { case BEHAT_EXITCODE_CONFIG: $text = 'Behat config error: ' . $text; break; case BEHAT_EXITCODE_REQUIREMENT: $text = 'Behat requirement not satisfied: ' . $text; break; case BEHAT_EXITCODE_PERMISSIONS: $text = 'Behat permissions problem: ' . $text . ', check the permissions'; break; case BEHAT_EXITCODE_REINSTALL: $path = testing_cli_argument_path('/admin/tool/behat/cli/init.php'); $text = "Reinstall Behat: ".$text.", use:\n php ".$path; break; case BEHAT_EXITCODE_INSTALL: $path = testing_cli_argument_path('/admin/tool/behat/cli/init.php'); $text = "Install Behat before enabling it, use:\n php ".$path; break; case BEHAT_EXITCODE_INSTALLED: $text = "The Behat site is already installed"; break; default: $text = 'Unknown error ' . $errorcode . ' ' . $text; break; } testing_error($errorcode, $text); } /** * Return logical error string. * * @param int $errtype php error type. * @return string string which will be returned. */ function behat_get_error_string($errtype) { switch ($errtype) { case E_USER_ERROR: $errnostr = 'Fatal error'; break; case E_WARNING: case E_USER_WARNING: $errnostr = 'Warning'; break; case E_NOTICE: case E_USER_NOTICE: case E_STRICT: $errnostr = 'Notice'; break; case E_RECOVERABLE_ERROR: $errnostr = 'Catchable'; break; default: $errnostr = 'Unknown error type'; } return $errnostr; } /** * PHP errors handler to use when running behat tests. * * Adds specific CSS classes to identify * the messages. * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @return bool */ function behat_error_handler($errno, $errstr, $errfile, $errline) { // If is preceded by an @ we don't show it. if (!error_reporting()) { return true; } // This error handler receives E_ALL | E_STRICT, running the behat test site the debug level is // set to DEVELOPER and will always include E_NOTICE,E_USER_NOTICE... as part of E_ALL, if the current // error_reporting() value does not include one of those levels is because it has been forced through // the moodle code (see fix_utf8() for example) in that cases we respect the forced error level value. $respect = array(E_NOTICE, E_USER_NOTICE, E_STRICT, E_WARNING, E_USER_WARNING, E_DEPRECATED, E_USER_DEPRECATED); foreach ($respect as $respectable) { // If the current value does not include this kind of errors and the reported error is // at that level don't print anything. if ($errno == $respectable && !(error_reporting() & $respectable)) { return true; } } // Using the default one in case there is a fatal catchable error. default_error_handler($errno, $errstr, $errfile, $errline); $errnostr = behat_get_error_string($errno); // If ajax script then throw exception, so the calling api catch it and show it on web page. if (defined('AJAX_SCRIPT')) { throw new Exception("$errnostr: $errstr in $errfile on line $errline"); } else { // Wrapping the output. echo '<div class="phpdebugmessage" data-rel="phpdebugmessage">' . PHP_EOL; echo "$errnostr: $errstr in $errfile on line $errline" . PHP_EOL; echo '</div>'; } // Also use the internal error handler so we keep the usual behaviour. return false; } /** * Before shutdown save last error entries, so we can fail the test. */ function behat_shutdown_function() { // If any error found, then save it. if ($error = error_get_last()) { // Ignore E_WARNING, as they might come via ( @ )suppression and might lead to false failure. if (isset($error['type']) && !($error['type'] & E_WARNING)) { $errors = behat_get_shutdown_process_errors(); $errors[] = $error; $errorstosave = json_encode($errors); set_config('process_errors', $errorstosave, 'tool_behat'); } } } /** * Return php errors save which were save during shutdown. * * @return array */ function behat_get_shutdown_process_errors() { global $DB; // Don't use get_config, as it use cache and return invalid value, between selenium and cli process. $phperrors = $DB->get_field('config_plugins', 'value', array('name' => 'process_errors', 'plugin' => 'tool_behat')); if (!empty($phperrors)) { return json_decode($phperrors, true); } else { return array(); } } /** * Restrict the config.php settings allowed. * * When running the behat features the config.php * settings should not affect the results. * * @return void */ function behat_clean_init_config() { global $CFG; $allowed = array_flip(array( 'wwwroot', 'dataroot', 'dirroot', 'admin', 'directorypermissions', 'filepermissions', 'umaskpermissions', 'dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'prefix', 'dboptions', 'proxyhost', 'proxyport', 'proxytype', 'proxyuser', 'proxypassword', 'proxybypass', 'pathtogs', 'pathtophp', 'pathtodu', 'aspellpath', 'pathtodot', 'skiplangupgrade', 'altcacheconfigpath', 'pathtounoconv', 'alternative_file_system_class', 'pathtopython' )); // Add extra allowed settings. if (!empty($CFG->behat_extraallowedsettings)) { $allowed = array_merge($allowed, array_flip($CFG->behat_extraallowedsettings)); } // Also allowing behat_ prefixed attributes. foreach ($CFG as $key => $value) { if (!isset($allowed[$key]) && strpos($key, 'behat_') !== 0) { unset($CFG->{$key}); } } } /** * Checks that the behat config vars are properly set. * * @return void Stops execution with error code if something goes wrong. */ function behat_check_config_vars() { global $CFG; $moodleprefix = empty($CFG->prefix) ? '' : $CFG->prefix; $behatprefix = empty($CFG->behat_prefix) ? '' : $CFG->behat_prefix; $phpunitprefix = empty($CFG->phpunit_prefix) ? '' : $CFG->phpunit_prefix; $behatdbname = empty($CFG->behat_dbname) ? $CFG->dbname : $CFG->behat_dbname; $phpunitdbname = empty($CFG->phpunit_dbname) ? $CFG->dbname : $CFG->phpunit_dbname; $behatdbhost = empty($CFG->behat_dbhost) ? $CFG->dbhost : $CFG->behat_dbhost; $phpunitdbhost = empty($CFG->phpunit_dbhost) ? $CFG->dbhost : $CFG->phpunit_dbhost; // Verify prefix value. if (empty($CFG->behat_prefix)) { behat_error(BEHAT_EXITCODE_CONFIG, 'Define $CFG->behat_prefix in config.php'); } if ($behatprefix == $moodleprefix && $behatdbname == $CFG->dbname && $behatdbhost == $CFG->dbhost) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_prefix in config.php must be different from $CFG->prefix' . ' when $CFG->behat_dbname and $CFG->behat_host are not set or when $CFG->behat_dbname equals $CFG->dbname' . ' and $CFG->behat_dbhost equals $CFG->dbhost'); } if ($phpunitprefix !== '' && $behatprefix == $phpunitprefix && $behatdbname == $phpunitdbname && $behatdbhost == $phpunitdbhost) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_prefix in config.php must be different from $CFG->phpunit_prefix' . ' when $CFG->behat_dbname equals $CFG->phpunit_dbname' . ' and $CFG->behat_dbhost equals $CFG->phpunit_dbhost'); } // Verify behat wwwroot value. if (empty($CFG->behat_wwwroot)) { behat_error(BEHAT_EXITCODE_CONFIG, 'Define $CFG->behat_wwwroot in config.php'); } if (!empty($CFG->wwwroot) and $CFG->behat_wwwroot == $CFG->wwwroot) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_wwwroot in config.php must be different from $CFG->wwwroot'); } // Verify behat dataroot value. if (empty($CFG->behat_dataroot)) { behat_error(BEHAT_EXITCODE_CONFIG, 'Define $CFG->behat_dataroot in config.php'); } clearstatcache(); if (!file_exists($CFG->behat_dataroot_parent)) { $permissions = isset($CFG->directorypermissions) ? $CFG->directorypermissions : 02777; umask(0); if (!mkdir($CFG->behat_dataroot_parent, $permissions, true)) { behat_error(BEHAT_EXITCODE_PERMISSIONS, '$CFG->behat_dataroot directory can not be created'); } } $CFG->behat_dataroot_parent = realpath($CFG->behat_dataroot_parent); if (empty($CFG->behat_dataroot_parent) or !is_dir($CFG->behat_dataroot_parent) or !is_writable($CFG->behat_dataroot_parent)) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_dataroot in config.php must point to an existing writable directory'); } if (!empty($CFG->dataroot) and $CFG->behat_dataroot_parent == realpath($CFG->dataroot)) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_dataroot in config.php must be different from $CFG->dataroot'); } if (!empty($CFG->phpunit_dataroot) and $CFG->behat_dataroot_parent == realpath($CFG->phpunit_dataroot)) { behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_dataroot in config.php must be different from $CFG->phpunit_dataroot'); } // This request is coming from admin/tool/behat/cli/util.php which will call util_single.php. So just return from // here as we don't need to create a dataroot for single run. if (defined('BEHAT_PARALLEL_UTIL') && BEHAT_PARALLEL_UTIL && empty($CFG->behatrunprocess)) { return; } if (!file_exists($CFG->behat_dataroot)) { $permissions = isset($CFG->directorypermissions) ? $CFG->directorypermissions : 02777; umask(0); if (!mkdir($CFG->behat_dataroot, $permissions, true)) { behat_error(BEHAT_EXITCODE_PERMISSIONS, '$CFG->behat_dataroot directory can not be created'); } } $CFG->behat_dataroot = realpath($CFG->behat_dataroot); } /** * Should we switch to the test site data? * @return bool */ function behat_is_test_site() { global $CFG; if (defined('BEHAT_UTIL')) { // This is the admin tool that installs/drops the test site install. return true; } if (defined('BEHAT_TEST')) { // This is the main vendor/bin/behat script. return true; } if (empty($CFG->behat_wwwroot)) { return false; } if (isset($_SERVER['REMOTE_ADDR']) and behat_is_requested_url($CFG->behat_wwwroot)) { // Something is accessing the web server like a real browser. return true; } return false; } /** * Fix variables for parallel behat testing. * - behat_wwwroot = behat_wwwroot{behatrunprocess} * - behat_dataroot = behat_dataroot{behatrunprocess} * - behat_prefix = behat_prefix.{behatrunprocess}_ (For oracle it will be firstletter of prefix and behatrunprocess) **/ function behat_update_vars_for_process() { global $CFG; $allowedconfigoverride = array('dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'behat_prefix', 'behat_wwwroot', 'behat_dataroot'); $behatrunprocess = behat_get_run_process(); $CFG->behatrunprocess = $behatrunprocess; // Data directory will be a directory under parent directory. $CFG->behat_dataroot_parent = $CFG->behat_dataroot; $CFG->behat_dataroot .= '/'. BEHAT_PARALLEL_SITE_NAME; if ($behatrunprocess) { if (empty($CFG->behat_parallel_run[$behatrunprocess - 1]['behat_wwwroot'])) { // Set www root for run process. if (isset($CFG->behat_wwwroot) && !preg_match("#/" . BEHAT_PARALLEL_SITE_NAME . $behatrunprocess . "\$#", $CFG->behat_wwwroot)) { $CFG->behat_wwwroot .= "/" . BEHAT_PARALLEL_SITE_NAME . $behatrunprocess; } } if (empty($CFG->behat_parallel_run[$behatrunprocess - 1]['behat_dataroot'])) { // Set behat_dataroot. if (!preg_match("#" . $behatrunprocess . "\$#", $CFG->behat_dataroot)) { $CFG->behat_dataroot .= $behatrunprocess; } } // Set behat_prefix for db, just suffix run process number, to avoid max length exceed. // For oracle only 2 letter prefix is possible. // NOTE: This will not work for parallel process > 9. if ($CFG->dbtype === 'oci') { $CFG->behat_prefix = substr($CFG->behat_prefix, 0, 1); $CFG->behat_prefix .= "{$behatrunprocess}"; } else { $CFG->behat_prefix .= "{$behatrunprocess}_"; } if (!empty($CFG->behat_parallel_run[$behatrunprocess - 1])) { // Override allowed config vars. foreach ($allowedconfigoverride as $config) { if (isset($CFG->behat_parallel_run[$behatrunprocess - 1][$config])) { $CFG->$config = $CFG->behat_parallel_run[$behatrunprocess - 1][$config]; } } } } } /** * Checks if the URL requested by the user matches the provided argument * * @param string $url * @return bool Returns true if it matches. */ function behat_is_requested_url($url) { $parsedurl = parse_url($url . '/'); if (!isset($parsedurl['port'])) { $parsedurl['port'] = ($parsedurl['scheme'] === 'https') ? 443 : 80; } $parsedurl['path'] = rtrim($parsedurl['path'], '/'); // Removing the port. $pos = strpos($_SERVER['HTTP_HOST'], ':'); if ($pos !== false) { $requestedhost = substr($_SERVER['HTTP_HOST'], 0, $pos); } else { $requestedhost = $_SERVER['HTTP_HOST']; } // The path should also match. if (empty($parsedurl['path'])) { $matchespath = true; } else if (strpos($_SERVER['SCRIPT_NAME'], $parsedurl['path']) === 0) { $matchespath = true; } // The host and the port should match if ($parsedurl['host'] == $requestedhost && $parsedurl['port'] == $_SERVER['SERVER_PORT'] && !empty($matchespath)) { return true; } return false; } /** * Get behat run process from either $_SERVER or command config. * * @return bool|int false if single run, else run process number. */ function behat_get_run_process() { global $argv, $CFG; $behatrunprocess = false; // Get behat run process, if set. if (defined('BEHAT_CURRENT_RUN') && BEHAT_CURRENT_RUN) { $behatrunprocess = BEHAT_CURRENT_RUN; } else if (!empty($_SERVER['REMOTE_ADDR'])) { // Try get it from config if present. if (!empty($CFG->behat_parallel_run)) { foreach ($CFG->behat_parallel_run as $run => $behatconfig) { if (isset($behatconfig['behat_wwwroot']) && behat_is_requested_url($behatconfig['behat_wwwroot'])) { $behatrunprocess = $run + 1; // We start process from 1. break; } } } // Check if parallel site prefix is used. if (empty($behatrunprocess) && preg_match('#/' . BEHAT_PARALLEL_SITE_NAME . '(.+?)/#', $_SERVER['REQUEST_URI'])) { $dirrootrealpath = str_replace("\\", "/", realpath($CFG->dirroot)); $serverrealpath = str_replace("\\", "/", realpath($_SERVER['SCRIPT_FILENAME'])); $afterpath = str_replace($dirrootrealpath.'/', '', $serverrealpath); if (!$behatrunprocess = preg_filter("#.*/" . BEHAT_PARALLEL_SITE_NAME . "(.+?)/$afterpath#", '$1', $_SERVER['SCRIPT_FILENAME'])) { throw new Exception("Unable to determine behat process [afterpath=" . $afterpath . ", scriptfilename=" . $_SERVER['SCRIPT_FILENAME'] . "]!"); } } } else if (defined('BEHAT_TEST') || defined('BEHAT_UTIL')) { $behatconfig = ''; if ($match = preg_filter('#--run=(.+)#', '$1', $argv)) { // Try to guess the run from the existence of the --run arg. $behatrunprocess = reset($match); } else { // Try to guess the run from the existence of the --config arg. Note there are 2 alternatives below. if ($k = array_search('--config', $argv)) { // Alternative 1: --config /path/to/config.yml => (next arg, pick it). $behatconfig = str_replace("\\", "/", $argv[$k + 1]); } else if ($config = preg_filter('#^(?:--config[ =]*)(.+)$#', '$1', $argv)) { // Alternative 2: --config=/path/to/config.yml => (same arg, just get the path part). $behatconfig = str_replace("\\", "/", reset($config)); } // Try get it from config if present. if ($behatconfig) { if (!empty($CFG->behat_parallel_run)) { foreach ($CFG->behat_parallel_run as $run => $parallelconfig) { if (!empty($parallelconfig['behat_dataroot']) && $parallelconfig['behat_dataroot'] . '/behat/behat.yml' == $behatconfig) { $behatrunprocess = $run + 1; // We start process from 1. break; } } } // Check if default behat dataroot increment was done. if (empty($behatrunprocess)) { $behatdataroot = str_replace("\\", "/", $CFG->behat_dataroot . '/' . BEHAT_PARALLEL_SITE_NAME); $behatrunprocess = preg_filter("#^{$behatdataroot}" . "(.+?)[/|\\\]behat[/|\\\]behat\.yml#", '$1', $behatconfig); } } } } return $behatrunprocess; } /** * Execute commands in parallel. * * @param array $cmds list of commands to be executed. * @param string $cwd absolute path of working directory. * @param int $delay time in seconds to add delay between each parallel process. * @return array list of processes. */ function cli_execute_parallel($cmds, $cwd = null, $delay = 0) { require_once(__DIR__ . "/../../vendor/autoload.php"); $processes = array(); // Create child process. foreach ($cmds as $name => $cmd) { if (method_exists('\\Symfony\\Component\\Process\\Process', 'fromShellCommandline')) { // Process 4.2 and up. $process = Symfony\Component\Process\Process::fromShellCommandline($cmd); } else { // Process 4.1 and older. $process = new Symfony\Component\Process\Process(null); $process->setCommandLine($cmd); } $process->setWorkingDirectory($cwd); $process->setTimeout(null); $processes[$name] = $process; $processes[$name]->start(); // If error creating process then exit. if ($processes[$name]->getStatus() !== 'started') { echo "Error starting process: $name"; foreach ($processes[$name] as $process) { if ($process) { $process->signal(SIGKILL); } } exit(1); } // Sleep for specified delay. if ($delay) { sleep($delay); } } return $processes; } home3/cpr76684/public_html/Aem/admin/tool/moodlenet/lib.php 0000644 00000007564 15151264442 0017320 0 ustar 00 <?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/>. /** * This page lists public api for tool_moodlenet plugin. * * @package tool_moodlenet * @copyright 2020 Peter Dias * @license http://www.gnu.org/copyleft/gpl.html GNU */ defined('MOODLE_INTERNAL') || die; use \core_course\local\entity\activity_chooser_footer; /** * The default endpoint to MoodleNet. */ define('MOODLENET_DEFAULT_ENDPOINT', "lms/moodle/search"); /** * Generate the endpoint url to the user's moodlenet site. * * @param string $profileurl The user's moodlenet profile page * @param int $course The moodle course the mnet resource will be added to * @param int $section The section of the course will be added to. Defaults to the 0th element. * @return string the resulting endpoint * @throws moodle_exception */ function generate_mnet_endpoint(string $profileurl, int $course, int $section = 0) { global $CFG; $urlportions = explode('@', $profileurl); $domain = end($urlportions); $parsedurl = parse_url($domain); $params = [ 'site' => $CFG->wwwroot, 'course' => $course, 'section' => $section ]; $endpoint = new moodle_url(MOODLENET_DEFAULT_ENDPOINT, $params); return (isset($parsedurl['scheme']) ? $domain : "https://$domain")."/{$endpoint->out(false)}"; } /** * Hooking function to build up the initial Activity Chooser footer information for MoodleNet * * @param int $courseid The course the user is currently in and wants to add resources to * @param int $sectionid The section the user is currently in and wants to add resources to * @return activity_chooser_footer * @throws dml_exception * @throws moodle_exception */ function tool_moodlenet_custom_chooser_footer(int $courseid, int $sectionid): activity_chooser_footer { global $CFG, $USER, $OUTPUT; $defaultlink = get_config('tool_moodlenet', 'defaultmoodlenet'); $enabled = get_config('tool_moodlenet', 'enablemoodlenet'); $advanced = false; // We are in the MoodleNet lib. It is safe assume we have our own functions here. $mnetprofile = \tool_moodlenet\profile_manager::get_moodlenet_user_profile($USER->id); if ($mnetprofile !== null) { $advanced = $mnetprofile->get_domain() ?? false; } $defaultlink = generate_mnet_endpoint($defaultlink, $courseid, $sectionid); if ($advanced !== false) { $advanced = generate_mnet_endpoint($advanced, $courseid, $sectionid); } $renderedfooter = $OUTPUT->render_from_template('tool_moodlenet/chooser_footer', (object)[ 'enabled' => (bool)$enabled, 'generic' => $defaultlink, 'advanced' => $advanced, 'courseID' => $courseid, 'sectionID' => $sectionid, 'img' => $OUTPUT->image_url('MoodleNet', 'tool_moodlenet')->out(false), ]); $renderedcarousel = $OUTPUT->render_from_template('tool_moodlenet/chooser_moodlenet', (object)[ 'buttonName' => get_config('tool_moodlenet', 'defaultmoodlenetname'), 'generic' => $defaultlink, 'courseID' => $courseid, 'sectionID' => $sectionid, 'img' => $OUTPUT->image_url('MoodleNet', 'tool_moodlenet')->out(false), ]); return new activity_chooser_footer( 'tool_moodlenet/instance_form', $renderedfooter, $renderedcarousel ); } home3/cpr76684/public_html/Aem/plagiarism/lib.php 0000644 00000010101 15151264607 0015375 0 ustar 00 <?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/>. /** * lib.php - Contains Plagiarism base class used by plugins. * * @since Moodle 2.0 * @package core_plagiarism * @copyright 2010 Dan Marsden http://danmarsden.com * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page } /** * Plagiarism base class used by plugins. * * @since Moodle 2.0 * @package core_plagiarism * @copyright 2010 Dan Marsden http://danmarsden.com * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class plagiarism_plugin { /** * Return the list of form element names. * @deprecated Since Moodle 4.0 - this function was a placeholder and not used in core. * @todo MDL-71326 Remove this method. * @return array contains the form element names. */ public function get_configs() { return array(); } /** * hook to allow plagiarism specific information to be displayed beside a submission * @param array $linkarraycontains all relevant information for the plugin to generate a link * @return string */ public function get_links($linkarray) { return ''; } /** * hook to allow plagiarism specific information to be returned unformatted * @deprecated Since Moodle 4.0 - this function was a placeholder and not used in core Moodle code. * @todo MDL-71326 Remove this method. * @param int $cmid * @param int $userid * @param $file file object * @return array containing at least: * - 'analyzed' - whether the file has been successfully analyzed * - 'score' - similarity score - ('' if not known) * - 'reporturl' - url of originality report - '' if unavailable */ public function get_file_results($cmid, $userid, $file) { return array('analyzed' => '', 'score' => '', 'reporturl' => ''); } /** * hook to add plagiarism specific settings to a module settings page * @deprecated Since Moodle 3.9. MDL-65835 Please use {plugin name}_coursemodule_edit_post_actions() instead. * @todo MDL-67526 Remove this method. * @param object $mform - Moodle form * @param object $context - current context * @param string $modulename - Name of the module */ public function get_form_elements_module($mform, $context, $modulename = "") { } /** * hook to save plagiarism specific settings on a module settings page * @deprecated Since Moodle 3.9. MDL-65835 Please use {plugin name}_coursemodule_standard_elements() instead. * @todo MDL-67526 Remove this method. * @param object $data - data from an mform submission. */ public function save_form_elements($data) { } /** * hook to allow a disclosure to be printed notifying users what will happen with their submission * @param int $cmid - course module id * @return string */ public function print_disclosure($cmid) { } /** * hook to allow status of submitted files to be updated - called on grading/report pages. * @deprecated Since Moodle 4.0 - Please use {plugin name}_before_standard_top_of_body_html instead. * @todo MDL-71326 Remove this method. * @param object $course - full Course object * @param object $cm - full cm object */ public function update_status($course, $cm) { } } home3/cpr76684/public_html/Aem/lib/editor/textarea/lib.php 0000644 00000003133 15151264623 0017123 0 ustar 00 <?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/>. /** * Failsafe textarea editor support. * * @package editor * @subpackage textarea * @copyright 2009 Petr Skoda (http://skodak.org) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); class textarea_texteditor extends texteditor { public function supported_by_browser() { return true; } public function get_supported_formats() { return array(FORMAT_HTML => FORMAT_HTML, FORMAT_MOODLE => FORMAT_MOODLE, FORMAT_PLAIN => FORMAT_PLAIN, FORMAT_MARKDOWN => FORMAT_MARKDOWN, ); } public function get_preferred_format() { return FORMAT_MOODLE; } public function supports_repositories() { return true; } public function use_editor($elementid, array $options=null, $fpoptions=null) { return; } } home3/cpr76684/public_html/Aem/admin/tool/policy/lib.php 0000644 00000017116 15151264627 0016630 0 ustar 00 <?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/>. /** * Plugin version and other meta-data are defined here. * * @package tool_policy * @copyright 2018 David Mudrák <david@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); use core_user\output\myprofile\tree; use tool_policy\api; use tool_policy\policy_version; /** * Add nodes to myprofile page. * * @param tree $tree Tree object * @param stdClass $user User object * @param bool $iscurrentuser * @param stdClass $course Course object * @return bool * @throws coding_exception * @throws dml_exception * @throws moodle_exception */ function tool_policy_myprofile_navigation(tree $tree, $user, $iscurrentuser, $course) { global $CFG; // Do nothing if we are not set as the site policies handler. if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') { return; } // Get the Privacy and policies category. if (!array_key_exists('privacyandpolicies', $tree->__get('categories'))) { // Create the category. $categoryname = get_string('privacyandpolicies', 'admin'); $category = new core_user\output\myprofile\category('privacyandpolicies', $categoryname, 'contact'); $tree->add_category($category); } else { // Get the existing category. $category = $tree->__get('categories')['privacyandpolicies']; } // Add "Policies and agreements" node only for current user or users who can accept on behalf of current user. $usercontext = \context_user::instance($user->id); if ($iscurrentuser || has_capability('tool/policy:acceptbehalf', $usercontext)) { $url = new moodle_url('/admin/tool/policy/user.php', ['userid' => $user->id]); $node = new core_user\output\myprofile\node('privacyandpolicies', 'tool_policy', get_string('policiesagreements', 'tool_policy'), null, $url); $category->add_node($node); } return true; } /** * Load policy message for guests. * * @return string The HTML code to insert before the head. */ function tool_policy_before_standard_html_head() { global $CFG, $PAGE, $USER; $message = null; if (!empty($CFG->sitepolicyhandler) && $CFG->sitepolicyhandler == 'tool_policy' && empty($USER->policyagreed) && (isguestuser() || !isloggedin())) { $output = $PAGE->get_renderer('tool_policy'); try { $page = new \tool_policy\output\guestconsent(); $message = $output->render($page); } catch (dml_read_exception $e) { // During upgrades, the new plugin code with new SQL could be in place but the DB not upgraded yet. $message = null; } } return $message; } /** * Callback to add footer elements. * * @return string HTML footer content */ function tool_policy_standard_footer_html() { global $CFG, $PAGE; $output = ''; if (!empty($CFG->sitepolicyhandler) && $CFG->sitepolicyhandler == 'tool_policy') { $policies = api::get_current_versions_ids(); if (!empty($policies)) { $url = new moodle_url('/admin/tool/policy/viewall.php', ['returnurl' => $PAGE->url]); $output .= html_writer::link($url, get_string('userpolicysettings', 'tool_policy')); $output = html_writer::div($output, 'policiesfooter'); } } return $output; } /** * Hooks redirection to policy acceptance pages before sign up. */ function tool_policy_pre_signup_requests() { global $CFG; // Do nothing if we are not set as the site policies handler. if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') { return; } $policies = api::get_current_versions_ids(policy_version::AUDIENCE_LOGGEDIN); $userpolicyagreed = cache::make('core', 'presignup')->get('tool_policy_userpolicyagreed'); if (!empty($policies) && !$userpolicyagreed) { // Redirect to "Policy" pages for consenting before creating the user. cache::make('core', 'presignup')->set('tool_policy_issignup', 1); redirect(new \moodle_url('/admin/tool/policy/index.php')); } } /** * Serve the embedded files. * * @param stdClass $course the course object * @param stdClass $cm the course module object * @param stdClass $context the context * @param string $filearea the name of the file area * @param array $args extra arguments (itemid, path) * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if the file not found, just send the file otherwise and do not return anything */ function tool_policy_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG, $PAGE; // Do not allow access to files if we are not set as the site policy handler. if (empty($CFG->sitepolicyhandler) || $CFG->sitepolicyhandler !== 'tool_policy') { return false; } if ($context->contextlevel != CONTEXT_SYSTEM) { return false; } $PAGE->set_context($context); if ($filearea !== 'policydocumentsummary' && $filearea !== 'policydocumentcontent') { return false; } $itemid = array_shift($args); $policy = api::get_policy_version($itemid); if ($policy->status != policy_version::STATUS_ACTIVE) { require_login(); } if (!api::can_user_view_policy_version($policy)) { return false; } $filename = array_pop($args); if (!$args) { $filepath = '/'; } else { $filepath = '/'.implode('/', $args).'/'; } $fs = get_file_storage(); $file = $fs->get_file($context->id, 'tool_policy', $filearea, $itemid, $filepath, $filename); if (!$file) { return false; } send_stored_file($file, null, 0, $forcedownload, $options); } /** * Map icons for font-awesome themes. */ function tool_policy_get_fontawesome_icon_map() { return [ 'tool_policy:agreed' => 'fa-check text-success', 'tool_policy:declined' => 'fa-times text-danger', 'tool_policy:pending' => 'fa-clock-o text-warning', 'tool_policy:partial' => 'fa-exclamation-triangle text-warning', 'tool_policy:level' => 'fa-level-up fa-rotate-90 text-muted', ]; } /** * Serve the new group form as a fragment. * * @param array $args List of named arguments for the fragment loader. * @return string */ function tool_policy_output_fragment_accept_on_behalf($args) { $args = (object) $args; $data = []; if (!empty($args->jsonformdata)) { $serialiseddata = json_decode($args->jsonformdata); parse_str($serialiseddata, $data); } $mform = new \tool_policy\form\accept_policy(null, $data); if (!empty($args->jsonformdata)) { // If we were passed non-empty form data we want the mform to call validation functions and show errors. $mform->is_validated(); } return $mform->render(); } home3/cpr76684/public_html/Aem/mod/imscp/lib.php 0000644 00000043043 15151264627 0015154 0 ustar 00 <?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/>. /** * Mandatory public API of imscp module * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * List of features supported in IMS CP module * @param string $feature FEATURE_xx constant for requested feature * @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose. */ function imscp_supports($feature) { switch($feature) { case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE; case FEATURE_GROUPS: return false; case FEATURE_GROUPINGS: return false; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_GRADE_HAS_GRADE: return false; case FEATURE_GRADE_OUTCOMES: return false; case FEATURE_BACKUP_MOODLE2: return true; case FEATURE_SHOW_DESCRIPTION: return true; case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_CONTENT; default: return null; } } /** * This function is used by the reset_course_userdata function in moodlelib. * * @param stdClass $data the data submitted from the reset course. * @return array status array */ function imscp_reset_userdata($data) { // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. // See MDL-9367. return array(); } /** * List the actions that correspond to a view of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = 'r' and edulevel = LEVEL_PARTICIPATING will * be considered as view action. * * @return array */ function imscp_get_view_actions() { return array('view', 'view all'); } /** * List the actions that correspond to a post of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING * will be considered as post action. * * @return array */ function imscp_get_post_actions() { return array('update', 'add'); } /** * Add imscp instance. * @param object $data * @param object $mform * @return int new imscp instance id */ function imscp_add_instance($data, $mform) { global $CFG, $DB; require_once("$CFG->dirroot/mod/imscp/locallib.php"); $cmid = $data->coursemodule; $data->timemodified = time(); $data->revision = 1; $data->structure = null; $data->id = $DB->insert_record('imscp', $data); // We need to use context now, so we need to make sure all needed info is already in db. $DB->set_field('course_modules', 'instance', $data->id, array('id' => $cmid)); $context = context_module::instance($cmid); $imscp = $DB->get_record('imscp', array('id' => $data->id), '*', MUST_EXIST); if (!empty($data->package)) { // Save uploaded files to 'backup' filearea. $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_imscp', 'backup', 1); file_save_draft_area_files($data->package, $context->id, 'mod_imscp', 'backup', 1, array('subdirs' => 0, 'maxfiles' => 1)); // Get filename of zip that was uploaded. $files = $fs->get_area_files($context->id, 'mod_imscp', 'backup', 1, '', false); if ($files) { // Extract package content to 'content' filearea. $package = reset($files); $packer = get_file_packer('application/zip'); $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', 1, '/'); $structure = imscp_parse_structure($imscp, $context); $imscp->structure = is_array($structure) ? serialize($structure) : null; $DB->update_record('imscp', $imscp); } } $completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null; \core_completion\api::update_completion_date_event($cmid, 'imscp', $data->id, $completiontimeexpected); return $data->id; } /** * Update imscp instance. * @param object $data * @param object $mform * @return bool true */ function imscp_update_instance($data, $mform) { global $CFG, $DB; require_once("$CFG->dirroot/mod/imscp/locallib.php"); $cmid = $data->coursemodule; $data->timemodified = time(); $data->id = $data->instance; $data->structure = null; // Better reparse structure after each update. $DB->update_record('imscp', $data); $context = context_module::instance($cmid); $imscp = $DB->get_record('imscp', array('id' => $data->id), '*', MUST_EXIST); if (!empty($data->package) && ($draftareainfo = file_get_draft_area_info($data->package)) && $draftareainfo['filecount']) { $fs = get_file_storage(); $imscp->revision++; $DB->update_record('imscp', $imscp); // Get a list of existing packages before adding new package. if ($imscp->keepold > -1) { $packages = $fs->get_area_files($context->id, 'mod_imscp', 'backup', false, "itemid ASC", false); } else { $packages = array(); } file_save_draft_area_files($data->package, $context->id, 'mod_imscp', 'backup', $imscp->revision, array('subdirs' => 0, 'maxfiles' => 1)); $files = $fs->get_area_files($context->id, 'mod_imscp', 'backup', $imscp->revision, '', false); $package = reset($files); // Purge all extracted content. $fs->delete_area_files($context->id, 'mod_imscp', 'content'); // Extract package content. if ($package) { $packer = get_file_packer('application/zip'); $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', $imscp->revision, '/'); } // Cleanup old package files, keep current + keep old. while ($packages and (count($packages) > $imscp->keepold)) { $package = array_shift($packages); $fs->delete_area_files($context->id, 'mod_imscp', 'backup', $package->get_itemid()); } } $structure = imscp_parse_structure($imscp, $context); $imscp->structure = is_array($structure) ? serialize($structure) : null; $DB->update_record('imscp', $imscp); $completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null; \core_completion\api::update_completion_date_event($cmid, 'imscp', $imscp->id, $completiontimeexpected); return true; } /** * Delete imscp instance. * @param int $id * @return bool true */ function imscp_delete_instance($id) { global $DB; if (!$imscp = $DB->get_record('imscp', array('id' => $id))) { return false; } $cm = get_coursemodule_from_instance('imscp', $id); \core_completion\api::update_completion_date_event($cm->id, 'imscp', $id, null); // Note: all context files are deleted automatically. $DB->delete_records('imscp', array('id' => $imscp->id)); return true; } /** * Lists all browsable file areas * * @package mod_imscp * @category files * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @return array */ function imscp_get_file_areas($course, $cm, $context) { $areas = array(); $areas['content'] = get_string('areacontent', 'imscp'); $areas['backup'] = get_string('areabackup', 'imscp'); return $areas; } /** * File browsing support for imscp module ontent area. * * @package mod_imscp * @category files * @param stdClass $browser file browser * @param stdClass $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param int $itemid item ID * @param string $filepath file path * @param string $filename file name * @return file_info instance or null if not found */ function imscp_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { global $CFG, $DB; // Note: imscp_intro handled in file_browser automatically. if (!has_capability('moodle/course:managefiles', $context)) { // No peeking here for students! return null; } if ($filearea !== 'content' and $filearea !== 'backup') { return null; } require_once("$CFG->dirroot/mod/imscp/locallib.php"); if (is_null($itemid)) { return new imscp_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid); } $fs = get_file_storage(); $filepath = is_null($filepath) ? '/' : $filepath; $filename = is_null($filename) ? '.' : $filename; if (!$storedfile = $fs->get_file($context->id, 'mod_imscp', $filearea, $itemid, $filepath, $filename)) { return null; } // Do not allow manual modification of any files! $urlbase = $CFG->wwwroot.'/pluginfile.php'; return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemid, true, true, false, false); // No writing here! } /** * Serves the imscp files. * * @package mod_imscp * @category files * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if file not found, does not return if found - justsend the file */ function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG, $DB; if ($context->contextlevel != CONTEXT_MODULE) { return false; } require_login($course, true, $cm); if ($filearea === 'content') { if (!has_capability('mod/imscp:view', $context)) { return false; } $revision = array_shift($args); $fs = get_file_storage(); $relativepath = implode('/', $args); if ($relativepath === 'imsmanifest.xml') { if (!has_capability('moodle/course:managefiles', $context)) { // No stealing of detailed package info. return false; } } $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath"; if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } // Finally send the file. send_stored_file($file, null, 0, $forcedownload, $options); } else if ($filearea === 'backup') { if (!has_capability('moodle/course:managefiles', $context)) { // No stealing of package backups. return false; } $revision = array_shift($args); $fs = get_file_storage(); $relativepath = implode('/', $args); $fullpath = "/$context->id/mod_imscp/$filearea/$revision/$relativepath"; if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } // Finally send the file. send_stored_file($file, null, 0, $forcedownload, $options); } else { return false; } } /** * Return a list of page types * @param string $pagetype current page type * @param stdClass $parentcontext Block's parent context * @param stdClass $currentcontext Current context of block * @return array $modulepagetype list */ function imscp_page_type_list($pagetype, $parentcontext, $currentcontext) { $modulepagetype = array('mod-imscp-*' => get_string('page-mod-imscp-x', 'imscp')); return $modulepagetype; } /** * Export imscp resource contents * * @param stdClass $cm Course module object * @param string $baseurl Base URL for file downloads * @return array of file content */ function imscp_export_contents($cm, $baseurl) { global $DB; $contents = array(); $context = context_module::instance($cm->id); $imscp = $DB->get_record('imscp', array('id' => $cm->instance), '*', MUST_EXIST); // We export the IMSCP structure as json encoded string. $structure = array(); $structure['type'] = 'content'; $structure['filename'] = 'structure'; $structure['filepath'] = '/'; $structure['filesize'] = 0; $structure['fileurl'] = null; $structure['timecreated'] = $imscp->timemodified; $structure['timemodified'] = $imscp->timemodified; $structure['content'] = json_encode(unserialize($imscp->structure)); $structure['sortorder'] = 0; $structure['userid'] = null; $structure['author'] = null; $structure['license'] = null; $contents[] = $structure; // Area files. $fs = get_file_storage(); $files = $fs->get_area_files($context->id, 'mod_imscp', 'content', $imscp->revision, 'id ASC', false); foreach ($files as $fileinfo) { $file = array(); $file['type'] = 'file'; $file['filename'] = $fileinfo->get_filename(); $file['filepath'] = $fileinfo->get_filepath(); $file['filesize'] = $fileinfo->get_filesize(); $file['fileurl'] = moodle_url::make_webservice_pluginfile_url( $context->id, 'mod_imscp', 'content', $imscp->revision, $fileinfo->get_filepath(), $fileinfo->get_filename())->out(false); $file['timecreated'] = $fileinfo->get_timecreated(); $file['timemodified'] = $fileinfo->get_timemodified(); $file['sortorder'] = $fileinfo->get_sortorder(); $file['userid'] = $fileinfo->get_userid(); $file['author'] = $fileinfo->get_author(); $file['license'] = $fileinfo->get_license(); $file['mimetype'] = $fileinfo->get_mimetype(); $file['isexternalfile'] = $fileinfo->is_external_file(); if ($file['isexternalfile']) { $file['repositorytype'] = $fileinfo->get_repository_type(); } $contents[] = $file; } return $contents; } /** * Mark the activity completed (if required) and trigger the course_module_viewed event. * * @param stdClass $imscp imscp object * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @since Moodle 3.0 */ function imscp_view($imscp, $course, $cm, $context) { // Trigger course_module_viewed event. $params = array( 'context' => $context, 'objectid' => $imscp->id ); $event = \mod_imscp\event\course_module_viewed::create($params); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('imscp', $imscp); $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($cm); } /** * Check if the module has any update that affects the current user since a given time. * * @param cm_info $cm course module data * @param int $from the time to check updates from * @param array $filter if we need to check only specific updates * @return stdClass an object with the different type of areas indicating if they were updated or not * @since Moodle 3.2 */ function imscp_check_updates_since(cm_info $cm, $from, $filter = array()) { $updates = course_check_module_updates_since($cm, $from, array('content'), $filter); return $updates; } /** * This function receives a calendar event and returns the action associated with it, or null if there is none. * * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event * is not displayed on the block. * * @param calendar_event $event * @param \core_calendar\action_factory $factory * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). * @return \core_calendar\local\event\entities\action_interface|null */ function mod_imscp_core_calendar_provide_event_action(calendar_event $event, \core_calendar\action_factory $factory, int $userid = 0) { $cm = get_fast_modinfo($event->courseid, $userid)->instances['imscp'][$event->instance]; if (!$cm->uservisible) { // The module is not visible to the user for any reason. return null; } $completion = new \completion_info($cm->get_course()); $completiondata = $completion->get_data($cm, false, $userid); if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { return null; } return $factory->create_instance( get_string('view'), new \moodle_url('/mod/imscp/view.php', ['id' => $cm->id]), 1, true ); } home3/cpr76684/public_html/Aem/mod/wiki/lib.php 0000644 00000071533 15151772524 0015011 0 ustar 00 <?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/>. /** * Library of functions and constants for module wiki * * It contains the great majority of functions defined by Moodle * that are mandatory to develop a module. * * @package mod_wiki * @copyright 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu * * @author Jordi Piguillem * @author Marc Alier * @author David Jimenez * @author Josep Arus * @author Kenneth Riba * * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Given an object containing all the necessary data, * (defined by the form in mod.html) this function * will create a new instance and return the id number * of the new instance. * * @param object $instance An object from the form in mod.html * @return int The id of the newly inserted wiki record **/ function wiki_add_instance($wiki) { global $DB; $wiki->timemodified = time(); # May have to add extra stuff in here # if (empty($wiki->forceformat)) { $wiki->forceformat = 0; } $id = $DB->insert_record('wiki', $wiki); $completiontimeexpected = !empty($wiki->completionexpected) ? $wiki->completionexpected : null; \core_completion\api::update_completion_date_event($wiki->coursemodule, 'wiki', $id, $completiontimeexpected); return $id; } /** * Given an object containing all the necessary data, * (defined by the form in mod.html) this function * will update an existing instance with new data. * * @param object $instance An object from the form in mod.html * @return boolean Success/Fail **/ function wiki_update_instance($wiki) { global $DB; $wiki->timemodified = time(); $wiki->id = $wiki->instance; if (empty($wiki->forceformat)) { $wiki->forceformat = 0; } $completiontimeexpected = !empty($wiki->completionexpected) ? $wiki->completionexpected : null; \core_completion\api::update_completion_date_event($wiki->coursemodule, 'wiki', $wiki->id, $completiontimeexpected); # May have to add extra stuff in here # return $DB->update_record('wiki', $wiki); } /** * Given an ID of an instance of this module, * this function will permanently delete the instance * and any data that depends on it. * * @param int $id Id of the module instance * @return boolean Success/Failure **/ function wiki_delete_instance($id) { global $DB; if (!$wiki = $DB->get_record('wiki', array('id' => $id))) { return false; } $result = true; # Get subwiki information # $subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id)); foreach ($subwikis as $subwiki) { # Get existing links, and delete them # if (!$DB->delete_records('wiki_links', array('subwikiid' => $subwiki->id), IGNORE_MISSING)) { $result = false; } # Get existing pages # if ($pages = $DB->get_records('wiki_pages', array('subwikiid' => $subwiki->id))) { foreach ($pages as $page) { # Get locks, and delete them # if (!$DB->delete_records('wiki_locks', array('pageid' => $page->id), IGNORE_MISSING)) { $result = false; } # Get versions, and delete them # if (!$DB->delete_records('wiki_versions', array('pageid' => $page->id), IGNORE_MISSING)) { $result = false; } } # Delete pages # if (!$DB->delete_records('wiki_pages', array('subwikiid' => $subwiki->id), IGNORE_MISSING)) { $result = false; } } # Get existing synonyms, and delete them # if (!$DB->delete_records('wiki_synonyms', array('subwikiid' => $subwiki->id), IGNORE_MISSING)) { $result = false; } # Delete any subwikis # if (!$DB->delete_records('wiki_subwikis', array('id' => $subwiki->id), IGNORE_MISSING)) { $result = false; } } $cm = get_coursemodule_from_instance('wiki', $id); \core_completion\api::update_completion_date_event($cm->id, 'wiki', $wiki->id, null); # Delete any dependent records here # if (!$DB->delete_records('wiki', array('id' => $wiki->id))) { $result = false; } return $result; } /** * Implements callback to reset course * * @param stdClass $data * @return boolean|array */ function wiki_reset_userdata($data) { global $CFG,$DB; require_once($CFG->dirroot . '/mod/wiki/pagelib.php'); require_once($CFG->dirroot . "/mod/wiki/locallib.php"); $componentstr = get_string('modulenameplural', 'wiki'); $status = array(); //get the wiki(s) in this course. if (!$wikis = $DB->get_records('wiki', array('course' => $data->courseid))) { return false; } if (empty($data->reset_wiki_comments) && empty($data->reset_wiki_tags) && empty($data->reset_wiki_pages)) { return $status; } foreach ($wikis as $wiki) { if (!$cm = get_coursemodule_from_instance('wiki', $wiki->id, $data->courseid)) { continue; } $context = context_module::instance($cm->id); // Remove tags or all pages. if (!empty($data->reset_wiki_pages) || !empty($data->reset_wiki_tags)) { // Get subwiki information. $subwikis = wiki_get_subwikis($wiki->id); foreach ($subwikis as $subwiki) { // Get existing pages. if ($pages = wiki_get_page_list($subwiki->id)) { // If the wiki page isn't selected then we are only removing tags. if (empty($data->reset_wiki_pages)) { // Go through each page and delete the tags. foreach ($pages as $page) { core_tag_tag::remove_all_item_tags('mod_wiki', 'wiki_pages', $page->id); } } else { // Otherwise we are removing pages and tags. wiki_delete_pages($context, $pages, $subwiki->id); } } if (!empty($data->reset_wiki_pages)) { // Delete any subwikis. $DB->delete_records('wiki_subwikis', array('id' => $subwiki->id), IGNORE_MISSING); // Delete any attached files. $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_wiki', 'attachments'); } } if (!empty($data->reset_wiki_pages)) { $status[] = array('component' => $componentstr, 'item' => get_string('deleteallpages', 'wiki'), 'error' => false); } if (!empty($data->reset_wiki_tags)) { $status[] = array('component' => $componentstr, 'item' => get_string('tagsdeleted', 'wiki'), 'error' => false); } } // Remove all comments. if (!empty($data->reset_wiki_comments) || !empty($data->reset_wiki_pages)) { $DB->delete_records_select('comments', "contextid = ? AND commentarea='wiki_page'", array($context->id)); if (!empty($data->reset_wiki_comments)) { $status[] = array('component' => $componentstr, 'item' => get_string('deleteallcomments'), 'error' => false); } } } // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. // See MDL-9367. shift_course_mod_dates('wiki', array('editbegin', 'editend'), $data->timeshift, $data->courseid); $status[] = array('component' => $componentstr, 'item' => get_string('datechanged'), 'error' => false); return $status; } function wiki_reset_course_form_definition(&$mform) { $mform->addElement('header', 'wikiheader', get_string('modulenameplural', 'wiki')); $mform->addElement('advcheckbox', 'reset_wiki_pages', get_string('deleteallpages', 'wiki')); $mform->addElement('advcheckbox', 'reset_wiki_tags', get_string('removeallwikitags', 'wiki')); $mform->addElement('advcheckbox', 'reset_wiki_comments', get_string('deleteallcomments')); } /** * Indicates API features that the wiki supports. * * @uses FEATURE_GROUPS * @uses FEATURE_GROUPINGS * @uses FEATURE_MOD_INTRO * @uses FEATURE_COMPLETION_TRACKS_VIEWS * @uses FEATURE_COMPLETION_HAS_RULES * @uses FEATURE_GRADE_HAS_GRADE * @uses FEATURE_GRADE_OUTCOMES * @param string $feature * @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose. */ function wiki_supports($feature) { switch ($feature) { case FEATURE_GROUPS: return true; case FEATURE_GROUPINGS: return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_GRADE_HAS_GRADE: return false; case FEATURE_GRADE_OUTCOMES: return false; case FEATURE_RATE: return false; case FEATURE_BACKUP_MOODLE2: return true; case FEATURE_SHOW_DESCRIPTION: return true; case FEATURE_COMMENT: return true; case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_COLLABORATION; default: return null; } } /** * Given a course and a time, this module should find recent activity * that has occurred in wiki activities and print it out. * Return true if there was output, or false is there was none. * * @global $CFG * @global $DB * @uses CONTEXT_MODULE * @uses VISIBLEGROUPS * @param object $course * @param bool $viewfullnames capability * @param int $timestart * @return boolean **/ function wiki_print_recent_activity($course, $viewfullnames, $timestart) { global $CFG, $DB, $OUTPUT; $sql = "SELECT p.id, p.timemodified, p.subwikiid, sw.wikiid, w.wikimode, sw.userid, sw.groupid FROM {wiki_pages} p JOIN {wiki_subwikis} sw ON sw.id = p.subwikiid JOIN {wiki} w ON w.id = sw.wikiid WHERE p.timemodified > ? AND w.course = ? ORDER BY p.timemodified ASC"; if (!$pages = $DB->get_records_sql($sql, array($timestart, $course->id))) { return false; } require_once($CFG->dirroot . "/mod/wiki/locallib.php"); $wikis = array(); $modinfo = get_fast_modinfo($course); $subwikivisible = array(); foreach ($pages as $page) { if (!isset($subwikivisible[$page->subwikiid])) { $subwiki = (object)array('id' => $page->subwikiid, 'wikiid' => $page->wikiid, 'groupid' => $page->groupid, 'userid' => $page->userid); $wiki = (object)array('id' => $page->wikiid, 'course' => $course->id, 'wikimode' => $page->wikimode); $subwikivisible[$page->subwikiid] = wiki_user_can_view($subwiki, $wiki); } if ($subwikivisible[$page->subwikiid]) { $wikis[] = $page; } } unset($subwikivisible); unset($pages); if (!$wikis) { return false; } echo $OUTPUT->heading(get_string("updatedwikipages", 'wiki') . ':', 6); foreach ($wikis as $wiki) { $cm = $modinfo->instances['wiki'][$wiki->wikiid]; $link = $CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $wiki->id; print_recent_activity_note($wiki->timemodified, $wiki, $cm->name, $link, false, $viewfullnames); } return true; // True if anything was printed, otherwise false } /** * Must return an array of grades for a given instance of this module, * indexed by user. It also returns a maximum allowed grade. * * Example: * $return->grades = array of grades; * $return->maxgrade = maximum allowed grade; * * return $return; * * @param int $wikiid ID of an instance of this module * @return mixed Null or object with an array of grades and with the maximum grade **/ function wiki_grades($wikiid) { return null; } /** * @deprecated since Moodle 3.8 */ function wiki_scale_used() { throw new coding_exception('wiki_scale_used() can not be used anymore. Plugins can implement ' . '<modname>_scale_used_anywhere, all implementations of <modname>_scale_used are now ignored'); } /** * Checks if scale is being used by any instance of wiki. * This function was added in 1.9 * * This is used to find out if scale used anywhere * @param $scaleid int * @return boolean True if the scale is used by any wiki */ function wiki_scale_used_anywhere($scaleid) { global $DB; //if ($scaleid and $DB->record_exists('wiki', array('grade' => -$scaleid))) { // return true; //} else { // return false; //} return false; } /** * file serving callback * * @copyright Josep Arus * @package mod_wiki * @category files * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if the file was not found, just send the file otherwise and do not return anything */ function wiki_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG; if ($context->contextlevel != CONTEXT_MODULE) { return false; } require_login($course, true, $cm); require_once($CFG->dirroot . "/mod/wiki/locallib.php"); if ($filearea == 'attachments') { $swid = (int) array_shift($args); if (!$subwiki = wiki_get_subwiki($swid)) { return false; } require_capability('mod/wiki:viewpage', $context); $relativepath = implode('/', $args); $fullpath = "/$context->id/mod_wiki/attachments/$swid/$relativepath"; $fs = get_file_storage(); if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } send_stored_file($file, null, 0, $options); } } /** * Search for wiki * * @param stdClass $cm course module object * @param string $search searchword. * @param stdClass $subwiki Optional Subwiki. * @return Search wiki input form */ function wiki_search_form($cm, $search = '', $subwiki = null) { global $OUTPUT; $hiddenfields = [ (object) ['type' => 'hidden', 'name' => 'courseid', 'value' => $cm->course], (object) ['type' => 'hidden', 'name' => 'cmid', 'value' => $cm->id], (object) ['type' => 'hidden', 'name' => 'searchwikicontent', 'value' => 1], ]; if (!empty($subwiki->id)) { $hiddenfields[] = (object) ['type' => 'hidden', 'name' => 'subwikiid', 'value' => $subwiki->id]; } $data = [ 'action' => new moodle_url('/mod/wiki/search.php'), 'hiddenfields' => $hiddenfields, 'inputname' => 'searchstring', 'query' => s($search, true), 'searchstring' => get_string('searchwikis', 'wiki'), 'extraclasses' => 'mt-2' ]; return $OUTPUT->render_from_template('core/search_input', $data); } /** * Extends the global navigation tree by adding wiki nodes if there is a relevant content * * This can be called by an AJAX request so do not rely on $PAGE as it might not be set up properly. * * @param navigation_node $navref An object representing the navigation tree node of the workshop module instance * @param stdClass $course the course object * @param stdClass $instance the activity record object * @param cm_info $cm the course module object */ function wiki_extend_navigation(navigation_node $navref, stdClass $course, stdClass $instance, cm_info $cm) { global $CFG, $USER; require_once($CFG->dirroot . '/mod/wiki/locallib.php'); $context = context_module::instance($cm->id); $userid = ($instance->wikimode == 'individual') ? $USER->id : 0; $gid = groups_get_activity_group($cm) ?: 0; if (!$subwiki = wiki_get_subwiki_by_group($cm->instance, $gid, $userid)) { return; } $pageid = optional_param('pageid', null, PARAM_INT); if (empty($pageid)) { // wiki main page $page = wiki_get_page_by_title($subwiki->id, $instance->firstpagetitle); $pageid = $page->id; } if (wiki_can_create_pages($context)) { $link = new moodle_url('/mod/wiki/create.php', ['action' => 'new', 'swid' => $subwiki->id]); $navref->add(get_string('newpage', 'wiki'), $link, navigation_node::TYPE_SETTING); } if (empty($pageid)) { return; } $canviewpage = has_capability('mod/wiki:viewpage', $context); if ($canviewpage) { $link = new moodle_url('/mod/wiki/view.php', ['pageid' => $pageid]); $navref->add(get_string('view', 'wiki'), $link, navigation_node::TYPE_SETTING); } if (wiki_user_can_edit($subwiki)) { $link = new moodle_url('/mod/wiki/edit.php', ['pageid' => $pageid]); $navref->add(get_string('edit', 'wiki'), $link, navigation_node::TYPE_SETTING); } if (has_capability('mod/wiki:viewcomment', $context)) { $link = new moodle_url('/mod/wiki/comments.php', ['pageid' => $pageid]); $navref->add(get_string('comments', 'wiki'), $link, navigation_node::TYPE_SETTING); } if ($canviewpage) { $link = new moodle_url('/mod/wiki/history.php', ['pageid' => $pageid]); $navref->add(get_string('history', 'wiki'), $link, navigation_node::TYPE_SETTING); $link = new moodle_url('/mod/wiki/map.php', ['pageid' => $pageid]); $navref->add(get_string('map', 'wiki'), $link, navigation_node::TYPE_SETTING); $link = new moodle_url('/mod/wiki/files.php', ['pageid' => $pageid]); $navref->add(get_string('files', 'wiki'), $link, navigation_node::TYPE_SETTING); } if (has_capability('mod/wiki:managewiki', $context)) { $link = new moodle_url('/mod/wiki/admin.php', ['pageid' => $pageid]); $navref->add(get_string('admin', 'wiki'), $link, navigation_node::TYPE_SETTING); } } /** * Returns all other caps used in wiki module * * @return array */ function wiki_get_extra_capabilities() { return array('moodle/comment:view', 'moodle/comment:post', 'moodle/comment:delete'); } /** * Running addtional permission check on plugin, for example, plugins * may have switch to turn on/off comments option, this callback will * affect UI display, not like pluginname_comment_validate only throw * exceptions. * Capability check has been done in comment->check_permissions(), we * don't need to do it again here. * * @package mod_wiki * @category comment * * @param stdClass $comment_param { * context => context the context object * courseid => int course id * cm => stdClass course module object * commentarea => string comment area * itemid => int itemid * } * @return array */ function wiki_comment_permissions($comment_param) { return array('post'=>true, 'view'=>true); } /** * Validate comment parameter before perform other comments actions * * @param stdClass $comment_param { * context => context the context object * courseid => int course id * cm => stdClass course module object * commentarea => string comment area * itemid => int itemid * } * * @package mod_wiki * @category comment * * @return boolean */ function wiki_comment_validate($comment_param) { global $DB, $CFG; require_once($CFG->dirroot . '/mod/wiki/locallib.php'); // validate comment area if ($comment_param->commentarea != 'wiki_page') { throw new comment_exception('invalidcommentarea'); } // validate itemid if (!$record = $DB->get_record('wiki_pages', array('id'=>$comment_param->itemid))) { throw new comment_exception('invalidcommentitemid'); } if (!$subwiki = wiki_get_subwiki($record->subwikiid)) { throw new comment_exception('invalidsubwikiid'); } if (!$wiki = wiki_get_wiki_from_pageid($comment_param->itemid)) { throw new comment_exception('invalidid', 'data'); } if (!$course = $DB->get_record('course', array('id'=>$wiki->course))) { throw new comment_exception('coursemisconf'); } if (!$cm = get_coursemodule_from_instance('wiki', $wiki->id, $course->id)) { throw new comment_exception('invalidcoursemodule'); } $context = context_module::instance($cm->id); // group access if ($subwiki->groupid) { $groupmode = groups_get_activity_groupmode($cm, $course); if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { if (!groups_is_member($subwiki->groupid)) { throw new comment_exception('notmemberofgroup'); } } } // validate context id if ($context->id != $comment_param->context->id) { throw new comment_exception('invalidcontext'); } // validation for comment deletion if (!empty($comment_param->commentid)) { if ($comment = $DB->get_record('comments', array('id'=>$comment_param->commentid))) { if ($comment->commentarea != 'wiki_page') { throw new comment_exception('invalidcommentarea'); } if ($comment->contextid != $context->id) { throw new comment_exception('invalidcontext'); } if ($comment->itemid != $comment_param->itemid) { throw new comment_exception('invalidcommentitemid'); } } else { throw new comment_exception('invalidcommentid'); } } return true; } /** * Return a list of page types * @param string $pagetype current page type * @param stdClass $parentcontext Block's parent context * @param stdClass $currentcontext Current context of block */ function wiki_page_type_list($pagetype, $parentcontext, $currentcontext) { $module_pagetype = array( 'mod-wiki-*'=>get_string('page-mod-wiki-x', 'wiki'), 'mod-wiki-view'=>get_string('page-mod-wiki-view', 'wiki'), 'mod-wiki-comments'=>get_string('page-mod-wiki-comments', 'wiki'), 'mod-wiki-history'=>get_string('page-mod-wiki-history', 'wiki'), 'mod-wiki-map'=>get_string('page-mod-wiki-map', 'wiki') ); return $module_pagetype; } /** * Mark the activity completed (if required) and trigger the course_module_viewed event. * * @param stdClass $wiki Wiki object. * @param stdClass $course Course object. * @param stdClass $cm Course module object. * @param stdClass $context Context object. * @since Moodle 3.1 */ function wiki_view($wiki, $course, $cm, $context) { // Trigger course_module_viewed event. $params = array( 'context' => $context, 'objectid' => $wiki->id ); $event = \mod_wiki\event\course_module_viewed::create($params); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('wiki', $wiki); $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($cm); } /** * Mark the activity completed (if required) and trigger the page_viewed event. * * @param stdClass $wiki Wiki object. * @param stdClass $page Page object. * @param stdClass $course Course object. * @param stdClass $cm Course module object. * @param stdClass $context Context object. * @param int $uid Optional User ID. * @param array $other Optional Other params: title, wiki ID, group ID, groupanduser, prettyview. * @param stdClass $subwiki Optional Subwiki. * @since Moodle 3.1 */ function wiki_page_view($wiki, $page, $course, $cm, $context, $uid = null, $other = null, $subwiki = null) { // Trigger course_module_viewed event. $params = array( 'context' => $context, 'objectid' => $page->id ); if ($uid != null) { $params['relateduserid'] = $uid; } if ($other != null) { $params['other'] = $other; } $event = \mod_wiki\event\page_viewed::create($params); $event->add_record_snapshot('wiki_pages', $page); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('wiki', $wiki); if ($subwiki != null) { $event->add_record_snapshot('wiki_subwikis', $subwiki); } $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($cm); } /** * Check if the module has any update that affects the current user since a given time. * * @param cm_info $cm course module data * @param int $from the time to check updates from * @param array $filter if we need to check only specific updates * @return stdClass an object with the different type of areas indicating if they were updated or not * @since Moodle 3.2 */ function wiki_check_updates_since(cm_info $cm, $from, $filter = array()) { global $DB, $CFG; require_once($CFG->dirroot . '/mod/wiki/locallib.php'); $updates = new stdClass(); if (!has_capability('mod/wiki:viewpage', $cm->context)) { return $updates; } $updates = course_check_module_updates_since($cm, $from, array('attachments'), $filter); // Check only pages updated in subwikis the user can access. $updates->pages = (object) array('updated' => false); $wiki = $DB->get_record($cm->modname, array('id' => $cm->instance), '*', MUST_EXIST); if ($subwikis = wiki_get_visible_subwikis($wiki, $cm, $cm->context)) { $subwikisids = array(); foreach ($subwikis as $subwiki) { $subwikisids[] = $subwiki->id; } list($subwikissql, $params) = $DB->get_in_or_equal($subwikisids, SQL_PARAMS_NAMED); $select = 'subwikiid ' . $subwikissql . ' AND (timemodified > :since1 OR timecreated > :since2)'; $params['since1'] = $from; $params['since2'] = $from; $pages = $DB->get_records_select('wiki_pages', $select, $params, '', 'id'); if (!empty($pages)) { $updates->pages->updated = true; $updates->pages->itemids = array_keys($pages); } } return $updates; } /** * Get icon mapping for font-awesome. */ function mod_wiki_get_fontawesome_icon_map() { return [ 'mod_wiki:attachment' => 'fa-paperclip', ]; } /** * This function receives a calendar event and returns the action associated with it, or null if there is none. * * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event * is not displayed on the block. * * @param calendar_event $event * @param \core_calendar\action_factory $factory * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). * @return \core_calendar\local\event\entities\action_interface|null */ function mod_wiki_core_calendar_provide_event_action(calendar_event $event, \core_calendar\action_factory $factory, int $userid = 0) { global $USER; if (!$userid) { $userid = $USER->id; } $cm = get_fast_modinfo($event->courseid, $userid)->instances['wiki'][$event->instance]; if (!$cm->uservisible) { // The module is not visible to the user for any reason. return null; } $completion = new \completion_info($cm->get_course()); $completiondata = $completion->get_data($cm, false, $userid); if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { return null; } return $factory->create_instance( get_string('view'), new \moodle_url('/mod/wiki/view.php', ['id' => $cm->id]), 1, true ); } /** * Sets dynamic information about a course module * * This callback is called from cm_info when checking module availability (incl. $cm->uservisible) * * Main viewing capability in mod_wiki is 'mod/wiki:viewpage' instead of the expected standardised 'mod/wiki:view'. * The method cm_info::is_user_access_restricted_by_capability() does not work for wiki, we need to implement * this callback. * * @param cm_info $cm */ function wiki_cm_info_dynamic(cm_info $cm) { if (!has_capability('mod/wiki:viewpage', $cm->context, $cm->get_modinfo()->get_user_id())) { $cm->set_available(false); } } home3/cpr76684/public_html/Aem/enrol/manual/lib.php 0000644 00000061367 15151777376 0015701 0 ustar 00 <?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/>. /** * Manual enrolment plugin main library file. * * @package enrol_manual * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); class enrol_manual_plugin extends enrol_plugin { protected $lasternoller = null; protected $lasternollerinstanceid = 0; public function roles_protected() { // Users may tweak the roles later. return false; } public function allow_enrol(stdClass $instance) { // Users with enrol cap may unenrol other users manually manually. return true; } public function allow_unenrol(stdClass $instance) { // Users with unenrol cap may unenrol other users manually manually. return true; } public function allow_manage(stdClass $instance) { // Users with manage cap may tweak period and status. return true; } /** * Returns link to manual enrol UI if exists. * Does the access control tests automatically. * * @param stdClass $instance * @return moodle_url */ public function get_manual_enrol_link($instance) { $name = $this->get_name(); if ($instance->enrol !== $name) { throw new coding_exception('invalid enrol instance!'); } if (!enrol_is_enabled($name)) { return NULL; } $context = context_course::instance($instance->courseid, MUST_EXIST); if (!has_capability('enrol/manual:enrol', $context)) { // Note: manage capability not used here because it is used for editing // of existing enrolments which is not possible here. return NULL; } return new moodle_url('/enrol/manual/manage.php', array('enrolid'=>$instance->id, 'id'=>$instance->courseid)); } /** * Return true if we can add a new instance to this course. * * @param int $courseid * @return boolean */ public function can_add_instance($courseid) { global $DB; $context = context_course::instance($courseid, MUST_EXIST); if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/manual:config', $context)) { return false; } if ($DB->record_exists('enrol', array('courseid'=>$courseid, 'enrol'=>'manual'))) { // Multiple instances not supported. return false; } return true; } /** * Returns edit icons for the page with list of instances. * @param stdClass $instance * @return array */ public function get_action_icons(stdClass $instance) { global $OUTPUT; $context = context_course::instance($instance->courseid); $icons = array(); if (has_capability('enrol/manual:enrol', $context) or has_capability('enrol/manual:unenrol', $context)) { $managelink = new moodle_url("/enrol/manual/manage.php", array('enrolid'=>$instance->id)); $icons[] = $OUTPUT->action_icon($managelink, new pix_icon('t/enrolusers', get_string('enrolusers', 'enrol_manual'), 'core', array('class'=>'iconsmall'))); } $parenticons = parent::get_action_icons($instance); $icons = array_merge($icons, $parenticons); return $icons; } /** * Add new instance of enrol plugin with default settings. * @param stdClass $course * @return int id of new instance, null if can not be created */ public function add_default_instance($course) { $expirynotify = $this->get_config('expirynotify', 0); if ($expirynotify == 2) { $expirynotify = 1; $notifyall = 1; } else { $notifyall = 0; } $fields = array( 'status' => $this->get_config('status'), 'roleid' => $this->get_config('roleid', 0), 'enrolperiod' => $this->get_config('enrolperiod', 0), 'expirynotify' => $expirynotify, 'notifyall' => $notifyall, 'expirythreshold' => $this->get_config('expirythreshold', 86400), ); return $this->add_instance($course, $fields); } /** * Add new instance of enrol plugin. * @param stdClass $course * @param array instance fields * @return int id of new instance, null if can not be created */ public function add_instance($course, array $fields = NULL) { global $DB; if ($DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'))) { // only one instance allowed, sorry return NULL; } return parent::add_instance($course, $fields); } /** * Update instance of enrol plugin. * @param stdClass $instance * @param stdClass $data modified instance fields * @return boolean */ public function update_instance($instance, $data) { global $DB; // Delete all other instances, leaving only one. if ($instances = $DB->get_records('enrol', array('courseid' => $instance->courseid, 'enrol' => 'manual'), 'id ASC')) { foreach ($instances as $anotherinstance) { if ($anotherinstance->id != $instance->id) { $this->delete_instance($anotherinstance); } } } return parent::update_instance($instance, $data); } /** * Returns a button to manually enrol users through the manual enrolment plugin. * * By default the first manual enrolment plugin instance available in the course is used. * If no manual enrolment instances exist within the course then false is returned. * * This function also adds a quickenrolment JS ui to the page so that users can be enrolled * via AJAX. * * @param course_enrolment_manager $manager * @return enrol_user_button */ public function get_manual_enrol_button(course_enrolment_manager $manager) { global $CFG, $PAGE; require_once($CFG->dirroot.'/cohort/lib.php'); static $called = false; $instance = null; foreach ($manager->get_enrolment_instances() as $tempinstance) { if ($tempinstance->enrol == 'manual') { if ($instance === null) { $instance = $tempinstance; } } } if (empty($instance)) { return false; } $link = $this->get_manual_enrol_link($instance); if (!$link) { return false; } $button = new enrol_user_button($link, get_string('enrolusers', 'enrol_manual'), 'get'); $button->class .= ' enrol_manual_plugin'; $button->primary = true; $context = context_course::instance($instance->courseid); $arguments = array('contextid' => $context->id); if (!$called) { $called = true; // Calling the following more than once will cause unexpected results. $PAGE->requires->js_call_amd('enrol_manual/quickenrolment', 'init', array($arguments)); } return $button; } /** * Sync all meta course links. * * @param progress_trace $trace * @param int $courseid one course, empty mean all * @return int 0 means ok, 1 means error, 2 means plugin disabled */ public function sync(progress_trace $trace, $courseid = null) { global $DB; if (!enrol_is_enabled('manual')) { $trace->finished(); return 2; } // Unfortunately this may take a long time, execution can be interrupted safely here. core_php_time_limit::raise(); raise_memory_limit(MEMORY_HUGE); $trace->output('Verifying manual enrolment expiration...'); $params = array('now'=>time(), 'useractive'=>ENROL_USER_ACTIVE, 'courselevel'=>CONTEXT_COURSE); $coursesql = ""; if ($courseid) { $coursesql = "AND e.courseid = :courseid"; $params['courseid'] = $courseid; } // Deal with expired accounts. $action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP); if ($action == ENROL_EXT_REMOVED_UNENROL) { $instances = array(); $sql = "SELECT ue.*, e.courseid, c.id AS contextid FROM {user_enrolments} ue JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual') JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel) WHERE ue.timeend > 0 AND ue.timeend < :now $coursesql"; $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $ue) { if (empty($instances[$ue->enrolid])) { $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); } $instance = $instances[$ue->enrolid]; // Always remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here. role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true); $this->unenrol_user($instance, $ue->userid); $trace->output("unenrolling expired user $ue->userid from course $instance->courseid", 1); } $rs->close(); unset($instances); } else if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES or $action == ENROL_EXT_REMOVED_SUSPEND) { $instances = array(); $sql = "SELECT ue.*, e.courseid, c.id AS contextid FROM {user_enrolments} ue JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'manual') JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel) WHERE ue.timeend > 0 AND ue.timeend < :now AND ue.status = :useractive $coursesql"; $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $ue) { if (empty($instances[$ue->enrolid])) { $instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid)); } $instance = $instances[$ue->enrolid]; if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) { // Remove all manually assigned roles here, this may break enrol_self roles but we do not want hardcoded hacks here. role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true); $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); $trace->output("suspending expired user $ue->userid in course $instance->courseid, roles unassigned", 1); } else { $this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED); $trace->output("suspending expired user $ue->userid in course $instance->courseid, roles kept", 1); } } $rs->close(); unset($instances); } else { // ENROL_EXT_REMOVED_KEEP means no changes. } $trace->output('...manual enrolment updates finished.'); $trace->finished(); return 0; } /** * Returns the user who is responsible for manual enrolments in given instance. * * Usually it is the first editing teacher - the person with "highest authority" * as defined by sort_by_roleassignment_authority() having 'enrol/manual:manage' * capability. * * @param int $instanceid enrolment instance id * @return stdClass user record */ protected function get_enroller($instanceid) { global $DB; if ($this->lasternollerinstanceid == $instanceid and $this->lasternoller) { return $this->lasternoller; } $instance = $DB->get_record('enrol', array('id'=>$instanceid, 'enrol'=>$this->get_name()), '*', MUST_EXIST); $context = context_course::instance($instance->courseid); if ($users = get_enrolled_users($context, 'enrol/manual:manage')) { $users = sort_by_roleassignment_authority($users, $context); $this->lasternoller = reset($users); unset($users); } else { $this->lasternoller = parent::get_enroller($instanceid); } $this->lasternollerinstanceid = $instanceid; return $this->lasternoller; } /** * The manual plugin has several bulk operations that can be performed. * @param course_enrolment_manager $manager * @return array */ public function get_bulk_operations(course_enrolment_manager $manager) { global $CFG; require_once($CFG->dirroot.'/enrol/manual/locallib.php'); $context = $manager->get_context(); $bulkoperations = array(); if (has_capability("enrol/manual:manage", $context)) { $bulkoperations['editselectedusers'] = new enrol_manual_editselectedusers_operation($manager, $this); } if (has_capability("enrol/manual:unenrol", $context)) { $bulkoperations['deleteselectedusers'] = new enrol_manual_deleteselectedusers_operation($manager, $this); } return $bulkoperations; } /** * Restore instance and map settings. * * @param restore_enrolments_structure_step $step * @param stdClass $data * @param stdClass $course * @param int $oldid */ public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) { global $DB; // There is only I manual enrol instance allowed per course. if ($instances = $DB->get_records('enrol', array('courseid'=>$data->courseid, 'enrol'=>'manual'), 'id')) { $instance = reset($instances); $instanceid = $instance->id; } else { $instanceid = $this->add_instance($course, (array)$data); } $step->set_mapping('enrol', $oldid, $instanceid); } /** * Restore user enrolment. * * @param restore_enrolments_structure_step $step * @param stdClass $data * @param stdClass $instance * @param int $oldinstancestatus * @param int $userid */ public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) { global $DB; // Note: this is a bit tricky because other types may be converted to manual enrolments, // and manual is restricted to one enrolment per user. $ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid)); $enrol = false; if ($ue and $ue->status == ENROL_USER_ACTIVE) { // We do not want to restrict current active enrolments, let's kind of merge the times only. // This prevents some teacher lockouts too. if ($data->status == ENROL_USER_ACTIVE) { if ($data->timestart > $ue->timestart) { $data->timestart = $ue->timestart; $enrol = true; } if ($data->timeend == 0) { if ($ue->timeend != 0) { $enrol = true; } } else if ($ue->timeend == 0) { $data->timeend = 0; } else if ($data->timeend < $ue->timeend) { $data->timeend = $ue->timeend; $enrol = true; } } } else { if ($instance->status == ENROL_INSTANCE_ENABLED and $oldinstancestatus != ENROL_INSTANCE_ENABLED) { // Make sure that user enrolments are not activated accidentally, // we do it only here because it is not expected that enrolments are migrated to other plugins. $data->status = ENROL_USER_SUSPENDED; } $enrol = true; } if ($enrol) { $this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, $data->status); } } /** * Restore role assignment. * * @param stdClass $instance * @param int $roleid * @param int $userid * @param int $contextid */ public function restore_role_assignment($instance, $roleid, $userid, $contextid) { // This is necessary only because we may migrate other types to this instance, // we do not use component in manual or self enrol. role_assign($roleid, $userid, $contextid, '', 0); } /** * Restore user group membership. * @param stdClass $instance * @param int $groupid * @param int $userid */ public function restore_group_member($instance, $groupid, $userid) { global $CFG; require_once("$CFG->dirroot/group/lib.php"); // This might be called when forcing restore as manual enrolments. groups_add_member($groupid, $userid); } /** * Is it possible to delete enrol instance via standard UI? * * @param object $instance * @return bool */ public function can_delete_instance($instance) { $context = context_course::instance($instance->courseid); return has_capability('enrol/manual:config', $context); } /** * Is it possible to hide/show enrol instance via standard UI? * * @param stdClass $instance * @return bool */ public function can_hide_show_instance($instance) { $context = context_course::instance($instance->courseid); return has_capability('enrol/manual:config', $context); } /** * Enrol all not enrolled cohort members into course via enrol instance. * * @param stdClass $instance * @param int $cohortid * @param int $roleid optional role id * @param int $timestart 0 means unknown * @param int $timeend 0 means forever * @param int $status default to ENROL_USER_ACTIVE for new enrolments, no change by default in updates * @param bool $recovergrades restore grade history * @return int The number of enrolled cohort users */ public function enrol_cohort(stdClass $instance, $cohortid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) { global $DB; $context = context_course::instance($instance->courseid); list($esql, $params) = get_enrolled_sql($context); $sql = "SELECT cm.userid FROM {cohort_members} cm LEFT JOIN ($esql) u ON u.id = cm.userid ". "WHERE cm.cohortid = :cohortid AND u.id IS NULL"; $params['cohortid'] = $cohortid; $members = $DB->get_fieldset_sql($sql, $params); foreach ($members as $userid) { $this->enrol_user($instance, $userid, $roleid, $timestart, $timeend, $status, $recovergrades); } return count($members); } /** * We are a good plugin and don't invent our own UI/validation code path. * * @return boolean */ public function use_standard_editing_ui() { return true; } /** * Return an array of valid options for the status. * * @return array */ protected function get_status_options() { $options = array(ENROL_INSTANCE_ENABLED => get_string('yes'), ENROL_INSTANCE_DISABLED => get_string('no')); return $options; } /** * Return an array of valid options for the roleid. * * @param stdClass $instance * @param context $context * @return array */ protected function get_roleid_options($instance, $context) { if ($instance->id) { $roles = get_default_enrol_roles($context, $instance->roleid); } else { $roles = get_default_enrol_roles($context, $this->get_config('roleid')); } return $roles; } /** * Return an array of valid options for the expirynotify. * * @return array */ protected function get_expirynotify_options() { $options = array( 0 => get_string('no'), 1 => get_string('expirynotifyenroller', 'core_enrol'), 2 => get_string('expirynotifyall', 'core_enrol') ); return $options; } /** * Add elements to the edit instance form. * * @param stdClass $instance * @param MoodleQuickForm $mform * @param context $context * @return bool */ public function edit_instance_form($instance, MoodleQuickForm $mform, $context) { $options = $this->get_status_options(); $mform->addElement('select', 'status', get_string('status', 'enrol_manual'), $options); $mform->addHelpButton('status', 'status', 'enrol_manual'); $mform->setDefault('status', $this->get_config('status')); $roles = $this->get_roleid_options($instance, $context); $mform->addElement('select', 'roleid', get_string('defaultrole', 'role'), $roles); $mform->setDefault('roleid', $this->get_config('roleid')); $options = array('optional' => true, 'defaultunit' => 86400); $mform->addElement('duration', 'enrolperiod', get_string('defaultperiod', 'enrol_manual'), $options); $mform->setDefault('enrolperiod', $this->get_config('enrolperiod')); $mform->addHelpButton('enrolperiod', 'defaultperiod', 'enrol_manual'); $options = $this->get_expirynotify_options(); $mform->addElement('select', 'expirynotify', get_string('expirynotify', 'core_enrol'), $options); $mform->addHelpButton('expirynotify', 'expirynotify', 'core_enrol'); $options = array('optional' => false, 'defaultunit' => 86400); $mform->addElement('duration', 'expirythreshold', get_string('expirythreshold', 'core_enrol'), $options); $mform->addHelpButton('expirythreshold', 'expirythreshold', 'core_enrol'); $mform->disabledIf('expirythreshold', 'expirynotify', 'eq', 0); if (enrol_accessing_via_instance($instance)) { $warntext = get_string('instanceeditselfwarningtext', 'core_enrol'); $mform->addElement('static', 'selfwarn', get_string('instanceeditselfwarning', 'core_enrol'), $warntext); } } /** * Perform custom validation of the data used to edit the instance. * * @param array $data array of ("fieldname"=>value) of submitted data * @param array $files array of uploaded files "element_name"=>tmp_file_path * @param object $instance The instance loaded from the DB * @param context $context The context of the instance we are editing * @return array of "element_name"=>"error_description" if there are errors, * or an empty array if everything is OK. * @return void */ public function edit_instance_validation($data, $files, $instance, $context) { $errors = array(); if ($data['expirynotify'] > 0 and $data['expirythreshold'] < 86400) { $errors['expirythreshold'] = get_string('errorthresholdlow', 'core_enrol'); } $validstatus = array_keys($this->get_status_options()); $validroles = array_keys($this->get_roleid_options($instance, $context)); $validexpirynotify = array_keys($this->get_expirynotify_options()); $tovalidate = array( 'status' => $validstatus, 'roleid' => $validroles, 'enrolperiod' => PARAM_INT, 'expirynotify' => $validexpirynotify, 'expirythreshold' => PARAM_INT ); $typeerrors = $this->validate_param_types($data, $tovalidate); $errors = array_merge($errors, $typeerrors); return $errors; } } /** * Serve the manual enrol users form as a fragment. * * @param array $args List of named arguments for the fragment loader. * @return string */ function enrol_manual_output_fragment_enrol_users_form($args) { $args = (object) $args; $context = $args->context; $o = ''; require_capability('enrol/manual:enrol', $context); $mform = new enrol_manual_enrol_users_form(null, $args); ob_start(); $mform->display(); $o .= ob_get_contents(); ob_end_clean(); return $o; } home3/cpr76684/public_html/Aem/admin/tool/brickfield/lib.php 0000644 00000006457 15152026560 0017426 0 ustar 00 <?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/>. /** * This file contains hooks and callbacks needed for the accessibility toolkit. * * @package tool_brickfield * @category admin * @copyright 2020 Brickfield Education Labs, https://www.brickfield.ie - Author: Karen Holland * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use tool_brickfield\accessibility; use tool_brickfield\manager; use tool_brickfield\registration; /** * This function extends the navigation with the report items * * @param navigation_node $navigation The navigation node to extend * @param stdClass $course The course to object for the report * @param context $context The context of the course * @throws coding_exception * @throws moodle_exception */ function tool_brickfield_extend_navigation_course(\navigation_node $navigation, \stdClass $course, \context $context) { if (!accessibility::is_accessibility_enabled()) { // The feature has been explicitly disabled. return; } if (!has_capability(accessibility::get_capability_name('viewcoursetools'), $context)) { // The user does not have the capability to view the course tools. return; } // Display in the navigation if the user has site:config ability, or if the site is registered. $enabled = has_capability('moodle/site:config', \context_system::instance()); $enabled = $enabled || (new registration())->toolkit_is_active(); if (!$enabled) { return; } $url = new moodle_url(accessibility::get_plugin_url(), ['courseid' => $course->id]); $navigation->add( get_string('pluginname', manager::PLUGINNAME), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '') ); } /** * Get icon mapping for font-awesome. * @return string[] */ function tool_brickfield_get_fontawesome_icon_map() { return [ manager::PLUGINNAME . ':f/award' => 'fa-tachometer', manager::PLUGINNAME . ':f/done' => 'fa-check-circle-o', manager::PLUGINNAME . ':f/done2' => 'fa-check-square-o', manager::PLUGINNAME . ':f/error' => 'fa-times-circle-o', manager::PLUGINNAME . ':f/find' => 'fa-bar-chart', manager::PLUGINNAME . ':f/total' => 'fa-calculator', manager::PLUGINNAME . ':f/form' => 'fa-pencil-square-o', manager::PLUGINNAME . ':f/image' => 'fa-image', manager::PLUGINNAME . ':f/layout' => 'fa-th-large', manager::PLUGINNAME . ':f/link' => 'fa-link', manager::PLUGINNAME . ':f/media' => 'fa-play-circle-o', manager::PLUGINNAME . ':f/table' => 'fa-table', manager::PLUGINNAME . ':f/text' => 'fa-font', ]; } home3/cpr76684/public_html/Aem/course/format/singleactivity/lib.php 0000644 00000053632 15152035505 0021105 0 ustar 00 <?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/>. /** * This file contains main class for the course format singleactivity * * @package format_singleactivity * @copyright 2012 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot. '/course/format/lib.php'); /** * Main class for the singleactivity course format * * @package format_singleactivity * @copyright 2012 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class format_singleactivity extends core_courseformat\base { /** @var cm_info the current activity. Use get_activity() to retrieve it. */ private $activity = false; /** @var int The category ID guessed from the form data. */ private $categoryid = false; /** * The URL to use for the specified course * * @param int|stdClass $section Section object from database or just field course_sections.section * if null the course view page is returned * @param array $options options for view URL. At the moment core uses: * 'navigation' (bool) if true and section has no separate page, the function returns null * 'sr' (int) used by multipage formats to specify to which section to return * @return null|moodle_url */ public function get_view_url($section, $options = array()) { $sectionnum = $section; if (is_object($sectionnum)) { $sectionnum = $section->section; } if ($sectionnum == 1) { return new moodle_url('/course/view.php', array('id' => $this->courseid, 'section' => 1)); } if (!empty($options['navigation']) && $section !== null) { return null; } return new moodle_url('/course/view.php', array('id' => $this->courseid)); } /** * Loads all of the course sections into the navigation * * @param global_navigation $navigation * @param navigation_node $node The course node within the navigation */ public function extend_course_navigation($navigation, navigation_node $node) { // Display orphaned activities for the users who can see them. $context = context_course::instance($this->courseid); if (has_capability('moodle/course:viewhiddensections', $context)) { $modinfo = get_fast_modinfo($this->courseid); if (!empty($modinfo->sections[1])) { $section1 = $modinfo->get_section_info(1); // Show orphaned activities. $orphanednode = $node->add(get_string('orphaned', 'format_singleactivity'), $this->get_view_url(1), navigation_node::TYPE_SECTION, null, $section1->id); $orphanednode->nodetype = navigation_node::NODETYPE_BRANCH; $orphanednode->add_class('orphaned'); foreach ($modinfo->sections[1] as $cmid) { if (has_capability('moodle/course:viewhiddenactivities', context_module::instance($cmid))) { $this->navigation_add_activity($orphanednode, $modinfo->cms[$cmid]); } } } } } /** * Adds a course module to the navigation node * * This is basically copied from function global_navigation::load_section_activities() * because it is not accessible from outside. * * @param navigation_node $node * @param cm_info $cm * @return null|navigation_node */ protected function navigation_add_activity(navigation_node $node, $cm) { if (!$cm->uservisible) { return null; } $action = $cm->url; if (!$action) { // Do not add to navigation activity without url (i.e. labels). return null; } $activityname = format_string($cm->name, true, array('context' => context_module::instance($cm->id))); if ($cm->icon) { $icon = new pix_icon($cm->icon, $cm->modfullname, $cm->iconcomponent); } else { $icon = new pix_icon('monologo', $cm->modfullname, $cm->modname); } $activitynode = $node->add($activityname, $action, navigation_node::TYPE_ACTIVITY, null, $cm->id, $icon); if (global_navigation::module_extends_navigation($cm->modname)) { $activitynode->nodetype = navigation_node::NODETYPE_BRANCH; } else { $activitynode->nodetype = navigation_node::NODETYPE_LEAF; } return $activitynode; } /** * Returns the list of blocks to be automatically added for the newly created course * * @return array of default blocks, must contain two keys BLOCK_POS_LEFT and BLOCK_POS_RIGHT * each of values is an array of block names (for left and right side columns) */ public function get_default_blocks() { // No blocks for this format because course view page is not displayed anyway. return array( BLOCK_POS_LEFT => array(), BLOCK_POS_RIGHT => array() ); } /** * Definitions of the additional options that this course format uses for course * * Singleactivity course format uses one option 'activitytype' * * @param bool $foreditform * @return array of options */ public function course_format_options($foreditform = false) { static $courseformatoptions = false; $fetchtypes = $courseformatoptions === false; $fetchtypes = $fetchtypes || ($foreditform && !isset($courseformatoptions['activitytype']['label'])); if ($fetchtypes) { $availabletypes = $this->get_supported_activities(); if ($this->courseid) { // The course exists. Test against the course. $testcontext = context_course::instance($this->courseid); } else if ($this->categoryid) { // The course does not exist yet, but we have a category ID that we can test against. $testcontext = context_coursecat::instance($this->categoryid); } else { // The course does not exist, and we somehow do not have a category. Test capabilities against the system context. $testcontext = context_system::instance(); } foreach (array_keys($availabletypes) as $activity) { $capability = "mod/{$activity}:addinstance"; if (!has_capability($capability, $testcontext)) { unset($availabletypes[$activity]); } } } if ($courseformatoptions === false) { $config = get_config('format_singleactivity'); $courseformatoptions = array( 'activitytype' => array( 'default' => $config->activitytype, 'type' => PARAM_TEXT, ), ); if (!empty($availabletypes) && !isset($availabletypes[$config->activitytype])) { $courseformatoptions['activitytype']['default'] = array_keys($availabletypes)[0]; } } if ($foreditform && !isset($courseformatoptions['activitytype']['label'])) { $courseformatoptionsedit = array( 'activitytype' => array( 'label' => new lang_string('activitytype', 'format_singleactivity'), 'help' => 'activitytype', 'help_component' => 'format_singleactivity', 'element_type' => 'select', 'element_attributes' => array($availabletypes), ), ); $courseformatoptions = array_merge_recursive($courseformatoptions, $courseformatoptionsedit); } return $courseformatoptions; } /** * Adds format options elements to the course/section edit form * * This function is called from {@link course_edit_form::definition_after_data()} * * Format singleactivity adds a warning when format of the course is about to be changed. * * @param MoodleQuickForm $mform form the elements are added to * @param bool $forsection 'true' if this is a section edit form, 'false' if this is course edit form * @return array array of references to the added form elements */ public function create_edit_form_elements(&$mform, $forsection = false) { global $PAGE; if (!$this->course && $submitvalues = $mform->getSubmitValues()) { $this->categoryid = $submitvalues['category']; } $elements = parent::create_edit_form_elements($mform, $forsection); if (!$forsection && ($course = $PAGE->course) && !empty($course->format) && $course->format !== 'site' && $course->format !== 'singleactivity') { // This is the existing course in other format, display a warning. $element = $mform->addElement('static', '', '', html_writer::tag('span', get_string('warningchangeformat', 'format_singleactivity'), array('class' => 'error'))); array_unshift($elements, $element); } return $elements; } /** * Make sure that current active activity is in section 0 * * All other activities are moved to section 1 that will be displayed as 'Orphaned'. * It may be needed after the course format was changed or activitytype in * course settings has been changed. * * @return null|cm_info current activity */ public function reorder_activities() { course_create_sections_if_missing($this->courseid, array(0, 1)); foreach ($this->get_sections() as $sectionnum => $section) { if (($sectionnum && $section->visible) || (!$sectionnum && !$section->visible)) { // Make sure that 0 section is visible and all others are hidden. set_section_visible($this->courseid, $sectionnum, $sectionnum == 0); } } $modinfo = get_fast_modinfo($this->courseid); // Find the current activity (first activity with the specified type in all course activities). $activitytype = $this->get_activitytype(); $activity = null; if (!empty($activitytype)) { foreach ($modinfo->sections as $sectionnum => $cmlist) { foreach ($cmlist as $cmid) { if ($modinfo->cms[$cmid]->modname === $activitytype) { $activity = $modinfo->cms[$cmid]; break 2; } } } } // Make sure the current activity is in the 0-section. $changed = false; if ($activity && $activity->sectionnum != 0) { moveto_module($activity, $modinfo->get_section_info(0)); $changed = true; } if ($activity && !$activity->visible) { set_coursemodule_visible($activity->id, 1); $changed = true; } if ($changed) { // Cache was reset so get modinfo again. $modinfo = get_fast_modinfo($this->courseid); } // Move all other activities into section 1 (the order must be kept). $hasvisibleactivities = false; $firstorphanedcm = null; foreach ($modinfo->sections as $sectionnum => $cmlist) { if ($sectionnum && !empty($cmlist) && $firstorphanedcm === null) { $firstorphanedcm = reset($cmlist); } foreach ($cmlist as $cmid) { if ($sectionnum > 1) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1)); } else if (!$hasvisibleactivities && $sectionnum == 1 && $modinfo->get_cm($cmid)->visible) { $hasvisibleactivities = true; } } } if (!empty($modinfo->sections[0])) { foreach ($modinfo->sections[0] as $cmid) { if (!$activity || $cmid != $activity->id) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1), $firstorphanedcm); } } } if ($hasvisibleactivities) { set_section_visible($this->courseid, 1, false); } return $activity; } /** * Returns the name of activity type used for this course * * @return string|null */ protected function get_activitytype() { $options = $this->get_format_options(); $availabletypes = $this->get_supported_activities(); if (!empty($options['activitytype']) && array_key_exists($options['activitytype'], $availabletypes)) { return $options['activitytype']; } else { return null; } } /** * Returns the current activity if exists * * @return null|cm_info */ protected function get_activity() { if ($this->activity === false) { $this->activity = $this->reorder_activities(); } return $this->activity; } /** * Get the activities supported by the format. * * Here we ignore the modules that do not have a page of their own, like the label. * * @return array array($module => $name of the module). */ public static function get_supported_activities() { $availabletypes = get_module_types_names(); foreach ($availabletypes as $module => $name) { if (plugin_supports('mod', $module, FEATURE_NO_VIEW_LINK, false)) { unset($availabletypes[$module]); } } return $availabletypes; } /** * Checks if the current user can add the activity of the specified type to this course. * * @return bool */ protected function can_add_activity() { global $CFG; if (!($modname = $this->get_activitytype())) { return false; } if (!has_capability('moodle/course:manageactivities', context_course::instance($this->courseid))) { return false; } if (!course_allowed_module($this->get_course(), $modname)) { return false; } $libfile = "$CFG->dirroot/mod/$modname/lib.php"; if (!file_exists($libfile)) { return null; } return true; } /** * Checks if the activity type has multiple items in the activity chooser. * * @return bool|null (null if the check is not possible) */ public function activity_has_subtypes() { global $USER; if (!($modname = $this->get_activitytype())) { return null; } $contentitemservice = \core_course\local\factory\content_item_service_factory::get_content_item_service(); $metadata = $contentitemservice->get_content_items_for_user_in_course($USER, $this->get_course()); // If there are multiple items originating from this mod_xxx component, then it's deemed to have subtypes. // If there is only 1 item, but it's not a reference to the core content item for the module, then it's also deemed to // have subtypes. $count = 0; foreach ($metadata as $key => $moduledata) { if ('mod_'.$modname === $moduledata->componentname) { $count ++; } } if ($count > 1) { return true; } else { // Get the single item. $itemmetadata = $metadata[array_search('mod_' . $modname, array_column($metadata, 'componentname'))]; $urlbase = new \moodle_url('/course/mod.php', ['id' => $this->get_course()->id]); $referenceurl = new \moodle_url($urlbase, ['add' => $modname]); if ($referenceurl->out(false) != $itemmetadata->link) { return true; } } return false; } /** * Allows course format to execute code on moodle_page::set_course() * * This function is executed before the output starts. * * If everything is configured correctly, user is redirected from the * default course view page to the activity view page. * * "Section 1" is the administrative page to manage orphaned activities * * If user is on course view page and there is no module added to the course * and the user has 'moodle/course:manageactivities' capability, redirect to create module * form. * * @param moodle_page $page instance of page calling set_course */ public function page_set_course(moodle_page $page) { global $PAGE; $page->add_body_class('format-'. $this->get_format()); if ($PAGE == $page && $page->has_set_url() && $page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) { $edit = optional_param('edit', -1, PARAM_BOOL); if (($edit == 0 || $edit == 1) && confirm_sesskey()) { // This is a request to turn editing mode on or off, do not redirect here, /course/view.php will do redirection. return; } $cm = $this->get_activity(); $cursection = optional_param('section', null, PARAM_INT); if (!empty($cursection) && has_capability('moodle/course:viewhiddensections', context_course::instance($this->courseid))) { // Display orphaned activities (course view page, section 1). return; } if (!$this->get_activitytype()) { if (has_capability('moodle/course:update', context_course::instance($this->courseid))) { // Teacher is redirected to edit course page. $url = new moodle_url('/course/edit.php', array('id' => $this->courseid)); redirect($url, get_string('erroractivitytype', 'format_singleactivity')); } else { // Student sees an empty course page. return; } } if ($cm === null) { if ($this->can_add_activity()) { // This is a user who has capability to create an activity. if ($this->activity_has_subtypes()) { // Activity has multiple items in the activity chooser, it can not be added automatically. if (optional_param('addactivity', 0, PARAM_INT)) { return; } else { $url = new moodle_url('/course/view.php', array('id' => $this->courseid, 'addactivity' => 1)); redirect($url); } } // Redirect to the add activity form. $url = new moodle_url('/course/mod.php', array('id' => $this->courseid, 'section' => 0, 'sesskey' => sesskey(), 'add' => $this->get_activitytype())); redirect($url); } else { // Student views an empty course page. return; } } else if (!$cm->uservisible || !$cm->url) { // Activity is set but not visible to current user or does not have url. // Display course page (either empty or with availability restriction info). return; } else { // Everything is set up and accessible, redirect to the activity page! redirect($cm->url); } } } /** * Allows course format to execute code on moodle_page::set_cm() * * If we are inside the main module for this course, remove extra node level * from navigation: substitute course node with activity node, move all children * * @param moodle_page $page instance of page calling set_cm */ public function page_set_cm(moodle_page $page) { global $PAGE; parent::page_set_cm($page); if ($PAGE == $page && ($cm = $this->get_activity()) && $cm->uservisible && ($cm->id === $page->cm->id) && ($activitynode = $page->navigation->find($cm->id, navigation_node::TYPE_ACTIVITY)) && ($node = $page->navigation->find($page->course->id, navigation_node::TYPE_COURSE))) { // Substitute course node with activity node, move all children. $node->action = $activitynode->action; $node->type = $activitynode->type; $node->id = $activitynode->id; $node->key = $activitynode->key; $node->isactive = $node->isactive || $activitynode->isactive; $node->icon = null; if ($activitynode->children->count()) { foreach ($activitynode->children as &$child) { $child->remove(); $node->add_node($child); } } else { $node->search_for_active_node(); } $activitynode->remove(); } } /** * Returns true if the course has a front page. * * @return boolean false */ public function has_view_page() { return false; } /** * Return the plugin configs for external functions. * * @return array the list of configuration settings * @since Moodle 3.5 */ public function get_config_for_external() { // Return everything (nothing to hide). return $this->get_format_options(); } } home3/cpr76684/public_html/Aem/mod/lti/backup/moodle1/lib.php 0000644 00000012325 15152065054 0017427 0 ustar 00 <?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/>. /** * 1.9 to 2.0 backup format converter. (Also currently used in common cartridge import process) * * @package mod_lti * @copyright Copyright (c) 2011 Moodlerooms Inc. (http://www.moodlerooms.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Darko Miletic */ defined('MOODLE_INTERNAL') || die(); class moodle1_mod_lti_handler extends moodle1_mod_handler { /** @var moodle1_file_manager */ protected $fileman = null; /** @var int cmid */ protected $moduleid = null; /** * Declare the paths in moodle.xml we are able to convert * * The method returns list of {@link convert_path} instances. * For each path returned, the corresponding conversion method must be * defined. * * Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI does not * actually exist in the file. The last element with the module name was * appended by the moodle1_converter class. * * @return array of {@link convert_path} instances */ public function get_paths() { return array( new convert_path( 'basiclti', '/MOODLE_BACKUP/COURSE/MODULES/MOD/LTI' ) ); } /** * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI * data available */ public function process_basiclti($data) { global $DB; // Get the course module id and context id. $instanceid = $data['id']; $cminfo = $this->get_cminfo($instanceid); $this->moduleid = $cminfo['id']; $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $this->moduleid); // Get a fresh new file manager for this instance. $this->fileman = $this->converter->get_file_manager($contextid, 'mod_lti'); // Convert course files embedded into the intro. $this->fileman->filearea = 'intro'; $this->fileman->itemid = 0; $data['intro'] = moodle1_converter::migrate_referenced_files($data['intro'], $this->fileman); // Start writing assignment.xml. $this->open_xml_writer("activities/lti_{$this->moduleid}/lti.xml"); $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $this->moduleid, 'modulename' => 'lti', 'contextid' => $contextid)); $this->xmlwriter->begin_tag('lti', array('id' => $instanceid)); $ignorefields = array('id', 'modtype'); if (!$DB->record_exists('lti_types', array('id' => $data['typeid']))) { $ntypeid = false; $toolurls = $DB->get_records_select( 'lti_types_config', "name = 'toolurl' AND " . $DB->sql_compare_text('value', 256) . ' = ' . $DB->sql_compare_text('?', 256), [$data['toolurl']], '', 'id, value' ); foreach ($toolurls as $id => $value) { if ($value == $data['toolurl']) { $ntypeid = $id; break; } } if ($ntypeid === false) { $ntypeid = $DB->get_field('lti_types_config', 'typeid', array(), IGNORE_MULTIPLE); } if ($ntypeid === false) { $ntypeid = 0; } $data['typeid'] = $ntypeid; } if (empty($data['servicesalt'])) { $data['servicesalt'] = uniqid('', true); } foreach ($data as $field => $value) { if (!in_array($field, $ignorefields)) { $this->xmlwriter->full_tag($field, $value); } } return $data; } /** * This is executed when we reach the closing </MOD> tag of our 'lti' path */ public function on_basiclti_end() { // Finish writing basiclti.xml. $this->xmlwriter->end_tag('lti'); $this->xmlwriter->end_tag('activity'); $this->close_xml_writer(); // Write inforef.xml. $this->open_xml_writer("activities/lti_{$this->moduleid}/inforef.xml"); $this->xmlwriter->begin_tag('inforef'); $this->xmlwriter->begin_tag('fileref'); foreach ($this->fileman->get_fileids() as $fileid) { $this->write_xml('file', array('id' => $fileid)); } $this->xmlwriter->end_tag('fileref'); $this->xmlwriter->end_tag('inforef'); $this->close_xml_writer(); } } home3/cpr76684/public_html/Aem/admin/tool/recyclebin/lib.php 0000644 00000014323 15152114172 0017433 0 ustar 00 <?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/>. /** * Local lib code * * @package tool_recyclebin * @copyright 2015 Skylar Kelty <S.Kelty@kent.ac.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; /** * Adds a recycle bin link to the course admin menu. * * @param navigation_node $navigation The navigation node to extend * @param stdClass $course The course to object for the tool * @param context $context The context of the course * @return void|null return null if we don't want to display the node. */ function tool_recyclebin_extend_navigation_course($navigation, $course, $context) { global $PAGE; // Only add this settings item on non-site course pages. if (!$PAGE->course || $PAGE->course->id == SITEID || !\tool_recyclebin\course_bin::is_enabled()) { return null; } $coursebin = new \tool_recyclebin\course_bin($context->instanceid); // Check we can view the recycle bin. if (!$coursebin->can_view()) { return null; } $url = null; $settingnode = null; $url = new moodle_url('/admin/tool/recyclebin/index.php', array( 'contextid' => $context->id )); // If we are set to auto-hide, check the number of items. $autohide = get_config('tool_recyclebin', 'autohide'); if ($autohide) { $items = $coursebin->get_items(); if (empty($items)) { return null; } } // Add the recyclebin link. $pluginname = get_string('pluginname', 'tool_recyclebin'); $node = navigation_node::create( $pluginname, $url, navigation_node::NODETYPE_LEAF, 'tool_recyclebin', 'tool_recyclebin', new pix_icon('trash', $pluginname, 'tool_recyclebin') ); if ($PAGE->url->compare($url, URL_MATCH_BASE)) { $node->make_active(); } $navigation->add_node($node); } /** * Adds a recycle bin link to the course admin menu. * * @param navigation_node $navigation The navigation node to extend * @param context $context The context of the course * @return void|null return null if we don't want to display the node. */ function tool_recyclebin_extend_navigation_category_settings($navigation, $context) { global $PAGE; // Check if it is enabled. if (!\tool_recyclebin\category_bin::is_enabled()) { return null; } $categorybin = new \tool_recyclebin\category_bin($context->instanceid); // Check we can view the recycle bin. if (!$categorybin->can_view()) { return null; } $url = null; $settingnode = null; // Add a link to the category recyclebin. $url = new moodle_url('/admin/tool/recyclebin/index.php', array( 'contextid' => $context->id )); // If we are set to auto-hide, check the number of items. $autohide = get_config('tool_recyclebin', 'autohide'); if ($autohide) { $items = $categorybin->get_items(); if (empty($items)) { return null; } } // Add the recyclebin link. $pluginname = get_string('pluginname', 'tool_recyclebin'); $node = navigation_node::create( $pluginname, $url, navigation_node::NODETYPE_LEAF, 'tool_recyclebin', 'tool_recyclebin', new pix_icon('trash', $pluginname, 'tool_recyclebin') ); if ($PAGE->url->compare($url, URL_MATCH_BASE)) { $node->make_active(); } $navigation->add_node($node); } /** * Hook called before we delete a course module. * * @param \stdClass $cm The course module record. */ function tool_recyclebin_pre_course_module_delete($cm) { if (\tool_recyclebin\course_bin::is_enabled()) { $coursebin = new \tool_recyclebin\course_bin($cm->course); $coursebin->store_item($cm); } } /** * Hook called to check whether async course module deletion should be performed or not. * * @return true if background deletion is required (is the recyclebin is enabled), false otherwise. */ function tool_recyclebin_course_module_background_deletion_recommended() { if (\tool_recyclebin\course_bin::is_enabled()) { return true; } } /** * Hook called before we delete a course. * * @param \stdClass $course The course record. */ function tool_recyclebin_pre_course_delete($course) { // It is possible that the course deletion which triggered this hook // was from an in progress course restore. In that case we do not want // it in the recycle bin. if (isset($course->deletesource) && $course->deletesource == 'restore') { return; } // Delete all the items in the course recycle bin, regardless if it enabled or not. // It may have been enabled, then disabled later on, so may still have content. $coursebin = new \tool_recyclebin\course_bin($course->id); $coursebin->delete_all_items(); if (\tool_recyclebin\category_bin::is_enabled()) { $categorybin = new \tool_recyclebin\category_bin($course->category); $categorybin->store_item($course); } } /** * Hook called before we delete a category. * * @param \stdClass $category The category record. */ function tool_recyclebin_pre_course_category_delete($category) { // Delete all the items in the category recycle bin, regardless if it enabled or not. // It may have been enabled, then disabled later on, so may still have content. $categorybin = new \tool_recyclebin\category_bin($category->id); $categorybin->delete_all_items(); } /** * Map icons for font-awesome themes. */ function tool_recyclebin_get_fontawesome_icon_map() { return [ 'tool_recyclebin:trash' => 'fa-trash' ]; } home3/cpr76684/public_html/Aem/repository/s3/lib.php 0000644 00000026374 15152170166 0016031 0 ustar 00 <?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/>. /** * This plugin is used to access s3 files * * @since Moodle 2.0 * @package repository_s3 * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/repository/lib.php'); require_once($CFG->dirroot . '/repository/s3/S3.php'); // This constant is not defined in php 5.4. Set it to avoid errors. if (!defined('CURL_SSLVERSION_TLSv1')) { define('CURL_SSLVERSION_TLSv1', 1); } /** * This is a repository class used to browse Amazon S3 content. * * @since Moodle 2.0 * @package repository_s3 * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_s3 extends repository { /** * Constructor * @param int $repositoryid * @param object $context * @param array $options */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { global $CFG; parent::__construct($repositoryid, $context, $options); $this->access_key = get_config('s3', 'access_key'); $this->secret_key = get_config('s3', 'secret_key'); $this->endpoint = get_config('s3', 'endpoint'); if ($this->endpoint === false) { // If no endpoint has been set, use the default. $this->endpoint = 's3.amazonaws.com'; } $this->s = new S3($this->access_key, $this->secret_key, false, $this->endpoint); $this->s->setExceptions(true); // Port of curl::__construct(). if (!empty($CFG->proxyhost)) { if (empty($CFG->proxyport)) { $proxyhost = $CFG->proxyhost; } else { $proxyhost = $CFG->proxyhost . ':' . $CFG->proxyport; } $proxytype = CURLPROXY_HTTP; $proxyuser = null; $proxypass = null; if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) { $proxyuser = $CFG->proxyuser; $proxypass = $CFG->proxypassword; } if (!empty($CFG->proxytype) && $CFG->proxytype == 'SOCKS5') { $proxytype = CURLPROXY_SOCKS5; } $this->s->setProxy($proxyhost, $proxyuser, $proxypass, $proxytype); } } /** * Extracts the Bucket and URI from the path * * @param string $path path in this format 'bucket/path/to/folder/and/file' * @return array including bucket and uri */ protected function explode_path($path) { $parts = explode('/', $path, 2); if (isset($parts[1]) && $parts[1] !== '') { list($bucket, $uri) = $parts; } else { $bucket = $parts[0]; $uri = ''; } return array($bucket, $uri); } /** * Get S3 file list * * @param string $path * @return array The file list and options */ public function get_listing($path = '', $page = '') { global $CFG, $OUTPUT; if (empty($this->access_key)) { throw new moodle_exception('needaccesskey', 'repository_s3'); } $list = array(); $list['list'] = array(); $list['path'] = array( array('name' => get_string('pluginname', 'repository_s3'), 'path' => '') ); // the management interface url $list['manage'] = false; // dynamically loading $list['dynload'] = true; // the current path of this list. // set to true, the login link will be removed $list['nologin'] = true; // set to true, the search button will be removed $list['nosearch'] = true; $tree = array(); if (empty($path)) { try { $buckets = $this->s->listBuckets(); } catch (S3Exception $e) { throw new moodle_exception( 'errorwhilecommunicatingwith', 'repository', '', $this->get_name(), $e->getMessage() ); } foreach ($buckets as $bucket) { $folder = array( 'title' => $bucket, 'children' => array(), 'thumbnail' => $OUTPUT->image_url(file_folder_icon(90))->out(false), 'path' => $bucket ); $tree[] = $folder; } } else { $files = array(); $folders = array(); list($bucket, $uri) = $this->explode_path($path); try { $contents = $this->s->getBucket($bucket, $uri, null, null, '/', true); } catch (S3Exception $e) { throw new moodle_exception( 'errorwhilecommunicatingwith', 'repository', '', $this->get_name(), $e->getMessage() ); } foreach ($contents as $object) { // If object has a prefix, it is a 'CommonPrefix', which we consider a folder if (isset($object['prefix'])) { $title = rtrim($object['prefix'], '/'); } else { $title = $object['name']; } // Removes the prefix (folder path) from the title if (strlen($uri) > 0) { $title = substr($title, strlen($uri)); // Check if title is empty and not zero if (empty($title) && !is_numeric($title)) { // Amazon returns the prefix itself, we skip it continue; } } // This is a so-called CommonPrefix, we consider it as a folder if (isset($object['prefix'])) { $folders[] = array( 'title' => $title, 'children' => array(), 'thumbnail'=> $OUTPUT->image_url(file_folder_icon(90))->out(false), 'path' => $bucket . '/' . $object['prefix'] ); } else { $files[] = array( 'title' => $title, 'size' => $object['size'], 'datemodified' => $object['time'], 'source' => $bucket . '/' . $object['name'], 'thumbnail' => $OUTPUT->image_url(file_extension_icon($title, 90))->out(false) ); } } $tree = array_merge($folders, $files); } $trail = ''; if (!empty($path)) { $parts = explode('/', $path); if (count($parts) > 1) { foreach ($parts as $part) { if (!empty($part)) { $trail .= $part . '/'; $list['path'][] = array('name' => $part, 'path' => $trail); } } } else { $list['path'][] = array('name' => $path, 'path' => $path); } } $list['list'] = $tree; return $list; } /** * Download S3 files to moodle * * @param string $filepath * @param string $file The file path in moodle * @return array The local stored path */ public function get_file($filepath, $file = '') { list($bucket, $uri) = $this->explode_path($filepath); $path = $this->prepare_file($file); try { $this->s->getObject($bucket, $uri, $path); } catch (S3Exception $e) { throw new moodle_exception( 'errorwhilecommunicatingwith', 'repository', '', $this->get_name(), $e->getMessage() ); } return array('path' => $path); } /** * Return the source information * * @param stdClass $filepath * @return string */ public function get_file_source_info($filepath) { return 'Amazon S3: ' . $filepath; } /** * S3 doesn't require login * * @return bool */ public function check_login() { return true; } /** * S3 doesn't provide search * * @return bool */ public function global_search() { return false; } public static function get_type_option_names() { return array('access_key', 'secret_key', 'endpoint', 'pluginname'); } public static function type_config_form($mform, $classname = 'repository') { parent::type_config_form($mform); $strrequired = get_string('required'); $endpointselect = array( // List of possible Amazon S3 Endpoints. "s3.amazonaws.com" => "s3.amazonaws.com", "s3-external-1.amazonaws.com" => "s3-external-1.amazonaws.com", "s3-us-west-2.amazonaws.com" => "s3-us-west-2.amazonaws.com", "s3-us-west-1.amazonaws.com" => "s3-us-west-1.amazonaws.com", "s3-eu-west-1.amazonaws.com" => "s3-eu-west-1.amazonaws.com", "s3.eu-central-1.amazonaws.com" => "s3.eu-central-1.amazonaws.com", "s3-eu-central-1.amazonaws.com" => "s3-eu-central-1.amazonaws.com", "s3-ap-southeast-1.amazonaws.com" => "s3-ap-southeast-1.amazonaws.com", "s3-ap-southeast-2.amazonaws.com" => "s3-ap-southeast-2.amazonaws.com", "s3-ap-northeast-1.amazonaws.com" => "s3-ap-northeast-1.amazonaws.com", "s3-sa-east-1.amazonaws.com" => "s3-sa-east-1.amazonaws.com" ); $mform->addElement('text', 'access_key', get_string('access_key', 'repository_s3')); $mform->setType('access_key', PARAM_RAW_TRIMMED); $mform->addElement('text', 'secret_key', get_string('secret_key', 'repository_s3')); $mform->setType('secret_key', PARAM_RAW_TRIMMED); $mform->addElement('select', 'endpoint', get_string('endpoint', 'repository_s3'), $endpointselect); $mform->setDefault('endpoint', 's3.amazonaws.com'); // Default to US Endpoint. $mform->addRule('access_key', $strrequired, 'required', null, 'client'); $mform->addRule('secret_key', $strrequired, 'required', null, 'client'); } /** * S3 plugins doesn't support return links of files * * @return int */ public function supported_returntypes() { return FILE_INTERNAL; } /** * Is this repository accessing private data? * * @return bool */ public function contains_private_data() { return false; } } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/media/lib.php 0000644 00000012637 15152177312 0021025 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_media * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Initialise the js strings required for this plugin */ function atto_media_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('add', 'addcaptionstrack', 'addchapterstrack', 'adddescriptionstrack', 'addmetadatatrack', 'addsource', 'addsubtitlestrack', 'addtrack', 'advancedsettings', 'audio', 'audiosourcelabel', 'autoplay', 'browserepositories', 'browserepositories', 'captions', 'captionssourcelabel', 'chapters', 'chapterssourcelabel', 'controls', 'createmedia', 'default', 'descriptions', 'descriptionssourcelabel', 'displayoptions', 'entername', 'entertitle', 'entersource', 'enterurl', 'height', 'kind', 'label', 'languagesavailable', 'languagesinstalled', 'link', 'loop', 'metadata', 'metadatasourcelabel', 'mute', 'poster', 'remove', 'size', 'srclang', 'subtitles', 'subtitlessourcelabel', 'track', 'tracks', 'video', 'videoheight', 'videosourcelabel', 'videowidth', 'width'), 'atto_media'); $PAGE->requires->strings_for_js(array('expand', 'collapse'), 'moodle'); } /** * Sends the parameters to the JS module. * * @return array */ function atto_media_params_for_js() { global $OUTPUT; global $PAGE; $currentlang = current_language(); $langsinstalled = get_string_manager()->get_list_of_translations(true); $langsavailable = get_string_manager()->get_list_of_languages(); $params = [ 'langs' => ['installed' => [], 'available' => []], 'help' => [] ]; foreach ($langsinstalled as $code => $name) { $params['langs']['installed'][] = [ 'lang' => $name, 'code' => $code, 'default' => $currentlang == $code ]; } foreach ($langsavailable as $code => $name) { // See MDL-50829 for an explanation of this lrm thing. $lrm = json_decode('"\u200E"'); $params['langs']['available'][] = [ 'lang' => $name . ' ' . $lrm . '(' . $code . ')' . $lrm, 'code' => $code]; } $params['help'] = [ 'addsource' => $OUTPUT->help_icon('addsource', 'atto_media'), 'tracks' => $OUTPUT->help_icon('tracks', 'atto_media'), 'subtitles' => $OUTPUT->help_icon('subtitles', 'atto_media'), 'captions' => $OUTPUT->help_icon('captions', 'atto_media'), 'descriptions' => $OUTPUT->help_icon('descriptions', 'atto_media'), 'chapters' => $OUTPUT->help_icon('chapters', 'atto_media'), 'metadata' => $OUTPUT->help_icon('metadata', 'atto_media') ]; return $params; } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/title/lib.php 0000644 00000002347 15152177325 0021070 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_title * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); function atto_title_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('h3', 'h4', 'h5', 'pre', 'p'), 'atto_title'); } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/image/lib.php 0000644 00000003122 15152177330 0021015 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_image * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Initialise the strings required for js */ function atto_image_strings_for_js() { global $PAGE; $strings = array( 'alignment', 'alignment_bottom', 'alignment_left', 'alignment_middle', 'alignment_right', 'alignment_top', 'browserepositories', 'constrain', 'saveimage', 'imageproperties', 'customstyle', 'enterurl', 'enteralt', 'height', 'presentation', 'presentationoraltrequired', 'imageurlrequired', 'size', 'width', 'uploading', ); $PAGE->requires->strings_for_js($strings, 'atto_image'); } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/emoticon/lib.php 0000644 00000003133 15152177332 0021554 0 ustar 00 <?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/>. /** * Atto text editor emoticon plugin lib. * * @package atto_emoticon * @copyright 2014 Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Initialise the strings required for JS. * * @return void */ function atto_emoticon_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('insertemoticon'), 'atto_emoticon'); // Load the strings required by the emotes. $manager = get_emoticon_manager(); foreach ($manager->get_emoticons(true) as $emote) { $PAGE->requires->string_for_js($emote->altidentifier, $emote->altcomponent); } } /** * Sends the parameters to JS module. * * @return array */ function atto_emoticon_params_for_js($elementid, $options, $fpoptions) { $manager = get_emoticon_manager(); return array( 'emoticons' => $manager->get_emoticons(true) ); } home3/cpr76684/public_html/Aem/mod/assign/lib.php 0000644 00000201407 15152203166 0015315 0 ustar 00 <?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/>. /** * This file contains the moodle hooks for the assign module. * * It delegates most functions to the assignment class. * * @package mod_assign * @copyright 2012 NetSpot {@link http://www.netspot.com.au} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once(__DIR__ . '/deprecatedlib.php'); /** * Adds an assignment instance * * This is done by calling the add_instance() method of the assignment type class * @param stdClass $data * @param mod_assign_mod_form $form * @return int The instance id of the new assignment */ function assign_add_instance(stdClass $data, mod_assign_mod_form $form = null) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $assignment = new assign(context_module::instance($data->coursemodule), null, null); return $assignment->add_instance($data, true); } /** * delete an assignment instance * @param int $id * @return bool */ function assign_delete_instance($id) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $cm = get_coursemodule_from_instance('assign', $id, 0, false, MUST_EXIST); $context = context_module::instance($cm->id); $assignment = new assign($context, null, null); return $assignment->delete_instance(); } /** * This function is used by the reset_course_userdata function in moodlelib. * This function will remove all assignment submissions and feedbacks in the database * and clean up any related data. * * @param stdClass $data the data submitted from the reset course. * @return array */ function assign_reset_userdata($data) { global $CFG, $DB; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $status = array(); $params = array('courseid'=>$data->courseid); $sql = "SELECT a.id FROM {assign} a WHERE a.course=:courseid"; $course = $DB->get_record('course', array('id'=>$data->courseid), '*', MUST_EXIST); if ($assigns = $DB->get_records_sql($sql, $params)) { foreach ($assigns as $assign) { $cm = get_coursemodule_from_instance('assign', $assign->id, $data->courseid, false, MUST_EXIST); $context = context_module::instance($cm->id); $assignment = new assign($context, $cm, $course); $status = array_merge($status, $assignment->reset_userdata($data)); } } return $status; } /** * This standard function will check all instances of this module * and make sure there are up-to-date events created for each of them. * If courseid = 0, then every assignment event in the site is checked, else * only assignment events belonging to the course specified are checked. * * @param int $courseid * @param int|stdClass $instance Assign module instance or ID. * @param int|stdClass $cm Course module object or ID (not used in this module). * @return bool */ function assign_refresh_events($courseid = 0, $instance = null, $cm = null) { global $CFG, $DB; require_once($CFG->dirroot . '/mod/assign/locallib.php'); // If we have instance information then we can just update the one event instead of updating all events. if (isset($instance)) { if (!is_object($instance)) { $instance = $DB->get_record('assign', array('id' => $instance), '*', MUST_EXIST); } if (isset($cm)) { if (!is_object($cm)) { assign_prepare_update_events($instance); return true; } else { $course = get_course($instance->course); assign_prepare_update_events($instance, $course, $cm); return true; } } } if ($courseid) { // Make sure that the course id is numeric. if (!is_numeric($courseid)) { return false; } if (!$assigns = $DB->get_records('assign', array('course' => $courseid))) { return false; } // Get course from courseid parameter. if (!$course = $DB->get_record('course', array('id' => $courseid), '*')) { return false; } } else { if (!$assigns = $DB->get_records('assign')) { return false; } } foreach ($assigns as $assign) { assign_prepare_update_events($assign); } return true; } /** * This actually updates the normal and completion calendar events. * * @param stdClass $assign Assignment object (from DB). * @param stdClass $course Course object. * @param stdClass $cm Course module object. */ function assign_prepare_update_events($assign, $course = null, $cm = null) { global $DB; if (!isset($course)) { // Get course and course module for the assignment. list($course, $cm) = get_course_and_cm_from_instance($assign->id, 'assign', $assign->course); } // Refresh the assignment's calendar events. $context = context_module::instance($cm->id); $assignment = new assign($context, $cm, $course); $assignment->update_calendar($cm->id); // Refresh the calendar events also for the assignment overrides. $overrides = $DB->get_records('assign_overrides', ['assignid' => $assign->id], '', 'id, groupid, userid, duedate, sortorder, timelimit'); foreach ($overrides as $override) { if (empty($override->userid)) { unset($override->userid); } if (empty($override->groupid)) { unset($override->groupid); } assign_update_events($assignment, $override); } } /** * Removes all grades from gradebook * * @param int $courseid The ID of the course to reset * @param string $type Optional type of assignment to limit the reset to a particular assignment type */ function assign_reset_gradebook($courseid, $type='') { global $CFG, $DB; $params = array('moduletype'=>'assign', 'courseid'=>$courseid); $sql = 'SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid FROM {assign} a, {course_modules} cm, {modules} m WHERE m.name=:moduletype AND m.id=cm.module AND cm.instance=a.id AND a.course=:courseid'; if ($assignments = $DB->get_records_sql($sql, $params)) { foreach ($assignments as $assignment) { assign_grade_item_update($assignment, 'reset'); } } } /** * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the assignment. * @param moodleform $mform form passed by reference */ function assign_reset_course_form_definition(&$mform) { $mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign')); $name = get_string('deleteallsubmissions', 'assign'); $mform->addElement('advcheckbox', 'reset_assign_submissions', $name); $mform->addElement('advcheckbox', 'reset_assign_user_overrides', get_string('removealluseroverrides', 'assign')); $mform->addElement('advcheckbox', 'reset_assign_group_overrides', get_string('removeallgroupoverrides', 'assign')); } /** * Course reset form defaults. * @param object $course * @return array */ function assign_reset_course_form_defaults($course) { return array('reset_assign_submissions' => 1, 'reset_assign_group_overrides' => 1, 'reset_assign_user_overrides' => 1); } /** * Update an assignment instance * * This is done by calling the update_instance() method of the assignment type class * @param stdClass $data * @param stdClass $form - unused * @return object */ function assign_update_instance(stdClass $data, $form) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $context = context_module::instance($data->coursemodule); $assignment = new assign($context, null, null); return $assignment->update_instance($data); } /** * This function updates the events associated to the assign. * If $override is non-zero, then it updates only the events * associated with the specified override. * * @param assign $assign the assign object. * @param object $override (optional) limit to a specific override */ function assign_update_events($assign, $override = null) { global $CFG, $DB; require_once($CFG->dirroot . '/calendar/lib.php'); $assigninstance = $assign->get_instance(); // Load the old events relating to this assign. $conds = array('modulename' => 'assign', 'instance' => $assigninstance->id); if (!empty($override)) { // Only load events for this override. if (isset($override->userid)) { $conds['userid'] = $override->userid; } else if (isset($override->groupid)) { $conds['groupid'] = $override->groupid; } else { // This is not a valid override, it may have been left from a bad import or restore. $conds['groupid'] = $conds['userid'] = 0; } } $oldevents = $DB->get_records('event', $conds, 'id ASC'); // Now make a to-do list of all that needs to be updated. if (empty($override)) { // We are updating the primary settings for the assignment, so we need to add all the overrides. $overrides = $DB->get_records('assign_overrides', array('assignid' => $assigninstance->id), 'id ASC'); // It is necessary to add an empty stdClass to the beginning of the array as the $oldevents // list contains the original (non-override) event for the module. If this is not included // the logic below will end up updating the wrong row when we try to reconcile this $overrides // list against the $oldevents list. array_unshift($overrides, new stdClass()); } else { // Just do the one override. $overrides = array($override); } if (!empty($assign->get_course_module())) { $cmid = $assign->get_course_module()->id; } else { $cmid = get_coursemodule_from_instance('assign', $assigninstance->id, $assigninstance->course)->id; } foreach ($overrides as $current) { $groupid = isset($current->groupid) ? $current->groupid : 0; $userid = isset($current->userid) ? $current->userid : 0; $duedate = isset($current->duedate) ? $current->duedate : $assigninstance->duedate; $timelimit = isset($current->timelimit) ? $current->timelimit : 0; // Only add 'due' events for an override if they differ from the assign default. $addclose = empty($current->id) || !empty($current->duedate); $event = new stdClass(); $event->type = CALENDAR_EVENT_TYPE_ACTION; $event->description = format_module_intro('assign', $assigninstance, $cmid, false); $event->format = FORMAT_HTML; // Events module won't show user events when the courseid is nonzero. $event->courseid = ($userid) ? 0 : $assigninstance->course; $event->groupid = $groupid; $event->userid = $userid; $event->modulename = 'assign'; $event->instance = $assigninstance->id; $event->timestart = $duedate; $event->timeduration = $timelimit; $event->timesort = $event->timestart + $event->timeduration; $event->visible = instance_is_visible('assign', $assigninstance); $event->eventtype = ASSIGN_EVENT_TYPE_DUE; $event->priority = null; // Determine the event name and priority. if ($groupid) { // Group override event. $params = new stdClass(); $params->assign = $assigninstance->name; $params->group = groups_get_group_name($groupid); if ($params->group === false) { // Group doesn't exist, just skip it. continue; } $eventname = get_string('overridegroupeventname', 'assign', $params); // Set group override priority. if (isset($current->sortorder)) { $event->priority = $current->sortorder; } } else if ($userid) { // User override event. $params = new stdClass(); $params->assign = $assigninstance->name; $eventname = get_string('overrideusereventname', 'assign', $params); // Set user override priority. $event->priority = CALENDAR_EVENT_USER_OVERRIDE_PRIORITY; } else { // The parent event. $eventname = $assigninstance->name; } if ($duedate && $addclose) { if ($oldevent = array_shift($oldevents)) { $event->id = $oldevent->id; } else { unset($event->id); } $event->name = $eventname.' ('.get_string('duedate', 'assign').')'; calendar_event::create($event, false); } } // Delete any leftover events. foreach ($oldevents as $badevent) { $badevent = calendar_event::load($badevent); $badevent->delete(); } } /** * Return the list if Moodle features this module supports * * @param string $feature FEATURE_xx constant for requested feature * @return mixed True if module supports feature, false if not, null if doesn't know or string for the module purpose. */ function assign_supports($feature) { switch($feature) { case FEATURE_GROUPS: return true; case FEATURE_GROUPINGS: return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_COMPLETION_HAS_RULES: return true; case FEATURE_GRADE_HAS_GRADE: return true; case FEATURE_GRADE_OUTCOMES: return true; case FEATURE_BACKUP_MOODLE2: return true; case FEATURE_SHOW_DESCRIPTION: return true; case FEATURE_ADVANCED_GRADING: return true; case FEATURE_PLAGIARISM: return true; case FEATURE_COMMENT: return true; case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT; default: return null; } } /** * extend an assigment navigation settings * * @param settings_navigation $settings * @param navigation_node $navref * @return void */ function assign_extend_settings_navigation(settings_navigation $settings, navigation_node $navref) { global $DB; // We want to add these new nodes after the Edit settings node, and before the // Locally assigned roles node. Of course, both of those are controlled by capabilities. $keys = $navref->get_children_key_list(); $beforekey = null; $i = array_search('modedit', $keys); if ($i === false and array_key_exists(0, $keys)) { $beforekey = $keys[0]; } else if (array_key_exists($i + 1, $keys)) { $beforekey = $keys[$i + 1]; } $cm = $settings->get_page()->cm; if (!$cm) { return; } $context = $cm->context; $course = $settings->get_page()->course; if (!$course) { return; } if (has_capability('mod/assign:manageoverrides', $settings->get_page()->cm->context)) { $url = new moodle_url('/mod/assign/overrides.php', ['cmid' => $settings->get_page()->cm->id, 'mode' => 'user']); $node = navigation_node::create(get_string('overrides', 'assign'), $url, navigation_node::TYPE_SETTING, null, 'mod_assign_useroverrides'); $navref->add_node($node, $beforekey); } if (has_capability('mod/assign:revealidentities', $context)) { $dbparams = array('id'=>$cm->instance); $assignment = $DB->get_record('assign', $dbparams, 'blindmarking, revealidentities'); if ($assignment && $assignment->blindmarking && !$assignment->revealidentities) { $urlparams = array('id' => $cm->id, 'action'=>'revealidentities'); $url = new moodle_url('/mod/assign/view.php', $urlparams); $linkname = get_string('revealidentities', 'assign'); $node = $navref->add($linkname, $url, navigation_node::TYPE_SETTING); } } } /** * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information * for the course (see resource). * * Given a course_module object, this function returns any "extra" information that may be needed * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php. * * @param stdClass $coursemodule The coursemodule object (record). * @return cached_cm_info An object on information that the courses * will know about (most noticeably, an icon). */ function assign_get_coursemodule_info($coursemodule) { global $DB; $dbparams = array('id'=>$coursemodule->instance); $fields = 'id, name, alwaysshowdescription, allowsubmissionsfromdate, intro, introformat, completionsubmit, duedate, cutoffdate, allowsubmissionsfromdate'; if (! $assignment = $DB->get_record('assign', $dbparams, $fields)) { return false; } $result = new cached_cm_info(); $result->name = $assignment->name; if ($coursemodule->showdescription) { if ($assignment->alwaysshowdescription || time() > $assignment->allowsubmissionsfromdate) { // Convert intro to html. Do not filter cached version, filters run at display time. $result->content = format_module_intro('assign', $assignment, $coursemodule->id, false); } } // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'. if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) { $result->customdata['customcompletionrules']['completionsubmit'] = $assignment->completionsubmit; } // Populate some other values that can be used in calendar or on dashboard. if ($assignment->duedate) { $result->customdata['duedate'] = $assignment->duedate; } if ($assignment->cutoffdate) { $result->customdata['cutoffdate'] = $assignment->cutoffdate; } if ($assignment->allowsubmissionsfromdate) { $result->customdata['allowsubmissionsfromdate'] = $assignment->allowsubmissionsfromdate; } return $result; } /** * Sets dynamic information about a course module * * This function is called from cm_info when displaying the module * * @param cm_info $cm */ function mod_assign_cm_info_dynamic(cm_info $cm) { global $USER; $cache = cache::make('mod_assign', 'overrides'); $override = $cache->get("{$cm->instance}_u_{$USER->id}"); if (!$override) { $override = (object) [ 'allowsubmissionsfromdate' => null, 'duedate' => null, 'cutoffdate' => null, ]; } // No need to look for group overrides if there are user overrides for all allowsubmissionsfromdate, duedate and cutoffdate. if (is_null($override->allowsubmissionsfromdate) || is_null($override->duedate) || is_null($override->cutoffdate)) { $selectedgroupoverride = (object) [ 'allowsubmissionsfromdate' => null, 'duedate' => null, 'cutoffdate' => null, 'sortorder' => PHP_INT_MAX, // So that every sortorder read from DB is less than this. ]; $groupings = groups_get_user_groups($cm->course, $USER->id); foreach ($groupings[0] as $groupid) { $groupoverride = $cache->get("{$cm->instance}_g_{$groupid}"); if ($groupoverride) { if ($groupoverride->sortorder < $selectedgroupoverride->sortorder) { $selectedgroupoverride = $groupoverride; } } } // If there is a user override for a setting, ignore the group override. if (is_null($override->allowsubmissionsfromdate)) { $override->allowsubmissionsfromdate = $selectedgroupoverride->allowsubmissionsfromdate; } if (is_null($override->duedate)) { $override->duedate = $selectedgroupoverride->duedate; } if (is_null($override->cutoffdate)) { $override->cutoffdate = $selectedgroupoverride->cutoffdate; } } // Calculate relative dates. The assignment module calculates relative date only for duedate. // A user or group override always has higher priority over any relative date calculation. if (empty($override->duedate) && !empty($cm->customdata['duedate'])) { $course = get_course($cm->course); $usercoursedates = course_get_course_dates_for_user_id($course, $USER->id); if ($usercoursedates['start']) { $override->duedate = $cm->customdata['duedate'] + $usercoursedates['startoffset']; } } // Populate some other values that can be used in calendar or on dashboard. if (!is_null($override->allowsubmissionsfromdate)) { $cm->override_customdata('allowsubmissionsfromdate', $override->allowsubmissionsfromdate); } if (!is_null($override->duedate)) { $cm->override_customdata('duedate', $override->duedate); } if (!is_null($override->cutoffdate)) { $cm->override_customdata('cutoffdate', $override->cutoffdate); } } /** * Callback which returns human-readable strings describing the active completion custom rules for the module instance. * * @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules'] * @return array $descriptions the array of descriptions for the custom rules. */ function mod_assign_get_completion_active_rule_descriptions($cm) { // Values will be present in cm_info, and we assume these are up to date. if (empty($cm->customdata['customcompletionrules']) || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) { return []; } $descriptions = []; foreach ($cm->customdata['customcompletionrules'] as $key => $val) { switch ($key) { case 'completionsubmit': if (!empty($val)) { $descriptions[] = get_string('completionsubmit', 'assign'); } break; default: break; } } return $descriptions; } /** * Return a list of page types * @param string $pagetype current page type * @param stdClass $parentcontext Block's parent context * @param stdClass $currentcontext Current context of block */ function assign_page_type_list($pagetype, $parentcontext, $currentcontext) { $modulepagetype = array( 'mod-assign-*' => get_string('page-mod-assign-x', 'assign'), 'mod-assign-view' => get_string('page-mod-assign-view', 'assign'), ); return $modulepagetype; } /** * @deprecated since Moodle 3.3, when the block_course_overview block was removed. */ function assign_print_overview() { throw new coding_exception('assign_print_overview() can not be used any more and is obsolete.'); } /** * @deprecated since Moodle 3.3, when the block_course_overview block was removed. */ function assign_get_mysubmission_details_for_print_overview() { throw new coding_exception('assign_get_mysubmission_details_for_print_overview() can not be used any more and is obsolete.'); } /** * @deprecated since Moodle 3.3, when the block_course_overview block was removed. */ function assign_get_grade_details_for_print_overview() { throw new coding_exception('assign_get_grade_details_for_print_overview() can not be used any more and is obsolete.'); } /** * Print recent activity from all assignments in a given course * * This is used by the recent activity block * @param mixed $course the course to print activity for * @param bool $viewfullnames boolean to determine whether to show full names or not * @param int $timestart the time the rendering started * @return bool true if activity was printed, false otherwise. */ function assign_print_recent_activity($course, $viewfullnames, $timestart) { global $CFG, $USER, $DB, $OUTPUT; require_once($CFG->dirroot . '/mod/assign/locallib.php'); // Do not use log table if possible, it may be huge. $dbparams = array($timestart, $course->id, 'assign', ASSIGN_SUBMISSION_STATUS_SUBMITTED); $userfieldsapi = \core_user\fields::for_userpic(); $namefields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects;; if (!$submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, um.id as recordid, $namefields FROM {assign_submission} asb JOIN {assign} a ON a.id = asb.assignment JOIN {course_modules} cm ON cm.instance = a.id JOIN {modules} md ON md.id = cm.module JOIN {user} u ON u.id = asb.userid LEFT JOIN {assign_user_mapping} um ON um.userid = u.id AND um.assignment = a.id WHERE asb.timemodified > ? AND asb.latest = 1 AND a.course = ? AND md.name = ? AND asb.status = ? ORDER BY asb.timemodified ASC", $dbparams)) { return false; } $modinfo = get_fast_modinfo($course); $show = array(); $grader = array(); $showrecentsubmissions = get_config('assign', 'showrecentsubmissions'); foreach ($submissions as $submission) { if (!array_key_exists($submission->cmid, $modinfo->get_cms())) { continue; } $cm = $modinfo->get_cm($submission->cmid); if (!$cm->uservisible) { continue; } if ($submission->userid == $USER->id) { $show[] = $submission; continue; } $context = context_module::instance($submission->cmid); // The act of submitting of assignment may be considered private - // only graders will see it if specified. if (empty($showrecentsubmissions)) { if (!array_key_exists($cm->id, $grader)) { $grader[$cm->id] = has_capability('moodle/grade:viewall', $context); } if (!$grader[$cm->id]) { continue; } } $groupmode = groups_get_activity_groupmode($cm, $course); if ($groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context)) { if (isguestuser()) { // Shortcut - guest user does not belong into any group. continue; } // This will be slow - show only users that share group with me in this cm. if (!$modinfo->get_groups($cm->groupingid)) { continue; } $usersgroups = groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); if (is_array($usersgroups)) { $usersgroups = array_keys($usersgroups); $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); if (empty($intersect)) { continue; } } } $show[] = $submission; } if (empty($show)) { return false; } echo $OUTPUT->heading(get_string('newsubmissions', 'assign') . ':', 6); foreach ($show as $submission) { $cm = $modinfo->get_cm($submission->cmid); $context = context_module::instance($submission->cmid); $assign = new assign($context, $cm, $cm->course); $link = $CFG->wwwroot.'/mod/assign/view.php?id='.$cm->id; // Obscure first and last name if blind marking enabled. if ($assign->is_blind_marking()) { $submission->firstname = get_string('participant', 'mod_assign'); if (empty($submission->recordid)) { $submission->recordid = $assign->get_uniqueid_for_user($submission->userid); } $submission->lastname = $submission->recordid; } print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames); } return true; } /** * Returns all assignments since a given time. * * @param array $activities The activity information is returned in this array * @param int $index The current index in the activities array * @param int $timestart The earliest activity to show * @param int $courseid Limit the search to this course * @param int $cmid The course module id * @param int $userid Optional user id * @param int $groupid Optional group id * @return void */ function assign_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) { global $CFG, $COURSE, $USER, $DB; require_once($CFG->dirroot . '/mod/assign/locallib.php'); if ($COURSE->id == $courseid) { $course = $COURSE; } else { $course = $DB->get_record('course', array('id'=>$courseid)); } $modinfo = get_fast_modinfo($course); $cm = $modinfo->get_cm($cmid); $params = array(); if ($userid) { $userselect = 'AND u.id = :userid'; $params['userid'] = $userid; } else { $userselect = ''; } if ($groupid) { $groupselect = 'AND gm.groupid = :groupid'; $groupjoin = 'JOIN {groups_members} gm ON gm.userid=u.id'; $params['groupid'] = $groupid; } else { $groupselect = ''; $groupjoin = ''; } $params['cminstance'] = $cm->instance; $params['timestart'] = $timestart; $params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED; $userfieldsapi = \core_user\fields::for_userpic(); $userfields = $userfieldsapi->get_sql('u', false, '', 'userid', false)->selects; if (!$submissions = $DB->get_records_sql('SELECT asb.id, asb.timemodified, ' . $userfields . ' FROM {assign_submission} asb JOIN {assign} a ON a.id = asb.assignment JOIN {user} u ON u.id = asb.userid ' . $groupjoin . ' WHERE asb.timemodified > :timestart AND asb.status = :submitted AND a.id = :cminstance ' . $userselect . ' ' . $groupselect . ' ORDER BY asb.timemodified ASC', $params)) { return; } $groupmode = groups_get_activity_groupmode($cm, $course); $cmcontext = context_module::instance($cm->id); $grader = has_capability('moodle/grade:viewall', $cmcontext); $accessallgroups = has_capability('moodle/site:accessallgroups', $cmcontext); $viewfullnames = has_capability('moodle/site:viewfullnames', $cmcontext); $showrecentsubmissions = get_config('assign', 'showrecentsubmissions'); $show = array(); foreach ($submissions as $submission) { if ($submission->userid == $USER->id) { $show[] = $submission; continue; } // The act of submitting of assignment may be considered private - // only graders will see it if specified. if (empty($showrecentsubmissions)) { if (!$grader) { continue; } } if ($groupmode == SEPARATEGROUPS and !$accessallgroups) { if (isguestuser()) { // Shortcut - guest user does not belong into any group. continue; } // This will be slow - show only users that share group with me in this cm. if (!$modinfo->get_groups($cm->groupingid)) { continue; } $usersgroups = groups_get_all_groups($course->id, $submission->userid, $cm->groupingid); if (is_array($usersgroups)) { $usersgroups = array_keys($usersgroups); $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); if (empty($intersect)) { continue; } } } $show[] = $submission; } if (empty($show)) { return; } if ($grader) { require_once($CFG->libdir.'/gradelib.php'); $userids = array(); foreach ($show as $id => $submission) { $userids[] = $submission->userid; } $grades = grade_get_grades($courseid, 'mod', 'assign', $cm->instance, $userids); } $aname = format_string($cm->name, true); foreach ($show as $submission) { $activity = new stdClass(); $activity->type = 'assign'; $activity->cmid = $cm->id; $activity->name = $aname; $activity->sectionnum = $cm->sectionnum; $activity->timestamp = $submission->timemodified; $activity->user = new stdClass(); if ($grader) { $activity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade; } $userfields = explode(',', implode(',', \core_user\fields::get_picture_fields())); foreach ($userfields as $userfield) { if ($userfield == 'id') { // Aliased in SQL above. $activity->user->{$userfield} = $submission->userid; } else { $activity->user->{$userfield} = $submission->{$userfield}; } } $activity->user->fullname = fullname($submission, $viewfullnames); $activities[$index++] = $activity; } return; } /** * Print recent activity from all assignments in a given course * * This is used by course/recent.php * @param stdClass $activity * @param int $courseid * @param bool $detail * @param array $modnames */ function assign_print_recent_mod_activity($activity, $courseid, $detail, $modnames) { global $CFG, $OUTPUT; echo '<table border="0" cellpadding="3" cellspacing="0" class="assignment-recent">'; echo '<tr><td class="userpicture" valign="top">'; echo $OUTPUT->user_picture($activity->user); echo '</td><td>'; if ($detail) { $modname = $modnames[$activity->type]; echo '<div class="title">'; echo $OUTPUT->image_icon('monologo', $modname, 'assign'); echo '<a href="' . $CFG->wwwroot . '/mod/assign/view.php?id=' . $activity->cmid . '">'; echo $activity->name; echo '</a>'; echo '</div>'; } if (isset($activity->grade)) { echo '<div class="grade">'; echo get_string('gradenoun') . ': '; echo $activity->grade; echo '</div>'; } echo '<div class="user">'; echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->id}&course=$courseid\">"; echo "{$activity->user->fullname}</a> - " . userdate($activity->timestamp); echo '</div>'; echo '</td></tr></table>'; } /** * @deprecated since Moodle 3.8 */ function assign_scale_used() { throw new coding_exception('assign_scale_used() can not be used anymore. Plugins can implement ' . '<modname>_scale_used_anywhere, all implementations of <modname>_scale_used are now ignored'); } /** * Checks if scale is being used by any instance of assignment * * This is used to find out if scale used anywhere * @param int $scaleid * @return boolean True if the scale is used by any assignment */ function assign_scale_used_anywhere($scaleid) { global $DB; if ($scaleid and $DB->record_exists('assign', array('grade'=>-$scaleid))) { return true; } else { return false; } } /** * List the actions that correspond to a view of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = 'r' and edulevel = LEVEL_PARTICIPATING will * be considered as view action. * * @return array */ function assign_get_view_actions() { return array('view submission', 'view feedback'); } /** * List the actions that correspond to a post of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING * will be considered as post action. * * @return array */ function assign_get_post_actions() { return array('upload', 'submit', 'submit for grading'); } /** * Returns all other capabilities used by this module. * @return array Array of capability strings */ function assign_get_extra_capabilities() { return ['gradereport/grader:view', 'moodle/grade:viewall']; } /** * Create grade item for given assignment. * * @param stdClass $assign record with extra cmidnumber * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook * @return int 0 if ok, error code otherwise */ function assign_grade_item_update($assign, $grades=null) { global $CFG; require_once($CFG->libdir.'/gradelib.php'); if (!isset($assign->courseid)) { $assign->courseid = $assign->course; } $params = array('itemname'=>$assign->name, 'idnumber'=>$assign->cmidnumber); // Check if feedback plugin for gradebook is enabled, if yes then // gradetype = GRADE_TYPE_TEXT else GRADE_TYPE_NONE. $gradefeedbackenabled = false; if (isset($assign->gradefeedbackenabled)) { $gradefeedbackenabled = $assign->gradefeedbackenabled; } else if ($assign->grade == 0) { // Grade feedback is needed only when grade == 0. require_once($CFG->dirroot . '/mod/assign/locallib.php'); $mod = get_coursemodule_from_instance('assign', $assign->id, $assign->courseid); $cm = context_module::instance($mod->id); $assignment = new assign($cm, null, null); $gradefeedbackenabled = $assignment->is_gradebook_feedback_enabled(); } if ($assign->grade > 0) { $params['gradetype'] = GRADE_TYPE_VALUE; $params['grademax'] = $assign->grade; $params['grademin'] = 0; } else if ($assign->grade < 0) { $params['gradetype'] = GRADE_TYPE_SCALE; $params['scaleid'] = -$assign->grade; } else if ($gradefeedbackenabled) { // $assign->grade == 0 and feedback enabled. $params['gradetype'] = GRADE_TYPE_TEXT; } else { // $assign->grade == 0 and no feedback enabled. $params['gradetype'] = GRADE_TYPE_NONE; } if ($grades === 'reset') { $params['reset'] = true; $grades = null; } return grade_update('mod/assign', $assign->courseid, 'mod', 'assign', $assign->id, 0, $grades, $params); } /** * Return grade for given user or all users. * * @param stdClass $assign record of assign with an additional cmidnumber * @param int $userid optional user id, 0 means all users * @return array array of grades, false if none */ function assign_get_user_grades($assign, $userid=0) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $cm = get_coursemodule_from_instance('assign', $assign->id, 0, false, MUST_EXIST); $context = context_module::instance($cm->id); $assignment = new assign($context, null, null); $assignment->set_instance($assign); return $assignment->get_user_grades_for_gradebook($userid); } /** * Update activity grades. * * @param stdClass $assign database record * @param int $userid specific user only, 0 means all * @param bool $nullifnone - not used */ function assign_update_grades($assign, $userid=0, $nullifnone=true) { global $CFG; require_once($CFG->libdir.'/gradelib.php'); if ($assign->grade == 0) { assign_grade_item_update($assign); } else if ($grades = assign_get_user_grades($assign, $userid)) { foreach ($grades as $k => $v) { if ($v->rawgrade == -1) { $grades[$k]->rawgrade = null; } } assign_grade_item_update($assign, $grades); } else { assign_grade_item_update($assign); } } /** * List the file areas that can be browsed. * * @param stdClass $course * @param stdClass $cm * @param stdClass $context * @return array */ function assign_get_file_areas($course, $cm, $context) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $areas = array( ASSIGN_INTROATTACHMENT_FILEAREA => get_string('introattachments', 'mod_assign'), ASSIGN_ACTIVITYATTACHMENT_FILEAREA => get_string('activityattachments', 'mod_assign'), ); $assignment = new assign($context, $cm, $course); foreach ($assignment->get_submission_plugins() as $plugin) { if ($plugin->is_visible()) { $pluginareas = $plugin->get_file_areas(); if ($pluginareas) { $areas = array_merge($areas, $pluginareas); } } } foreach ($assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible()) { $pluginareas = $plugin->get_file_areas(); if ($pluginareas) { $areas = array_merge($areas, $pluginareas); } } } return $areas; } /** * File browsing support for assign module. * * @param file_browser $browser * @param object $areas * @param object $course * @param object $cm * @param object $context * @param string $filearea * @param int $itemid * @param string $filepath * @param string $filename * @return object file_info instance or null if not found */ function assign_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); if ($context->contextlevel != CONTEXT_MODULE) { return null; } $urlbase = $CFG->wwwroot.'/pluginfile.php'; $fs = get_file_storage(); $filepath = is_null($filepath) ? '/' : $filepath; $filename = is_null($filename) ? '.' : $filename; // Need to find where this belongs to. $assignment = new assign($context, $cm, $course); if ($filearea === ASSIGN_INTROATTACHMENT_FILEAREA || $filearea === ASSIGN_ACTIVITYATTACHMENT_FILEAREA) { if (!has_capability('moodle/course:managefiles', $context)) { // Students can not peak here! return null; } if (!($storedfile = $fs->get_file($assignment->get_context()->id, 'mod_assign', $filearea, 0, $filepath, $filename))) { return null; } return new file_info_stored($browser, $assignment->get_context(), $storedfile, $urlbase, $filearea, $itemid, true, true, false); } $pluginowner = null; foreach ($assignment->get_submission_plugins() as $plugin) { if ($plugin->is_visible()) { $pluginareas = $plugin->get_file_areas(); if (array_key_exists($filearea, $pluginareas)) { $pluginowner = $plugin; break; } } } if (!$pluginowner) { foreach ($assignment->get_feedback_plugins() as $plugin) { if ($plugin->is_visible()) { $pluginareas = $plugin->get_file_areas(); if (array_key_exists($filearea, $pluginareas)) { $pluginowner = $plugin; break; } } } } if (!$pluginowner) { return null; } $result = $pluginowner->get_file_info($browser, $filearea, $itemid, $filepath, $filename); return $result; } /** * Prints the complete info about a user's interaction with an assignment. * * @param stdClass $course * @param stdClass $user * @param stdClass $coursemodule * @param stdClass $assign the database assign record * * This prints the submission summary and feedback summary for this student. */ function assign_user_complete($course, $user, $coursemodule, $assign) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $context = context_module::instance($coursemodule->id); $assignment = new assign($context, $coursemodule, $course); echo $assignment->view_student_summary($user, false); } /** * Rescale all grades for this activity and push the new grades to the gradebook. * * @param stdClass $course Course db record * @param stdClass $cm Course module db record * @param float $oldmin * @param float $oldmax * @param float $newmin * @param float $newmax */ function assign_rescale_activity_grades($course, $cm, $oldmin, $oldmax, $newmin, $newmax) { global $DB; if ($oldmax <= $oldmin) { // Grades cannot be scaled. return false; } $scale = ($newmax - $newmin) / ($oldmax - $oldmin); if (($newmax - $newmin) <= 1) { // We would lose too much precision, lets bail. return false; } $params = array( 'p1' => $oldmin, 'p2' => $scale, 'p3' => $newmin, 'a' => $cm->instance ); // Only rescale grades that are greater than or equal to 0. Anything else is a special value. $sql = 'UPDATE {assign_grades} set grade = (((grade - :p1) * :p2) + :p3) where assignment = :a and grade >= 0'; $dbupdate = $DB->execute($sql, $params); if (!$dbupdate) { return false; } // Now re-push all grades to the gradebook. $dbparams = array('id' => $cm->instance); $assign = $DB->get_record('assign', $dbparams); $assign->cmidnumber = $cm->idnumber; assign_update_grades($assign); return true; } /** * Print the grade information for the assignment for this user. * * @param stdClass $course * @param stdClass $user * @param stdClass $coursemodule * @param stdClass $assignment */ function assign_user_outline($course, $user, $coursemodule, $assignment) { global $CFG; require_once($CFG->libdir.'/gradelib.php'); require_once($CFG->dirroot.'/grade/grading/lib.php'); $gradinginfo = grade_get_grades($course->id, 'mod', 'assign', $assignment->id, $user->id); $gradingitem = $gradinginfo->items[0]; $gradebookgrade = $gradingitem->grades[$user->id]; if (empty($gradebookgrade->str_long_grade)) { return null; } $result = new stdClass(); if (!$gradingitem->hidden || has_capability('moodle/grade:viewhidden', context_course::instance($course->id))) { $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->str_long_grade); } else { $result->info = get_string('gradenoun') . ': ' . get_string('hidden', 'grades'); } $result->time = $gradebookgrade->dategraded; return $result; } /** * Serves intro attachment files. * * @param mixed $course course or id of the course * @param mixed $cm course module or id of the course module * @param context $context * @param string $filearea * @param array $args * @param bool $forcedownload * @param array $options additional options affecting the file serving * @return bool false if file not found, does not return if found - just send the file */ function assign_pluginfile($course, $cm, context $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG; if ($context->contextlevel != CONTEXT_MODULE) { return false; } require_login($course, false, $cm); if (!has_capability('mod/assign:view', $context)) { return false; } require_once($CFG->dirroot . '/mod/assign/locallib.php'); $assign = new assign($context, $cm, $course); if ($filearea !== ASSIGN_INTROATTACHMENT_FILEAREA && $filearea !== ASSIGN_ACTIVITYATTACHMENT_FILEAREA) { return false; } if (!$assign->show_intro()) { return false; } $itemid = (int)array_shift($args); if ($itemid != 0) { return false; } $relativepath = implode('/', $args); $fullpath = "/{$context->id}/mod_assign/$filearea/$itemid/$relativepath"; $fs = get_file_storage(); if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { return false; } send_stored_file($file, 0, 0, $forcedownload, $options); } /** * Serve the grading panel as a fragment. * * @param array $args List of named arguments for the fragment loader. * @return string */ function mod_assign_output_fragment_gradingpanel($args) { global $CFG; $context = $args['context']; if ($context->contextlevel != CONTEXT_MODULE) { return null; } require_once($CFG->dirroot . '/mod/assign/locallib.php'); $assign = new assign($context, null, null); $userid = clean_param($args['userid'], PARAM_INT); $participant = $assign->get_participant($userid); $isfiltered = $assign->is_userid_filtered($userid); if (!$participant || !$isfiltered) { // User is not enrolled or filtered out by filters and table preferences. return ''; } $attemptnumber = clean_param($args['attemptnumber'], PARAM_INT); $formdata = array(); if (!empty($args['jsonformdata'])) { $serialiseddata = json_decode($args['jsonformdata']); parse_str($serialiseddata, $formdata); } $viewargs = array( 'userid' => $userid, 'attemptnumber' => $attemptnumber, 'formdata' => $formdata ); return $assign->view('gradingpanel', $viewargs); } /** * Check if the module has any update that affects the current user since a given time. * * @param cm_info $cm course module data * @param int $from the time to check updates from * @param array $filter if we need to check only specific updates * @return stdClass an object with the different type of areas indicating if they were updated or not * @since Moodle 3.2 */ function assign_check_updates_since(cm_info $cm, $from, $filter = array()) { global $DB, $USER, $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $updates = new stdClass(); $updates = course_check_module_updates_since($cm, $from, array(ASSIGN_INTROATTACHMENT_FILEAREA), $filter); // Check if there is a new submission by the user or new grades. $select = 'assignment = :id AND userid = :userid AND (timecreated > :since1 OR timemodified > :since2)'; $params = array('id' => $cm->instance, 'userid' => $USER->id, 'since1' => $from, 'since2' => $from); $updates->submissions = (object) array('updated' => false); $submissions = $DB->get_records_select('assign_submission', $select, $params, '', 'id'); if (!empty($submissions)) { $updates->submissions->updated = true; $updates->submissions->itemids = array_keys($submissions); } $updates->grades = (object) array('updated' => false); $grades = $DB->get_records_select('assign_grades', $select, $params, '', 'id'); if (!empty($grades)) { $updates->grades->updated = true; $updates->grades->itemids = array_keys($grades); } // Now, teachers should see other students updates. if (has_capability('mod/assign:viewgrades', $cm->context)) { $params = array('id' => $cm->instance, 'since1' => $from, 'since2' => $from); $select = 'assignment = :id AND (timecreated > :since1 OR timemodified > :since2)'; if (groups_get_activity_groupmode($cm) == SEPARATEGROUPS) { $groupusers = array_keys(groups_get_activity_shared_group_members($cm)); if (empty($groupusers)) { return $updates; } list($insql, $inparams) = $DB->get_in_or_equal($groupusers, SQL_PARAMS_NAMED); $select .= ' AND userid ' . $insql; $params = array_merge($params, $inparams); } $updates->usersubmissions = (object) array('updated' => false); $submissions = $DB->get_records_select('assign_submission', $select, $params, '', 'id'); if (!empty($submissions)) { $updates->usersubmissions->updated = true; $updates->usersubmissions->itemids = array_keys($submissions); } $updates->usergrades = (object) array('updated' => false); $grades = $DB->get_records_select('assign_grades', $select, $params, '', 'id'); if (!empty($grades)) { $updates->usergrades->updated = true; $updates->usergrades->itemids = array_keys($grades); } } return $updates; } /** * Is the event visible? * * This is used to determine global visibility of an event in all places throughout Moodle. For example, * the ASSIGN_EVENT_TYPE_GRADINGDUE event will not be shown to students on their calendar. * * @param calendar_event $event * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). * @return bool Returns true if the event is visible to the current user, false otherwise. */ function mod_assign_core_calendar_is_event_visible(calendar_event $event, $userid = 0) { global $CFG, $USER; require_once($CFG->dirroot . '/mod/assign/locallib.php'); if (empty($userid)) { $userid = $USER->id; } $cm = get_fast_modinfo($event->courseid, $userid)->instances['assign'][$event->instance]; $context = context_module::instance($cm->id); $assign = new assign($context, $cm, null); if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) { return $assign->can_grade($userid); } else { return true; } } /** * This function receives a calendar event and returns the action associated with it, or null if there is none. * * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event * is not displayed on the block. * * @param calendar_event $event * @param \core_calendar\action_factory $factory * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). * @return \core_calendar\local\event\entities\action_interface|null */ function mod_assign_core_calendar_provide_event_action(calendar_event $event, \core_calendar\action_factory $factory, $userid = 0) { global $CFG, $USER; require_once($CFG->dirroot . '/mod/assign/locallib.php'); if (empty($userid)) { $userid = $USER->id; } $cm = get_fast_modinfo($event->courseid, $userid)->instances['assign'][$event->instance]; $context = context_module::instance($cm->id); $completion = new \completion_info($cm->get_course()); $completiondata = $completion->get_data($cm, false, $userid); if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { return null; } $assign = new assign($context, $cm, null); // Apply overrides. $assign->update_effective_access($userid); if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) { $name = get_string('gradeverb'); $url = new \moodle_url('/mod/assign/view.php', [ 'id' => $cm->id, 'action' => 'grader' ]); $actionable = $assign->can_grade($userid) && (time() >= $assign->get_instance()->allowsubmissionsfromdate); $itemcount = $actionable ? $assign->count_submissions_need_grading() : 0; } else { $usersubmission = $assign->get_user_submission($userid, false); if ($usersubmission && $usersubmission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) { // The user has already submitted. // We do not want to change the text to edit the submission, we want to remove the event from the Dashboard entirely. return null; } $participant = $assign->get_participant($userid); if (!$participant) { // If the user is not a participant in the assignment then they have // no action to take. This will filter out the events for teachers. return null; } // The user has not yet submitted anything. Show the addsubmission link. $name = get_string('addsubmission', 'assign'); $url = new \moodle_url('/mod/assign/view.php', [ 'id' => $cm->id, 'action' => 'editsubmission' ]); $itemcount = 1; $actionable = $assign->is_any_submission_plugin_enabled() && $assign->can_edit_submission($userid, $userid); } return $factory->create_instance( $name, $url, $itemcount, $actionable ); } /** * Callback function that determines whether an action event should be showing its item count * based on the event type and the item count. * * @param calendar_event $event The calendar event. * @param int $itemcount The item count associated with the action event. * @return bool */ function mod_assign_core_calendar_event_action_shows_item_count(calendar_event $event, $itemcount = 0) { // List of event types where the action event's item count should be shown. $eventtypesshowingitemcount = [ ASSIGN_EVENT_TYPE_GRADINGDUE ]; // For mod_assign, item count should be shown if the event type is 'gradingdue' and there is one or more item count. return in_array($event->eventtype, $eventtypesshowingitemcount) && $itemcount > 0; } /** * This function calculates the minimum and maximum cutoff values for the timestart of * the given event. * * It will return an array with two values, the first being the minimum cutoff value and * the second being the maximum cutoff value. Either or both values can be null, which * indicates there is no minimum or maximum, respectively. * * If a cutoff is required then the function must return an array containing the cutoff * timestamp and error string to display to the user if the cutoff value is violated. * * A minimum and maximum cutoff return value will look like: * [ * [1505704373, 'The due date must be after the sbumission start date'], * [1506741172, 'The due date must be before the cutoff date'] * ] * * If the event does not have a valid timestart range then [false, false] will * be returned. * * @param calendar_event $event The calendar event to get the time range for * @param stdClass $instance The module instance to get the range from * @return array */ function mod_assign_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance) { global $CFG; require_once($CFG->dirroot . '/mod/assign/locallib.php'); $courseid = $event->courseid; $modulename = $event->modulename; $instanceid = $event->instance; $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid]; $context = context_module::instance($coursemodule->id); $assign = new assign($context, null, null); $assign->set_instance($instance); return $assign->get_valid_calendar_event_timestart_range($event); } /** * This function will update the assign module according to the * event that has been modified. * * @throws \moodle_exception * @param \calendar_event $event * @param stdClass $instance The module instance to get the range from */ function mod_assign_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $instance) { global $CFG, $DB; require_once($CFG->dirroot . '/mod/assign/locallib.php'); if (empty($event->instance) || $event->modulename != 'assign') { return; } if ($instance->id != $event->instance) { return; } if (!in_array($event->eventtype, [ASSIGN_EVENT_TYPE_DUE, ASSIGN_EVENT_TYPE_GRADINGDUE])) { return; } $courseid = $event->courseid; $modulename = $event->modulename; $instanceid = $event->instance; $modified = false; $coursemodule = get_fast_modinfo($courseid)->instances[$modulename][$instanceid]; $context = context_module::instance($coursemodule->id); // The user does not have the capability to modify this activity. if (!has_capability('moodle/course:manageactivities', $context)) { return; } $assign = new assign($context, $coursemodule, null); $assign->set_instance($instance); if ($event->eventtype == ASSIGN_EVENT_TYPE_DUE) { // This check is in here because due date events are currently // the only events that can be overridden, so we can save a DB // query if we don't bother checking other events. if ($assign->is_override_calendar_event($event)) { // This is an override event so we should ignore it. return; } $newduedate = $event->timestart; if ($newduedate != $instance->duedate) { $instance->duedate = $newduedate; $modified = true; } } else if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) { $newduedate = $event->timestart; if ($newduedate != $instance->gradingduedate) { $instance->gradingduedate = $newduedate; $modified = true; } } if ($modified) { $instance->timemodified = time(); // Persist the assign instance changes. $DB->update_record('assign', $instance); $assign->update_calendar($coursemodule->id); $event = \core\event\course_module_updated::create_from_cm($coursemodule, $context); $event->trigger(); } } /** * Return a list of all the user preferences used by mod_assign. * * @return array */ function mod_assign_user_preferences() { $preferences = array(); $preferences['assign_filter'] = array( 'type' => PARAM_ALPHA, 'null' => NULL_NOT_ALLOWED, 'default' => '' ); $preferences['assign_workflowfilter'] = array( 'type' => PARAM_ALPHA, 'null' => NULL_NOT_ALLOWED, 'default' => '' ); $preferences['assign_markerfilter'] = array( 'type' => PARAM_ALPHANUMEXT, 'null' => NULL_NOT_ALLOWED, 'default' => '' ); return $preferences; } /** * Given an array with a file path, it returns the itemid and the filepath for the defined filearea. * * @param string $filearea The filearea. * @param array $args The path (the part after the filearea and before the filename). * @return array The itemid and the filepath inside the $args path, for the defined filearea. */ function mod_assign_get_path_from_pluginfile(string $filearea, array $args) : array { // Assign never has an itemid (the number represents the revision but it's not stored in database). array_shift($args); // Get the filepath. if (empty($args)) { $filepath = '/'; } else { $filepath = '/' . implode('/', $args) . '/'; } return [ 'itemid' => 0, 'filepath' => $filepath, ]; } /** * Callback to fetch the activity event type lang string. * * @param string $eventtype The event type. * @return lang_string The event type lang string. */ function mod_assign_core_calendar_get_event_action_string(string $eventtype): string { $modulename = get_string('modulename', 'assign'); switch ($eventtype) { case ASSIGN_EVENT_TYPE_DUE: $identifier = 'calendardue'; break; case ASSIGN_EVENT_TYPE_GRADINGDUE: $identifier = 'calendargradingdue'; break; default: return get_string('requiresaction', 'calendar', $modulename); } return get_string($identifier, 'assign', $modulename); } home3/cpr76684/public_html/Aem/admin/tool/generator/lib.php 0000644 00000003645 15152205720 0017307 0 ustar 00 <?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/>. /** * Generator tool functions. * * @package tool_generator * @copyright David Monllaó * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Files support. * * Exits if the required permissions are not satisfied. * * @param stdClass $course course object * @param stdClass $cm * @param stdClass $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return void The file is sent along with it's headers */ function tool_generator_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { // Only for admins or CLI. if (!defined('CLI_SCRIPT') && !is_siteadmin()) { die; } if ($context->contextlevel != CONTEXT_SYSTEM) { send_file_not_found(); } $fs = get_file_storage(); $file = $fs->get_file($context->id, 'tool_generator', $filearea, $args[0], '/', $args[1]); // Send the file, always forcing download, we don't want options. \core\session\manager::write_close(); send_stored_file($file, 0, 0, true); } home3/cpr76684/public_html/Aem/enrol/imsenterprise/lib.php 0000644 00000136466 15152206460 0017276 0 ustar 00 <?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/>. /** * IMS Enterprise file enrolment plugin. * * This plugin lets the user specify an IMS Enterprise file to be processed. * The IMS Enterprise file is mainly parsed on a regular cron, * but can also be imported via the UI (Admin Settings). * @package enrol_imsenterprise * @copyright 2010 Eugene Venter * @author Eugene Venter - based on code by Dan Stowell * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot.'/group/lib.php'); /** * IMS Enterprise file enrolment plugin. * * @copyright 2010 Eugene Venter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class enrol_imsenterprise_plugin extends enrol_plugin { /** * @var IMSENTERPRISE_ADD imsenterprise add action. */ const IMSENTERPRISE_ADD = 1; /** * @var IMSENTERPRISE_UPDATE imsenterprise update action. */ const IMSENTERPRISE_UPDATE = 2; /** * @var IMSENTERPRISE_DELETE imsenterprise delete action. */ const IMSENTERPRISE_DELETE = 3; /** * @var $logfp resource file pointer for writing log data to. */ protected $logfp; /** * @var $continueprocessing bool flag to determine if processing should continue. */ protected $continueprocessing; /** * @var $xmlcache string cache of xml lines. */ protected $xmlcache; /** * @var $coursemappings array of mappings between IMS data fields and moodle course fields. */ protected $coursemappings; /** * @var $rolemappings array of mappings between IMS roles and moodle roles. */ protected $rolemappings; /** * @var $defaultcategoryid id of default category. */ protected $defaultcategoryid; /** * Read in an IMS Enterprise file. * Originally designed to handle v1.1 files but should be able to handle * earlier types as well, I believe. * This cron feature has been converted to a scheduled task and it can now be scheduled * from the UI. */ public function cron() { global $CFG; // Get configs. $imsfilelocation = $this->get_config('imsfilelocation'); $logtolocation = $this->get_config('logtolocation'); $mailadmins = $this->get_config('mailadmins'); $prevtime = $this->get_config('prev_time'); $prevmd5 = $this->get_config('prev_md5'); $prevpath = $this->get_config('prev_path'); if (empty($imsfilelocation)) { $filename = "$CFG->dataroot/1/imsenterprise-enrol.xml"; // Default location. } else { $filename = $imsfilelocation; } $this->logfp = false; if (!empty($logtolocation)) { $this->logfp = fopen($logtolocation, 'a'); } $this->defaultcategoryid = null; $fileisnew = false; if ( file_exists($filename) ) { core_php_time_limit::raise(); $starttime = time(); $this->log_line('----------------------------------------------------------------------'); $this->log_line("IMS Enterprise enrol cron process launched at " . userdate(time())); $this->log_line('Found file '.$filename); $this->xmlcache = ''; $categoryseparator = trim($this->get_config('categoryseparator')); $categoryidnumber = $this->get_config('categoryidnumber'); // Make sure we understand how to map the IMS-E roles to Moodle roles. $this->load_role_mappings(); // Make sure we understand how to map the IMS-E course names to Moodle course names. $this->load_course_mappings(); $md5 = md5_file($filename); // NB We'll write this value back to the database at the end of the cron. $filemtime = filemtime($filename); // Decide if we want to process the file (based on filepath, modification time, and MD5 hash) // This is so we avoid wasting the server's efforts processing a file unnecessarily. if ($categoryidnumber && empty($categoryseparator)) { $this->log_line('Category idnumber is enabled but category separator is not defined - skipping processing.'); } else if (empty($prevpath) || ($filename != $prevpath)) { $fileisnew = true; } else if (isset($prevtime) && ($filemtime <= $prevtime)) { $this->log_line('File modification time is not more recent than last update - skipping processing.'); } else if (isset($prevmd5) && ($md5 == $prevmd5)) { $this->log_line('File MD5 hash is same as on last update - skipping processing.'); } else { $fileisnew = true; // Let's process it! } if ($fileisnew) { // The <properties> tag is allowed to halt processing if we're demanding a matching target. $this->continueprocessing = true; // Run through the file and process the group/person entries. if (($fh = fopen($filename, "r")) != false) { $line = 0; while ((!feof($fh)) && $this->continueprocessing) { $line++; $curline = fgets($fh); $this->xmlcache .= $curline; // Add a line onto the XML cache. while (true) { // If we've got a full tag (i.e. the most recent line has closed the tag) then process-it-and-forget-it. // Must always make sure to remove tags from cache so they don't clog up our memory. if ($tagcontents = $this->full_tag_found_in_cache('group', $curline)) { $this->process_group_tag($tagcontents); $this->remove_tag_from_cache('group'); } else if ($tagcontents = $this->full_tag_found_in_cache('person', $curline)) { $this->process_person_tag($tagcontents); $this->remove_tag_from_cache('person'); } else if ($tagcontents = $this->full_tag_found_in_cache('membership', $curline)) { $this->process_membership_tag($tagcontents); $this->remove_tag_from_cache('membership'); } else if ($tagcontents = $this->full_tag_found_in_cache('comments', $curline)) { $this->remove_tag_from_cache('comments'); } else if ($tagcontents = $this->full_tag_found_in_cache('properties', $curline)) { $this->process_properties_tag($tagcontents); $this->remove_tag_from_cache('properties'); } else { break; } } } fclose($fh); fix_course_sortorder(); } $timeelapsed = time() - $starttime; $this->log_line('Process has completed. Time taken: '.$timeelapsed.' seconds.'); } // These variables are stored so we can compare them against the IMS file, next time round. $this->set_config('prev_time', $filemtime); $this->set_config('prev_md5', $md5); $this->set_config('prev_path', $filename); } else { $this->log_line('File not found: '.$filename); } if (!empty($mailadmins) && $fileisnew) { $timeelapsed = isset($timeelapsed) ? $timeelapsed : 0; $msg = "An IMS enrolment has been carried out within Moodle.\nTime taken: $timeelapsed seconds.\n\n"; if (!empty($logtolocation)) { if ($this->logfp) { $msg .= "Log data has been written to:\n"; $msg .= "$logtolocation\n"; $msg .= "(Log file size: ".ceil(filesize($logtolocation) / 1024)."Kb)\n\n"; } else { $msg .= "The log file appears not to have been successfully written.\n"; $msg .= "Check that the file is writeable by the server:\n"; $msg .= "$logtolocation\n\n"; } } else { $msg .= "Logging is currently not active."; } $eventdata = new \core\message\message(); $eventdata->courseid = SITEID; $eventdata->modulename = 'moodle'; $eventdata->component = 'enrol_imsenterprise'; $eventdata->name = 'imsenterprise_enrolment'; $eventdata->userfrom = get_admin(); $eventdata->userto = get_admin(); $eventdata->subject = "Moodle IMS Enterprise enrolment notification"; $eventdata->fullmessage = $msg; $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = ''; $eventdata->smallmessage = ''; message_send($eventdata); $this->log_line('Notification email sent to administrator.'); } if ($this->logfp) { fclose($this->logfp); } } /** * Check if a complete tag is found in the cached data, which usually happens * when the end of the tag has only just been loaded into the cache. * * @param string $tagname Name of tag to look for * @param string $latestline The very last line in the cache (used for speeding up the match) * @return bool|string false, or the contents of the tag (including start and end). */ protected function full_tag_found_in_cache($tagname, $latestline) { // Return entire element if found. Otherwise return false. if (strpos(strtolower($latestline), '</'.strtolower($tagname).'>') === false) { return false; } else if (preg_match('{(<'.$tagname.'\b.*?>.*?</'.$tagname.'>)}is', $this->xmlcache, $matches)) { return $matches[1]; } else { return false; } } /** * Remove complete tag from the cached data (including all its contents) - so * that the cache doesn't grow to unmanageable size * * @param string $tagname Name of tag to look for */ protected function remove_tag_from_cache($tagname) { // Trim the cache so we're not in danger of running out of memory. // "1" so that we replace only the FIRST instance. $this->xmlcache = trim(preg_replace('{<'.$tagname.'\b.*?>.*?</'.$tagname.'>}is', '', $this->xmlcache, 1)); } /** * Very simple convenience function to return the "recstatus" found in person/group/role tags. * 1=Add, 2=Update, 3=Delete, as specified by IMS, and we also use 0 to indicate "unspecified". * * @param string $tagdata the tag XML data * @param string $tagname the name of the tag we're interested in * @return int recstatus value */ protected static function get_recstatus($tagdata, $tagname) { if (preg_match('{<'.$tagname.'\b[^>]*recstatus\s*=\s*["\'](\d)["\']}is', $tagdata, $matches)) { return intval($matches[1]); } else { return 0; // Unspecified. } } /** * Process the group tag. This defines a Moodle course. * * @param string $tagcontents The raw contents of the XML element */ protected function process_group_tag($tagcontents) { global $DB, $CFG; // Get configs. $truncatecoursecodes = $this->get_config('truncatecoursecodes'); $createnewcourses = $this->get_config('createnewcourses'); $updatecourses = $this->get_config('updatecourses'); if ($createnewcourses) { require_once("$CFG->dirroot/course/lib.php"); } // Process tag contents. $group = new stdClass(); if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)) { $group->coursecode = trim($matches[1]); } $matches = array(); if (preg_match('{<description>.*?<long>(.*?)</long>.*?</description>}is', $tagcontents, $matches)) { $group->long = trim($matches[1]); } $matches = array(); if (preg_match('{<description>.*?<short>(.*?)</short>.*?</description>}is', $tagcontents, $matches)) { $group->short = trim($matches[1]); } $matches = array(); if (preg_match('{<description>.*?<full>(.*?)</full>.*?</description>}is', $tagcontents, $matches)) { $group->full = trim($matches[1]); } if (preg_match('{<org>(.*?)</org>}is', $tagcontents, $matchesorg)) { if (preg_match_all('{<orgunit>(.*?)</orgunit>}is', $matchesorg[1], $matchesorgunit)) { $group->categories = array_map('trim', $matchesorgunit[1]); } } $recstatus = ($this->get_recstatus($tagcontents, 'group')); if (empty($group->coursecode)) { $this->log_line('Error: Unable to find course code in \'group\' element.'); } else { // First, truncate the course code if desired. if (intval($truncatecoursecodes) > 0) { $group->coursecode = ($truncatecoursecodes > 0) ? substr($group->coursecode, 0, intval($truncatecoursecodes)) : $group->coursecode; } // For compatibility with the (currently inactive) course aliasing, we need this to be an array. $group->coursecode = array($group->coursecode); // Third, check if the course(s) exist. foreach ($group->coursecode as $coursecode) { $coursecode = trim($coursecode); $dbcourse = $DB->get_record('course', array('idnumber' => $coursecode)); if (!$dbcourse) { if (!$createnewcourses) { $this->log_line("Course $coursecode not found in Moodle's course idnumbers."); } else { // Create the (hidden) course(s) if not found. $courseconfig = get_config('moodlecourse'); // Load Moodle Course shell defaults. // New course. $course = new stdClass(); foreach ($this->coursemappings as $courseattr => $imsname) { if ($imsname == 'ignore') { continue; } // Check if the IMS file contains the mapped tag, otherwise fallback on coursecode. if ($imsname == 'coursecode') { $course->{$courseattr} = $coursecode; } else if (!empty($group->{$imsname})) { $course->{$courseattr} = $group->{$imsname}; } else { $this->log_line('No ' . $imsname . ' description tag found for ' .$coursecode . ' coursecode, using ' . $coursecode . ' instead'); $course->{$courseattr} = $coursecode; } } $course->idnumber = $coursecode; $course->format = $courseconfig->format; $course->visible = $courseconfig->visible; $course->newsitems = $courseconfig->newsitems; $course->showgrades = $courseconfig->showgrades; $course->showreports = $courseconfig->showreports; $course->maxbytes = $courseconfig->maxbytes; $course->groupmode = $courseconfig->groupmode; $course->groupmodeforce = $courseconfig->groupmodeforce; $course->enablecompletion = $courseconfig->enablecompletion; // Insert default names for teachers/students, from the current language. // Handle course categorisation (taken from the group.org.orgunit or group.org.id fields if present). $course->category = $this->get_category_from_group($group->categories); $course->startdate = time(); // Choose a sort order that puts us at the start of the list! $course->sortorder = 0; $course = create_course($course); $this->log_line("Created course $coursecode in Moodle (Moodle ID is $course->id)"); } } else if (($recstatus == self::IMSENTERPRISE_UPDATE) && $dbcourse) { if ($updatecourses) { // Update course. Allowed fields to be updated are: // Short Name, and Full Name. $hasupdates = false; if (!empty($group->short)) { if ($group->short != $dbcourse->shortname) { $dbcourse->shortname = $group->short; $hasupdates = true; } } if (!empty($group->full)) { if ($group->full != $dbcourse->fullname) { $dbcourse->fullname = $group->full; $hasupdates = true; } } if ($hasupdates) { update_course($dbcourse); $courseid = $dbcourse->id; $this->log_line("Updated course $coursecode in Moodle (Moodle ID is $courseid)"); } } else { // Update courses option is not enabled. Ignore. $this->log_line("Ignoring update to course $coursecode"); } } else if (($recstatus == self::IMSENTERPRISE_DELETE) && $dbcourse) { // If course does exist, but recstatus==3 (delete), then set the course as hidden. $courseid = $dbcourse->id; $show = false; course_change_visibility($courseid, $show); $this->log_line("Updated (set to hidden) course $coursecode in Moodle (Moodle ID is $courseid)"); } } } } /** * Process the person tag. This defines a Moodle user. * * @param string $tagcontents The raw contents of the XML element */ protected function process_person_tag($tagcontents) { global $CFG, $DB; // Get plugin configs. $imssourcedidfallback = $this->get_config('imssourcedidfallback'); $fixcaseusernames = $this->get_config('fixcaseusernames'); $fixcasepersonalnames = $this->get_config('fixcasepersonalnames'); $imsdeleteusers = $this->get_config('imsdeleteusers'); $createnewusers = $this->get_config('createnewusers'); $imsupdateusers = $this->get_config('imsupdateusers'); $person = new stdClass(); if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)) { $person->idnumber = trim($matches[1]); } $matches = array(); if (preg_match('{<name>.*?<n>.*?<given>(.+?)</given>.*?</n>.*?</name>}is', $tagcontents, $matches)) { $person->firstname = trim($matches[1]); } $matches = array(); if (preg_match('{<name>.*?<n>.*?<family>(.+?)</family>.*?</n>.*?</name>}is', $tagcontents, $matches)) { $person->lastname = trim($matches[1]); } $matches = array(); if (preg_match('{<userid.*?>(.*?)</userid>}is', $tagcontents, $matches)) { $person->username = trim($matches[1]); } $matches = array(); if (preg_match('{<userid\s+authenticationtype\s*=\s*"*(.+?)"*>.*?</userid>}is', $tagcontents, $matches)) { $person->auth = trim($matches[1]); } if ($imssourcedidfallback && trim($person->username) == '') { // This is the point where we can fall back to useing the "sourcedid" if "userid" is not supplied. // NB We don't use an "elseif" because the tag may be supplied-but-empty. $person->username = $person->idnumber; } $matches = array(); if (preg_match('{<email>(.*?)</email>}is', $tagcontents, $matches)) { $person->email = trim($matches[1]); } $matches = array(); if (preg_match('{<url>(.*?)</url>}is', $tagcontents, $matches)) { $person->url = trim($matches[1]); } $matches = array(); if (preg_match('{<adr>.*?<locality>(.+?)</locality>.*?</adr>}is', $tagcontents, $matches)) { $person->city = trim($matches[1]); } $matches = array(); if (preg_match('{<adr>.*?<country>(.+?)</country>.*?</adr>}is', $tagcontents, $matches)) { $person->country = trim($matches[1]); } // Fix case of some of the fields if required. if ($fixcaseusernames && isset($person->username)) { $person->username = strtolower($person->username); } if ($fixcasepersonalnames) { if (isset($person->firstname)) { $person->firstname = ucwords(strtolower($person->firstname)); } if (isset($person->lastname)) { $person->lastname = ucwords(strtolower($person->lastname)); } } $recstatus = ($this->get_recstatus($tagcontents, 'person')); // Now if the recstatus is 3, we should delete the user if-and-only-if the setting for delete users is turned on. if ($recstatus == self::IMSENTERPRISE_DELETE) { if ($imsdeleteusers) { // If we're allowed to delete user records. // Do not dare to hack the user.deleted field directly in database!!! $params = array('username' => $person->username, 'mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 0); if ($user = $DB->get_record('user', $params)) { if (delete_user($user)) { $this->log_line("Deleted user '$person->username' (ID number $person->idnumber)."); } else { $this->log_line("Error deleting '$person->username' (ID number $person->idnumber)."); } } else { $this->log_line("Can not delete user '$person->username' (ID number $person->idnumber) - user does not exist."); } } else { $this->log_line("Ignoring deletion request for user '$person->username' (ID number $person->idnumber)."); } } else if ($recstatus == self::IMSENTERPRISE_UPDATE) { // Update user. if ($imsupdateusers) { if ($id = $DB->get_field('user', 'id', array('idnumber' => $person->idnumber))) { $person->id = $id; $DB->update_record('user', $person); $this->log_line("Updated user $person->username"); } else { $this->log_line("Ignoring update request for non-existent user $person->username"); } } else { $this->log_line("Ignoring update request for user $person->username"); } } else { // Add or update record. // If the user exists (matching sourcedid) then we don't need to do anything. if (!$DB->get_field('user', 'id', array('idnumber' => $person->idnumber)) && $createnewusers) { // If they don't exist and haven't a defined username, we log this as a potential problem. if ((!isset($person->username)) || (strlen($person->username) == 0)) { $this->log_line("Cannot create new user for ID # $person->idnumber". "- no username listed in IMS data for this person."); } else if ($DB->get_field('user', 'id', array('username' => $person->username))) { // If their idnumber is not registered but their user ID is, then add their idnumber to their record. $DB->set_field('user', 'idnumber', $person->idnumber, array('username' => $person->username)); } else { // If they don't exist and they have a defined username, and $createnewusers == true, we create them. $person->lang = $CFG->lang; // TODO: MDL-15863 this needs more work due to multiauth changes, use first auth for now. if (empty($person->auth)) { $auth = explode(',', $CFG->auth); $auth = reset($auth); $person->auth = $auth; } $person->confirmed = 1; $person->timemodified = time(); $person->mnethostid = $CFG->mnet_localhost_id; $id = $DB->insert_record('user', $person); $this->log_line("Created user record ('.$id.') for user '$person->username' (ID number $person->idnumber)."); } } else if ($createnewusers) { $username = $person->username ?? "[unknown username]"; $personnumber = $person->idnumber ?? "[unknown ID number]"; $this->log_line("User record already exists for user '" . $username . "' (ID number " . $personnumber . ")."); // It is totally wrong to mess with deleted users flag directly in database!!! // There is no official way to undelete user, sorry.. } else { $this->log_line("No user record found for '$person->username' (ID number $person->idnumber)."); } } } /** * Process the membership tag. This defines whether the specified Moodle users * should be added/removed as teachers/students. * * @param string $tagcontents The raw contents of the XML element */ protected function process_membership_tag($tagcontents) { global $DB; // Get plugin configs. $truncatecoursecodes = $this->get_config('truncatecoursecodes'); $imscapitafix = $this->get_config('imscapitafix'); $memberstally = 0; $membersuntally = 0; // In order to reduce the number of db queries required, group name/id associations are cached in this array. $groupids = array(); $ship = new stdClass(); if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)) { $ship->coursecode = ($truncatecoursecodes > 0) ? substr(trim($matches[1]), 0, intval($truncatecoursecodes)) : trim($matches[1]); $ship->courseid = $DB->get_field('course', 'id', array('idnumber' => $ship->coursecode)); } if ($ship->courseid && preg_match_all('{<member>(.*?)</member>}is', $tagcontents, $membermatches, PREG_SET_ORDER)) { $courseobj = new stdClass(); $courseobj->id = $ship->courseid; foreach ($membermatches as $mmatch) { $member = new stdClass(); $memberstoreobj = new stdClass(); $matches = array(); if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $mmatch[1], $matches)) { $member->idnumber = trim($matches[1]); } $matches = array(); if (preg_match('{<role\s+roletype=["\'](.+?)["\'].*?>}is', $mmatch[1], $matches)) { // 01 means Student, 02 means Instructor, 3 means ContentDeveloper, and there are more besides. $member->roletype = trim($matches[1]); } else if ($imscapitafix && preg_match('{<roletype>(.+?)</roletype>}is', $mmatch[1], $matches)) { // The XML that comes out of Capita Student Records seems to contain a misinterpretation of // the IMS specification! 01 means Student, 02 means Instructor, 3 means ContentDeveloper, // and there are more besides. $member->roletype = trim($matches[1]); } $matches = array(); if (preg_match('{<role\b.*?<status>(.+?)</status>.*?</role>}is', $mmatch[1], $matches)) { // 1 means active, 0 means inactive - treat this as enrol vs unenrol. $member->status = trim($matches[1]); } $recstatus = ($this->get_recstatus($mmatch[1], 'role')); if ($recstatus == self::IMSENTERPRISE_DELETE) { // See above - recstatus of 3 (==delete) is treated the same as status of 0. $member->status = 0; } $timeframe = new stdClass(); $timeframe->begin = 0; $timeframe->end = 0; $matches = array(); if (preg_match('{<role\b.*?<timeframe>(.+?)</timeframe>.*?</role>}is', $mmatch[1], $matches)) { $timeframe = $this->decode_timeframe($matches[1]); } $matches = array(); if (preg_match('{<role\b.*?<extension>.*?<cohort>(.+?)</cohort>.*?</extension>.*?</role>}is', $mmatch[1], $matches)) { $member->groupname = trim($matches[1]); // The actual processing (ensuring a group record exists, etc) occurs below, in the enrol-a-student clause. } // Add or remove this student or teacher to the course... $memberstoreobj->userid = $DB->get_field('user', 'id', array('idnumber' => $member->idnumber)); $memberstoreobj->enrol = 'imsenterprise'; $memberstoreobj->course = $ship->courseid; $memberstoreobj->time = time(); $memberstoreobj->timemodified = time(); if ($memberstoreobj->userid) { // Decide the "real" role (i.e. the Moodle role) that this user should be assigned to. // Zero means this roletype is supposed to be skipped. $moodleroleid = (isset($member->roletype) && isset($this->rolemappings[$member->roletype])) ? $this->rolemappings[$member->roletype] : null; if (!$moodleroleid) { $this->log_line("SKIPPING role " . ($member->roletype ?? "[]") . " for $memberstoreobj->userid " . "($member->idnumber) in course $memberstoreobj->course"); continue; } if (intval($member->status) == 1) { // Enrol the member. $einstance = $DB->get_record('enrol', array('courseid' => $courseobj->id, 'enrol' => $memberstoreobj->enrol)); if (empty($einstance)) { // Only add an enrol instance to the course if non-existent. $enrolid = $this->add_instance($courseobj); $einstance = $DB->get_record('enrol', array('id' => $enrolid)); } $this->enrol_user($einstance, $memberstoreobj->userid, $moodleroleid, $timeframe->begin, $timeframe->end); $this->log_line("Enrolled user #$memberstoreobj->userid ($member->idnumber) " ."to role $member->roletype in course $memberstoreobj->course"); $memberstally++; // At this point we can also ensure the group membership is recorded if present. if (isset($member->groupname)) { // Create the group if it doesn't exist - either way, make sure we know the group ID. if (isset($groupids[$member->groupname])) { $member->groupid = $groupids[$member->groupname]; // Recall the group ID from cache if available. } else { $params = array('courseid' => $ship->courseid, 'name' => $member->groupname); if ($groupid = $DB->get_field('groups', 'id', $params)) { $member->groupid = $groupid; $groupids[$member->groupname] = $groupid; // Store ID in cache. } else { // Attempt to create the group. $group = new stdClass(); $group->name = $member->groupname; $group->courseid = $ship->courseid; $group->timecreated = time(); $group->timemodified = time(); $groupid = $DB->insert_record('groups', $group); $this->log_line('Added a new group for this course: '.$group->name); $groupids[$member->groupname] = $groupid; // Store ID in cache. $member->groupid = $groupid; // Invalidate the course group data cache just in case. cache_helper::invalidate_by_definition('core', 'groupdata', array(), array($ship->courseid)); } } // Add the user-to-group association if it doesn't already exist. if ($member->groupid) { groups_add_member($member->groupid, $memberstoreobj->userid, 'enrol_imsenterprise', $einstance->id); } } } else if ($this->get_config('imsunenrol')) { // Unenrol member. $unenrolsetting = $this->get_config('unenrolaction'); $einstances = $DB->get_records('enrol', array('enrol' => $memberstoreobj->enrol, 'courseid' => $courseobj->id)); switch ($unenrolsetting) { case ENROL_EXT_REMOVED_SUSPEND: case ENROL_EXT_REMOVED_SUSPENDNOROLES: { foreach ($einstances as $einstance) { $this->update_user_enrol($einstance, $memberstoreobj->userid, ENROL_USER_SUSPENDED, $timeframe->begin, $timeframe->end); $this->log_line("Suspending user enrolment for $member->idnumber in " . " course $ship->coursecode "); if (intval($unenrolsetting) === intval(ENROL_EXT_REMOVED_SUSPENDNOROLES)) { if (!$context = context_course::instance($courseobj->id, IGNORE_MISSING)) { $this->log_line("Unable to process IMS unenrolment request " . " because course context not found. User: " . "#$memberstoreobj->userid ($member->idnumber) , " . " course: $memberstoreobj->course"); } else { role_unassign_all([ 'contextid' => $context->id, 'userid' => $memberstoreobj->userid, 'component' => 'enrol_imsenterprise', 'itemid' => $einstance->id ]); $this->log_line("Removing role assignments for user " . "$member->idnumber from role $moodleroleid in course " . "$ship->coursecode "); } } } } break; case ENROL_EXT_REMOVED_UNENROL: { foreach ($einstances as $einstance) { $this->unenrol_user($einstance, $memberstoreobj->userid); $this->log_line("Removing user enrolment record for $member->idnumber " . " in course $ship->coursecode "); } } break; case ENROL_EXT_REMOVED_KEEP: { $this->log_line("Processed KEEP IMS unenrol instruction (i.e. do nothing)"); } break; default: $this->log_line("Unable to process IMS unenrolment request because " . " the value set for plugin parameter, unenrol action, is not recognised. " . " User: #$memberstoreobj->userid ($member->idnumber) " . " , course: $memberstoreobj->course"); break; } $membersuntally++; } } } $this->log_line("Added $memberstally users to course $ship->coursecode"); if ($membersuntally > 0) { $this->log_line("Processed $membersuntally unenrol instructions for course $ship->coursecode"); } } } // End process_membership_tag(). /** * Process the properties tag. The only data from this element * that is relevant is whether a <target> is specified. * * @param string $tagcontents The raw contents of the XML element */ protected function process_properties_tag($tagcontents) { $imsrestricttarget = $this->get_config('imsrestricttarget'); if ($imsrestricttarget) { if (!(preg_match('{<target>'.preg_quote($imsrestricttarget).'</target>}is', $tagcontents, $matches))) { $this->log_line("Skipping processing: required target \"$imsrestricttarget\" not specified in this data."); $this->continueprocessing = false; } } } /** * Store logging information. This does two things: uses the {@link mtrace()} * function to print info to screen/STDOUT, and also writes log to a text file * if a path has been specified. * @param string $string Text to write (newline will be added automatically) */ protected function log_line($string) { if (!PHPUNIT_TEST) { mtrace($string); } if ($this->logfp) { fwrite($this->logfp, $string . "\n"); } } /** * Process the INNER contents of a <timeframe> tag, to return beginning/ending dates. * * @param string $string tag to decode. * @return stdClass beginning and/or ending is returned, in unix time, zero indicating not specified. */ protected static function decode_timeframe($string) { $ret = new stdClass(); $ret->begin = $ret->end = 0; // Explanatory note: The matching will ONLY match if the attribute restrict="1" // because otherwise the time markers should be ignored (participation should be // allowed outside the period). if (preg_match('{<begin\s+restrict="1">(\d\d\d\d)-(\d\d)-(\d\d)</begin>}is', $string, $matches)) { $ret->begin = mktime(0, 0, 0, $matches[2], $matches[3], $matches[1]); } $matches = array(); if (preg_match('{<end\s+restrict="1">(\d\d\d\d)-(\d\d)-(\d\d)</end>}is', $string, $matches)) { $ret->end = mktime(0, 0, 0, $matches[2], $matches[3], $matches[1]); } return $ret; } /** * Load the role mappings (from the config), so we can easily refer to * how an IMS-E role corresponds to a Moodle role */ protected function load_role_mappings() { require_once('locallib.php'); $imsroles = new imsenterprise_roles(); $imsroles = $imsroles->get_imsroles(); $this->rolemappings = array(); foreach ($imsroles as $imsrolenum => $imsrolename) { $this->rolemappings[$imsrolenum] = $this->rolemappings[$imsrolename] = $this->get_config('imsrolemap' . $imsrolenum); } } /** * Load the name mappings (from the config), so we can easily refer to * how an IMS-E course properties corresponds to a Moodle course properties */ protected function load_course_mappings() { require_once('locallib.php'); $imsnames = new imsenterprise_courses(); $courseattrs = $imsnames->get_courseattrs(); $this->coursemappings = array(); foreach ($courseattrs as $courseattr) { $this->coursemappings[$courseattr] = $this->get_config('imscoursemap' . $courseattr); } } /** * Get the default category id (often known as 'Miscellaneous'), * statically cached to avoid multiple DB lookups on big imports. * * @return int id of default category. */ private function get_default_category_id() { global $CFG; if ($this->defaultcategoryid === null) { $category = core_course_category::get_default(); $this->defaultcategoryid = $category->id; } return $this->defaultcategoryid; } /** * Find the category using idnumber or name. * * @param array $categories List of categories * * @return int id of category found. */ private function get_category_from_group($categories) { global $DB; if (empty($categories)) { $catid = $this->get_default_category_id(); } else { $createnewcategories = $this->get_config('createnewcategories'); $categoryseparator = trim($this->get_config('categoryseparator')); $nestedcategories = trim($this->get_config('nestedcategories')); $searchbyidnumber = trim($this->get_config('categoryidnumber')); if (!empty($categoryseparator)) { $sep = '{\\'.$categoryseparator.'}'; } $catid = 0; $fullnestedcatname = ''; foreach ($categories as $categoryinfo) { if ($searchbyidnumber) { $values = preg_split($sep, $categoryinfo, -1, PREG_SPLIT_NO_EMPTY); if (count($values) < 2) { $this->log_line('Category ' . $categoryinfo . ' missing name or idnumber. Using default category instead.'); $catid = $this->get_default_category_id(); break; } $categoryname = $values[0]; $categoryidnumber = $values[1]; } else { $categoryname = $categoryinfo; $categoryidnumber = null; if (empty($categoryname)) { $this->log_line('Category ' . $categoryinfo . ' missing name. Using default category instead.'); $catid = $this->get_default_category_id(); break; } } if (!empty($fullnestedcatname)) { $fullnestedcatname .= ' / '; } $fullnestedcatname .= $categoryname; $parentid = $catid; // Check if category exist. $params = array(); if ($searchbyidnumber) { $params['idnumber'] = $categoryidnumber; } else { $params['name'] = $categoryname; } if ($nestedcategories) { $params['parent'] = $parentid; } if ($catid = $DB->get_field('course_categories', 'id', $params)) { continue; // This category already exists. } // If we're allowed to create new categories, let's create this one. if ($createnewcategories) { $newcat = new stdClass(); $newcat->name = $categoryname; $newcat->visible = 0; $newcat->parent = $parentid; $newcat->idnumber = $categoryidnumber; $newcat = core_course_category::create($newcat); $catid = $newcat->id; $this->log_line("Created new (hidden) category '$fullnestedcatname'"); } else { // If not found and not allowed to create, stick with default. $this->log_line('Category ' . $categoryinfo . ' not found in Moodle database. Using default category instead.'); $catid = $this->get_default_category_id(); break; } } } return $catid; } /** * Is it possible to delete enrol instance via standard UI? * * @param object $instance * @return bool */ public function can_delete_instance($instance) { $context = context_course::instance($instance->courseid); return has_capability('enrol/imsenterprise:config', $context); } /** * Is it possible to hide/show enrol instance via standard UI? * * @param stdClass $instance * @return bool */ public function can_hide_show_instance($instance) { $context = context_course::instance($instance->courseid); return has_capability('enrol/imsenterprise:config', $context); } } /** * Called whenever anybody tries (from the normal interface) to remove a group * member which is registered as being created by this component. (Not called * when deleting an entire group or course at once.) * @param int $itemid Item ID that was stored in the group_members entry * @param int $groupid Group ID * @param int $userid User ID being removed from group * @return bool True if the remove is permitted, false to give an error */ function enrol_imsenterprise_allow_group_member_remove($itemid, $groupid, $userid) { return false; } home3/cpr76684/public_html/Aem/portfolio/mahara/lib.php 0000644 00000037434 15152217215 0016527 0 ustar 00 <?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/>. /** * This file contains the class definition for the mahara portfolio plugin * * @since Moodle 2.0 * @package moodlecore * @subpackage portfolio * @copyright 2009 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('PORTFOLIO_MAHARA_ERR_NETWORKING_OFF', 'err_networkingoff'); define('PORTFOLIO_MAHARA_ERR_NOHOSTS', 'err_nomnethosts'); define('PORTFOLIO_MAHARA_ERR_INVALIDHOST', 'err_invalidhost'); define('PORTFOLIO_MAHARA_ERR_NOMNETAUTH', 'err_nomnetauth'); require_once($CFG->libdir . '/portfoliolib.php'); require_once($CFG->libdir . '/portfolio/plugin.php'); require_once($CFG->libdir . '/portfolio/exporter.php'); require_once($CFG->dirroot . '/mnet/lib.php'); define('PORTFOLIO_MAHARA_QUEUE', PORTFOLIO_TIME_HIGH); define('PORTFOLIO_MAHARA_IMMEDIATE', PORTFOLIO_TIME_MODERATE); class portfolio_plugin_mahara extends portfolio_plugin_pull_base { private $hosts; // used in the admin config form private $mnethost; // privately set during export from the admin config value (mnethostid) private $hostrecord; // the host record that corresponds to the peer private $token; // during-transfer token private $sendtype; // whatever mahara has said it can handle (immediate or queued) private $filesmanifest; // manifest of files to send to mahara (set during prepare_package and sent later) private $totalsize; // total size of all included files added together private $continueurl; // if we've been sent back a specific url to continue to (eg folder id) protected function init() { $this->mnet = get_mnet_environment(); } public function __wakeup() { $this->mnet = get_mnet_environment(); } public static function get_name() { return get_string('pluginname', 'portfolio_mahara'); } public static function get_allowed_config() { return array('mnethostid', 'enableleap2a'); } public function supported_formats() { if ($this->get_config('enableleap2a')) { return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_LEAP2A); } return array(PORTFOLIO_FORMAT_FILE); } public function expected_time($callertime) { if ($this->sendtype == PORTFOLIO_MAHARA_QUEUE) { return PORTFOLIO_TIME_FORCEQUEUE; } return $callertime; } public static function has_admin_config() { return true; } public static function admin_config_form(&$mform) { $strrequired = get_string('required'); $hosts = self::get_mnet_hosts(); // this is called by sanity check but it's ok because it's cached foreach ($hosts as $host) { $hosts[$host->id] = $host->name; } $mform->addElement('select', 'mnethostid', get_string('mnethost', 'portfolio_mahara'), $hosts); $mform->addRule('mnethostid', $strrequired, 'required', null, 'client'); $mform->setType('mnethostid', PARAM_INT); $mform->addElement('selectyesno', 'enableleap2a', get_string('enableleap2a', 'portfolio_mahara')); $mform->setType('enableleap2a', PARAM_BOOL); } public function instance_sanity_check() { // make sure the host record exists since we don't have referential integrity if (!is_enabled_auth('mnet')) { return PORTFOLIO_MAHARA_ERR_NOMNETAUTH; } try { $this->ensure_mnethost(); } catch (portfolio_exception $e) { return PORTFOLIO_MAHARA_ERR_INVALIDHOST; } // make sure we have the right services $hosts = $this->get_mnet_hosts(); if (!array_key_exists($this->get_config('mnethostid'), $hosts)) { return PORTFOLIO_MAHARA_ERR_INVALIDHOST; } return 0; } public static function plugin_sanity_check() { global $CFG, $DB; $errorcode = 0; if (!isset($CFG->mnet_dispatcher_mode) || $CFG->mnet_dispatcher_mode != 'strict') { $errorcode = PORTFOLIO_MAHARA_ERR_NETWORKING_OFF; } if (!is_enabled_auth('mnet')) { $errorcode = PORTFOLIO_MAHARA_ERR_NOMNETAUTH; } if (!self::get_mnet_hosts()) { $errorcode = PORTFOLIO_MAHARA_ERR_NOHOSTS; } return $errorcode; } private static function get_mnet_hosts() { global $DB, $CFG; static $hosts; if (isset($hosts)) { return $hosts; } $hosts = $DB->get_records_sql(' SELECT h.id, h.wwwroot, h.ip_address, h.name, h.public_key, h.public_key_expires, h.transport, h.portno, h.last_connect_time, h.last_log_id, h.applicationid, a.name as app_name, a.display_name as app_display_name, a.xmlrpc_server_url FROM {mnet_host} h JOIN {mnet_application} a ON h.applicationid=a.id JOIN {mnet_host2service} hs1 ON hs1.hostid = h.id JOIN {mnet_service} s1 ON hs1.serviceid = s1.id JOIN {mnet_host2service} hs2 ON hs2.hostid = h.id JOIN {mnet_service} s2 ON hs2.serviceid = s2.id JOIN {mnet_host2service} hs3 ON hs3.hostid = h.id JOIN {mnet_service} s3 ON hs3.serviceid = s3.id WHERE h.id <> ? AND h.deleted = 0 AND a.name = ? AND s1.name = ? AND hs1.publish = ? AND s2.name = ? AND hs2.subscribe = ? AND s3.name = ? AND hs3.subscribe = ? AND s3.name = ? AND hs3.publish = ?', array($CFG->mnet_localhost_id, 'mahara', 'sso_idp', 1, 'sso_sp', 1, 'pf', 1, 'pf', 1)); return $hosts; } public function prepare_package() { $files = $this->exporter->get_tempfiles(); $this->totalsize = 0; foreach ($files as $f) { $this->filesmanifest[$f->get_contenthash()] = array( 'filename' => $f->get_filename(), 'sha1' => $f->get_contenthash(), 'size' => $f->get_filesize(), ); $this->totalsize += $f->get_filesize(); } $this->set('file', $this->exporter->zip_tempfiles()); // this will throw a file_exception which the exporter catches separately. } public function send_package() { global $CFG; // send the 'content_ready' request to mahara require_once($CFG->dirroot . '/mnet/xmlrpc/client.php'); $client = new mnet_xmlrpc_client(); $client->set_method('portfolio/mahara/lib.php/send_content_ready'); $client->add_param($this->token); $client->add_param($this->get('user')->username); $client->add_param($this->resolve_format()); $client->add_param(array( 'filesmanifest' => $this->filesmanifest, 'zipfilesha1' => $this->get('file')->get_contenthash(), 'zipfilesize' => $this->get('file')->get_filesize(), 'totalsize' => $this->totalsize, )); $client->add_param($this->get_export_config('wait')); $this->ensure_mnethost(); if (!$client->send($this->mnethost)) { foreach ($client->error as $errormessage) { list($code, $message) = array_map('trim',explode(':', $errormessage, 2)); $message .= "ERROR $code:<br/>$errormessage<br/>"; } throw new portfolio_export_exception($this->get('exporter'), 'failedtoping', 'portfolio_mahara', '', $message); } // we should get back... an ok and a status // either we've been waiting a while and mahara has fetched the file or has queued it. $response = (object)$client->response; if (!$response->status) { throw new portfolio_export_exception($this->get('exporter'), 'failedtoping', 'portfolio_mahara'); } if ($response->type =='queued') { $this->exporter->set_forcequeue(); } if (isset($response->querystring)) { $this->continueurl = $response->querystring; } // if we're not queuing the logging might have already happened $this->exporter->update_log_url($this->get_static_continue_url()); } public function get_static_continue_url() { $remoteurl = ''; if ($this->resolve_format() == 'file') { $remoteurl = '/artefact/file/'; // we hopefully get the files that were imported highlighted } if (isset($this->continueurl)) { $remoteurl .= $this->continueurl; } return $remoteurl; } public function resolve_static_continue_url($remoteurl) { global $CFG; $this->ensure_mnethost(); $u = new moodle_url('/auth/mnet/jump.php', array('hostid' => $this->get_config('mnethostid'), 'wantsurl' => $remoteurl)); return $u->out(); } public function get_interactive_continue_url() { return $this->resolve_static_continue_url($this->get_static_continue_url()); } public function steal_control($stage) { if ($stage != PORTFOLIO_STAGE_CONFIG) { return false; } global $CFG; return $CFG->wwwroot . '/portfolio/mahara/preconfig.php?id=' . $this->exporter->get('id'); } public function verify_file_request_params($params) { return false; // the data comes from an xmlrpc request, // not a request to file.php } /** * sends the 'content_intent' ping to mahara * if all goes well, this will set the 'token' and 'sendtype' member variables. */ public function send_intent() { global $CFG, $DB; require_once($CFG->dirroot . '/mnet/xmlrpc/client.php'); $client = new mnet_xmlrpc_client(); $client->set_method('portfolio/mahara/lib.php/send_content_intent'); $client->add_param($this->get('user')->username); $this->ensure_mnethost(); if (!$client->send($this->mnethost)) { foreach ($client->error as $errormessage) { list($code, $message) = array_map('trim',explode(':', $errormessage, 2)); $message .= "ERROR $code:<br/>$errormessage<br/>"; } throw new portfolio_export_exception($this->get('exporter'), 'failedtoping', 'portfolio_mahara', '', $message); } // we should get back... the send type and a shared token $response = (object)$client->response; if (empty($response->sendtype) || empty($response->token)) { throw new portfolio_export_exception($this->get('exporter'), 'senddisallowed', 'portfolio_mahara'); } switch ($response->sendtype) { case 'immediate': $this->sendtype = PORTFOLIO_MAHARA_IMMEDIATE; break; case 'queue': $this->sendtype = PORTFOLIO_MAHARA_QUEUE; break; case 'none': default: throw new portfolio_export_exception($this->get('exporter'), 'senddisallowed', 'portfolio_mahara'); } $this->token = $response->token; $this->get('exporter')->save(); // put the entry in the mahara queue table now too $q = new stdClass; $q->token = $this->token; $q->transferid = $this->get('exporter')->get('id'); $DB->insert_record('portfolio_mahara_queue', $q); } private function ensure_mnethost() { if (!empty($this->hostrecord) && !empty($this->mnethost)) { return; } global $DB; if (!$this->hostrecord = $DB->get_record('mnet_host', array('id' => $this->get_config('mnethostid')))) { throw new portfolio_plugin_exception(PORTFOLIO_MAHARA_ERR_INVALIDHOST, 'portfolio_mahara'); } $this->mnethost = new mnet_peer(); $this->mnethost->set_wwwroot($this->hostrecord->wwwroot); } /** * xmlrpc (mnet) function to get the file. * reads in the file and returns it base_64 encoded * so that it can be enrypted by mnet. * * @param string $token the token recieved previously during send_content_intent */ public static function fetch_file($token) { global $DB; $remoteclient = get_mnet_remote_client(); try { if (!$transferid = $DB->get_field('portfolio_mahara_queue', 'transferid', array('token' => $token))) { throw new mnet_server_exception(8009, 'mnet_notoken', 'portfolio_mahara'); } $exporter = portfolio_exporter::rewaken_object($transferid); } catch (portfolio_exception $e) { throw new mnet_server_exception(8010, 'mnet_noid', 'portfolio_mahara'); } if ($exporter->get('instance')->get_config('mnethostid') != $remoteclient->id) { throw new mnet_server_exception(8011, 'mnet_wronghost', 'portfolio_mahara'); } global $CFG; try { $i = $exporter->get('instance'); $f = $i->get('file'); if (empty($f) || !($f instanceof stored_file)) { throw new mnet_server_exception(8012, 'mnet_nofile', 'portfolio_mahara'); } try { $c = $f->get_content(); } catch (file_exception $e) { throw new mnet_server_exception(8013, 'mnet_nofilecontents', 'portfolio_mahara', $e->getMessage()); } $contents = base64_encode($c); } catch (Exception $e) { throw new mnet_server_exception(8013, 'mnet_nofile', 'portfolio_mahara'); } $exporter->log_transfer(); $exporter->process_stage_cleanup(true); return $contents; } public function cleanup() { global $DB; $DB->delete_records('portfolio_mahara_queue', array('transferid' => $this->get('exporter')->get('id'), 'token' => $this->token)); } /** * internal helper function, that converts between the format constant, * which might be too specific (eg 'image') and the class in our *supported* list * which might be higher up the format hierarchy tree (eg 'file') */ private function resolve_format() { global $CFG; $thisformat = $this->get_export_config('format'); $allformats = portfolio_supported_formats(); require_once($CFG->libdir . '/portfolio/formats.php'); $thisobj = new $allformats[$thisformat]; foreach ($this->supported_formats() as $f) { $class = $allformats[$f]; if ($thisobj instanceof $class) { return $f; } } } } home3/cpr76684/public_html/Aem/grade/grading/lib.php 0000644 00000056260 15152217547 0015764 0 ustar 00 <?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/>. /** * Advanced grading methods support * * @package core_grading * @copyright 2011 David Mudrak <david@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); use core_grades\component_gradeitems; /** * Factory method returning an instance of the grading manager * * There are basically ways how to use this factory method. If the area record * id is known to the caller, get the manager for that area by providing just * the id. If the area record id is not know, the context, component and area name * can be provided. Note that null values are allowed in the second case as the context, * component and the area name can be set explicitly later. * * @category grading * @example $manager = get_grading_manager($areaid); * @example $manager = get_grading_manager(context_system::instance()); * @example $manager = get_grading_manager($context, 'mod_assignment', 'submission'); * @param stdClass|int|null $context_or_areaid if $areaid is passed, no other parameter is needed * @param string|null $component the frankenstyle name of the component * @param string|null $area the name of the gradable area * @return grading_manager */ function get_grading_manager($context_or_areaid = null, $component = null, $area = null) { global $DB; $manager = new grading_manager(); if (is_object($context_or_areaid)) { $context = $context_or_areaid; } else { $context = null; if (is_numeric($context_or_areaid)) { $manager->load($context_or_areaid); return $manager; } } if (!is_null($context)) { $manager->set_context($context); } if (!is_null($component)) { $manager->set_component($component); } if (!is_null($area)) { $manager->set_area($area); } return $manager; } /** * General class providing access to common grading features * * Grading manager provides access to the particular grading method controller * in that area. * * Fully initialized instance of the grading manager operates over a single * gradable area. It is possible to work with a partially initialized manager * that knows just context and component without known area, for example. * It is also possible to change context, component and area of an existing * manager. Such pattern is used when copying form definitions, for example. * * @package core_grading * @copyright 2011 David Mudrak <david@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @category grading */ class grading_manager { /** @var stdClass the context */ protected $context; /** @var string the frankenstyle name of the component */ protected $component; /** @var string the name of the gradable area */ protected $area; /** @var stdClass|false|null the raw record from {grading_areas}, false if does not exist, null if invalidated cache */ private $areacache = null; /** * Returns grading manager context * * @return stdClass grading manager context */ public function get_context() { return $this->context; } /** * Sets the context the manager operates on * * @param stdClass $context */ public function set_context(stdClass $context) { $this->areacache = null; $this->context = $context; } /** * Returns grading manager component * * @return string grading manager component */ public function get_component() { return $this->component; } /** * Sets the component the manager operates on * * @param string $component the frankenstyle name of the component */ public function set_component($component) { $this->areacache = null; list($type, $name) = core_component::normalize_component($component); $this->component = $type.'_'.$name; } /** * Returns grading manager area name * * @return string grading manager area name */ public function get_area() { return $this->area; } /** * Sets the area the manager operates on * * @param string $area the name of the gradable area */ public function set_area($area) { $this->areacache = null; $this->area = $area; } /** * Returns a text describing the context and the component * * At the moment this works for gradable areas in course modules. In the future, this * method should be improved so it works for other contexts (blocks, gradebook items etc) * or subplugins. * * @return string */ public function get_component_title() { $this->ensure_isset(array('context', 'component')); if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { if ($this->get_component() == 'core_grading') { $title = ''; // we are in the bank UI } else { throw new coding_exception('Unsupported component at the system context'); } } else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) { list($context, $course, $cm) = get_context_info_array($this->get_context()->id); if ($cm && strval($cm->name) !== '') { $title = format_string($cm->name, true, array('context' => $context)); } else { debugging('Gradable areas are currently supported at the course module level only', DEBUG_DEVELOPER); $title = $this->get_component(); } } else { throw new coding_exception('Unsupported gradable area context level'); } return $title; } /** * Returns the localized title of the currently set area * * @return string */ public function get_area_title() { if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { return ''; } else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) { $this->ensure_isset(array('context', 'component', 'area')); $areas = $this->get_available_areas(); if (array_key_exists($this->get_area(), $areas)) { return $areas[$this->get_area()]; } else { debugging('Unknown area!'); return '???'; } } else { throw new coding_exception('Unsupported context level'); } } /** * Loads the gradable area info from the database * * @param int $areaid */ public function load($areaid) { global $DB; $this->areacache = $DB->get_record('grading_areas', array('id' => $areaid), '*', MUST_EXIST); $this->context = context::instance_by_id($this->areacache->contextid, MUST_EXIST); $this->component = $this->areacache->component; $this->area = $this->areacache->areaname; } /** * Returns the list of installed grading plugins together, optionally extended * with a simple direct grading. * * @param bool $includenone should the 'Simple direct grading' be included * @return array of the (string)name => (string)localized title of the method */ public static function available_methods($includenone = true) { if ($includenone) { $list = array('' => get_string('gradingmethodnone', 'core_grading')); } else { $list = array(); } foreach (core_component::get_plugin_list('gradingform') as $name => $location) { $list[$name] = get_string('pluginname', 'gradingform_'.$name); } return $list; } /** * Returns the list of available grading methods in the given context * * Currently this is just a static list obtained from {@link self::available_methods()}. * In the future, the list of available methods may be controlled per-context. * * Requires the context property to be set in advance. * * @param bool $includenone should the 'Simple direct grading' be included * @return array of the (string)name => (string)localized title of the method */ public function get_available_methods($includenone = true) { $this->ensure_isset(array('context')); return self::available_methods($includenone); } /** * Returns the list of gradable areas provided by the given component * * This performs a callback to the library of the relevant plugin to obtain * the list of supported areas. * * @param string $component normalized component name * @return array of (string)areacode => (string)localized title of the area */ public static function available_areas($component) { global $CFG; if (component_gradeitems::defines_advancedgrading_itemnames_for_component($component)) { $result = []; foreach (component_gradeitems::get_advancedgrading_itemnames_for_component($component) as $itemnumber => $itemname) { $result[$itemname] = get_string("gradeitem:{$itemname}", $component); } return $result; } list($plugintype, $pluginname) = core_component::normalize_component($component); if ($component === 'core_grading') { return array(); } else if ($plugintype === 'mod') { $callbackfunction = "grading_areas_list"; if (component_callback_exists($component, $callbackfunction)) { debugging( "Components supporting advanced grading should be updated to implement the component_gradeitems class", DEBUG_DEVELOPER ); return component_callback($component, $callbackfunction, [], []); } } else { throw new coding_exception('Unsupported area location'); } } /** * Returns the list of gradable areas in the given context and component * * This performs a callback to the library of the relevant plugin to obtain * the list of supported areas. * @return array of (string)areacode => (string)localized title of the area */ public function get_available_areas() { global $CFG; $this->ensure_isset(array('context', 'component')); if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) { if ($this->get_component() !== 'core_grading') { throw new coding_exception('Unsupported component at the system context'); } else { return array(); } } else if ($this->get_context()->contextlevel == CONTEXT_MODULE) { $modulecontext = $this->get_context(); $coursecontext = $modulecontext->get_course_context(); $cm = get_fast_modinfo($coursecontext->instanceid)->get_cm($modulecontext->instanceid); return self::available_areas("mod_{$cm->modname}"); } else { throw new coding_exception('Unsupported gradable area context level'); } } /** * Returns the currently active grading method in the gradable area * * @return string|null the name of the grading plugin of null if it has not been set */ public function get_active_method() { global $DB; $this->ensure_isset(array('context', 'component', 'area')); // get the current grading area record if it exists if (is_null($this->areacache)) { $this->areacache = $DB->get_record('grading_areas', array( 'contextid' => $this->context->id, 'component' => $this->component, 'areaname' => $this->area), '*', IGNORE_MISSING); } if ($this->areacache === false) { // no area record yet return null; } return $this->areacache->activemethod; } /** * Sets the currently active grading method in the gradable area * * @param string $method the method name, eg 'rubric' (must be available) * @return bool true if the method changed or was just set, false otherwise */ public function set_active_method($method) { global $DB; $this->ensure_isset(array('context', 'component', 'area')); // make sure the passed method is empty or a valid plugin name if (empty($method)) { $method = null; } else { if ('gradingform_'.$method !== clean_param('gradingform_'.$method, PARAM_COMPONENT)) { throw new moodle_exception('invalid_method_name', 'core_grading'); } $available = $this->get_available_methods(false); if (!array_key_exists($method, $available)) { throw new moodle_exception('invalid_method_name', 'core_grading'); } } // get the current grading area record if it exists if (is_null($this->areacache)) { $this->areacache = $DB->get_record('grading_areas', array( 'contextid' => $this->context->id, 'component' => $this->component, 'areaname' => $this->area), '*', IGNORE_MISSING); } $methodchanged = false; if ($this->areacache === false) { // no area record yet, create one with the active method set $area = array( 'contextid' => $this->context->id, 'component' => $this->component, 'areaname' => $this->area, 'activemethod' => $method); $DB->insert_record('grading_areas', $area); $methodchanged = true; } else { // update the existing record if needed if ($this->areacache->activemethod !== $method) { $DB->set_field('grading_areas', 'activemethod', $method, array('id' => $this->areacache->id)); $methodchanged = true; } } $this->areacache = null; return $methodchanged; } /** * Extends the settings navigation with the grading settings * * This function is called when the context for the page is an activity module with the * FEATURE_ADVANCED_GRADING and the user has the permission moodle/grade:managegradingforms. * * @param settings_navigation $settingsnav {@link settings_navigation} * @param navigation_node $modulenode {@link navigation_node} */ public function extend_settings_navigation(settings_navigation $settingsnav, navigation_node $modulenode=null) { $this->ensure_isset(array('context', 'component')); $areas = $this->get_available_areas(); if (empty($areas)) { // no money, no funny return; } else { // make just a single node for the management screen $areatitle = reset($areas); $areaname = key($areas); $this->set_area($areaname); $managementnode = $modulenode->add(get_string('gradingmanagement', 'core_grading'), $this->get_management_url(), settings_navigation::TYPE_CUSTOM, null, 'advgrading'); } } /** * Extends the module navigation with the advanced grading information * * This function is called when the context for the page is an activity module with the * FEATURE_ADVANCED_GRADING. * * @param global_navigation $navigation * @param navigation_node $modulenode */ public function extend_navigation(global_navigation $navigation, navigation_node $modulenode=null) { $this->ensure_isset(array('context', 'component')); $areas = $this->get_available_areas(); foreach ($areas as $areaname => $areatitle) { $this->set_area($areaname); if ($controller = $this->get_active_controller()) { $controller->extend_navigation($navigation, $modulenode); } } } /** * Returns the given method's controller in the gradable area * * @param string $method the method name, eg 'rubric' (must be available) * @return gradingform_controller */ public function get_controller($method) { global $CFG, $DB; $this->ensure_isset(array('context', 'component', 'area')); // make sure the passed method is a valid plugin name if ('gradingform_'.$method !== clean_param('gradingform_'.$method, PARAM_COMPONENT)) { throw new moodle_exception('invalid_method_name', 'core_grading'); } $available = $this->get_available_methods(false); if (!array_key_exists($method, $available)) { throw new moodle_exception('invalid_method_name', 'core_grading'); } // get the current grading area record if it exists if (is_null($this->areacache)) { $this->areacache = $DB->get_record('grading_areas', array( 'contextid' => $this->context->id, 'component' => $this->component, 'areaname' => $this->area), '*', IGNORE_MISSING); } if ($this->areacache === false) { // no area record yet, create one $area = array( 'contextid' => $this->context->id, 'component' => $this->component, 'areaname' => $this->area); $areaid = $DB->insert_record('grading_areas', $area); // reload the cache $this->areacache = $DB->get_record('grading_areas', array('id' => $areaid), '*', MUST_EXIST); } require_once($CFG->dirroot.'/grade/grading/form/'.$method.'/lib.php'); $classname = 'gradingform_'.$method.'_controller'; return new $classname($this->context, $this->component, $this->area, $this->areacache->id); } /** * Returns the controller for the active method if it is available * * @return null|gradingform_controller */ public function get_active_controller() { if ($gradingmethod = $this->get_active_method()) { $controller = $this->get_controller($gradingmethod); if ($controller->is_form_available()) { return $controller; } } return null; } /** * Returns the URL of the grading area management page * * @param moodle_url $returnurl optional URL of the page where the user should be sent back to * @return moodle_url */ public function get_management_url(moodle_url $returnurl = null) { $this->ensure_isset(array('context', 'component')); if ($this->areacache) { $params = array('areaid' => $this->areacache->id); } else { $params = array('contextid' => $this->context->id, 'component' => $this->component); if ($this->area) { $params['area'] = $this->area; } } if (!is_null($returnurl)) { $params['returnurl'] = $returnurl->out(false); } return new moodle_url('/grade/grading/manage.php', $params); } /** * Creates a new shared area to hold a grading form template * * Shared area are implemented as virtual gradable areas at the system level context * with the component set to core_grading and unique random area name. * * @param string $method the name of the plugin we create the area for * @return int the new area id */ public function create_shared_area($method) { global $DB; // generate some unique random name for the new area $name = $method . '_' . sha1(rand().uniqid($method, true)); // create new area record $area = array( 'contextid' => context_system::instance()->id, 'component' => 'core_grading', 'areaname' => $name, 'activemethod' => $method); return $DB->insert_record('grading_areas', $area); } /** * Removes all data associated with the given context * * This is called by {@link context::delete_content()} * * @param int $contextid context id */ public static function delete_all_for_context($contextid) { global $DB; $areaids = $DB->get_fieldset_select('grading_areas', 'id', 'contextid = ?', array($contextid)); $methods = array_keys(self::available_methods(false)); foreach($areaids as $areaid) { $manager = get_grading_manager($areaid); foreach ($methods as $method) { $controller = $manager->get_controller($method); $controller->delete_definition(); } } $DB->delete_records_list('grading_areas', 'id', $areaids); } /** * Helper method to tokenize the given string * * Splits the given string into smaller strings. This is a helper method for * full text searching in grading forms. If the given string is surrounded with * double quotes, the resulting array consists of a single item containing the * quoted content. * * Otherwise, string like 'grammar, english language' would be tokenized into * the three tokens 'grammar', 'english', 'language'. * * One-letter tokens like are dropped in non-phrase mode. Repeated tokens are * returned just once. * * @param string $needle * @return array */ public static function tokenize($needle) { // check if we are searching for the exact phrase if (preg_match('/^[\s]*"[\s]*(.*?)[\s]*"[\s]*$/', $needle, $matches)) { $token = $matches[1]; if ($token === '') { return array(); } else { return array($token); } } // split the needle into smaller parts separated by non-word characters $tokens = preg_split("/\W/u", $needle); // keep just non-empty parts $tokens = array_filter($tokens); // distinct $tokens = array_unique($tokens); // drop one-letter tokens foreach ($tokens as $ix => $token) { if (strlen($token) == 1) { unset($tokens[$ix]); } } return array_values($tokens); } // ////////////////////////////////////////////////////////////////////////// /** * Make sure that the given properties were set to some not-null value * * @param array $properties the list of properties * @throws coding_exception */ private function ensure_isset(array $properties) { foreach ($properties as $property) { if (!isset($this->$property)) { throw new coding_exception('The property "'.$property.'" is not set.'); } } } } home3/cpr76684/public_html/Aem/auth/shibboleth/lib.php 0000644 00000004041 15152217752 0016337 0 ustar 00 <?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/>. /** * This file contains the hooks for the Shibboleth authentication module. * * @package auth_shibboleth * @copyright 2018 Fabrice Ménard * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; /** * Serves the logo file settings. * * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if file not found, does not return if found - justsend the file */ function auth_shibboleth_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { if ($context->contextlevel != CONTEXT_SYSTEM) { return false; } if ($filearea !== 'logo' ) { return false; } $itemid = 0; $filename = array_pop($args); if (!$args) { $filepath = '/'; } else { $filepath = '/'.implode('/', $args).'/'; } $fs = get_file_storage(); $file = $fs->get_file($context->id, 'auth_shibboleth', $filearea, $itemid, $filepath, $filename); if (!$file) { return false; } send_stored_file($file, null, 0, $forcedownload, $options); } home3/cpr76684/public_html/Aem/customfield/field/textarea/lib.php 0000644 00000006201 15152234047 0020465 0 ustar 00 <?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/>. /** * Callbacks * * @package customfield_textarea * @copyright 2018 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; /** * Serve the files from the customfield_textarea file areas * * @param stdClass $course the course object * @param stdClass $cm the course module object * @param context $context the context * @param string $filearea the name of the file area * @param array $args extra arguments (itemid, path) * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if the file not found, just send the file otherwise and do not return */ function customfield_textarea_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $DB; $itemid = array_shift($args); if ($filearea === 'value') { // Value of the data, itemid = id in data table. $datarecord = $DB->get_record(\core_customfield\data::TABLE, ['id' => $itemid], '*', MUST_EXIST); $field = \core_customfield\field_controller::create($datarecord->fieldid); $data = \core_customfield\data_controller::create(0, $datarecord, $field); $handler = $field->get_handler(); if ($field->get('type') !== 'textarea' || !$handler->can_view($field, $data->get('instanceid')) || $data->get_context()->id != $context->id) { send_file_not_found(); } } else if ($filearea === 'defaultvalue') { // Default value of the field, itemid = id in the field table. $field = \core_customfield\field_controller::create($itemid); $handler = $field->get_handler(); if ($field->get('type') !== 'textarea' || $handler->get_configuration_context()->id != $context->id) { send_file_not_found(); } } else { send_file_not_found(); } $filename = array_pop($args); // The last item in the $args array. $filepath = '/' . ($args ? implode('/', $args) . '/' : ''); // Retrieve the file from the Files API. $fs = get_file_storage(); $file = $fs->get_file($context->id, 'customfield_textarea', $filearea, $itemid, $filepath, $filename); if (!$file) { send_file_not_found(); } // We can now send the file back to the browser - in this case with a cache lifetime of 1 day and no filtering. send_file($file, 86400, 0, $forcedownload, $options); } home3/cpr76684/public_html/Aem/mod/workshop/tests/generator/lib.php 0000644 00000013345 15152263111 0021033 0 ustar 00 <?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/>. /** * mod_workshop data generator. * * @package mod_workshop * @category test * @copyright 2013 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * mod_workshop data generator class. * * @package mod_workshop * @category test * @copyright 2013 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class mod_workshop_generator extends testing_module_generator { public function create_instance($record = null, array $options = null) { global $CFG; require_once($CFG->libdir.'/filelib.php'); $workshopconfig = get_config('workshop'); // Add default values for workshop. $record = (array)$record + array( 'strategy' => $workshopconfig->strategy, 'grade' => $workshopconfig->grade, 'gradinggrade' => $workshopconfig->gradinggrade, 'gradedecimals' => $workshopconfig->gradedecimals, 'nattachments' => 1, 'submissionfiletypes' => null, 'maxbytes' => $workshopconfig->maxbytes, 'latesubmissions' => 0, 'useselfassessment' => 0, 'overallfeedbackmode' => 1, 'overallfeedbackfiles' => 0, 'overallfeedbackfiletypes' => null, 'overallfeedbackmaxbytes' => $workshopconfig->maxbytes, 'useexamples' => 0, 'examplesmode' => $workshopconfig->examplesmode, 'submissionstart' => 0, 'submissionend' => 0, 'phaseswitchassessment' => 0, 'assessmentstart' => 0, 'assessmentend' => 0, ); if (!isset($record['gradecategory']) || !isset($record['gradinggradecategory'])) { require_once($CFG->libdir.'/gradelib.php'); $courseid = is_object($record['course']) ? $record['course']->id : $record['course']; $gradecategories = grade_get_categories_menu($courseid); reset($gradecategories); $defaultcategory = key($gradecategories); $record += array( 'gradecategory' => $defaultcategory, 'gradinggradecategory' => $defaultcategory ); } if (!isset($record['instructauthorseditor'])) { $record['instructauthorseditor'] = array( 'text' => 'Instructions for submission '.($this->instancecount+1), 'format' => FORMAT_MOODLE, 'itemid' => file_get_unused_draft_itemid() ); } if (!isset($record['instructreviewerseditor'])) { $record['instructreviewerseditor'] = array( 'text' => 'Instructions for assessment '.($this->instancecount+1), 'format' => FORMAT_MOODLE, 'itemid' => file_get_unused_draft_itemid() ); } if (!isset($record['conclusioneditor'])) { $record['conclusioneditor'] = array( 'text' => 'Conclusion '.($this->instancecount+1), 'format' => FORMAT_MOODLE, 'itemid' => file_get_unused_draft_itemid() ); } return parent::create_instance($record, (array)$options); } /** * Generates a submission authored by the given user. * * @param int $workshopid Workshop instance id. * @param int $authorid Author user id. * @param stdClass|array $options Optional explicit properties. * @return int The new submission id. */ public function create_submission($workshopid, $authorid, $options = null) { global $DB; $timenow = time(); $options = (array)$options; $record = $options + array( 'workshopid' => $workshopid, 'example' => 0, 'authorid' => $authorid, 'timecreated' => $timenow, 'timemodified' => $timenow, 'title' => 'Generated submission', 'content' => 'Generated content', 'contentformat' => FORMAT_MARKDOWN, 'contenttrust' => 0, ); $id = $DB->insert_record('workshop_submissions', $record); return $id; } /** * Generates an allocation of the given submission for peer-assessment by the given user * * @param int $submissionid Submission id. * @param int $reviewerid Reviewer's user id. * @param stdClass|array $options Optional explicit properties. * @return int The new assessment id. */ public function create_assessment($submissionid, $reviewerid, $options = null) { global $DB; $timenow = time(); $options = (array)$options; $record = $options + array( 'submissionid' => $submissionid, 'reviewerid' => $reviewerid, 'weight' => 1, 'timecreated' => $timenow, 'timemodified' => $timenow, 'grade' => null, 'feedbackauthor' => '', 'feedbackreviewer' => '', ); $id = $DB->insert_record('workshop_assessments', $record); return $id; } } home3/cpr76684/public_html/Aem/admin/tool/usertours/lib.php 0000644 00000007165 15152263163 0017402 0 ustar 00 <?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/>. /** * Tour. * * @package tool_usertours * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); use core\output\inplace_editable; use tool_usertours\helper; /** * Manage inplace editable saves. * * @param string $itemtype The type of item. * @param int $itemid The ID of the item. * @param mixed $newvalue The new value * @return inplace_editable */ function tool_usertours_inplace_editable($itemtype, $itemid, $newvalue) { $context = \context_system::instance(); external_api::validate_context($context); require_capability('tool/usertours:managetours', $context); if ($itemtype === 'tourname') { $tour = helper::get_tour($itemid); $tour->set_name($newvalue)->persist(); return helper::render_tourname_inplace_editable($tour); } else if ($itemtype === 'tourdescription') { $tour = helper::get_tour($itemid); $tour->set_description($newvalue)->persist(); return helper::render_tourdescription_inplace_editable($tour); } else if ($itemtype === 'tourenabled') { $tour = helper::get_tour($itemid); $tour->set_enabled(!!$newvalue)->persist(); return helper::render_tourenabled_inplace_editable($tour); } else if ($itemtype === 'stepname') { $step = helper::get_step($itemid); $step->set_title($newvalue)->persist(); return helper::render_stepname_inplace_editable($step); } } /** * Extend the user navigation to bootstrap tours. */ function tool_usertours_extend_navigation_user() { \tool_usertours\helper::bootstrap(); } /** * Add JS to bootstrap tours. Only in Moodle 3.3+ */ function tool_usertours_before_footer() { \tool_usertours\helper::bootstrap(); } /** * Map icons for font-awesome themes. */ function tool_usertours_get_fontawesome_icon_map() { return [ 'tool_usertours:t/export' => 'fa-download', 'tool_usertours:i/reload' => 'fa-refresh', 'tool_usertours:t/filler' => 'fa-spacer', ]; } /** * Serves any files associated with the user tour content. * * @param stdClass $course Course object * @param stdClass $cm Course module object * @param context $context Context * @param string $filearea File area for data privacy * @param array $args Arguments * @param bool $forcedownload If we are forcing the download * @param array $options More options * @return bool Returns false if we don't find a file. */ function tool_usertours_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = []): bool { if ($context->contextlevel != CONTEXT_SYSTEM) { return false; } $fs = get_file_storage(); $file = $fs->get_file($context->id, 'tool_usertours', $filearea, $args[0], '/', $args[1]); if (!$file) { return false; // No such file. } send_stored_file($file, null, 0, $forcedownload, $options); return true; } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/equation/lib.php 0000644 00000006334 15152272777 0021603 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_equation * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Get the list of strings for this plugin. * @param string $elementid */ function atto_equation_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('saveequation', 'editequation', 'preview', 'cursorinfo', 'update', 'librarygroup1', 'librarygroup2', 'librarygroup3', 'librarygroup4'), 'atto_equation'); } /** * Set params for this plugin. * * @param string $elementid * @param stdClass $options - the options for the editor, including the context. * @param stdClass $fpoptions - unused. */ function atto_equation_params_for_js($elementid, $options, $fpoptions) { $texexample = '$$\pi$$'; // Format a string with the active filter set. // If it is modified - we assume that some sort of text filter is working in this context. $result = format_text($texexample, true, $options); $texfilteractive = ($texexample !== $result); $context = $options['context']; if (!$context) { $context = context_system::instance(); } // Tex example librarys. $library = array( 'group1' => array( 'groupname' => 'librarygroup1', 'elements' => get_config('atto_equation', 'librarygroup1'), 'active' => true, ), 'group2' => array( 'groupname' => 'librarygroup2', 'elements' => get_config('atto_equation', 'librarygroup2'), ), 'group3' => array( 'groupname' => 'librarygroup3', 'elements' => get_config('atto_equation', 'librarygroup3'), ), 'group4' => array( 'groupname' => 'librarygroup4', 'elements' => get_config('atto_equation', 'librarygroup4'), )); return array('texfilteractive' => $texfilteractive, 'contextid' => $context->id, 'library' => $library, 'texdocsurl' => get_docs_url('Using_TeX_Notation')); } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/link/lib.php 0000644 00000002660 15152306412 0020671 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_link * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Initialise this plugin * @param string $elementid */ function atto_link_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('createlink', 'unlink', 'enterurl', 'browserepositories', 'openinnewwindow', 'texttodisplay'), 'atto_link'); } home3/cpr76684/public_html/Aem/lib/editor/atto/plugins/table/lib.php 0000644 00000007060 15152331561 0021025 0 ustar 00 <?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/>. /** * Atto text editor integration version file. * * @package atto_table * @copyright 2013 Damyon Wiese <damyon@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Initialise the js strings required for this module. */ function atto_table_strings_for_js() { global $PAGE; $PAGE->requires->strings_for_js(array('createtable', 'updatetable', 'appearance', 'headers', 'caption', 'columns', 'rows', 'numberofcolumns', 'numberofrows', 'both', 'edittable', 'addcolumnafter', 'addrowafter', 'movecolumnright', 'movecolumnleft', 'moverowdown', 'moverowup', 'deleterow', 'deletecolumn', 'captionposition', 'borders', 'bordersize', 'bordercolour', 'borderstyles', 'none', 'all', 'backgroundcolour', 'width', 'outer', 'noborder', 'themedefault', 'dotted', 'dashed', 'solid'), 'atto_table'); $PAGE->requires->strings_for_js(array('top', 'bottom'), 'editor'); } /** * Set params for this plugin * @param string $elementid * @param string $options * @param string $foptions */ function atto_table_params_for_js($elementid, $options, $foptions) { $params = array('allowBorders' => (bool) get_config('atto_table', 'allowborders'), 'allowWidth' => (bool) get_config('atto_table', 'allowwidth'), 'allowBackgroundColour' => (bool) get_config('atto_table', 'allowbackgroundcolour')); return $params; }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.01 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�