Ejemplo n.º 1
0
    /**
     * Return all courses this rule applies to.
     *
     * @return array A list of courses.
     */
    public function get_courses()
    {
        global $CFG, $DB;
        if (isset($this->courses)) {
            return $this->courses;
        }
        require_once $CFG->libdir . '/coursecatlib.php';
        $coursecat = \coursecat::get($this->id);
        $courselist = $coursecat->get_courses(array('recursive' => true, 'idonly' => true));
        // Generate the SQL.
        list($sql, $params) = $DB->get_in_or_equal($courselist);
        $ctxlevel = \CONTEXT_COURSE;
        $preload = \context_helper::get_preload_record_columns_sql('ctx');
        $sql = <<<SQL
            SELECT c.*, {$preload}
            FROM {course} c
            INNER JOIN {context} ctx
                ON ctx.instanceid = c.id AND ctx.contextlevel = {$ctxlevel}
            WHERE c.id {$sql}
SQL;
        // Get the courses and preload contexts.
        $this->courses = $DB->get_records_sql($sql, $params);
        foreach ($this->courses as $course) {
            \context_helper::preload_from_record($course);
        }
        return $this->courses;
    }
Ejemplo n.º 2
0
/**
 * Returns shortname of activities in course
 *
 * @param int $courseid id of course for which activity shortname is needed
 * @return string|bool list of child shortname
 */
function block_course_overview_get_child_shortnames($courseid)
{
    global $DB;
    $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
    $sql = "SELECT c.id, c.shortname, {$ctxselect}\n            FROM {enrol} e\n            JOIN {course} c ON (c.id = e.customint1)\n            JOIN {context} ctx ON (ctx.instanceid = e.customint1)\n            WHERE e.courseid = :courseid AND e.enrol = :method AND ctx.contextlevel = :contextlevel ORDER BY e.sortorder";
    $params = array('method' => 'meta', 'courseid' => $courseid, 'contextlevel' => CONTEXT_COURSE);
    if ($results = $DB->get_records_sql($sql, $params)) {
        $shortnames = array();
        // Preload the context we will need it to format the category name shortly.
        foreach ($results as $res) {
            context_helper::preload_from_record($res);
            $context = context_course::instance($res->id);
            $shortnames[] = format_string($res->shortname, true, $context);
        }
        $total = count($shortnames);
        $suffix = '';
        if ($total > 10) {
            $shortnames = array_slice($shortnames, 0, 10);
            $diff = $total - count($shortnames);
            if ($diff > 1) {
                $suffix = get_string('shortnamesufixprural', 'block_course_overview', $diff);
            } else {
                $suffix = get_string('shortnamesufixsingular', 'block_course_overview', $diff);
            }
        }
        $shortnames = get_string('shortnameprefix', 'block_course_overview', implode('; ', $shortnames));
        $shortnames .= $suffix;
    }
    return isset($shortnames) ? $shortnames : false;
}
Ejemplo n.º 3
0
 function definition()
 {
     global $CFG, $DB;
     $mform = $this->_form;
     $course = $this->_customdata;
     $this->course = $course;
     $existing = $DB->get_records('enrol', array('enrol' => 'meta', 'courseid' => $course->id), '', 'customint1, id');
     // TODO: this has to be done via ajax or else it will fail very badly on large sites!
     $courses = array('' => get_string('choosedots'));
     list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx');
     $sql = "SELECT c.id, c.fullname, c.shortname, c.visible {$select} FROM {course} c {$join} ORDER BY c.sortorder ASC";
     $rs = $DB->get_recordset_sql($sql);
     foreach ($rs as $c) {
         if ($c->id == SITEID or $c->id == $course->id or isset($existing[$c->id])) {
             continue;
         }
         context_helper::preload_from_record($c);
         $coursecontext = context_course::instance($c->id);
         if (!$c->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
             continue;
         }
         if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
             continue;
         }
         $courses[$c->id] = $coursecontext->get_context_name(false);
     }
     $rs->close();
     $mform->addElement('header', 'general', get_string('pluginname', 'enrol_meta'));
     $mform->addElement('select', 'link', get_string('linkedcourse', 'enrol_meta'), $courses);
     $mform->addRule('link', get_string('required'), 'required', null, 'client');
     $mform->addElement('hidden', 'id', null);
     $mform->setType('id', PARAM_INT);
     $this->add_action_buttons(true, get_string('addinstance', 'enrol'));
     $this->set_data(array('id' => $course->id));
 }
    /**
     * Test case for custom context classes
     */
    public function costcenter_custom_contexts_setup() {
     
        global $CFG;
        static $customcontexts = array(
            27 => 'context_costcenter'
       
        );

        // save any existing custom contexts
        $existingcustomcontexts = get_config(null, 'custom_context_classes');

        set_config('custom_context_classes', serialize($customcontexts));
        initialise_cfg();
        context_helper::reset_levels();
        $alllevels = context_helper::get_all_levels();
        
      ///  $this->assertEquals($alllevels[11], 'context_costcenter');
        

        // clean-up & restore any custom contexts
        //set_config('custom_context_classes', ($existingcustomcontexts === false) ? null : $existingcustomcontexts);
       // initialise_cfg();
       // context_helper::reset_levels();
      //  $alllevels = context_helper::get_all_levels();
        
      //  print_object($alllevels);
    }
Ejemplo n.º 5
0
 protected function get_capabitity_optgroups()
 {
     if (!empty($this->_optGroups)) {
         // I have absolutely no idea why this is necessary, but it does seem to be.
         // Bloody formslib. Somehow it is calling the constructor twice.
         return array();
     }
     $optgroups = array();
     $capabilities = context_system::instance()->get_capabilities();
     $contextlevel = 0;
     $component = '';
     $currentgroup = array();
     $currentgroupname = '';
     foreach ($capabilities as $capability) {
         // Start a new optgroup if the componentname or context level has changed.
         if (component_level_changed($capability, $component, $contextlevel)) {
             if ($currentgroup) {
                 $optgroups[$currentgroupname] = $currentgroup;
             }
             $currentgroup = array();
             $currentgroupname = context_helper::get_level_name($capability->contextlevel) . ': ' . get_component_string($capability->component, $capability->contextlevel);
         }
         $contextlevel = $capability->contextlevel;
         $component = $capability->component;
         $a = new stdClass();
         $a->name = get_capability_string($capability->name);
         $a->capabilityname = $capability->name;
         $currentgroup[$capability->name] = get_string('capabilityandname', 'tool_editrolesbycap', $a);
     }
     // Remeber to add the currently open optgroup.
     if ($currentgroup) {
         $optgroups[$currentgroupname] = $currentgroup;
     }
     return $optgroups;
 }
Ejemplo n.º 6
0
 /**
  * Do the job.
  * Throw exceptions on errors (the job will be retried).
  */
 public function execute()
 {
     // Context maintenance stuff.
     \context_helper::cleanup_instances();
     mtrace(' Cleaned up context instances');
     \context_helper::build_all_paths(false);
     // If you suspect that the context paths are somehow corrupt
     // replace the line below with: context_helper::build_all_paths(true).
 }
    public function definition()
    {
        global $CFG, $DB;
        $mform = $this->_form;
        $course = $this->_customdata['course'];
        $instance = $this->_customdata['instance'];
        $this->course = $course;
        $existing = array();
        if ($instance) {
            $existing = $DB->get_records('enrol_metaplus', array('enrolid' => $instance->id), '', 'courseid, id');
        }
        $courses = array();
        $select = context_helper::get_preload_record_columns_sql('ctx');
        $sql = <<<SQL
            SELECT c.id, c.fullname, c.shortname, c.visible, {$select}
            FROM {course} c
            LEFT JOIN {context} ctx
                ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)
SQL;
        $rs = $DB->get_recordset_sql($sql, array('contextlevel' => CONTEXT_COURSE));
        foreach ($rs as $c) {
            if ($c->id == SITEID || $c->id == $course->id) {
                continue;
            }
            context_helper::preload_from_record($c);
            $coursecontext = context_course::instance($c->id);
            if (!$c->visible && !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
                continue;
            }
            if (!has_capability('enrol/meta:selectaslinked', $coursecontext)) {
                continue;
            }
            $courses[$c->id] = $coursecontext->get_context_name(false);
        }
        $rs->close();
        $mform->addElement('header', 'general', get_string('pluginname', 'enrol_meta'));
        $mform->addElement('select', 'link', get_string('linkedcourse', 'enrol_metaplus'), $courses, array('multiple' => 'multiple', 'class' => 'chosen'));
        $mform->addRule('link', get_string('required'), 'required', null, 'server');
        // Add role sync list.
        $coursecontext = \context_course::instance($course->id);
        $roles = get_assignable_roles($coursecontext);
        $mform->addElement('select', 'roleexclusions', get_string('roleexclusions', 'enrol_metaplus'), $roles, array('multiple' => 'multiple'));
        $mform->addElement('hidden', 'id', null);
        $mform->setType('id', PARAM_INT);
        $mform->addElement('hidden', 'enrolid');
        $mform->setType('enrolid', PARAM_INT);
        $data = array('id' => $course->id);
        if ($instance) {
            $data['link'] = implode(',', array_keys($existing));
            $data['enrolid'] = $instance->id;
            $data['roleexclusions'] = $instance->customtext1;
            $this->add_action_buttons();
        } else {
            $this->add_add_buttons();
        }
        $this->set_data($data);
    }
 public function __construct($context, $roleid)
 {
     $this->roleid = $roleid;
     parent::__construct($context, 'defineroletable', $roleid);
     $this->displaypermissions = $this->allpermissions;
     $this->strperms[$this->allpermissions[CAP_INHERIT]] = get_string('notset', 'core_role');
     $this->allcontextlevels = array();
     $levels = context_helper::get_all_levels();
     foreach ($levels as $level => $classname) {
         $this->allcontextlevels[$level] = context_helper::get_level_name($level);
     }
 }
Ejemplo n.º 9
0
/**
 * ELIS(TM): Enterprise Learning Intelligence Suite
 * Copyright (C) 2008-2013 Remote-Learner.net Inc (http://www.remote-learner.net)
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    local_elisprogram
 * @author     Remote-Learner.net Inc
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @copyright  (C) 2008-2013 Remote Learner.net Inc http://www.remote-learner.net
 *
 */
function xmldb_local_elisprogram_install()
{
    global $CFG, $DB;
    $elisadminblockinstalled = file_exists($CFG->dirroot . '/local/elisprogram/lib/setup.php') && $DB->record_exists('block', array('name' => 'elisadmin'));
    if ($elisadminblockinstalled) {
        require_once $CFG->dirroot . '/blocks/elisadmin/lib.php';
    }
    require_once $CFG->dirroot . '/local/elisprogram/lib/lib.php';
    // Install custom context levels.
    \local_eliscore\context\helper::set_custom_levels(\local_elisprogram\context\contextinfo::get_contextinfo());
    \local_eliscore\context\helper::install_custom_levels();
    // Initialize custom context levels.
    context_helper::reset_levels();
    \local_eliscore\context\helper::reset_levels();
    \local_eliscore\context\helper::init_levels();
    // Migrate component.
    $migrator = new \local_elisprogram\install\migration\elis26();
    if ($migrator->old_component_installed() === true) {
        $migrator->migrate();
    }
    //make sure the site has exactly one curr admin block instance
    //that is viewable everywhere
    if ($elisadminblockinstalled) {
        block_elisadmin_create_instance();
    }
    // make sure that the manager role can be assigned to all PM context levels
    update_capabilities('local_elisprogram');
    // load context levels
    pm_ensure_role_assignable('manager');
    pm_ensure_role_assignable('curriculumadmin');
    // Migrate dataroot files
    pm_migrate_certificate_files();
    // These notifications are default-on.
    pm_set_config('notify_addedtowaitlist_user', 1);
    pm_set_config('notify_enroledfromwaitlist_user', 1);
    pm_set_config('notify_incompletecourse_user', 1);
    // Ensure ELIS scheduled tasks is initialized.
    require_once $CFG->dirroot . '/local/eliscore/lib/tasklib.php';
    elis_tasks_update_definition('local_elisprogram');
    // Remove some lingering subplugins that were renamed
    unset_all_config_for_plugin('usersetenrol_manual');
    unset_all_config_for_plugin('usersetenrol_moodle_profile');
}
Ejemplo n.º 10
0
 /**
  * Return the courses where both competency and user are.
  *
  * A user is considered being in a course when they are enrolled, the enrolment is valid,
  * the enrolment instance is enabled, and the enrolment plugin is enabled..
  *
  * @param int $competencyid The competency ID.
  * @param int $userid The user ID.
  * @return array Indexed by course ID.
  */
 public static function get_courses_with_competency_and_user($competencyid, $userid)
 {
     global $CFG, $DB;
     if (!($plugins = explode(',', $CFG->enrol_plugins_enabled))) {
         return array();
     }
     $ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
     list($plugins, $params) = $DB->get_in_or_equal($plugins, SQL_PARAMS_NAMED, 'ee');
     $params['competencyid'] = $competencyid;
     $params['userid'] = $userid;
     $params['enabled'] = ENROL_INSTANCE_ENABLED;
     $params['active'] = ENROL_USER_ACTIVE;
     $params['contextlevel'] = CONTEXT_COURSE;
     // Heavily based on enrol_get_shared_courses().
     $sql = "SELECT c.*, {$ctxfields}\n                  FROM {course} c\n                  JOIN {" . static::TABLE . "} cc\n                    ON cc.courseid = c.id\n                   AND cc.competencyid = :competencyid\n                  JOIN (\n                    SELECT DISTINCT c.id\n                      FROM {enrol} e\n                      JOIN {user_enrolments} ue\n                        ON ue.enrolid = e.id\n                       AND ue.status = :active\n                       AND ue.userid = :userid\n                      JOIN {course} c\n                        ON c.id = e.courseid\n                     WHERE e.status = :enabled\n                       AND e.enrol {$plugins}\n                  ) ec ON ec.id = c.id\n             LEFT JOIN {context} ctx\n                    ON ctx.instanceid = c.id\n                   AND ctx.contextlevel = :contextlevel\n              ORDER BY c.id";
     $courses = $DB->get_records_sql($sql, $params);
     array_map('context_helper::preload_from_record', $courses);
     return $courses;
 }
Ejemplo n.º 11
0
    /**
     * Gets the internal context id from the context reference.
     *
     * The context reference changes depending on the context
     * level, it can be the system, a user, a category, a course or
     * a module.
     *
     * @throws Exception
     * @param string $levelname The context level string introduced by the test writer
     * @param string $contextref The context reference introduced by the test writer
     * @return context
     */
    protected function get_context($levelname, $contextref) {
        global $DB;

        // Getting context levels and names (we will be using the English ones as it is the test site language).
        $contextlevels = context_helper::get_all_levels();
        $contextnames = array();
        foreach ($contextlevels as $level => $classname) {
            $contextnames[context_helper::get_level_name($level)] = $level;
        }

        if (empty($contextnames[$levelname])) {
            throw new Exception('The specified "' . $levelname . '" context level does not exist');
        }
        $contextlevel = $contextnames[$levelname];

        // Return it, we don't need to look for other internal ids.
        if ($contextlevel == CONTEXT_SYSTEM) {
            return context_system::instance();
        }

        switch ($contextlevel) {

            case CONTEXT_USER:
                $instanceid = $DB->get_field('user', 'id', array('username' => $contextref));
                break;

            case CONTEXT_COURSECAT:
                $instanceid = $DB->get_field('course_categories', 'id', array('idnumber' => $contextref));
                break;

            case CONTEXT_COURSE:
                $instanceid = $DB->get_field('course', 'id', array('shortname' => $contextref));
                break;

            case CONTEXT_MODULE:
                $instanceid = $DB->get_field('course_modules', 'id', array('idnumber' => $contextref));
                break;

            default:
                break;
        }

        $contextclass = $contextlevels[$contextlevel];
        if (!$context = $contextclass::instance($instanceid, IGNORE_MISSING)) {
            throw new Exception('The specified "' . $contextref . '" context reference does not exist');
        }

        return $context;
    }
Ejemplo n.º 12
0
 /**
  * Process the course data in the xml
  *
  * @param $groupnode
  * @param $xpath
  * @throws Exception
  * @throws coding_exception
  * @throws dml_missing_record_exception
  */
 private function process_course_group_node($groupnode, $xpath)
 {
     global $DB, $CFG;
     $course = new stdClass();
     if ($groupnode->getAttribute("recstatus") != 3) {
         $shortdesc = $xpath->evaluate("description/short", $groupnode)->item(0);
         if ($shortdesc) {
             $course->shortname = $shortdesc->nodeValue;
         }
         $longdesc = $xpath->evaluate("description/long", $groupnode)->item(0);
         if ($longdesc) {
             $course->fullname = $longdesc->nodeValue;
         }
         $idnumber = $xpath->evaluate("sourcedid/id", $groupnode)->item(0);
         if ($idnumber) {
             $course->idnumber = htmlspecialchars_decode($idnumber->nodeValue);
         }
         $course->format = 'topics';
         $course->visible = 0;
         $course->timecreated = time();
         $course->startdate = time();
         $course->sortorder = 0;
         $parentgroup = $xpath->evaluate("relationship/sourcedid/id", $groupnode)->item(0);
         if ($parentgroup) {
             $parentid = $DB->get_field_select('course_categories', 'id', 'description=\'' . htmlspecialchars_decode($parentgroup->nodeValue) . '\'');
             if ($parentid) {
                 $course->category = $parentid;
             } else {
                 $course->category = 4;
             }
         } else {
             $course->category = 4;
         }
         $settings = $xpath->evaluate("extension/settings", $groupnode);
         foreach ($settings as $setting) {
             $key = $xpath->evaluate("setting", $setting)->item(0)->nodeValue;
             $val = $xpath->evaluate("value", $setting)->item(0)->nodeValue;
             $course->{$key} = $val;
         }
         if (!$DB->get_field('course', 'id', array('idnumber' => $course->idnumber))) {
             // New Course.
             if (!isset($course->numsections)) {
                 $course->numsections = 10;
             }
             $courseid = $DB->insert_record('course', $course);
             // Setup the blocks.
             $course = $DB->get_record('course', array('id' => $courseid));
             blocks_add_default_course_blocks($course);
             $section = new stdClass();
             $section->course = $course->id;
             // Create a default section.
             $section->section = 0;
             $section->summaryformat = FORMAT_HTML;
             $section->id = $DB->insert_record("course_sections", $section);
             $enrol = enrol_get_plugin('manual');
             if ($audroleid = $DB->get_field('role', 'id', array('shortname' => 'auditor'))) {
                 $enrol->add_instance($course, array('roleid' => $audroleid));
             } else {
                 $enrol->add_instance($course);
             }
             $coursemanagement = new stdClass();
             // Get the start and end date for the course.
             $begin = $xpath->evaluate("timeframe/begin", $groupnode)->item(0);
             if ($begin) {
                 $coursemanagement->startdate = $begin->nodeValue;
             }
             $end = $xpath->evaluate("timeframe/end", $groupnode)->item(0);
             if ($end) {
                 $coursemanagement->enddate = $end->nodeValue;
             }
             if (isset($coursemanagement->startdate) && $coursemanagement->startdate > 0 && isset($coursemanagement->enddate) && $coursemanagement->enddate > 0) {
                 // The course validly has both start and end dates.
                 $coursemanagement->courseid = $course->id;
                 $coursemanagement->timemodified = time();
                 $DB->insert_record("eclass_course_management", $coursemanagement);
             } else {
                 if (isset($coursemanagement->startdate) || isset($coursemanagement->enddate)) {
                     // Something isn't right with the start or end date.
                     throw new Exception('UAIMS: Course Creation without valid start or end date');
                 }
             }
             // No else needed. No actions required if the course is validly lacking both start and end dates.
         } else {
             // Update existing Course, if corresponding eclass_course_management exist. Otherwise, create a
             // corresponding eclass_course_management entry.
             $ecourse = $DB->get_record('course', array('idnumber' => $course->idnumber), '*', MUST_EXIST);
             $enableqrtoggle = $this->get_config('enableqrvisibilitytoggle');
             // Disable or enable QR toggling.
             if (!isset($enableqrtoggle) || !$enableqrtoggle) {
                 unset($course->visible);
             } else {
                 // Otherwise update the startend dates in the eclass_course_management table from uaims documents.
                 $coursemanagement = $DB->get_record('eclass_course_management', array('courseid' => $ecourse->id), $fields = 'id', $strictness = IGNORE_MISSING);
                 // Get the start and end date for the course.
                 $begin = $xpath->evaluate("timeframe/begin", $groupnode)->item(0);
                 $end = $xpath->evaluate("timeframe/end", $groupnode)->item(0);
                 // To avoid errors when course is created outside of uaims (doesn't have eclass_course_management entry),
                 // create and set appropriate attributes of $coursemanagement that matches eclass_course_management
                 // database schema (or atleast NOT NULL fields).
                 $coursemanagementexist = $coursemanagement != false;
                 if (!$coursemanagementexist) {
                     $enrol = enrol_get_plugin('manual');
                     if ($audroleid = $DB->get_field('role', 'id', array('shortname' => 'auditor'))) {
                         $enrol->add_instance($ecourse, array('roleid' => $audroleid));
                     } else {
                         $enrol->add_instance($ecourse);
                     }
                     $coursemanagement = new stdClass();
                     // The test process_imsdoc_test::test_process_imsdoc_should_update_course_with_minimal_imsdoc
                     // implies that one of the requirement of this module is to ignore updates/insert in the case where
                     // course exist, yet no start/end date. (Note this differ from the case where the course don't exist
                     // in which case the requirements of this module requires it to throw an exception.
                     if ($begin and $end) {
                         // Set appropriate eclass_course_management row attributes and finally insert it to db.
                         $coursemanagement->courseid = $ecourse->id;
                         $coursemanagement->startdate = $begin->nodeValue;
                         $coursemanagement->enddate = $end->nodeValue;
                         $coursemanagement->timemodified = time();
                         $DB->insert_record("eclass_course_management", $coursemanagement);
                     }
                 } else {
                     // Since corresponding eclass_course_management entry exist, only we don't need all parameters
                     // to be present. Either/both $begin/$end dates is/are sufficient.
                     if ($begin) {
                         $coursemanagement->startdate = $begin->nodeValue;
                     }
                     if ($end) {
                         $coursemanagement->enddate = $end->nodeValue;
                     }
                     if (isset($coursemanagement->startdate) || isset($coursemanagement->enddate)) {
                         // If one of them is there then do the update.
                         if ($coursemanagement->startdate || $coursemanagement->enddate) {
                             $coursemanagement->timemodified = time();
                             $DB->update_record("eclass_course_management", $coursemanagement);
                         }
                     }
                 }
             }
             // The $course var should never have an 'id' attribute, but lets make sure.
             if (isset($course->id)) {
                 unset($course->id);
             }
             $ecourse = $this->extend($ecourse, $course);
             $DB->update_record('course', $ecourse);
             $classname = context_helper::get_class_for_level(CONTEXT_COURSE);
             $context = $classname::instance($ecourse->id, IGNORE_MISSING);
             $classname = context_helper::get_class_for_level(CONTEXT_COURSECAT);
             $newparent = $classname::instance($ecourse->category, IGNORE_MISSING);
             $context->update_moved($newparent);
             if (!($instanceid = $DB->get_field('enrol', 'id', array('enrol' => 'manual', 'courseid' => $ecourse->id)))) {
                 $enrol = enrol_get_plugin('manual');
                 if ($audroleid = $DB->get_field('role', 'id', array('shortname' => 'auditor'))) {
                     $enrol->add_instance($ecourse, array('roleid' => $audroleid));
                 } else {
                     $enrol->add_instance(${$ecourse});
                 }
             }
         }
     } else {
         $idnumber = $xpath->evaluate("sourcedid/id", $groupnode)->item(0);
         if ($idnumber) {
             $idnumber = htmlspecialchars_decode($idnumber->nodeValue);
             $course = $DB->get_record('course', array('idnumber' => $idnumber));
             delete_course($course, false);
         }
     }
 }
Ejemplo n.º 13
0
 /**
  * Finds all assignment notifications that have yet to be mailed out, and mails them.
  *
  * Cron function to be run periodically according to the moodle cron.
  *
  * @return bool
  */
 public static function cron()
 {
     global $DB;
     // Only ever send a max of one days worth of updates.
     $yesterday = time() - 24 * 3600;
     $timenow = time();
     $lastcron = $DB->get_field('modules', 'lastcron', array('name' => 'assign'));
     // Collect all submissions that require mailing.
     // Submissions are included if all are true:
     //   - The assignment is visible in the gradebook.
     //   - No previous notification has been sent.
     //   - If marking workflow is not enabled, the grade was updated in the past 24 hours, or
     //     if marking workflow is enabled, the workflow state is at 'released'.
     $sql = "SELECT g.id as gradeid, a.course, a.name, a.blindmarking, a.revealidentities,\n                       g.*, g.timemodified as lastmodified, cm.id as cmid\n                 FROM {assign} a\n                 JOIN {assign_grades} g ON g.assignment = a.id\n            LEFT JOIN {assign_user_flags} uf ON uf.assignment = a.id AND uf.userid = g.userid\n                 JOIN {course_modules} cm ON cm.course = a.course AND cm.instance = a.id\n                 JOIN {modules} md ON md.id = cm.module AND md.name = 'assign'\n                 JOIN {grade_items} gri ON gri.iteminstance = a.id AND gri.courseid = a.course AND gri.itemmodule = md.name\n                 WHERE ((a.markingworkflow = 0 AND g.timemodified >= :yesterday AND g.timemodified <= :today) OR\n                        (a.markingworkflow = 1 AND uf.workflowstate = :wfreleased)) AND\n                       uf.mailed = 0 AND gri.hidden = 0\n              ORDER BY a.course, cm.id";
     $params = array('yesterday' => $yesterday, 'today' => $timenow, 'wfreleased' => ASSIGN_MARKING_WORKFLOW_STATE_RELEASED);
     $submissions = $DB->get_records_sql($sql, $params);
     if (!empty($submissions)) {
         mtrace('Processing ' . count($submissions) . ' assignment submissions ...');
         // Preload courses we are going to need those.
         $courseids = array();
         foreach ($submissions as $submission) {
             $courseids[] = $submission->course;
         }
         // Filter out duplicates.
         $courseids = array_unique($courseids);
         $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
         list($courseidsql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
         $sql = 'SELECT c.*, ' . $ctxselect . ' FROM {course} c
              LEFT JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel
                  WHERE c.id ' . $courseidsql;
         $params['contextlevel'] = CONTEXT_COURSE;
         $courses = $DB->get_records_sql($sql, $params);
         // Clean up... this could go on for a while.
         unset($courseids);
         unset($ctxselect);
         unset($courseidsql);
         unset($params);
         // Message students about new feedback.
         foreach ($submissions as $submission) {
             mtrace("Processing assignment submission {$submission->id} ...");
             // Do not cache user lookups - could be too many.
             if (!($user = $DB->get_record('user', array('id' => $submission->userid)))) {
                 mtrace('Could not find user ' . $submission->userid);
                 continue;
             }
             // Use a cache to prevent the same DB queries happening over and over.
             if (!array_key_exists($submission->course, $courses)) {
                 mtrace('Could not find course ' . $submission->course);
                 continue;
             }
             $course = $courses[$submission->course];
             if (isset($course->ctxid)) {
                 // Context has not yet been preloaded. Do so now.
                 context_helper::preload_from_record($course);
             }
             // Override the language and timezone of the "current" user, so that
             // mail is customised for the receiver.
             cron_setup_user($user, $course);
             // Context lookups are already cached.
             $coursecontext = context_course::instance($course->id);
             if (!is_enrolled($coursecontext, $user->id)) {
                 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
                 mtrace(fullname($user) . ' not an active participant in ' . $courseshortname);
                 continue;
             }
             if (!($grader = $DB->get_record('user', array('id' => $submission->grader)))) {
                 mtrace('Could not find grader ' . $submission->grader);
                 continue;
             }
             $modinfo = get_fast_modinfo($course, $user->id);
             $cm = $modinfo->get_cm($submission->cmid);
             // Context lookups are already cached.
             $contextmodule = context_module::instance($cm->id);
             if (!$cm->uservisible) {
                 // Hold mail notification for assignments the user cannot access until later.
                 continue;
             }
             // Need to send this to the student.
             $messagetype = 'feedbackavailable';
             $eventtype = 'assign_notification';
             $updatetime = $submission->lastmodified;
             $modulename = get_string('modulename', 'assign');
             $uniqueid = 0;
             if ($submission->blindmarking && !$submission->revealidentities) {
                 $uniqueid = self::get_uniqueid_for_user_static($submission->assignment, $user->id);
             }
             $showusers = $submission->blindmarking && !$submission->revealidentities;
             self::send_assignment_notification($grader, $user, $messagetype, $eventtype, $updatetime, $cm, $contextmodule, $course, $modulename, $submission->name, $showusers, $uniqueid);
             $flags = $DB->get_record('assign_user_flags', array('userid' => $user->id, 'assignment' => $submission->assignment));
             if ($flags) {
                 $flags->mailed = 1;
                 $DB->update_record('assign_user_flags', $flags);
             } else {
                 $flags = new stdClass();
                 $flags->userid = $user->id;
                 $flags->assignment = $submission->assignment;
                 $flags->mailed = 1;
                 $DB->insert_record('assign_user_flags', $flags);
             }
             mtrace('Done');
         }
         mtrace('Done processing ' . count($submissions) . ' assignment submissions');
         cron_setup_user();
         // Free up memory just to be sure.
         unset($courses);
     }
     // Update calendar events to provide a description.
     $sql = 'SELECT id
                 FROM {assign}
                 WHERE
                     allowsubmissionsfromdate >= :lastcron AND
                     allowsubmissionsfromdate <= :timenow AND
                     alwaysshowdescription = 0';
     $params = array('lastcron' => $lastcron, 'timenow' => $timenow);
     $newlyavailable = $DB->get_records_sql($sql, $params);
     foreach ($newlyavailable as $record) {
         $cm = get_coursemodule_from_instance('assign', $record->id, 0, false, MUST_EXIST);
         $context = context_module::instance($cm->id);
         $assignment = new assign($context, null, null);
         $assignment->update_calendar($cm->id);
     }
     return true;
 }
Ejemplo n.º 14
0
 /**
  * Returns the name of specified context level
  *
  * @static
  * @param int $contextlevel
  * @return string name of the context level
  */
 public static function get_level_name($contextlevel)
 {
     $classname = context_helper::get_class_for_level($contextlevel);
     return $classname::get_level_name();
 }
Ejemplo n.º 15
0
/**
 * Execute cron tasks
 */
function cron_run()
{
    global $DB, $CFG, $OUTPUT;
    if (CLI_MAINTENANCE) {
        echo "CLI maintenance mode active, cron execution suspended.\n";
        exit(1);
    }
    if (moodle_needs_upgrading()) {
        echo "Moodle upgrade pending, cron execution suspended.\n";
        exit(1);
    }
    require_once $CFG->libdir . '/adminlib.php';
    require_once $CFG->libdir . '/gradelib.php';
    if (!empty($CFG->showcronsql)) {
        $DB->set_debug(true);
    }
    if (!empty($CFG->showcrondebugging)) {
        set_debugging(DEBUG_DEVELOPER, true);
    }
    set_time_limit(0);
    $starttime = microtime();
    // Increase memory limit
    raise_memory_limit(MEMORY_EXTRA);
    // Emulate normal session - we use admin accoutn by default
    cron_setup_user();
    // Start output log
    $timenow = time();
    mtrace("Server Time: " . date('r', $timenow) . "\n\n");
    // Run cleanup core cron jobs, but not every time since they aren't too important.
    // These don't have a timer to reduce load, so we'll use a random number
    // to randomly choose the percentage of times we should run these jobs.
    $random100 = rand(0, 100);
    if ($random100 < 20) {
        // Approximately 20% of the time.
        mtrace("Running clean-up tasks...");
        cron_trace_time_and_memory();
        // Delete users who haven't confirmed within required period
        if (!empty($CFG->deleteunconfirmed)) {
            $cuttime = $timenow - $CFG->deleteunconfirmed * 3600;
            $rs = $DB->get_recordset_sql("SELECT *\n                                             FROM {user}\n                                            WHERE confirmed = 0 AND firstaccess > 0\n                                                  AND firstaccess < ?", array($cuttime));
            foreach ($rs as $user) {
                delete_user($user);
                // we MUST delete user properly first
                $DB->delete_records('user', array('id' => $user->id));
                // this is a bloody hack, but it might work
                mtrace(" Deleted unconfirmed user for " . fullname($user, true) . " ({$user->id})");
            }
            $rs->close();
        }
        // Delete users who haven't completed profile within required period
        if (!empty($CFG->deleteincompleteusers)) {
            $cuttime = $timenow - $CFG->deleteincompleteusers * 3600;
            $rs = $DB->get_recordset_sql("SELECT *\n                                             FROM {user}\n                                            WHERE confirmed = 1 AND lastaccess > 0\n                                                  AND lastaccess < ? AND deleted = 0\n                                                  AND (lastname = '' OR firstname = '' OR email = '')", array($cuttime));
            foreach ($rs as $user) {
                if (isguestuser($user) or is_siteadmin($user)) {
                    continue;
                }
                delete_user($user);
                mtrace(" Deleted not fully setup user {$user->username} ({$user->id})");
            }
            $rs->close();
        }
        // Delete old logs to save space (this might need a timer to slow it down...)
        if (!empty($CFG->loglifetime)) {
            // value in days
            $loglifetime = $timenow - $CFG->loglifetime * 3600 * 24;
            $DB->delete_records_select("log", "time < ?", array($loglifetime));
            mtrace(" Deleted old log records");
        }
        // Delete old backup_controllers and logs.
        $loglifetime = get_config('backup', 'loglifetime');
        if (!empty($loglifetime)) {
            // Value in days.
            $loglifetime = $timenow - $loglifetime * 3600 * 24;
            // Delete child records from backup_logs.
            $DB->execute("DELETE FROM {backup_logs}\n                           WHERE EXISTS (\n                               SELECT 'x'\n                                 FROM {backup_controllers} bc\n                                WHERE bc.backupid = {backup_logs}.backupid\n                                  AND bc.timecreated < ?)", array($loglifetime));
            // Delete records from backup_controllers.
            $DB->execute("DELETE FROM {backup_controllers}\n                          WHERE timecreated < ?", array($loglifetime));
            mtrace(" Deleted old backup records");
        }
        // Delete old cached texts
        if (!empty($CFG->cachetext)) {
            // Defined in config.php
            $cachelifetime = time() - $CFG->cachetext - 60;
            // Add an extra minute to allow for really heavy sites
            $DB->delete_records_select('cache_text', "timemodified < ?", array($cachelifetime));
            mtrace(" Deleted old cache_text records");
        }
        if (!empty($CFG->usetags)) {
            require_once $CFG->dirroot . '/tag/lib.php';
            tag_cron();
            mtrace(' Executed tag cron');
        }
        // Context maintenance stuff
        context_helper::cleanup_instances();
        mtrace(' Cleaned up context instances');
        context_helper::build_all_paths(false);
        // If you suspect that the context paths are somehow corrupt
        // replace the line below with: context_helper::build_all_paths(true);
        mtrace(' Built context paths');
        // Remove expired cache flags
        gc_cache_flags();
        mtrace(' Cleaned cache flags');
        // Cleanup messaging
        if (!empty($CFG->messagingdeletereadnotificationsdelay)) {
            $notificationdeletetime = time() - $CFG->messagingdeletereadnotificationsdelay;
            $DB->delete_records_select('message_read', 'notification=1 AND timeread<:notificationdeletetime', array('notificationdeletetime' => $notificationdeletetime));
            mtrace(' Cleaned up read notifications');
        }
        mtrace(' Deleting temporary files...');
        cron_delete_from_temp();
        // Cleanup user password reset records
        // Delete any reset request records which are expired by more than a day.
        // (We keep recently expired requests around so we can give a different error msg to users who
        // are trying to user a recently expired reset attempt).
        $pwresettime = isset($CFG->pwresettime) ? $CFG->pwresettime : 1800;
        $earliestvalid = time() - $pwresettime - DAYSECS;
        $DB->delete_records_select('user_password_resets', "timerequested < ?", array($earliestvalid));
        mtrace(' Cleaned up old password reset records');
        mtrace("...finished clean-up tasks");
    }
    // End of occasional clean-up tasks
    // Send login failures notification - brute force protection in moodle is weak,
    // we should at least send notices early in each cron execution
    if (notify_login_failures()) {
        mtrace(' Notified login failures');
    }
    // Make sure all context instances are properly created - they may be required in auth, enrol, etc.
    context_helper::create_instances();
    mtrace(' Created missing context instances');
    // Session gc.
    mtrace("Running session gc tasks...");
    \core\session\manager::gc();
    mtrace("...finished stale session cleanup");
    // Run the auth cron, if any before enrolments
    // because it might add users that will be needed in enrol plugins
    $auths = get_enabled_auth_plugins();
    mtrace("Running auth crons if required...");
    cron_trace_time_and_memory();
    foreach ($auths as $auth) {
        $authplugin = get_auth_plugin($auth);
        if (method_exists($authplugin, 'cron')) {
            mtrace("Running cron for auth/{$auth}...");
            $authplugin->cron();
            if (!empty($authplugin->log)) {
                mtrace($authplugin->log);
            }
        }
        unset($authplugin);
    }
    // Generate new password emails for users - ppl expect these generated asap
    if ($DB->count_records('user_preferences', array('name' => 'create_password', 'value' => '1'))) {
        mtrace('Creating passwords for new users...');
        $usernamefields = get_all_user_name_fields(true, 'u');
        $newusers = $DB->get_recordset_sql("SELECT u.id as id, u.email,\n                                                 {$usernamefields}, u.username, u.lang,\n                                                 p.id as prefid\n                                            FROM {user} u\n                                            JOIN {user_preferences} p ON u.id=p.userid\n                                           WHERE p.name='create_password' AND p.value='1' AND u.email !='' AND u.suspended = 0 AND u.auth != 'nologin' AND u.deleted = 0");
        // note: we can not send emails to suspended accounts
        foreach ($newusers as $newuser) {
            // Use a low cost factor when generating bcrypt hash otherwise
            // hashing would be slow when emailing lots of users. Hashes
            // will be automatically updated to a higher cost factor the first
            // time the user logs in.
            if (setnew_password_and_mail($newuser, true)) {
                unset_user_preference('create_password', $newuser);
                set_user_preference('auth_forcepasswordchange', 1, $newuser);
            } else {
                trigger_error("Could not create and mail new user password!");
            }
        }
        $newusers->close();
    }
    // It is very important to run enrol early
    // because other plugins depend on correct enrolment info.
    mtrace("Running enrol crons if required...");
    $enrols = enrol_get_plugins(true);
    foreach ($enrols as $ename => $enrol) {
        // do this for all plugins, disabled plugins might want to cleanup stuff such as roles
        if (!$enrol->is_cron_required()) {
            continue;
        }
        mtrace("Running cron for enrol_{$ename}...");
        cron_trace_time_and_memory();
        $enrol->cron();
        $enrol->set_config('lastcron', time());
    }
    // Run all cron jobs for each module
    mtrace("Starting activity modules");
    get_mailer('buffer');
    if ($mods = $DB->get_records_select("modules", "cron > 0 AND ((? - lastcron) > cron) AND visible = 1", array($timenow))) {
        foreach ($mods as $mod) {
            $libfile = "{$CFG->dirroot}/mod/{$mod->name}/lib.php";
            if (file_exists($libfile)) {
                include_once $libfile;
                $cron_function = $mod->name . "_cron";
                if (function_exists($cron_function)) {
                    mtrace("Processing module function {$cron_function} ...", '');
                    cron_trace_time_and_memory();
                    $pre_dbqueries = null;
                    $pre_dbqueries = $DB->perf_get_queries();
                    $pre_time = microtime(1);
                    if ($cron_function()) {
                        $DB->set_field("modules", "lastcron", $timenow, array("id" => $mod->id));
                    }
                    if (isset($pre_dbqueries)) {
                        mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries");
                        mtrace("... used " . (microtime(1) - $pre_time) . " seconds");
                    }
                    // Reset possible changes by modules to time_limit. MDL-11597
                    @set_time_limit(0);
                    mtrace("done.");
                }
            }
        }
    }
    get_mailer('close');
    mtrace("Finished activity modules");
    mtrace("Starting blocks");
    if ($blocks = $DB->get_records_select("block", "cron > 0 AND ((? - lastcron) > cron) AND visible = 1", array($timenow))) {
        // We will need the base class.
        require_once $CFG->dirroot . '/blocks/moodleblock.class.php';
        foreach ($blocks as $block) {
            $blockfile = $CFG->dirroot . '/blocks/' . $block->name . '/block_' . $block->name . '.php';
            if (file_exists($blockfile)) {
                require_once $blockfile;
                $classname = 'block_' . $block->name;
                $blockobj = new $classname();
                if (method_exists($blockobj, 'cron')) {
                    mtrace("Processing cron function for " . $block->name . '....', '');
                    cron_trace_time_and_memory();
                    if ($blockobj->cron()) {
                        $DB->set_field('block', 'lastcron', $timenow, array('id' => $block->id));
                    }
                    // Reset possible changes by blocks to time_limit. MDL-11597
                    @set_time_limit(0);
                    mtrace('done.');
                }
            }
        }
    }
    mtrace('Finished blocks');
    mtrace('Starting admin reports');
    cron_execute_plugin_type('report');
    mtrace('Finished admin reports');
    mtrace('Starting main gradebook job...');
    cron_trace_time_and_memory();
    grade_cron();
    mtrace('done.');
    mtrace('Starting processing the event queue...');
    cron_trace_time_and_memory();
    events_cron();
    mtrace('done.');
    if ($CFG->enablecompletion) {
        // Completion cron
        mtrace('Starting the completion cron...');
        cron_trace_time_and_memory();
        require_once $CFG->dirroot . '/completion/cron.php';
        completion_cron();
        mtrace('done');
    }
    if ($CFG->enableportfolios) {
        // Portfolio cron
        mtrace('Starting the portfolio cron...');
        cron_trace_time_and_memory();
        require_once $CFG->libdir . '/portfoliolib.php';
        portfolio_cron();
        mtrace('done');
    }
    //now do plagiarism checks
    require_once $CFG->libdir . '/plagiarismlib.php';
    plagiarism_cron();
    mtrace('Starting course reports');
    cron_execute_plugin_type('coursereport');
    mtrace('Finished course reports');
    // run gradebook import/export/report cron
    mtrace('Starting gradebook plugins');
    cron_execute_plugin_type('gradeimport');
    cron_execute_plugin_type('gradeexport');
    cron_execute_plugin_type('gradereport');
    mtrace('Finished gradebook plugins');
    // run calendar cron
    require_once "{$CFG->dirroot}/calendar/lib.php";
    calendar_cron();
    // Run external blog cron if needed
    if (!empty($CFG->enableblogs) && $CFG->useexternalblogs) {
        require_once $CFG->dirroot . '/blog/lib.php';
        mtrace("Fetching external blog entries...", '');
        cron_trace_time_and_memory();
        $sql = "timefetched < ? OR timefetched = 0";
        $externalblogs = $DB->get_records_select('blog_external', $sql, array(time() - $CFG->externalblogcrontime));
        foreach ($externalblogs as $eb) {
            blog_sync_external_entries($eb);
        }
        mtrace('done.');
    }
    // Run blog associations cleanup
    if (!empty($CFG->enableblogs) && $CFG->useblogassociations) {
        require_once $CFG->dirroot . '/blog/lib.php';
        // delete entries whose contextids no longer exists
        mtrace("Deleting blog associations linked to non-existent contexts...", '');
        cron_trace_time_and_memory();
        $DB->delete_records_select('blog_association', 'contextid NOT IN (SELECT id FROM {context})');
        mtrace('done.');
    }
    // Run question bank clean-up.
    mtrace("Starting the question bank cron...", '');
    cron_trace_time_and_memory();
    require_once $CFG->libdir . '/questionlib.php';
    question_bank::cron();
    mtrace('done.');
    //Run registration updated cron
    mtrace(get_string('siteupdatesstart', 'hub'));
    cron_trace_time_and_memory();
    require_once $CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php';
    $registrationmanager = new registration_manager();
    $registrationmanager->cron();
    mtrace(get_string('siteupdatesend', 'hub'));
    // If enabled, fetch information about available updates and eventually notify site admins
    if (empty($CFG->disableupdatenotifications)) {
        $updateschecker = \core\update\checker::instance();
        $updateschecker->cron();
    }
    //cleanup old session linked tokens
    //deletes the session linked tokens that are over a day old.
    mtrace("Deleting session linked tokens more than one day old...", '');
    cron_trace_time_and_memory();
    $DB->delete_records_select('external_tokens', 'lastaccess < :onedayago AND tokentype = :tokentype', array('onedayago' => time() - DAYSECS, 'tokentype' => EXTERNAL_TOKEN_EMBEDDED));
    mtrace('done.');
    // all other plugins
    cron_execute_plugin_type('message', 'message plugins');
    cron_execute_plugin_type('filter', 'filters');
    cron_execute_plugin_type('editor', 'editors');
    cron_execute_plugin_type('format', 'course formats');
    cron_execute_plugin_type('profilefield', 'profile fields');
    cron_execute_plugin_type('webservice', 'webservices');
    cron_execute_plugin_type('repository', 'repository plugins');
    cron_execute_plugin_type('qbehaviour', 'question behaviours');
    cron_execute_plugin_type('qformat', 'question import/export formats');
    cron_execute_plugin_type('qtype', 'question types');
    cron_execute_plugin_type('plagiarism', 'plagiarism plugins');
    cron_execute_plugin_type('theme', 'themes');
    cron_execute_plugin_type('tool', 'admin tools');
    // and finally run any local cronjobs, if any
    if ($locals = core_component::get_plugin_list('local')) {
        mtrace('Processing customized cron scripts ...', '');
        // new cron functions in lib.php first
        cron_execute_plugin_type('local');
        // legacy cron files are executed directly
        foreach ($locals as $local => $localdir) {
            if (file_exists("{$localdir}/cron.php")) {
                include "{$localdir}/cron.php";
            }
        }
        mtrace('done.');
    }
    mtrace('Running cache cron routines');
    cache_helper::cron();
    mtrace('done.');
    // Run automated backups if required - these may take a long time to execute
    require_once $CFG->dirroot . '/backup/util/includes/backup_includes.php';
    require_once $CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php';
    backup_cron_automated_helper::run_automated_backup();
    // Run stats as at the end because they are known to take very long time on large sites
    if (!empty($CFG->enablestats) and empty($CFG->disablestatsprocessing)) {
        require_once $CFG->dirroot . '/lib/statslib.php';
        // check we're not before our runtime
        $timetocheck = stats_get_base_daily() + $CFG->statsruntimestarthour * 60 * 60 + $CFG->statsruntimestartminute * 60;
        if (time() > $timetocheck) {
            // process configured number of days as max (defaulting to 31)
            $maxdays = empty($CFG->statsruntimedays) ? 31 : abs($CFG->statsruntimedays);
            if (stats_cron_daily($maxdays)) {
                if (stats_cron_weekly()) {
                    if (stats_cron_monthly()) {
                        stats_clean_old();
                    }
                }
            }
            @set_time_limit(0);
        } else {
            mtrace('Next stats run after:' . userdate($timetocheck));
        }
    }
    // Run badges review cron.
    mtrace("Starting badges cron...");
    require_once $CFG->dirroot . '/badges/cron.php';
    badge_cron();
    mtrace('done.');
    // cleanup file trash - not very important
    $fs = get_file_storage();
    $fs->cron();
    mtrace("Cron script completed correctly");
    gc_collect_cycles();
    mtrace('Cron completed at ' . date('H:i:s') . '. Memory used ' . display_size(memory_get_usage()) . '.');
    $difftime = microtime_diff($starttime, microtime());
    mtrace("Execution took " . $difftime . " seconds");
}
Ejemplo n.º 16
0
/**
 * Fixes course category and course sortorder, also verifies category and course parents and paths.
 * (circular references are not fixed)
 *
 * @global object
 * @global object
 * @uses MAX_COURSES_IN_CATEGORY
 * @uses MAX_COURSE_CATEGORIES
 * @uses SITEID
 * @uses CONTEXT_COURSE
 * @return void
 */
function fix_course_sortorder()
{
    global $DB, $SITE;
    //WARNING: this is PHP5 only code!
    if ($unsorted = $DB->get_records('course_categories', array('sortorder' => 0))) {
        //move all categories that are not sorted yet to the end
        $DB->set_field('course_categories', 'sortorder', MAX_COURSES_IN_CATEGORY * MAX_COURSE_CATEGORIES, array('sortorder' => 0));
    }
    $allcats = $DB->get_records('course_categories', null, 'sortorder, id', 'id, sortorder, parent, depth, path');
    $topcats = array();
    $brokencats = array();
    foreach ($allcats as $cat) {
        $sortorder = (int) $cat->sortorder;
        if (!$cat->parent) {
            while (isset($topcats[$sortorder])) {
                $sortorder++;
            }
            $topcats[$sortorder] = $cat;
            continue;
        }
        if (!isset($allcats[$cat->parent])) {
            $brokencats[] = $cat;
            continue;
        }
        if (!isset($allcats[$cat->parent]->children)) {
            $allcats[$cat->parent]->children = array();
        }
        while (isset($allcats[$cat->parent]->children[$sortorder])) {
            $sortorder++;
        }
        $allcats[$cat->parent]->children[$sortorder] = $cat;
    }
    unset($allcats);
    // add broken cats to category tree
    if ($brokencats) {
        $defaultcat = reset($topcats);
        foreach ($brokencats as $cat) {
            $topcats[] = $cat;
        }
    }
    // now walk recursively the tree and fix any problems found
    $sortorder = 0;
    $fixcontexts = array();
    _fix_course_cats($topcats, $sortorder, 0, 0, '', $fixcontexts);
    // detect if there are "multiple" frontpage courses and fix them if needed
    $frontcourses = $DB->get_records('course', array('category' => 0), 'id');
    if (count($frontcourses) > 1) {
        if (isset($frontcourses[SITEID])) {
            $frontcourse = $frontcourses[SITEID];
            unset($frontcourses[SITEID]);
        } else {
            $frontcourse = array_shift($frontcourses);
        }
        $defaultcat = reset($topcats);
        foreach ($frontcourses as $course) {
            $DB->set_field('course', 'category', $defaultcat->id, array('id' => $course->id));
            $context = get_context_instance(CONTEXT_COURSE, $course->id);
            $fixcontexts[$context->id] = $context;
        }
        unset($frontcourses);
    } else {
        $frontcourse = reset($frontcourses);
    }
    // now fix the paths and depths in context table if needed
    if ($fixcontexts) {
        foreach ($fixcontexts as $fixcontext) {
            $fixcontext->reset_paths(false);
        }
        context_helper::build_all_paths(false);
        unset($fixcontexts);
    }
    // release memory
    unset($topcats);
    unset($brokencats);
    unset($fixcontexts);
    // fix frontpage course sortorder
    if ($frontcourse->sortorder != 1) {
        $DB->set_field('course', 'sortorder', 1, array('id' => $frontcourse->id));
    }
    // now fix the course counts in category records if needed
    $sql = "SELECT cc.id, cc.coursecount, COUNT(c.id) AS newcount\n              FROM {course_categories} cc\n              LEFT JOIN {course} c ON c.category = cc.id\n          GROUP BY cc.id, cc.coursecount\n            HAVING cc.coursecount <> COUNT(c.id)";
    if ($updatecounts = $DB->get_records_sql($sql)) {
        // categories with more courses than MAX_COURSES_IN_CATEGORY
        $categories = array();
        foreach ($updatecounts as $cat) {
            $cat->coursecount = $cat->newcount;
            if ($cat->coursecount >= MAX_COURSES_IN_CATEGORY) {
                $categories[] = $cat->id;
            }
            unset($cat->newcount);
            $DB->update_record_raw('course_categories', $cat, true);
        }
        if (!empty($categories)) {
            $str = implode(', ', $categories);
            debugging("The number of courses (category id: {$str}) has reached MAX_COURSES_IN_CATEGORY (" . MAX_COURSES_IN_CATEGORY . "), it will cause a sorting performance issue, please increase the value of MAX_COURSES_IN_CATEGORY in lib/datalib.php file. See tracker issue: MDL-25669", DEBUG_DEVELOPER);
        }
    }
    // now make sure that sortorders in course table are withing the category sortorder ranges
    $sql = "SELECT DISTINCT cc.id, cc.sortorder\n              FROM {course_categories} cc\n              JOIN {course} c ON c.category = cc.id\n             WHERE c.sortorder < cc.sortorder OR c.sortorder > cc.sortorder + " . MAX_COURSES_IN_CATEGORY;
    if ($fixcategories = $DB->get_records_sql($sql)) {
        //fix the course sortorder ranges
        foreach ($fixcategories as $cat) {
            $sql = "UPDATE {course}\n                       SET sortorder = " . $DB->sql_modulo('sortorder', MAX_COURSES_IN_CATEGORY) . " + ?\n                     WHERE category = ?";
            $DB->execute($sql, array($cat->sortorder, $cat->id));
        }
    }
    unset($fixcategories);
    // categories having courses with sortorder duplicates or having gaps in sortorder
    $sql = "SELECT DISTINCT c1.category AS id , cc.sortorder\n              FROM {course} c1\n              JOIN {course} c2 ON c1.sortorder = c2.sortorder\n              JOIN {course_categories} cc ON (c1.category = cc.id)\n             WHERE c1.id <> c2.id";
    $fixcategories = $DB->get_records_sql($sql);
    $sql = "SELECT cc.id, cc.sortorder, cc.coursecount, MAX(c.sortorder) AS maxsort, MIN(c.sortorder) AS minsort\n              FROM {course_categories} cc\n              JOIN {course} c ON c.category = cc.id\n          GROUP BY cc.id, cc.sortorder, cc.coursecount\n            HAVING (MAX(c.sortorder) <>  cc.sortorder + cc.coursecount) OR (MIN(c.sortorder) <>  cc.sortorder + 1)";
    $gapcategories = $DB->get_records_sql($sql);
    foreach ($gapcategories as $cat) {
        if (isset($fixcategories[$cat->id])) {
            // duplicates detected already
        } else {
            if ($cat->minsort == $cat->sortorder and $cat->maxsort == $cat->sortorder + $cat->coursecount - 1) {
                // easy - new course inserted with sortorder 0, the rest is ok
                $sql = "UPDATE {course}\n                       SET sortorder = sortorder + 1\n                     WHERE category = ?";
                $DB->execute($sql, array($cat->id));
            } else {
                // it needs full resorting
                $fixcategories[$cat->id] = $cat;
            }
        }
    }
    unset($gapcategories);
    // fix course sortorders in problematic categories only
    foreach ($fixcategories as $cat) {
        $i = 1;
        $courses = $DB->get_records('course', array('category' => $cat->id), 'sortorder ASC, id DESC', 'id, sortorder');
        foreach ($courses as $course) {
            if ($course->sortorder != $cat->sortorder + $i) {
                $course->sortorder = $cat->sortorder + $i;
                $DB->update_record_raw('course', $course, true);
            }
            $i++;
        }
    }
}
Ejemplo n.º 17
0
 /**
  * Finds all assignment notifications that have yet to be mailed out, and mails them.
  *
  * Cron function to be run periodically according to the moodle cron.
  *
  * @return bool
  */
 public static function cron()
 {
     global $DB;
     // Only ever send a max of one days worth of updates.
     $yesterday = time() - 24 * 3600;
     $timenow = time();
     // Collect all submissions from the past 24 hours that require mailing.
     $sql = 'SELECT g.id as gradeid, a.course, a.name, a.blindmarking, a.revealidentities,
                    g.*, g.timemodified as lastmodified
              FROM {assign} a
              JOIN {assign_grades} g ON g.assignment = a.id
              LEFT JOIN {assign_user_flags} uf ON uf.assignment = a.id AND uf.userid = g.userid
             WHERE g.timemodified >= :yesterday AND
                   g.timemodified <= :today AND
                   uf.mailed = 0';
     $params = array('yesterday' => $yesterday, 'today' => $timenow);
     $submissions = $DB->get_records_sql($sql, $params);
     if (empty($submissions)) {
         return true;
     }
     mtrace('Processing ' . count($submissions) . ' assignment submissions ...');
     // Preload courses we are going to need those.
     $courseids = array();
     foreach ($submissions as $submission) {
         $courseids[] = $submission->course;
     }
     // Filter out duplicates.
     $courseids = array_unique($courseids);
     $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
     list($courseidsql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
     $sql = 'SELECT c.*, ' . $ctxselect . ' FROM {course} c
          LEFT JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel
              WHERE c.id ' . $courseidsql;
     $params['contextlevel'] = CONTEXT_COURSE;
     $courses = $DB->get_records_sql($sql, $params);
     // Clean up... this could go on for a while.
     unset($courseids);
     unset($ctxselect);
     unset($courseidsql);
     unset($params);
     // Simple array we'll use for caching modules.
     $modcache = array();
     // Message students about new feedback.
     foreach ($submissions as $submission) {
         mtrace("Processing assignment submission {$submission->id} ...");
         // Do not cache user lookups - could be too many.
         if (!($user = $DB->get_record('user', array('id' => $submission->userid)))) {
             mtrace('Could not find user ' . $submission->userid);
             continue;
         }
         // Use a cache to prevent the same DB queries happening over and over.
         if (!array_key_exists($submission->course, $courses)) {
             mtrace('Could not find course ' . $submission->course);
             continue;
         }
         $course = $courses[$submission->course];
         if (isset($course->ctxid)) {
             // Context has not yet been preloaded. Do so now.
             context_helper::preload_from_record($course);
         }
         // Override the language and timezone of the "current" user, so that
         // mail is customised for the receiver.
         cron_setup_user($user, $course);
         // Context lookups are already cached.
         $coursecontext = context_course::instance($course->id);
         if (!is_enrolled($coursecontext, $user->id)) {
             $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
             mtrace(fullname($user) . ' not an active participant in ' . $courseshortname);
             continue;
         }
         if (!($grader = $DB->get_record('user', array('id' => $submission->grader)))) {
             mtrace('Could not find grader ' . $submission->grader);
             continue;
         }
         if (!array_key_exists($submission->assignment, $modcache)) {
             $mod = get_coursemodule_from_instance('assign', $submission->assignment, $course->id);
             if (empty($mod)) {
                 mtrace('Could not find course module for assignment id ' . $submission->assignment);
                 continue;
             }
             $modcache[$submission->assignment] = $mod;
         } else {
             $mod = $modcache[$submission->assignment];
         }
         // Context lookups are already cached.
         $contextmodule = context_module::instance($mod->id);
         if (!$mod->visible) {
             // Hold mail notification for hidden assignments until later.
             continue;
         }
         // Need to send this to the student.
         $messagetype = 'feedbackavailable';
         $eventtype = 'assign_notification';
         $updatetime = $submission->lastmodified;
         $modulename = get_string('modulename', 'assign');
         $uniqueid = 0;
         if ($submission->blindmarking && !$submission->revealidentities) {
             $uniqueid = self::get_uniqueid_for_user_static($submission->assignment, $user->id);
         }
         $showusers = $submission->blindmarking && !$submission->revealidentities;
         self::send_assignment_notification($grader, $user, $messagetype, $eventtype, $updatetime, $mod, $contextmodule, $course, $modulename, $submission->name, $showusers, $uniqueid);
         $flags = $DB->get_record('assign_user_flags', array('userid' => $user->id, 'assignment' => $submission->assignment));
         if ($flags) {
             $flags->mailed = 1;
             $DB->update_record('assign_user_flags', $flags);
         } else {
             $flags = new stdClass();
             $flags->userid = $user->id;
             $flags->assignment = $submission->assignment;
             $flags->mailed = 1;
             $DB->insert_record('assign_user_flags', $flags);
         }
         mtrace('Done');
     }
     mtrace('Done processing ' . count($submissions) . ' assignment submissions');
     cron_setup_user();
     // Free up memory just to be sure.
     unset($courses);
     unset($modcache);
     return true;
 }
Ejemplo n.º 18
0
}
if ($user->aim && !isset($hiddenfields['aimid'])) {
    print_row(get_string('aimid') . ':', '<a href="aim:goim?screenname=' . urlencode($user->aim) . '">' . s($user->aim) . '</a>');
}
if ($user->msn && !isset($hiddenfields['msnid'])) {
    print_row(get_string('msnid') . ':', s($user->msn));
}
/// Print the Custom User Fields
profile_display_fields($user->id);
if (!isset($hiddenfields['mycourses'])) {
    if ($mycourses = enrol_get_all_users_courses($user->id, true, NULL, 'visible DESC,sortorder ASC')) {
        $shown = 0;
        $courselisting = '';
        foreach ($mycourses as $mycourse) {
            if ($mycourse->category) {
                context_helper::preload_from_record($mycourse);
                $ccontext = context_course::instance($mycourse->id);
                $class = '';
                if ($mycourse->visible == 0) {
                    if (!has_capability('moodle/course:viewhiddencourses', $ccontext)) {
                        continue;
                    }
                    $class = 'class="dimmed"';
                }
                $courselisting .= "<a href=\"{$CFG->wwwroot}/user/view.php?id={$user->id}&amp;course={$mycourse->id}\" {$class} >" . $ccontext->get_context_name(false) . "</a>, ";
            }
            $shown++;
            if ($shown == 20) {
                $courselisting .= "...";
                break;
            }
Ejemplo n.º 19
0
/**
 * Gets all of the courses where the provided user has posted in a forum.
 *
 * @global moodle_database $DB The database connection
 * @param stdClass $user The user who's posts we are looking for
 * @param bool $discussionsonly If true only look for discussions started by the user
 * @param bool $includecontexts If set to trye contexts for the courses will be preloaded
 * @param int $limitfrom The offset of records to return
 * @param int $limitnum The number of records to return
 * @return array An array of courses
 */
function forum_get_courses_user_posted_in($user, $discussionsonly = false, $includecontexts = true, $limitfrom = null, $limitnum = null)
{
    global $DB;
    // If we are only after discussions we need only look at the forum_discussions
    // table and join to the userid there. If we are looking for posts then we need
    // to join to the forum_posts table.
    if (!$discussionsonly) {
        $subquery = "(SELECT DISTINCT fd.course\n                         FROM {forum_discussions} fd\n                         JOIN {forum_posts} fp ON fp.discussion = fd.id\n                        WHERE fp.userid = :userid )";
    } else {
        $subquery = "(SELECT DISTINCT fd.course\n                         FROM {forum_discussions} fd\n                        WHERE fd.userid = :userid )";
    }
    $params = array('userid' => $user->id);
    // Join to the context table so that we can preload contexts if required.
    if ($includecontexts) {
        $ctxselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
        $ctxjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
        $params['contextlevel'] = CONTEXT_COURSE;
    } else {
        $ctxselect = '';
        $ctxjoin = '';
    }
    // Now we need to get all of the courses to search.
    // All courses where the user has posted within a forum will be returned.
    $sql = "SELECT c.* {$ctxselect}\n            FROM {course} c\n            {$ctxjoin}\n            WHERE c.id IN ({$subquery})";
    $courses = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
    if ($includecontexts) {
        array_map('context_helper::preload_from_record', $courses);
    }
    return $courses;
}
Ejemplo n.º 20
0
/**
 * Upgrade moodle core
 * @param float $version target version
 * @param bool $verbose
 * @return void, may throw exception
 */
function upgrade_core($version, $verbose) {
    global $CFG, $SITE, $DB, $COURSE;

    raise_memory_limit(MEMORY_EXTRA);

    require_once($CFG->libdir.'/db/upgrade.php');    // Defines upgrades

    try {
        // Reset caches before any output.
        cache_helper::purge_all(true);
        purge_all_caches();

        // Upgrade current language pack if we can
        upgrade_language_pack();

        print_upgrade_part_start('moodle', false, $verbose);

        // Pre-upgrade scripts for local hack workarounds.
        $preupgradefile = "$CFG->dirroot/local/preupgrade.php";
        if (file_exists($preupgradefile)) {
            core_php_time_limit::raise();
            require($preupgradefile);
            // Reset upgrade timeout to default.
            upgrade_set_timeout();
        }

        $result = xmldb_main_upgrade($CFG->version);
        if ($version > $CFG->version) {
            // store version if not already there
            upgrade_main_savepoint($result, $version, false);
        }

        // In case structure of 'course' table has been changed and we forgot to update $SITE, re-read it from db.
        $SITE = $DB->get_record('course', array('id' => $SITE->id));
        $COURSE = clone($SITE);

        // perform all other component upgrade routines
        update_capabilities('moodle');
        log_update_descriptions('moodle');
        external_update_descriptions('moodle');
        events_update_definition('moodle');
        \core\task\manager::reset_scheduled_tasks_for_component('moodle');
        message_update_providers('moodle');
        \core\message\inbound\manager::update_handlers_for_component('moodle');
        // Update core definitions.
        cache_helper::update_definitions(true);

        // Purge caches again, just to be sure we arn't holding onto old stuff now.
        cache_helper::purge_all(true);
        purge_all_caches();

        // Clean up contexts - more and more stuff depends on existence of paths and contexts
        context_helper::cleanup_instances();
        context_helper::create_instances(null, false);
        context_helper::build_all_paths(false);
        $syscontext = context_system::instance();
        $syscontext->mark_dirty();

        print_upgrade_part_end('moodle', false, $verbose);
    } catch (Exception $ex) {
        upgrade_handle_exception($ex);
    }
}
 /**
  * Process the data returned by the query.
  *
  * @see self::compute_rank_start()
  * @return void
  */
 function build_table()
 {
     global $USER;
     $this->compute_rank_start();
     $rank = $this->startingrank;
     $lastlvl = $this->startinglevel;
     $lastxp = $this->startingxp;
     $offset = $this->startingoffset;
     $xptodiff = $this->startingxpdiff;
     if ($this->rawdata) {
         foreach ($this->rawdata as $row) {
             // Preload the context.
             context_helper::preload_from_record($row);
             // Show the real rank.
             if ($this->rankmode == block_xp_manager::RANK_ON) {
                 // If this row is different than the previous one.
                 if ($row->lvl != $lastlvl || $row->xp != $lastxp) {
                     $rank += $offset;
                     $offset = 1;
                     $lastlvl = $row->lvl;
                     $lastxp = $row->xp;
                 } else {
                     $offset++;
                 }
                 $row->rank = $rank;
                 // Show a "relative" rank, the difference between a student and another.
             } else {
                 if ($this->rankmode == block_xp_manager::RANK_REL) {
                     // There was no indication of what XP to diff with, let's take the first entry.
                     if ($xptodiff == -1 && $lastxp == -1) {
                         $xptodiff = $row->xp;
                     }
                     // The last row does not this one.
                     if ($row->xp != $lastxp) {
                         $rank = $row->xp - $xptodiff;
                         $lastxp = $row->xp;
                     }
                     $row->rank = $rank;
                 }
             }
             $classes = $this->userid == $row->userid ? 'highlight' : '';
             $formattedrow = $this->format_row($row);
             $this->add_data_keyed($formattedrow, $classes);
         }
     }
 }
Ejemplo n.º 22
0
/**
 * This function will handles the whole deletion process of a module. This includes calling
 * the modules delete_instance function, deleting files, events, grades, conditional data,
 * the data in the course_module and course_sections table and adding a module deletion
 * event to the DB.
 *
 * @param int $cmid the course module id
 * @since 2.5
 */
function course_delete_module($cmid)
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->dirroot . '/blog/lib.php';
    require_once $CFG->dirroot . '/calendar/lib.php';
    // Get the course module.
    if (!($cm = $DB->get_record('course_modules', array('id' => $cmid)))) {
        return true;
    }
    // Get the module context.
    $modcontext = context_module::instance($cm->id);
    // Get the course module name.
    $modulename = $DB->get_field('modules', 'name', array('id' => $cm->module), MUST_EXIST);
    // Get the file location of the delete_instance function for this module.
    $modlib = "{$CFG->dirroot}/mod/{$modulename}/lib.php";
    // Include the file required to call the delete_instance function for this module.
    if (file_exists($modlib)) {
        require_once $modlib;
    } else {
        throw new moodle_exception('cannotdeletemodulemissinglib', '', '', null, "Cannot delete this module as the file mod/{$modulename}/lib.php is missing.");
    }
    $deleteinstancefunction = $modulename . '_delete_instance';
    // Ensure the delete_instance function exists for this module.
    if (!function_exists($deleteinstancefunction)) {
        throw new moodle_exception('cannotdeletemodulemissingfunc', '', '', null, "Cannot delete this module as the function {$modulename}_delete_instance is missing in mod/{$modulename}/lib.php.");
    }
    // Call the delete_instance function, if it returns false throw an exception.
    if (!$deleteinstancefunction($cm->instance)) {
        throw new moodle_exception('cannotdeletemoduleinstance', '', '', null, "Cannot delete the module {$modulename} (instance).");
    }
    // Remove all module files in case modules forget to do that.
    $fs = get_file_storage();
    $fs->delete_area_files($modcontext->id);
    // Delete events from calendar.
    if ($events = $DB->get_records('event', array('instance' => $cm->instance, 'modulename' => $modulename))) {
        foreach ($events as $event) {
            $calendarevent = calendar_event::load($event->id);
            $calendarevent->delete();
        }
    }
    // Delete grade items, outcome items and grades attached to modules.
    if ($grade_items = grade_item::fetch_all(array('itemtype' => 'mod', 'itemmodule' => $modulename, 'iteminstance' => $cm->instance, 'courseid' => $cm->course))) {
        foreach ($grade_items as $grade_item) {
            $grade_item->delete('moddelete');
        }
    }
    // Delete completion and availability data; it is better to do this even if the
    // features are not turned on, in case they were turned on previously (these will be
    // very quick on an empty table).
    $DB->delete_records('course_modules_completion', array('coursemoduleid' => $cm->id));
    $DB->delete_records('course_modules_availability', array('coursemoduleid' => $cm->id));
    $DB->delete_records('course_modules_avail_fields', array('coursemoduleid' => $cm->id));
    $DB->delete_records('course_completion_criteria', array('moduleinstance' => $cm->id, 'criteriatype' => COMPLETION_CRITERIA_TYPE_ACTIVITY));
    // Delete the context.
    context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
    // Delete the module from the course_modules table.
    $DB->delete_records('course_modules', array('id' => $cm->id));
    // Delete module from that section.
    if (!delete_mod_from_section($cm->id, $cm->section)) {
        throw new moodle_exception('cannotdeletemodulefromsection', '', '', null, "Cannot delete the module {$modulename} (instance) from section.");
    }
    // Trigger event for course module delete action.
    $event = \core\event\course_module_deleted::create(array('courseid' => $cm->course, 'context' => $modcontext, 'objectid' => $cm->id, 'other' => array('modulename' => $modulename, 'instanceid' => $cm->instance)));
    $event->add_record_snapshot('course_modules', $cm);
    $event->trigger();
    rebuild_course_cache($cm->course, true);
}
Ejemplo n.º 23
0
 /**
  * This function gets called by {@link settings_navigation::load_user_settings()} and actually works out
  * what can be shown/done
  *
  * @param int $courseid The current course' id
  * @param int $userid The user id to load for
  * @param string $gstitle The string to pass to get_string for the branch title
  * @return navigation_node|false
  */
 protected function generate_user_settings($courseid, $userid, $gstitle = 'usercurrentsettings')
 {
     global $DB, $CFG, $USER, $SITE;
     if ($courseid != $SITE->id) {
         if (!empty($this->page->course->id) && $this->page->course->id == $courseid) {
             $course = $this->page->course;
         } else {
             $select = context_helper::get_preload_record_columns_sql('ctx');
             $sql = "SELECT c.*, {$select}\n                          FROM {course} c\n                          JOIN {context} ctx ON c.id = ctx.instanceid\n                         WHERE c.id = :courseid AND ctx.contextlevel = :contextlevel";
             $params = array('courseid' => $courseid, 'contextlevel' => CONTEXT_COURSE);
             $course = $DB->get_record_sql($sql, $params, MUST_EXIST);
             context_helper::preload_from_record($course);
         }
     } else {
         $course = $SITE;
     }
     $coursecontext = context_course::instance($course->id);
     // Course context
     $systemcontext = context_system::instance();
     $currentuser = $USER->id == $userid;
     if ($currentuser) {
         $user = $USER;
         $usercontext = context_user::instance($user->id);
         // User context
     } else {
         $select = context_helper::get_preload_record_columns_sql('ctx');
         $sql = "SELECT u.*, {$select}\n                      FROM {user} u\n                      JOIN {context} ctx ON u.id = ctx.instanceid\n                     WHERE u.id = :userid AND ctx.contextlevel = :contextlevel";
         $params = array('userid' => $userid, 'contextlevel' => CONTEXT_USER);
         $user = $DB->get_record_sql($sql, $params, IGNORE_MISSING);
         if (!$user) {
             return false;
         }
         context_helper::preload_from_record($user);
         // Check that the user can view the profile
         $usercontext = context_user::instance($user->id);
         // User context
         $canviewuser = has_capability('moodle/user:viewdetails', $usercontext);
         if ($course->id == $SITE->id) {
             if ($CFG->forceloginforprofiles && !has_coursecontact_role($user->id) && !$canviewuser) {
                 // Reduce possibility of "browsing" userbase at site level
                 // Teachers can browse and be browsed at site level. If not forceloginforprofiles, allow access (bug #4366)
                 return false;
             }
         } else {
             $canviewusercourse = has_capability('moodle/user:viewdetails', $coursecontext);
             $userisenrolled = is_enrolled($coursecontext, $user->id, '', true);
             if (!$canviewusercourse && !$canviewuser || !$userisenrolled) {
                 return false;
             }
             $canaccessallgroups = has_capability('moodle/site:accessallgroups', $coursecontext);
             if (!$canaccessallgroups && groups_get_course_groupmode($course) == SEPARATEGROUPS && !$canviewuser) {
                 // If groups are in use, make sure we can see that group (MDL-45874). That does not apply to parents.
                 if ($courseid == $this->page->course->id) {
                     $mygroups = get_fast_modinfo($this->page->course)->groups;
                 } else {
                     $mygroups = groups_get_user_groups($courseid);
                 }
                 $usergroups = groups_get_user_groups($courseid, $userid);
                 if (!array_intersect_key($mygroups[0], $usergroups[0])) {
                     return false;
                 }
             }
         }
     }
     $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $this->page->context));
     $key = $gstitle;
     $prefurl = new moodle_url('/user/preferences.php');
     if ($gstitle != 'usercurrentsettings') {
         $key .= $userid;
         $prefurl->param('userid', $userid);
     }
     // Add a user setting branch.
     if ($gstitle == 'usercurrentsettings') {
         $dashboard = $this->add(get_string('myhome'), new moodle_url('/my/'), self::TYPE_CONTAINER, null, 'dashboard');
         // This should be set to false as we don't want to show this to the user. It's only for generating the correct
         // breadcrumb.
         $dashboard->display = false;
         if (get_home_page() == HOMEPAGE_MY) {
             $dashboard->mainnavonly = true;
         }
         $iscurrentuser = $user->id == $USER->id;
         $baseargs = array('id' => $user->id);
         if ($course->id != $SITE->id && !$iscurrentuser) {
             $baseargs['course'] = $course->id;
             $issitecourse = false;
         } else {
             // Load all categories and get the context for the system.
             $issitecourse = true;
         }
         // Add the user profile to the dashboard.
         $profilenode = $dashboard->add(get_string('profile'), new moodle_url('/user/profile.php', array('id' => $user->id)), self::TYPE_SETTING, null, 'myprofile');
         if (!empty($CFG->navadduserpostslinks)) {
             // Add nodes for forum posts and discussions if the user can view either or both
             // There are no capability checks here as the content of the page is based
             // purely on the forums the current user has access too.
             $forumtab = $profilenode->add(get_string('forumposts', 'forum'));
             $forumtab->add(get_string('posts', 'forum'), new moodle_url('/mod/forum/user.php', $baseargs), null, 'myposts');
             $forumtab->add(get_string('discussions', 'forum'), new moodle_url('/mod/forum/user.php', array_merge($baseargs, array('mode' => 'discussions'))), null, 'mydiscussions');
         }
         // Add blog nodes.
         if (!empty($CFG->enableblogs)) {
             if (!$this->cache->cached('userblogoptions' . $user->id)) {
                 require_once $CFG->dirroot . '/blog/lib.php';
                 // Get all options for the user.
                 $options = blog_get_options_for_user($user);
                 $this->cache->set('userblogoptions' . $user->id, $options);
             } else {
                 $options = $this->cache->{'userblogoptions' . $user->id};
             }
             if (count($options) > 0) {
                 $blogs = $profilenode->add(get_string('blogs', 'blog'), null, navigation_node::TYPE_CONTAINER);
                 foreach ($options as $type => $option) {
                     if ($type == "rss") {
                         $blogs->add($option['string'], $option['link'], self::TYPE_SETTING, null, null, new pix_icon('i/rss', ''));
                     } else {
                         $blogs->add($option['string'], $option['link'], self::TYPE_SETTING, null, 'blog' . $type);
                     }
                 }
             }
         }
         // Add the messages link.
         // It is context based so can appear in the user's profile and in course participants information.
         if (!empty($CFG->messaging)) {
             $messageargs = array('user1' => $USER->id);
             if ($USER->id != $user->id) {
                 $messageargs['user2'] = $user->id;
             }
             if ($course->id != $SITE->id) {
                 $messageargs['viewing'] = MESSAGE_VIEW_COURSE . $course->id;
             }
             $url = new moodle_url('/message/index.php', $messageargs);
             $dashboard->add(get_string('messages', 'message'), $url, self::TYPE_SETTING, null, 'messages');
         }
         // Add the "My private files" link.
         // This link doesn't have a unique display for course context so only display it under the user's profile.
         if ($issitecourse && $iscurrentuser && has_capability('moodle/user:manageownfiles', $usercontext)) {
             $url = new moodle_url('/user/files.php');
             $dashboard->add(get_string('privatefiles'), $url, self::TYPE_SETTING);
         }
         // Add a node to view the users notes if permitted.
         if (!empty($CFG->enablenotes) && has_any_capability(array('moodle/notes:manage', 'moodle/notes:view'), $coursecontext)) {
             $url = new moodle_url('/notes/index.php', array('user' => $user->id));
             if ($coursecontext->instanceid != SITEID) {
                 $url->param('course', $coursecontext->instanceid);
             }
             $profilenode->add(get_string('notes', 'notes'), $url);
         }
         // Show the grades node.
         if ($issitecourse && $iscurrentuser || has_capability('moodle/user:viewdetails', $usercontext)) {
             require_once $CFG->dirroot . '/user/lib.php';
             // Set the grades node to link to the "Grades" page.
             if ($course->id == SITEID) {
                 $url = user_mygrades_url($user->id, $course->id);
             } else {
                 // Otherwise we are in a course and should redirect to the user grade report (Activity report version).
                 $url = new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, 'user' => $user->id));
             }
             $dashboard->add(get_string('grades', 'grades'), $url, self::TYPE_SETTING, null, 'mygrades');
         }
         // Let plugins hook into user navigation.
         $pluginsfunction = get_plugins_with_function('extend_navigation_user', 'lib.php');
         foreach ($pluginsfunction as $plugintype => $plugins) {
             if ($plugintype != 'report') {
                 foreach ($plugins as $pluginfunction) {
                     $pluginfunction($profilenode, $user, $usercontext, $course, $coursecontext);
                 }
             }
         }
         $usersetting = navigation_node::create(get_string('preferences', 'moodle'), $prefurl, self::TYPE_CONTAINER, null, $key);
         $dashboard->add_node($usersetting);
     } else {
         $usersetting = $this->add(get_string('preferences', 'moodle'), $prefurl, self::TYPE_CONTAINER, null, $key);
         $usersetting->display = false;
     }
     $usersetting->id = 'usersettings';
     // Check if the user has been deleted.
     if ($user->deleted) {
         if (!has_capability('moodle/user:update', $coursecontext)) {
             // We can't edit the user so just show the user deleted message.
             $usersetting->add(get_string('userdeleted'), null, self::TYPE_SETTING);
         } else {
             // We can edit the user so show the user deleted message and link it to the profile.
             if ($course->id == $SITE->id) {
                 $profileurl = new moodle_url('/user/profile.php', array('id' => $user->id));
             } else {
                 $profileurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
             }
             $usersetting->add(get_string('userdeleted'), $profileurl, self::TYPE_SETTING);
         }
         return true;
     }
     $userauthplugin = false;
     if (!empty($user->auth)) {
         $userauthplugin = get_auth_plugin($user->auth);
     }
     $useraccount = $usersetting->add(get_string('useraccount'), null, self::TYPE_CONTAINER, null, 'useraccount');
     // Add the profile edit link.
     if (isloggedin() && !isguestuser($user) && !is_mnet_remote_user($user)) {
         if (($currentuser || is_siteadmin($USER) || !is_siteadmin($user)) && has_capability('moodle/user:update', $systemcontext)) {
             $url = new moodle_url('/user/editadvanced.php', array('id' => $user->id, 'course' => $course->id));
             $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
         } else {
             if (has_capability('moodle/user:editprofile', $usercontext) && !is_siteadmin($user) || $currentuser && has_capability('moodle/user:editownprofile', $systemcontext)) {
                 if ($userauthplugin && $userauthplugin->can_edit_profile()) {
                     $url = $userauthplugin->edit_profile_url();
                     if (empty($url)) {
                         $url = new moodle_url('/user/edit.php', array('id' => $user->id, 'course' => $course->id));
                     }
                     $useraccount->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
                 }
             }
         }
     }
     // Change password link.
     if ($userauthplugin && $currentuser && !\core\session\manager::is_loggedinas() && !isguestuser() && has_capability('moodle/user:changeownpassword', $systemcontext) && $userauthplugin->can_change_password()) {
         $passwordchangeurl = $userauthplugin->change_password_url();
         if (empty($passwordchangeurl)) {
             $passwordchangeurl = new moodle_url('/login/change_password.php', array('id' => $course->id));
         }
         $useraccount->add(get_string("changepassword"), $passwordchangeurl, self::TYPE_SETTING, null, 'changepassword');
     }
     if (isloggedin() && !isguestuser($user) && !is_mnet_remote_user($user)) {
         if ($currentuser && has_capability('moodle/user:editownprofile', $systemcontext) || has_capability('moodle/user:editprofile', $usercontext)) {
             $url = new moodle_url('/user/language.php', array('id' => $user->id, 'course' => $course->id));
             $useraccount->add(get_string('preferredlanguage'), $url, self::TYPE_SETTING, null, 'preferredlanguage');
         }
     }
     $pluginmanager = core_plugin_manager::instance();
     $enabled = $pluginmanager->get_enabled_plugins('mod');
     if (isset($enabled['forum']) && isloggedin() && !isguestuser($user) && !is_mnet_remote_user($user)) {
         if ($currentuser && has_capability('moodle/user:editownprofile', $systemcontext) || has_capability('moodle/user:editprofile', $usercontext)) {
             $url = new moodle_url('/user/forum.php', array('id' => $user->id, 'course' => $course->id));
             $useraccount->add(get_string('forumpreferences'), $url, self::TYPE_SETTING);
         }
     }
     $editors = editors_get_enabled();
     if (count($editors) > 1) {
         if (isloggedin() && !isguestuser($user) && !is_mnet_remote_user($user)) {
             if ($currentuser && has_capability('moodle/user:editownprofile', $systemcontext) || has_capability('moodle/user:editprofile', $usercontext)) {
                 $url = new moodle_url('/user/editor.php', array('id' => $user->id, 'course' => $course->id));
                 $useraccount->add(get_string('editorpreferences'), $url, self::TYPE_SETTING);
             }
         }
     }
     // Add "Course preferences" link.
     if (isloggedin() && !isguestuser($user)) {
         if ($currentuser && has_capability('moodle/user:editownprofile', $systemcontext) || has_capability('moodle/user:editprofile', $usercontext)) {
             $url = new moodle_url('/user/course.php', array('id' => $user->id, 'course' => $course->id));
             $useraccount->add(get_string('coursepreferences'), $url, self::TYPE_SETTING, null, 'coursepreferences');
         }
     }
     // View the roles settings.
     if (has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:manage'), $usercontext)) {
         $roles = $usersetting->add(get_string('roles'), null, self::TYPE_SETTING);
         $url = new moodle_url('/admin/roles/usersroles.php', array('userid' => $user->id, 'courseid' => $course->id));
         $roles->add(get_string('thisusersroles', 'role'), $url, self::TYPE_SETTING);
         $assignableroles = get_assignable_roles($usercontext, ROLENAME_BOTH);
         if (!empty($assignableroles)) {
             $url = new moodle_url('/admin/roles/assign.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
             $roles->add(get_string('assignrolesrelativetothisuser', 'role'), $url, self::TYPE_SETTING);
         }
         if (has_capability('moodle/role:review', $usercontext) || count(get_overridable_roles($usercontext, ROLENAME_BOTH)) > 0) {
             $url = new moodle_url('/admin/roles/permissions.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
             $roles->add(get_string('permissions', 'role'), $url, self::TYPE_SETTING);
         }
         $url = new moodle_url('/admin/roles/check.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
         $roles->add(get_string('checkpermissions', 'role'), $url, self::TYPE_SETTING);
     }
     // Repositories.
     if (!$this->cache->cached('contexthasrepos' . $usercontext->id)) {
         require_once $CFG->dirroot . '/repository/lib.php';
         $editabletypes = repository::get_editable_types($usercontext);
         $haseditabletypes = !empty($editabletypes);
         unset($editabletypes);
         $this->cache->set('contexthasrepos' . $usercontext->id, $haseditabletypes);
     } else {
         $haseditabletypes = $this->cache->{'contexthasrepos' . $usercontext->id};
     }
     if ($haseditabletypes) {
         $repositories = $usersetting->add(get_string('repositories', 'repository'), null, self::TYPE_SETTING);
         $repositories->add(get_string('manageinstances', 'repository'), new moodle_url('/repository/manage_instances.php', array('contextid' => $usercontext->id)));
     }
     // Portfolio.
     if ($currentuser && !empty($CFG->enableportfolios) && has_capability('moodle/portfolio:export', $systemcontext)) {
         require_once $CFG->libdir . '/portfoliolib.php';
         if (portfolio_has_visible_instances()) {
             $portfolio = $usersetting->add(get_string('portfolios', 'portfolio'), null, self::TYPE_SETTING);
             $url = new moodle_url('/user/portfolio.php', array('courseid' => $course->id));
             $portfolio->add(get_string('configure', 'portfolio'), $url, self::TYPE_SETTING);
             $url = new moodle_url('/user/portfoliologs.php', array('courseid' => $course->id));
             $portfolio->add(get_string('logs', 'portfolio'), $url, self::TYPE_SETTING);
         }
     }
     $enablemanagetokens = false;
     if (!empty($CFG->enablerssfeeds)) {
         $enablemanagetokens = true;
     } else {
         if (!is_siteadmin($USER->id) && !empty($CFG->enablewebservices) && has_capability('moodle/webservice:createtoken', context_system::instance())) {
             $enablemanagetokens = true;
         }
     }
     // Security keys.
     if ($currentuser && $enablemanagetokens) {
         $url = new moodle_url('/user/managetoken.php', array('sesskey' => sesskey()));
         $useraccount->add(get_string('securitykeys', 'webservice'), $url, self::TYPE_SETTING);
     }
     // Messaging.
     if ($currentuser && has_capability('moodle/user:editownmessageprofile', $systemcontext) || !isguestuser($user) && has_capability('moodle/user:editmessageprofile', $usercontext) && !is_primary_admin($user->id)) {
         $url = new moodle_url('/message/edit.php', array('id' => $user->id));
         $useraccount->add(get_string('messaging', 'message'), $url, self::TYPE_SETTING);
     }
     // Blogs.
     if ($currentuser && !empty($CFG->enableblogs)) {
         $blog = $usersetting->add(get_string('blogs', 'blog'), null, navigation_node::TYPE_CONTAINER, null, 'blogs');
         if (has_capability('moodle/blog:view', $systemcontext)) {
             $blog->add(get_string('preferences', 'blog'), new moodle_url('/blog/preferences.php'), navigation_node::TYPE_SETTING);
         }
         if (!empty($CFG->useexternalblogs) && $CFG->maxexternalblogsperuser > 0 && has_capability('moodle/blog:manageexternal', $systemcontext)) {
             $blog->add(get_string('externalblogs', 'blog'), new moodle_url('/blog/external_blogs.php'), navigation_node::TYPE_SETTING);
             $blog->add(get_string('addnewexternalblog', 'blog'), new moodle_url('/blog/external_blog_edit.php'), navigation_node::TYPE_SETTING);
         }
         // Remove the blog node if empty.
         $blog->trim_if_empty();
     }
     // Badges.
     if ($currentuser && !empty($CFG->enablebadges)) {
         $badges = $usersetting->add(get_string('badges'), null, navigation_node::TYPE_CONTAINER, null, 'badges');
         if (has_capability('moodle/badges:manageownbadges', $usercontext)) {
             $url = new moodle_url('/badges/mybadges.php');
             $badges->add(get_string('managebadges', 'badges'), $url, self::TYPE_SETTING);
         }
         $badges->add(get_string('preferences', 'badges'), new moodle_url('/badges/preferences.php'), navigation_node::TYPE_SETTING);
         if (!empty($CFG->badges_allowexternalbackpack)) {
             $badges->add(get_string('backpackdetails', 'badges'), new moodle_url('/badges/mybackpack.php'), navigation_node::TYPE_SETTING);
         }
     }
     // Let plugins hook into user settings navigation.
     $pluginsfunction = get_plugins_with_function('extend_navigation_user_settings', 'lib.php');
     foreach ($pluginsfunction as $plugintype => $plugins) {
         foreach ($plugins as $pluginfunction) {
             $pluginfunction($usersetting, $user, $usercontext, $course, $coursecontext);
         }
     }
     return $usersetting;
 }
Ejemplo n.º 24
0
 /**
  * Return the context level associated with the context class name
  * @param $classname the class name
  * @throws coding_exception
  * @return int context level for given class name
  */
 public static function get_level_from_class_name($classname)
 {
     if (empty(self::$puballlevels)) {
         self::$puballlevels = parent::get_all_levels();
     }
     // Function get_called_class() does not prefix the result with a '\', as in the internal classnames.
     if ($classname[0] !== '\\') {
         $classname = '\\' . $classname;
     }
     $contextlevel = array_search($classname, self::$puballlevels);
     if (false !== $contextlevel) {
         return $contextlevel;
     }
     throw new \coding_exception('Context class name [' . $classname . '] not found in defined custom contexts.');
 }
Ejemplo n.º 25
0
    }
}
$course = $DB->get_record('course', $params, '*', MUST_EXIST);
$urlparams = array('id' => $course->id);
// Sectionid should get priority over section number
if ($sectionid) {
    $section = $DB->get_field('course_sections', 'section', array('id' => $sectionid, 'course' => $course->id), MUST_EXIST);
}
if ($section) {
    $urlparams['section'] = $section;
}
$PAGE->set_url('/course/view.php', $urlparams);
// Defined here to avoid notices on errors etc
// Prevent caching of this page to stop confusion when changing page after making AJAX changes
$PAGE->set_cacheable(false);
context_helper::preload_course($course->id);
$context = context_course::instance($course->id, MUST_EXIST);
// Remove any switched roles before checking login
if ($switchrole == 0 && confirm_sesskey()) {
    role_switch($switchrole, $context);
}
require_login($course);
// Switchrole - sanity check in cost-order...
$reset_user_allowed_editing = false;
if ($switchrole > 0 && confirm_sesskey() && has_capability('moodle/role:switchroles', $context)) {
    // is this role assignable in this context?
    // inquiring minds want to know...
    $aroles = get_switchable_roles($context);
    if (is_array($aroles) && isset($aroles[$switchrole])) {
        role_switch($switchrole, $context);
        // Double check that this role is allowed here
Ejemplo n.º 26
0
/**
 * Clear a course out completely, deleting all content but don't delete the course itself.
 *
 * This function does not verify any permissions.
 *
 * Please note this function also deletes all user enrolments,
 * enrolment instances and role assignments by default.
 *
 * $options:
 *  - 'keep_roles_and_enrolments' - false by default
 *  - 'keep_groups_and_groupings' - false by default
 *
 * @param int $courseid The id of the course that is being deleted
 * @param bool $showfeedback Whether to display notifications of each action the function performs.
 * @param array $options extra options
 * @return bool true if all the removals succeeded. false if there were any failures. If this
 *             method returns false, some of the removals will probably have succeeded, and others
 *             failed, but you have no way of knowing which.
 */
function remove_course_contents($courseid, $showfeedback = true, array $options = null)
{
    global $CFG, $DB, $OUTPUT;
    require_once $CFG->libdir . '/badgeslib.php';
    require_once $CFG->libdir . '/completionlib.php';
    require_once $CFG->libdir . '/questionlib.php';
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->dirroot . '/group/lib.php';
    require_once $CFG->dirroot . '/comment/lib.php';
    require_once $CFG->dirroot . '/rating/lib.php';
    require_once $CFG->dirroot . '/notes/lib.php';
    // Handle course badges.
    badges_handle_course_deletion($courseid);
    // NOTE: these concatenated strings are suboptimal, but it is just extra info...
    $strdeleted = get_string('deleted') . ' - ';
    // Some crazy wishlist of stuff we should skip during purging of course content.
    $options = (array) $options;
    $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
    $coursecontext = context_course::instance($courseid);
    $fs = get_file_storage();
    // Delete course completion information, this has to be done before grades and enrols.
    $cc = new completion_info($course);
    $cc->clear_criteria();
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('completion', 'completion'), 'notifysuccess');
    }
    // Remove all data from gradebook - this needs to be done before course modules
    // because while deleting this information, the system may need to reference
    // the course modules that own the grades.
    remove_course_grades($courseid, $showfeedback);
    remove_grade_letters($coursecontext, $showfeedback);
    // Delete course blocks in any all child contexts,
    // they may depend on modules so delete them first.
    $childcontexts = $coursecontext->get_child_contexts();
    // Returns all subcontexts since 2.2.
    foreach ($childcontexts as $childcontext) {
        blocks_delete_all_for_context($childcontext->id);
    }
    unset($childcontexts);
    blocks_delete_all_for_context($coursecontext->id);
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('type_block_plural', 'plugin'), 'notifysuccess');
    }
    // Get the list of all modules that are properly installed.
    $allmodules = $DB->get_records_menu('modules', array(), '', 'name, id');
    // Delete every instance of every module,
    // this has to be done before deleting of course level stuff.
    $locations = core_component::get_plugin_list('mod');
    foreach ($locations as $modname => $moddir) {
        if ($modname === 'NEWMODULE') {
            continue;
        }
        if (array_key_exists($modname, $allmodules)) {
            $sql = "SELECT cm.*, m.id AS modinstance, m.name, '{$modname}' AS modname\n              FROM {" . $modname . "} m\n                   LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid\n             WHERE m.course = :courseid";
            $instances = $DB->get_records_sql($sql, array('courseid' => $course->id, 'modulename' => $modname, 'moduleid' => $allmodules[$modname]));
            include_once "{$moddir}/lib.php";
            // Shows php warning only if plugin defective.
            $moddelete = $modname . '_delete_instance';
            // Delete everything connected to an instance.
            $moddeletecourse = $modname . '_delete_course';
            // Delete other stray stuff (uncommon).
            if ($instances) {
                foreach ($instances as $cm) {
                    if ($cm->id) {
                        // Delete activity context questions and question categories.
                        question_delete_activity($cm, $showfeedback);
                        // Notify the competency subsystem.
                        \core_competency\api::hook_course_module_deleted($cm);
                    }
                    if (function_exists($moddelete)) {
                        // This purges all module data in related tables, extra user prefs, settings, etc.
                        $moddelete($cm->modinstance);
                    } else {
                        // NOTE: we should not allow installation of modules with missing delete support!
                        debugging("Defective module '{$modname}' detected when deleting course contents: missing function {$moddelete}()!");
                        $DB->delete_records($modname, array('id' => $cm->modinstance));
                    }
                    if ($cm->id) {
                        // Delete cm and its context - orphaned contexts are purged in cron in case of any race condition.
                        context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
                        $DB->delete_records('course_modules', array('id' => $cm->id));
                    }
                }
            }
            if (function_exists($moddeletecourse)) {
                // Execute optional course cleanup callback. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
                debugging("Callback delete_course is deprecated. Function {$moddeletecourse} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER);
                $moddeletecourse($course, $showfeedback);
            }
            if ($instances and $showfeedback) {
                echo $OUTPUT->notification($strdeleted . get_string('pluginname', $modname), 'notifysuccess');
            }
        } else {
            // Ooops, this module is not properly installed, force-delete it in the next block.
        }
    }
    // We have tried to delete everything the nice way - now let's force-delete any remaining module data.
    // Remove all data from availability and completion tables that is associated
    // with course-modules belonging to this course. Note this is done even if the
    // features are not enabled now, in case they were enabled previously.
    $DB->delete_records_select('course_modules_completion', 'coursemoduleid IN (SELECT id from {course_modules} WHERE course=?)', array($courseid));
    // Remove course-module data that has not been removed in modules' _delete_instance callbacks.
    $cms = $DB->get_records('course_modules', array('course' => $course->id));
    $allmodulesbyid = array_flip($allmodules);
    foreach ($cms as $cm) {
        if (array_key_exists($cm->module, $allmodulesbyid)) {
            try {
                $DB->delete_records($allmodulesbyid[$cm->module], array('id' => $cm->instance));
            } catch (Exception $e) {
                // Ignore weird or missing table problems.
            }
        }
        context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
        $DB->delete_records('course_modules', array('id' => $cm->id));
    }
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('type_mod_plural', 'plugin'), 'notifysuccess');
    }
    // Cleanup the rest of plugins. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
    $cleanuplugintypes = array('report', 'coursereport', 'format');
    $callbacks = get_plugins_with_function('delete_course', 'lib.php');
    foreach ($cleanuplugintypes as $type) {
        if (!empty($callbacks[$type])) {
            foreach ($callbacks[$type] as $pluginfunction) {
                debugging("Callback delete_course is deprecated. Function {$pluginfunction} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER);
                $pluginfunction($course->id, $showfeedback);
            }
            if ($showfeedback) {
                echo $OUTPUT->notification($strdeleted . get_string('type_' . $type . '_plural', 'plugin'), 'notifysuccess');
            }
        }
    }
    // Delete questions and question categories.
    question_delete_course($course, $showfeedback);
    if ($showfeedback) {
        echo $OUTPUT->notification($strdeleted . get_string('questions', 'question'), 'notifysuccess');
    }
    // Make sure there are no subcontexts left - all valid blocks and modules should be already gone.
    $childcontexts = $coursecontext->get_child_contexts();
    // Returns all subcontexts since 2.2.
    foreach ($childcontexts as $childcontext) {
        $childcontext->delete();
    }
    unset($childcontexts);
    // Remove all roles and enrolments by default.
    if (empty($options['keep_roles_and_enrolments'])) {
        // This hack is used in restore when deleting contents of existing course.
        role_unassign_all(array('contextid' => $coursecontext->id, 'component' => ''), true);
        enrol_course_delete($course);
        if ($showfeedback) {
            echo $OUTPUT->notification($strdeleted . get_string('type_enrol_plural', 'plugin'), 'notifysuccess');
        }
    }
    // Delete any groups, removing members and grouping/course links first.
    if (empty($options['keep_groups_and_groupings'])) {
        groups_delete_groupings($course->id, $showfeedback);
        groups_delete_groups($course->id, $showfeedback);
    }
    // Filters be gone!
    filter_delete_all_for_context($coursecontext->id);
    // Notes, you shall not pass!
    note_delete_all($course->id);
    // Die comments!
    comment::delete_comments($coursecontext->id);
    // Ratings are history too.
    $delopt = new stdclass();
    $delopt->contextid = $coursecontext->id;
    $rm = new rating_manager();
    $rm->delete_ratings($delopt);
    // Delete course tags.
    core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
    // Notify the competency subsystem.
    \core_competency\api::hook_course_deleted($course);
    // Delete calendar events.
    $DB->delete_records('event', array('courseid' => $course->id));
    $fs->delete_area_files($coursecontext->id, 'calendar');
    // Delete all related records in other core tables that may have a courseid
    // This array stores the tables that need to be cleared, as
    // table_name => column_name that contains the course id.
    $tablestoclear = array('backup_courses' => 'courseid', 'user_lastaccess' => 'courseid');
    foreach ($tablestoclear as $table => $col) {
        $DB->delete_records($table, array($col => $course->id));
    }
    // Delete all course backup files.
    $fs->delete_area_files($coursecontext->id, 'backup');
    // Cleanup course record - remove links to deleted stuff.
    $oldcourse = new stdClass();
    $oldcourse->id = $course->id;
    $oldcourse->summary = '';
    $oldcourse->cacherev = 0;
    $oldcourse->legacyfiles = 0;
    if (!empty($options['keep_groups_and_groupings'])) {
        $oldcourse->defaultgroupingid = 0;
    }
    $DB->update_record('course', $oldcourse);
    // Delete course sections.
    $DB->delete_records('course_sections', array('course' => $course->id));
    // Delete legacy, section and any other course files.
    $fs->delete_area_files($coursecontext->id, 'course');
    // Files from summary and section.
    // Delete all remaining stuff linked to context such as files, comments, ratings, etc.
    if (empty($options['keep_roles_and_enrolments']) and empty($options['keep_groups_and_groupings'])) {
        // Easy, do not delete the context itself...
        $coursecontext->delete_content();
    } else {
        // Hack alert!!!!
        // We can not drop all context stuff because it would bork enrolments and roles,
        // there might be also files used by enrol plugins...
    }
    // Delete legacy files - just in case some files are still left there after conversion to new file api,
    // also some non-standard unsupported plugins may try to store something there.
    fulldelete($CFG->dataroot . '/' . $course->id);
    // Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion.
    $cachemodinfo = cache::make('core', 'coursemodinfo');
    $cachemodinfo->delete($courseid);
    // Trigger a course content deleted event.
    $event = \core\event\course_content_deleted::create(array('objectid' => $course->id, 'context' => $coursecontext, 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname, 'options' => $options)));
    $event->add_record_snapshot('course', $course);
    $event->trigger();
    return true;
}
Ejemplo n.º 27
0
            echo $OUTPUT->heading(get_string('nothingtodisplay'));
        }
    }
} else {
    $countrysort = strpos($sort, 'country') !== false;
    $timeformat = get_string('strftimedate');
    if ($userlist) {
        $usersprinted = array();
        foreach ($userlist as $user) {
            if (in_array($user->id, $usersprinted)) {
                // Prevent duplicates by r.hidden - MDL-13935.
                continue;
            }
            $usersprinted[] = $user->id;
            // Add new user to the array of users printed.
            context_helper::preload_from_record($user);
            if ($user->lastaccess) {
                $lastaccess = format_time(time() - $user->lastaccess, $datestring);
            } else {
                $lastaccess = $strnever;
            }
            if (empty($user->country)) {
                $country = '';
            } else {
                if ($countrysort) {
                    $country = '(' . $user->country . ') ' . $countries[$user->country];
                } else {
                    $country = $countries[$user->country];
                }
            }
            $usercontext = context_user::instance($user->id);
Ejemplo n.º 28
0
/**
 * Returns the default courses to display on the calendar when there isn't a specific
 * course to display.
 *
 * @return array $courses Array of courses to display
 */
function calendar_get_default_courses()
{
    global $CFG, $DB;
    if (!isloggedin()) {
        return array();
    }
    $courses = array();
    if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', context_system::instance())) {
        $select = ', ' . context_helper::get_preload_record_columns_sql('ctx');
        $join = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)";
        $sql = "SELECT c.* {$select}\n                  FROM {course} c\n                  {$join}\n                  WHERE EXISTS (SELECT 1 FROM {event} e WHERE e.courseid = c.id)\n                  ";
        $courses = $DB->get_records_sql($sql, array('contextlevel' => CONTEXT_COURSE), 0, 20);
        foreach ($courses as $course) {
            context_helper::preload_from_record($course);
        }
        return $courses;
    }
    $courses = enrol_get_my_courses();
    return $courses;
}
Ejemplo n.º 29
0
 /**
  * This function gets called by {@link settings_navigation::load_user_settings()} and actually works out
  * what can be shown/done
  *
  * @param int $courseid The current course' id
  * @param int $userid The user id to load for
  * @param string $gstitle The string to pass to get_string for the branch title
  * @return navigation_node|false
  */
 protected function generate_user_settings($courseid, $userid, $gstitle = 'usercurrentsettings')
 {
     global $DB, $CFG, $USER, $SITE;
     if ($courseid != $SITE->id) {
         if (!empty($this->page->course->id) && $this->page->course->id == $courseid) {
             $course = $this->page->course;
         } else {
             $select = context_helper::get_preload_record_columns_sql('ctx');
             $sql = "SELECT c.*, {$select}\n                          FROM {course} c\n                          JOIN {context} ctx ON c.id = ctx.instanceid\n                         WHERE c.id = :courseid AND ctx.contextlevel = :contextlevel";
             $params = array('courseid' => $courseid, 'contextlevel' => CONTEXT_COURSE);
             $course = $DB->get_record_sql($sql, $params, MUST_EXIST);
             context_helper::preload_from_record($course);
         }
     } else {
         $course = $SITE;
     }
     $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
     // Course context
     $systemcontext = get_system_context();
     $currentuser = $USER->id == $userid;
     if ($currentuser) {
         $user = $USER;
         $usercontext = get_context_instance(CONTEXT_USER, $user->id);
         // User context
     } else {
         $select = context_helper::get_preload_record_columns_sql('ctx');
         $sql = "SELECT u.*, {$select}\n                      FROM {user} u\n                      JOIN {context} ctx ON u.id = ctx.instanceid\n                     WHERE u.id = :userid AND ctx.contextlevel = :contextlevel";
         $params = array('userid' => $userid, 'contextlevel' => CONTEXT_USER);
         $user = $DB->get_record_sql($sql, $params, IGNORE_MISSING);
         if (!$user) {
             return false;
         }
         context_helper::preload_from_record($user);
         // Check that the user can view the profile
         $usercontext = get_context_instance(CONTEXT_USER, $user->id);
         // User context
         $canviewuser = has_capability('moodle/user:viewdetails', $usercontext);
         if ($course->id == $SITE->id) {
             if ($CFG->forceloginforprofiles && !has_coursecontact_role($user->id) && !$canviewuser) {
                 // Reduce possibility of "browsing" userbase at site level
                 // Teachers can browse and be browsed at site level. If not forceloginforprofiles, allow access (bug #4366)
                 return false;
             }
         } else {
             $canviewusercourse = has_capability('moodle/user:viewdetails', $coursecontext);
             $canaccessallgroups = has_capability('moodle/site:accessallgroups', $coursecontext);
             if (!$canviewusercourse && !$canviewuser || !can_access_course($course, $user->id)) {
                 return false;
             }
             if (!$canaccessallgroups && groups_get_course_groupmode($course) == SEPARATEGROUPS) {
                 // If groups are in use, make sure we can see that group
                 return false;
             }
         }
     }
     $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $this->page->context));
     $key = $gstitle;
     if ($gstitle != 'usercurrentsettings') {
         $key .= $userid;
     }
     // Add a user setting branch
     $usersetting = $this->add(get_string($gstitle, 'moodle', $fullname), null, self::TYPE_CONTAINER, null, $key);
     $usersetting->id = 'usersettings';
     if ($this->page->context->contextlevel == CONTEXT_USER && $this->page->context->instanceid == $user->id) {
         // Automatically start by making it active
         $usersetting->make_active();
     }
     // Check if the user has been deleted
     if ($user->deleted) {
         if (!has_capability('moodle/user:update', $coursecontext)) {
             // We can't edit the user so just show the user deleted message
             $usersetting->add(get_string('userdeleted'), null, self::TYPE_SETTING);
         } else {
             // We can edit the user so show the user deleted message and link it to the profile
             if ($course->id == $SITE->id) {
                 $profileurl = new moodle_url('/user/profile.php', array('id' => $user->id));
             } else {
                 $profileurl = new moodle_url('/user/view.php', array('id' => $user->id, 'course' => $course->id));
             }
             $usersetting->add(get_string('userdeleted'), $profileurl, self::TYPE_SETTING);
         }
         return true;
     }
     $userauthplugin = false;
     if (!empty($user->auth)) {
         $userauthplugin = get_auth_plugin($user->auth);
     }
     // Add the profile edit link
     if (isloggedin() && !isguestuser($user) && !is_mnet_remote_user($user)) {
         if (($currentuser || is_siteadmin($USER) || !is_siteadmin($user)) && has_capability('moodle/user:update', $systemcontext)) {
             $url = new moodle_url('/user/editadvanced.php', array('id' => $user->id, 'course' => $course->id));
             $usersetting->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
         } else {
             if (has_capability('moodle/user:editprofile', $usercontext) && !is_siteadmin($user) || $currentuser && has_capability('moodle/user:editownprofile', $systemcontext)) {
                 if ($userauthplugin && $userauthplugin->can_edit_profile()) {
                     $url = $userauthplugin->edit_profile_url();
                     if (empty($url)) {
                         $url = new moodle_url('/user/edit.php', array('id' => $user->id, 'course' => $course->id));
                     }
                     $usersetting->add(get_string('editmyprofile'), $url, self::TYPE_SETTING);
                 }
             }
         }
     }
     // Change password link
     if ($userauthplugin && $currentuser && !session_is_loggedinas() && !isguestuser() && has_capability('moodle/user:changeownpassword', $systemcontext) && $userauthplugin->can_change_password()) {
         $passwordchangeurl = $userauthplugin->change_password_url();
         if (empty($passwordchangeurl)) {
             $passwordchangeurl = new moodle_url('/login/change_password.php', array('id' => $course->id));
         }
         $usersetting->add(get_string("changepassword"), $passwordchangeurl, self::TYPE_SETTING);
     }
     // View the roles settings
     if (has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:manage'), $usercontext)) {
         $roles = $usersetting->add(get_string('roles'), null, self::TYPE_SETTING);
         $url = new moodle_url('/admin/roles/usersroles.php', array('userid' => $user->id, 'courseid' => $course->id));
         $roles->add(get_string('thisusersroles', 'role'), $url, self::TYPE_SETTING);
         $assignableroles = get_assignable_roles($usercontext, ROLENAME_BOTH);
         if (!empty($assignableroles)) {
             $url = new moodle_url('/admin/roles/assign.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
             $roles->add(get_string('assignrolesrelativetothisuser', 'role'), $url, self::TYPE_SETTING);
         }
         if (has_capability('moodle/role:review', $usercontext) || count(get_overridable_roles($usercontext, ROLENAME_BOTH)) > 0) {
             $url = new moodle_url('/admin/roles/permissions.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
             $roles->add(get_string('permissions', 'role'), $url, self::TYPE_SETTING);
         }
         $url = new moodle_url('/admin/roles/check.php', array('contextid' => $usercontext->id, 'userid' => $user->id, 'courseid' => $course->id));
         $roles->add(get_string('checkpermissions', 'role'), $url, self::TYPE_SETTING);
     }
     // Portfolio
     if ($currentuser && !empty($CFG->enableportfolios) && has_capability('moodle/portfolio:export', $systemcontext)) {
         require_once $CFG->libdir . '/portfoliolib.php';
         if (portfolio_instances(true, false)) {
             $portfolio = $usersetting->add(get_string('portfolios', 'portfolio'), null, self::TYPE_SETTING);
             $url = new moodle_url('/user/portfolio.php', array('courseid' => $course->id));
             $portfolio->add(get_string('configure', 'portfolio'), $url, self::TYPE_SETTING);
             $url = new moodle_url('/user/portfoliologs.php', array('courseid' => $course->id));
             $portfolio->add(get_string('logs', 'portfolio'), $url, self::TYPE_SETTING);
         }
     }
     $enablemanagetokens = false;
     if (!empty($CFG->enablerssfeeds)) {
         $enablemanagetokens = true;
     } else {
         if (!is_siteadmin($USER->id) && !empty($CFG->enablewebservices) && has_capability('moodle/webservice:createtoken', get_system_context())) {
             $enablemanagetokens = true;
         }
     }
     // Security keys
     if ($currentuser && $enablemanagetokens) {
         $url = new moodle_url('/user/managetoken.php', array('sesskey' => sesskey()));
         $usersetting->add(get_string('securitykeys', 'webservice'), $url, self::TYPE_SETTING);
     }
     // Repository
     if (!$currentuser && $usercontext->contextlevel == CONTEXT_USER) {
         if (!$this->cache->cached('contexthasrepos' . $usercontext->id)) {
             require_once $CFG->dirroot . '/repository/lib.php';
             $editabletypes = repository::get_editable_types($usercontext);
             $haseditabletypes = !empty($editabletypes);
             unset($editabletypes);
             $this->cache->set('contexthasrepos' . $usercontext->id, $haseditabletypes);
         } else {
             $haseditabletypes = $this->cache->{'contexthasrepos' . $usercontext->id};
         }
         if ($haseditabletypes) {
             $url = new moodle_url('/repository/manage_instances.php', array('contextid' => $usercontext->id));
             $usersetting->add(get_string('repositories', 'repository'), $url, self::TYPE_SETTING);
         }
     }
     // Messaging
     if ($currentuser && has_capability('moodle/user:editownmessageprofile', $systemcontext) || !isguestuser($user) && has_capability('moodle/user:editmessageprofile', $usercontext) && !is_primary_admin($user->id)) {
         $url = new moodle_url('/message/edit.php', array('id' => $user->id));
         $usersetting->add(get_string('editmymessage', 'message'), $url, self::TYPE_SETTING);
     }
     // Blogs
     if ($currentuser && !empty($CFG->bloglevel)) {
         $blog = $usersetting->add(get_string('blogs', 'blog'), null, navigation_node::TYPE_CONTAINER, null, 'blogs');
         $blog->add(get_string('preferences', 'blog'), new moodle_url('/blog/preferences.php'), navigation_node::TYPE_SETTING);
         if (!empty($CFG->useexternalblogs) && $CFG->maxexternalblogsperuser > 0 && has_capability('moodle/blog:manageexternal', get_context_instance(CONTEXT_SYSTEM))) {
             $blog->add(get_string('externalblogs', 'blog'), new moodle_url('/blog/external_blogs.php'), navigation_node::TYPE_SETTING);
             $blog->add(get_string('addnewexternalblog', 'blog'), new moodle_url('/blog/external_blog_edit.php'), navigation_node::TYPE_SETTING);
         }
     }
     // Login as ...
     if (!$user->deleted and !$currentuser && !session_is_loggedinas() && has_capability('moodle/user:loginas', $coursecontext) && !is_siteadmin($user->id)) {
         $url = new moodle_url('/course/loginas.php', array('id' => $course->id, 'user' => $user->id, 'sesskey' => sesskey()));
         $usersetting->add(get_string('loginas'), $url, self::TYPE_SETTING);
     }
     return $usersetting;
 }
Ejemplo n.º 30
0
 /**
  * Creates an instance of the class from record
  *
  * @param stdClass $record except fields from course table it may contain
  *     field hassummary indicating that summary field is not empty.
  *     Also it is recommended to have context fields here ready for
  *     context preloading
  */
 public function __construct(stdClass $record)
 {
     context_helper::preload_from_record($record);
     $this->record = new stdClass();
     foreach ($record as $key => $value) {
         $this->record->{$key} = $value;
     }
 }