public function test_set_user()
 {
     global $USER, $DB;
     $this->assertEquals(0, $USER->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $user = $DB->get_record('user', array('id' => 2));
     $this->assertNotEmpty($user);
     $this->setUser($user);
     $this->assertEquals(2, $USER->id);
     $this->assertEquals(2, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $USER->id = 3;
     $this->assertEquals(3, $USER->id);
     $this->assertEquals(3, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     \core\session\manager::set_user($user);
     $this->assertEquals(2, $USER->id);
     $this->assertEquals(2, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $USER = $DB->get_record('user', array('id' => 1));
     $this->assertNotEmpty($USER);
     $this->assertEquals(1, $USER->id);
     $this->assertEquals(1, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->setUser(null);
     $this->assertEquals(0, $USER->id);
     $this->assertSame($_SESSION['USER'], $USER);
 }
 public function test_set_user()
 {
     global $USER;
     $this->resetAfterTest();
     $user = $this->getDataGenerator()->create_user();
     $this->setUser(0);
     $this->assertEquals(0, $USER->id);
     \core\session\manager::set_user($user);
     $this->assertEquals($user->id, $USER->id);
 }
 public function execute()
 {
     global $CFG, $DB;
     require_once $CFG->dirroot . "/mod/turnitintooltwo/lib.php";
     require_once $CFG->dirroot . "/mod/turnitintooltwo/turnitintooltwo_view.class.php";
     $data = (array) $this->get_custom_data();
     // Make sure we are still wanted.
     $submission = $DB->get_record('turnitintooltwo_submissions', array('id' => $data['submissionid']));
     if (!$submission) {
         return true;
     }
     cli_writeln("Processing Turnitintooltwo submission: " . $data['submissionid']);
     $user = $DB->get_record('user', array('id' => $data['userid']));
     \core\session\manager::set_user($user);
     $turnitintooltwo = $DB->get_record('turnitintooltwo', array('id' => $data['tiiid']));
     list($course, $cm) = get_course_and_cm_from_instance($turnitintooltwo, 'turnitintooltwo');
     try {
         $turnitintooltwoassignment = new \turnitintooltwo_assignment($turnitintooltwo->id, $turnitintooltwo);
         $turnitintooltwosubmission = new \turnitintooltwo_submission($data['submissionid'], "moodle", $turnitintooltwoassignment);
         $parts = $turnitintooltwoassignment->get_parts();
         $tiisubmission = $turnitintooltwosubmission->do_tii_submission($cm, $turnitintooltwoassignment);
         // Update submission.
         $DB->update_record('turnitintooltwo_submissions', array('id' => $data['submissionid'], 'submission_modified' => $data['subtime']));
     } catch (\Exception $e) {
         $tiisubmission = array('success' => false, 'message' => $e->getMessage());
         cli_writeln($e->getMessage());
     }
     $digitalreceipt = $tiisubmission;
     $digitalreceipt['is_manual'] = 0;
     $digitalreceipt = json_encode($digitalreceipt);
     $this->update_sub_status($data['submissionid'], $tiisubmission['success'], $digitalreceipt);
     if ($tiisubmission['success'] === true) {
         $lockedassignment = new \stdClass();
         $lockedassignment->id = $turnitintooltwoassignment->turnitintooltwo->id;
         $lockedassignment->submitted = 1;
         $DB->update_record('turnitintooltwo', $lockedassignment);
         $lockedpart = new \stdClass();
         $lockedpart->id = $data['submissionpart'];
         $lockedpart->submitted = 1;
         // Disable anonymous marking if post date has passed.
         if ($parts[$data['submissionpart']]->dtpost <= time()) {
             $lockedpart->unanon = 1;
         }
         $DB->update_record('turnitintooltwo_parts', $lockedpart);
         cli_writeln("Finished processing successful submission: " . $data['submissionid']);
     } else {
         turnitintooltwo_add_to_log($course->id, "errored submission", 'view.php?id=' . $cm->id, "Failed to submit '" . $turnitintooltwosubmission->submission_title . "'", $cm->id, $user->id, array('submissionid' => $data['submissionid']));
         cli_writeln("Finished processing unsuccessful submission: " . $data['submissionid']);
     }
     \core\session\manager::set_user(get_admin());
     return $tiisubmission['success'];
 }
Beispiel #4
0
 public function test_set_user()
 {
     global $USER, $DB, $SESSION;
     $this->resetAfterTest();
     $this->assertEquals(0, $USER->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     $user = $DB->get_record('user', array('id' => 2));
     $this->assertNotEmpty($user);
     $this->setUser($user);
     $this->assertEquals(2, $USER->id);
     $this->assertEquals(2, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     $USER->id = 3;
     $this->assertEquals(3, $USER->id);
     $this->assertEquals(3, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     \core\session\manager::set_user($user);
     $this->assertEquals(2, $USER->id);
     $this->assertEquals(2, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     $USER = $DB->get_record('user', array('id' => 1));
     $this->assertNotEmpty($USER);
     $this->assertEquals(1, $USER->id);
     $this->assertEquals(1, $_SESSION['USER']->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     $this->setUser(null);
     $this->assertEquals(0, $USER->id);
     $this->assertSame($_SESSION['USER'], $USER);
     $this->assertSame($GLOBALS['USER'], $USER);
     // Ensure session is reset after setUser, as it may contain extra info.
     $SESSION->sometestvalue = true;
     $this->setUser($user);
     $this->assertObjectNotHasAttribute('sometestvalue', $SESSION);
 }
Beispiel #5
0
/**
 * Sets up current user and course environment (lang, etc.) in cron.
 * Do not use outside of cron script!
 *
 * @param stdClass $user full user object, null means default cron user (admin),
 *                 value 'reset' means reset internal static caches.
 * @param stdClass $course full course record, null means $SITE
 * @return void
 */
function cron_setup_user($user = NULL, $course = NULL)
{
    global $CFG, $SITE, $PAGE;
    if (!CLI_SCRIPT) {
        throw new coding_exception('Function cron_setup_user() cannot be used in normal requests!');
    }
    static $cronuser = NULL;
    static $cronsession = NULL;
    if ($user === 'reset') {
        $cronuser = null;
        $cronsession = null;
        \core\session\manager::init_empty_session();
        return;
    }
    if (empty($cronuser)) {
        /// ignore admins timezone, language and locale - use site default instead!
        $cronuser = get_admin();
        $cronuser->timezone = $CFG->timezone;
        $cronuser->lang = '';
        $cronuser->theme = '';
        unset($cronuser->description);
        $cronsession = new stdClass();
    }
    if (!$user) {
        // Cached default cron user (==modified admin for now).
        \core\session\manager::init_empty_session();
        \core\session\manager::set_user($cronuser);
        $GLOBALS['SESSION'] = $cronsession;
    } else {
        // Emulate real user session - needed for caps in cron.
        if ($GLOBALS['USER']->id != $user->id) {
            \core\session\manager::init_empty_session();
            \core\session\manager::set_user($user);
        }
    }
    // TODO MDL-19774 relying on global $PAGE in cron is a bad idea.
    // Temporary hack so that cron does not give fatal errors.
    $PAGE = new moodle_page();
    if ($course) {
        $PAGE->set_course($course);
    } else {
        $PAGE->set_course($SITE);
    }
    // TODO: it should be possible to improve perf by caching some limited number of users here ;-)
}
Beispiel #6
0
 /**
  * Authenticate user using username+password or token.
  * This function sets up $USER global.
  * It is safe to use has_capability() after this.
  * This method also verifies user is allowed to use this
  * server.
  */
 protected function authenticate_user()
 {
     global $CFG, $DB;
     if (!NO_MOODLE_COOKIES) {
         throw new coding_exception('Cookies must be disabled in WS servers!');
     }
     $loginfaileddefaultparams = array('context' => context_system::instance(), 'other' => array('method' => $this->authmethod, 'reason' => null));
     if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) {
         //we check that authentication plugin is enabled
         //it is only required by simple authentication
         if (!is_enabled_auth('webservice')) {
             throw new webservice_access_exception('The web service authentication plugin is disabled.');
         }
         if (!($auth = get_auth_plugin('webservice'))) {
             throw new webservice_access_exception('The web service authentication plugin is missing.');
         }
         $this->restricted_context = context_system::instance();
         if (!$this->username) {
             throw new moodle_exception('missingusername', 'webservice');
         }
         if (!$this->password) {
             throw new moodle_exception('missingpassword', 'webservice');
         }
         if (!$auth->user_login_webservice($this->username, $this->password)) {
             // Log failed login attempts.
             $params = $loginfaileddefaultparams;
             $params['other']['reason'] = 'password';
             $params['other']['username'] = $this->username;
             $event = \core\event\webservice_login_failed::create($params);
             $event->set_legacy_logdata(array(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . $this->username . "/" . $this->password . " - " . getremoteaddr(), 0));
             $event->trigger();
             throw new moodle_exception('wrongusernamepassword', 'webservice');
         }
         $user = $DB->get_record('user', array('username' => $this->username, 'mnethostid' => $CFG->mnet_localhost_id), '*', MUST_EXIST);
     } else {
         if ($this->authmethod == WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN) {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_PERMANENT);
         } else {
             $user = $this->authenticate_by_token(EXTERNAL_TOKEN_EMBEDDED);
         }
     }
     //Non admin can not authenticate if maintenance mode
     $hassiteconfig = has_capability('moodle/site:config', context_system::instance(), $user);
     if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) {
         throw new moodle_exception('sitemaintenance', 'admin');
     }
     //only confirmed user should be able to call web service
     if (!empty($user->deleted)) {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'user_deleted';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserdeleted', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for deleted username: '******'other']['reason'] = 'user_unconfirmed';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserunconfirmed', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new moodle_exception('wsaccessuserunconfirmed', 'webservice', '', $user->username);
     }
     //check the user is suspended
     if (!empty($user->suspended)) {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'user_unconfirmed';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessusersuspended', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for suspended username: '******'other']['reason'] = 'password_expired';
             $params['other']['username'] = $user->username;
             $event = \core\event\webservice_login_failed::create($params);
             $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessuserexpired', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
             $event->trigger();
             throw new webservice_access_exception('Refused web service access for password expired username: '******'nologin') {
         $params = $loginfaileddefaultparams;
         $params['other']['reason'] = 'login';
         $params['other']['username'] = $user->username;
         $event = \core\event\webservice_login_failed::create($params);
         $event->set_legacy_logdata(array(SITEID, '', '', '', get_string('wsaccessusernologin', 'webservice', $user->username) . " - " . getremoteaddr(), 0, $user->id));
         $event->trigger();
         throw new webservice_access_exception('Refused web service access for nologin authentication username: '******'You are not allowed to use the {$a} protocol (missing capability: webservice/' . $this->wsname . ':use)');
     }
     external_api::set_context_restriction($this->restricted_context);
 }
Beispiel #7
0
 /**
  * See if the request contains a proper username/password for login
  *
  * @param  Zend_Controller_Request_Http $request The request to check
  * @return boolean
  */
 public function isValid($request)
 {
     // No cookies !
     if (!PHPUNIT_TEST) {
         if (!defined('NO_MOODLE_COOKIES') or !NO_MOODLE_COOKIES) {
             $this->_error(self::LOGIN_COOKIE);
             return false;
         }
     }
     $wsusername = $request->getParam($this->_paramusername, '');
     $wsusername = clean_param($wsusername, PARAM_RAW);
     $wspassword = $request->getParam($this->_parampassword, '');
     $wspassword = clean_param($wspassword, PARAM_RAW);
     // Are they empty ?
     if (empty($wsusername) or empty($wspassword)) {
         $this->_error(self::LOGIN_MISSING);
         return false;
     }
     // Can we login ?
     if (!($user = authenticate_user_login($wsusername, $wspassword))) {
         $this->_error(self::LOGIN_FAIL);
         return false;
     }
     // Set the user to the session
     enrol_check_plugins($user);
     \core\session\manager::set_user($user);
     return true;
 }
 /**
  * Set the calendar type for this user.
  *
  * @param string $type the calendar type we want to set
  */
 private function set_calendar_type($type)
 {
     $this->user->calendartype = $type;
     \core\session\manager::set_user($this->user);
 }
Beispiel #9
0
/**
 * Require key login. Function terminates with error if key not found or incorrect.
 *
 * @uses NO_MOODLE_COOKIES
 * @uses PARAM_ALPHANUM
 * @param string $script unique script identifier
 * @param int $instance optional instance id
 * @return int Instance ID
 */
function require_user_key_login($script, $instance = null)
{
    global $DB;
    if (!NO_MOODLE_COOKIES) {
        print_error('sessioncookiesdisable');
    }
    // Extra safety.
    \core\session\manager::write_close();
    $keyvalue = required_param('key', PARAM_ALPHANUM);
    if (!($key = $DB->get_record('user_private_key', array('script' => $script, 'value' => $keyvalue, 'instance' => $instance)))) {
        print_error('invalidkey');
    }
    if (!empty($key->validuntil) and $key->validuntil < time()) {
        print_error('expiredkey');
    }
    if ($key->iprestriction) {
        $remoteaddr = getremoteaddr(null);
        if (empty($remoteaddr) or !address_in_subnet($remoteaddr, $key->iprestriction)) {
            print_error('ipmismatch');
        }
    }
    if (!($user = $DB->get_record('user', array('id' => $key->userid)))) {
        print_error('invaliduserid');
    }
    // Emulate normal session.
    enrol_check_plugins($user);
    \core\session\manager::set_user($user);
    // Note we are not using normal login.
    if (!defined('USER_KEY_LOGIN')) {
        define('USER_KEY_LOGIN', true);
    }
    // Return instance id - it might be empty.
    return $key->instance;
}
Beispiel #10
0
define('NO_OUTPUT_BUFFERING', true);
require __DIR__ . '/../../../../config.php';
require_once $CFG->libdir . '/clilib.php';
// CLI options.
list($options, $unrecognized) = cli_get_params(array('help' => false, 'size' => false, 'fixeddataset' => false, 'filesizelimit' => false, 'bypasscheck' => false, 'quiet' => false), array('h' => 'help'));
$sitesizes = '* ' . implode(PHP_EOL . '* ', tool_generator_site_backend::get_size_choices());
// Display help.
if (!empty($options['help']) || empty($options['size'])) {
    echo "\nUtility to generate a standard test site data set.\n\nNot for use on live sites; only normally works if debugging is set to DEVELOPER\nlevel.\n\nConsider that, depending on the size you select, this CLI tool can really generate a lot of data, aproximated sizes:\n\n{$sitesizes}\n\nOptions:\n--size           Size of the generated site, this value affects the number of courses and their size. Accepted values: XS, S, M, L, XL, or XXL (required)\n--fixeddataset   Use a fixed data set instead of randomly generated data\n--filesizelimit  Limits the size of the generated files to the specified bytes\n--bypasscheck    Bypasses the developer-mode check (be careful!)\n--quiet          Do not show any output\n\n-h, --help     Print out this help\n\nExample from Moodle root directory:\n\$ php admin/tool/generator/cli/maketestsite.php --size=S\n";
    // Exit with error unless we're showing this because they asked for it.
    exit(empty($options['help']) ? 1 : 0);
}
// Check debugging is set to developer level.
if (empty($options['bypasscheck']) && !$CFG->debugdeveloper) {
    cli_error(get_string('error_notdebugging', 'tool_generator'));
}
// Get options.
$sizename = $options['size'];
$fixeddataset = $options['fixeddataset'];
$filesizelimit = $options['filesizelimit'];
// Check size.
try {
    $size = tool_generator_site_backend::size_for_name($sizename);
} catch (coding_exception $e) {
    cli_error("Invalid size ({$sizename}). Use --help for help.");
}
// Switch to admin user account.
\core\session\manager::set_user(get_admin());
// Do backend code to generate site.
$backend = new tool_generator_site_backend($size, $options['bypasscheck'], $fixeddataset, $filesizelimit, empty($options['quiet']));
$backend->make();
 public function test_set_user()
 {
     global $USER;
     $this->resetAfterTest();
     $this->assertEquals(0, $USER->id);
     $user = $this->getDataGenerator()->create_user();
     $this->assertObjectHasAttribute('description', $user);
     $this->assertObjectHasAttribute('password', $user);
     \core\session\manager::set_user($user);
     $this->assertEquals($user->id, $USER->id);
     $this->assertObjectNotHasAttribute('description', $user);
     $this->assertObjectNotHasAttribute('password', $user);
     $this->assertObjectHasAttribute('sesskey', $user);
     $this->assertSame($user, $GLOBALS['USER']);
     $this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
     $this->assertSame($GLOBALS['USER'], $USER);
 }
/**
 * Sets up current user and course environment (lang, etc.) in cron.
 * Do not use outside of cron script!
 *
 * @param stdClass $user full user object, null means default cron user (admin)
 * @param $course full course record, null means $SITE
 * @return void
 */
function cron_setup_user($user = NULL, $course = NULL)
{
    global $CFG, $SITE, $PAGE;
    static $cronuser = NULL;
    static $cronsession = NULL;
    if (empty($cronuser)) {
        /// ignore admins timezone, language and locale - use site default instead!
        $cronuser = get_admin();
        $cronuser->timezone = $CFG->timezone;
        $cronuser->lang = '';
        $cronuser->theme = '';
        unset($cronuser->description);
        $cronsession = new stdClass();
    }
    if (!$user) {
        // cached default cron user (==modified admin for now)
        \core\session\manager::set_user($cronuser);
        $_SESSION['SESSION'] = $cronsession;
    } else {
        // emulate real user session - needed for caps in cron
        if ($_SESSION['USER']->id != $user->id) {
            \core\session\manager::set_user($user);
            $_SESSION['SESSION'] = new stdClass();
        }
    }
    // TODO MDL-19774 relying on global $PAGE in cron is a bad idea.
    // Temporary hack so that cron does not give fatal errors.
    $PAGE = new moodle_page();
    if ($course) {
        $PAGE->set_course($course);
    } else {
        $PAGE->set_course($SITE);
    }
    // TODO: it should be possible to improve perf by caching some limited number of users here ;-)
}
Beispiel #13
0
 /**
  * Set current $USER, reset access cache.
  * @static
  * @param null|int|stdClass $user user record, null or 0 means non-logged-in, positive integer means userid
  * @return void
  */
 public static function setUser($user = null)
 {
     global $CFG, $DB;
     if (is_object($user)) {
         $user = clone $user;
     } else {
         if (!$user) {
             $user = new stdClass();
             $user->id = 0;
             $user->mnethostid = $CFG->mnet_localhost_id;
         } else {
             $user = $DB->get_record('user', array('id' => $user));
         }
     }
     unset($user->description);
     unset($user->access);
     unset($user->preference);
     // Enusre session is empty, as it may contain caches and user specific info.
     \core\session\manager::init_empty_session();
     \core\session\manager::set_user($user);
 }
Beispiel #14
0
/**
 * Set the passed user ID to the session user.
 *
 * @param int $userid
 */
function lti_set_session_user($userid)
{
    global $DB;
    if ($user = $DB->get_record('user', array('id' => $userid))) {
        \core\session\manager::set_user($user);
    }
}
 /**
  * Resets the test environment.
  *
  * @param OutlineExampleEvent|ScenarioEvent $event event fired before scenario.
  * @throws coding_exception If here we are not using the test database it should be because of a coding error
  * @BeforeScenario
  */
 public function before_scenario($event)
 {
     global $DB, $CFG;
     // TODO: check config value to ensure site is set for performance data.
     $moreinfo = 'More info in ' . behat_command::DOCS_URL . '#Running_tests';
     $driverexceptionmsg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo;
     try {
         $session = $this->getSession();
     } catch (CurlExec $e) {
         // Exception thrown by WebDriver, so only @javascript tests will be caugth; in
         // behat_util::is_server_running() we already checked that the server is running.
         throw new Exception($driverexceptionmsg);
     } catch (DriverException $e) {
         throw new Exception($driverexceptionmsg);
     } catch (UnknownError $e) {
         // Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
         $this->throw_unknown_exception($e);
     }
     // We need the Mink session to do it and we do it only before the first scenario.
     if (self::is_first_scenario()) {
         behat_selectors::register_moodle_selectors($session);
         behat_context_helper::set_session($session);
     }
     // Reset mink session between the scenarios.
     $session->reset();
     // Assign valid data to admin user (some generator-related code needs a valid user).
     $user = $DB->get_record('user', array('username' => 'admin'));
     \core\session\manager::set_user($user);
     // Start always in the the homepage.
     try {
         // Let's be conservative as we never know when new upstream issues will affect us.
         $session->visit($this->locate_path('/'));
     } catch (UnknownError $e) {
         $this->throw_unknown_exception($e);
     }
 }
/**
 * Install Moodle DB,
 * config.php must exist, there must not be any tables in db yet.
 *
 * @param array $options adminpass is mandatory
 * @param bool $interactive
 * @return void
 */
function install_cli_database(array $options, $interactive)
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/environmentlib.php';
    require_once $CFG->libdir . '/upgradelib.php';
    // show as much debug as possible
    @error_reporting(E_ALL | E_STRICT);
    @ini_set('display_errors', '1');
    $CFG->debug = E_ALL | E_STRICT;
    $CFG->debugdisplay = true;
    $CFG->debugdeveloper = true;
    $CFG->version = '';
    $CFG->release = '';
    $CFG->branch = '';
    $version = null;
    $release = null;
    $branch = null;
    // read $version and $release
    require $CFG->dirroot . '/version.php';
    if ($DB->get_tables()) {
        cli_error(get_string('clitablesexist', 'install'));
    }
    if (empty($options['adminpass'])) {
        cli_error('Missing required admin password');
    }
    // test environment first
    list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
    if (!$envstatus) {
        $errors = environment_get_errors($environment_results);
        cli_heading(get_string('environment', 'admin'));
        foreach ($errors as $error) {
            list($info, $report) = $error;
            echo "!! {$info} !!\n{$report}\n\n";
        }
        exit(1);
    }
    if (!$DB->setup_is_unicodedb()) {
        if (!$DB->change_db_encoding()) {
            // If could not convert successfully, throw error, and prevent installation
            cli_error(get_string('unicoderequired', 'admin'));
        }
    }
    if ($interactive) {
        cli_separator();
        cli_heading(get_string('databasesetup'));
    }
    // install core
    install_core($version, true);
    set_config('release', $release);
    set_config('branch', $branch);
    if (PHPUNIT_TEST) {
        // mark as test database as soon as possible
        set_config('phpunittest', 'na');
    }
    // install all plugins types, local, etc.
    upgrade_noncore(true);
    // set up admin user password
    $DB->set_field('user', 'password', hash_internal_user_password($options['adminpass']), array('username' => 'admin'));
    // rename admin username if needed
    if (isset($options['adminuser']) and $options['adminuser'] !== 'admin' and $options['adminuser'] !== 'guest') {
        $DB->set_field('user', 'username', $options['adminuser'], array('username' => 'admin'));
    }
    // indicate that this site is fully configured
    set_config('rolesactive', 1);
    upgrade_finished();
    // log in as admin - we need do anything when applying defaults
    \core\session\manager::set_user(get_admin());
    // apply all default settings, do it twice to fill all defaults - some settings depend on other setting
    admin_apply_default_settings(NULL, true);
    admin_apply_default_settings(NULL, true);
    set_config('registerauth', '');
    // set the site name
    if (isset($options['shortname']) and $options['shortname'] !== '') {
        $DB->set_field('course', 'shortname', $options['shortname'], array('format' => 'site'));
    }
    if (isset($options['fullname']) and $options['fullname'] !== '') {
        $DB->set_field('course', 'fullname', $options['fullname'], array('format' => 'site'));
    }
}
Beispiel #17
0
/**
 * Setup $USER object - called during login, loginas, etc.
 *
 * Call sync_user_enrolments() manually after log-in, or log-in-as.
 *
 * @deprecated since 2.6
 * @param stdClass $user full user record object
 * @return void
 */
function session_set_user($user)
{
    debugging('session_set_user() is deprecated, use \\core\\session\\manager::set_user() instead', DEBUG_DEVELOPER);
    \core\session\manager::set_user($user);
}
 /**
  * Resets the test environment.
  *
  * @throws coding_exception If here we are not using the test database it should be because of a coding error
  * @BeforeScenario
  */
 public function before_scenario($event)
 {
     global $DB, $SESSION, $CFG;
     // As many checks as we can.
     if (!defined('BEHAT_TEST') || !defined('BEHAT_SITE_RUNNING') || php_sapi_name() != 'cli' || !behat_util::is_test_mode_enabled() || !behat_util::is_test_site()) {
         throw new coding_exception('Behat only can modify the test database and the test dataroot!');
     }
     $moreinfo = 'More info in ' . behat_command::DOCS_URL . '#Running_tests';
     $driverexceptionmsg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo;
     try {
         $session = $this->getSession();
     } catch (CurlExec $e) {
         // Exception thrown by WebDriver, so only @javascript tests will be caugth; in
         // behat_util::is_server_running() we already checked that the server is running.
         throw new Exception($driverexceptionmsg);
     } catch (DriverException $e) {
         throw new Exception($driverexceptionmsg);
     } catch (UnknownError $e) {
         // Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
         $this->throw_unknown_exception($e);
     }
     // We need the Mink session to do it and we do it only before the first scenario.
     if (self::is_first_scenario()) {
         behat_selectors::register_moodle_selectors($session);
         behat_context_helper::set_session($session);
     }
     // Reset $SESSION.
     \core\session\manager::init_empty_session();
     behat_util::reset_database();
     behat_util::reset_dataroot();
     accesslib_clear_all_caches(true);
     // Reset the nasty strings list used during the last test.
     nasty_strings::reset_used_strings();
     // Assign valid data to admin user (some generator-related code needs a valid user).
     $user = $DB->get_record('user', array('username' => 'admin'));
     \core\session\manager::set_user($user);
     // Reset the browser if specified in config.php.
     if (!empty($CFG->behat_restart_browser_after) && $this->running_javascript()) {
         $now = time();
         if (self::$lastbrowsersessionstart + $CFG->behat_restart_browser_after < $now) {
             $session->restart();
             self::$lastbrowsersessionstart = $now;
         }
     }
     // Start always in the the homepage.
     try {
         // Let's be conservative as we never know when new upstream issues will affect us.
         $session->visit($this->locate_path('/'));
     } catch (UnknownError $e) {
         $this->throw_unknown_exception($e);
     }
     // Checking that the root path is a Moodle test site.
     if (self::is_first_scenario()) {
         $notestsiteexception = new Exception('The base URL (' . $CFG->wwwroot . ') is not a behat test site, ' . 'ensure you started the built-in web server in the correct directory or your web server is correctly started and set up');
         $this->find("xpath", "//head/child::title[normalize-space(.)='" . behat_util::BEHATSITENAME . "']", $notestsiteexception);
         self::$initprocessesfinished = true;
     }
     // Run all test with medium (1024x768) screen size, to avoid responsive problems.
     $this->resize_window('medium');
 }
Beispiel #19
0
    /**
     * Set current $USER, reset access cache.
     * @static
     * @param null|int|stdClass $user user record, null or 0 means non-logged-in, positive integer means userid
     * @return void
     */
    public static function setUser($user = null) {
        global $CFG, $DB;

        if (is_object($user)) {
            $user = clone($user);
        } else if (!$user) {
            $user = new stdClass();
            $user->id = 0;
            $user->mnethostid = $CFG->mnet_localhost_id;
        } else {
            $user = $DB->get_record('user', array('id'=>$user));
        }
        unset($user->description);
        unset($user->access);
        unset($user->preference);

        \core\session\manager::set_user($user);
    }
 /**
  * Resets the test environment.
  *
  * @param OutlineExampleEvent|ScenarioEvent $event event fired before scenario.
  * @throws coding_exception If here we are not using the test database it should be because of a coding error
  * @BeforeScenario
  */
 public function before_scenario($event)
 {
     global $DB, $CFG;
     // TODO: check config value to ensure site is set for performance data.
     $moreinfo = 'More info in ' . behat_command::DOCS_URL . '#Running_tests';
     $driverexceptionmsg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo;
     try {
         $session = $this->getSession();
     } catch (CurlExec $e) {
         // Exception thrown by WebDriver, so only @javascript tests will be caugth; in
         // behat_util::is_server_running() we already checked that the server is running.
         throw new Exception($driverexceptionmsg);
     } catch (DriverException $e) {
         throw new Exception($driverexceptionmsg);
     } catch (UnknownError $e) {
         // Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
         $this->throw_unknown_exception($e);
     }
     // We need the Mink session to do it and we do it only before the first scenario.
     if (self::is_first_scenario()) {
         behat_selectors::register_moodle_selectors($session);
         behat_context_helper::set_session($session);
     }
     // Reset mink session between the scenarios.
     $session->reset();
     // Assign valid data to admin user (some generator-related code needs a valid user).
     $user = $DB->get_record('user', array('username' => 'admin'));
     \core\session\manager::set_user($user);
     // Start always in the the homepage.
     try {
         // Let's be conservative as we never know when new upstream issues will affect us.
         $session->visit($this->locate_path('/'));
     } catch (UnknownError $e) {
         $this->throw_unknown_exception($e);
     }
     // Checking that the root path is a Moodle test site.
     /*if (self::is_first_scenario()) {
                 $notestsiteexception = new Exception('The base URL (' . $CFG->wwwroot . ') is not a behat test site, ' .
                     'ensure you started the built-in web server in the correct directory or your web server is correctly started and set up');
                 $this->find("xpath", "//head/child::title[normalize-space(.)='" . behat_util::BEHATSITENAME . "']", $notestsiteexception);
     
                 self::$initprocessesfinished = true;
             }*/
 }
Beispiel #21
0
/**
 * Require key login. Function terminates with error if key not found or incorrect.
 *
 * @uses NO_MOODLE_COOKIES
 * @uses PARAM_ALPHANUM
 * @param string $script unique script identifier
 * @param int $instance optional instance id
 * @return int Instance ID
 */
function require_user_key_login($script, $instance = null)
{
    global $DB;
    if (!NO_MOODLE_COOKIES) {
        print_error('sessioncookiesdisable');
    }
    // Extra safety.
    \core\session\manager::write_close();
    $keyvalue = required_param('key', PARAM_ALPHANUM);
    $key = validate_user_key($keyvalue, $script, $instance);
    if (!($user = $DB->get_record('user', array('id' => $key->userid)))) {
        print_error('invaliduserid');
    }
    // Emulate normal session.
    enrol_check_plugins($user);
    \core\session\manager::set_user($user);
    // Note we are not using normal login.
    if (!defined('USER_KEY_LOGIN')) {
        define('USER_KEY_LOGIN', true);
    }
    // Return instance id - it might be empty.
    return $key->instance;
}
Beispiel #22
0
 /**
  * Resets the test environment.
  *
  * @param BeforeScenarioScope $scope scope passed by event fired before scenario.
  * @throws behat_stop_exception If here we are not using the test database it should be because of a coding error
  */
 public function before_scenario(BeforeScenarioScope $scope)
 {
     global $DB, $CFG;
     // As many checks as we can.
     if (!defined('BEHAT_TEST') || !defined('BEHAT_SITE_RUNNING') || php_sapi_name() != 'cli' || !behat_util::is_test_mode_enabled() || !behat_util::is_test_site()) {
         throw new behat_stop_exception('Behat only can modify the test database and the test dataroot!');
     }
     $moreinfo = 'More info in ' . behat_command::DOCS_URL . '#Running_tests';
     $driverexceptionmsg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo;
     try {
         $session = $this->getSession();
     } catch (CurlExec $e) {
         // Exception thrown by WebDriver, so only @javascript tests will be caugth; in
         // behat_util::check_server_status() we already checked that the server is running.
         throw new behat_stop_exception($driverexceptionmsg);
     } catch (DriverException $e) {
         throw new behat_stop_exception($driverexceptionmsg);
     } catch (UnknownError $e) {
         // Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
         throw new behat_stop_exception($e->getMessage());
     }
     $suitename = $scope->getSuite()->getName();
     // Register behat selectors for theme, if suite is changed. We do it for every suite change.
     if ($suitename !== self::$runningsuite) {
         behat_context_helper::set_environment($scope->getEnvironment());
         // We need the Mink session to do it and we do it only before the first scenario.
         $namedpartialclass = 'behat_partial_named_selector';
         $namedexactclass = 'behat_exact_named_selector';
         if ($suitename !== 'default') {
             // If override selector exist, then set it as default behat selectors class.
             $overrideclass = behat_config_util::get_behat_theme_selector_override_classname($suitename, 'named_partial', true);
             if (class_exists($overrideclass)) {
                 $namedpartialclass = $overrideclass;
             }
             // If override selector exist, then set it as default behat selectors class.
             $overrideclass = behat_config_util::get_behat_theme_selector_override_classname($suitename, 'named_exact', true);
             if (class_exists($overrideclass)) {
                 $namedexactclass = $overrideclass;
             }
         }
         $this->getSession()->getSelectorsHandler()->registerSelector('named_partial', new $namedpartialclass());
         $this->getSession()->getSelectorsHandler()->registerSelector('named_exact', new $namedexactclass());
     }
     // Reset mink session between the scenarios.
     $session->reset();
     // Reset $SESSION.
     \core\session\manager::init_empty_session();
     behat_util::reset_all_data();
     // Assign valid data to admin user (some generator-related code needs a valid user).
     $user = $DB->get_record('user', array('username' => 'admin'));
     \core\session\manager::set_user($user);
     // Reset the browser if specified in config.php.
     if (!empty($CFG->behat_restart_browser_after) && $this->running_javascript()) {
         $now = time();
         if (self::$lastbrowsersessionstart + $CFG->behat_restart_browser_after < $now) {
             $session->restart();
             self::$lastbrowsersessionstart = $now;
         }
     }
     // Set the theme if not default.
     if ($suitename !== "default") {
         set_config('theme', $suitename);
         self::$runningsuite = $suitename;
     }
     // Start always in the the homepage.
     try {
         // Let's be conservative as we never know when new upstream issues will affect us.
         $session->visit($this->locate_path('/'));
     } catch (UnknownError $e) {
         throw new behat_stop_exception($e->getMessage());
     }
     // Checking that the root path is a Moodle test site.
     if (self::is_first_scenario()) {
         $notestsiteexception = new behat_stop_exception('The base URL (' . $CFG->wwwroot . ') is not a behat test site, ' . 'ensure you started the built-in web server in the correct directory or your web server is correctly started and set up');
         $this->find("xpath", "//head/child::title[normalize-space(.)='" . behat_util::BEHATSITENAME . "']", $notestsiteexception);
         self::$initprocessesfinished = true;
     }
     // Run all test with medium (1024x768) screen size, to avoid responsive problems.
     $this->resize_window('medium');
 }
 /**
  * Reset contents of all database tables to initial values, reset caches, etc.
  *
  * Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care!
  *
  * @static
  * @param bool $detectchanges
  *      true  - changes in global state and database are reported as errors
  *      false - no errors reported
  *      null  - only critical problems are reported as errors
  * @return void
  */
 public static function reset_all_data($detectchanges = false)
 {
     global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION;
     // Stop any message redirection.
     phpunit_util::stop_message_redirection();
     // Stop any message redirection.
     phpunit_util::stop_phpmailer_redirection();
     // Stop any message redirection.
     phpunit_util::stop_event_redirection();
     // Release memory and indirectly call destroy() methods to release resource handles, etc.
     gc_collect_cycles();
     // Show any unhandled debugging messages, the runbare() could already reset it.
     self::display_debugging_messages();
     self::reset_debugging();
     // reset global $DB in case somebody mocked it
     $DB = self::get_global_backup('DB');
     if ($DB->is_transaction_started()) {
         // we can not reset inside transaction
         $DB->force_transaction_rollback();
     }
     $resetdb = self::reset_database();
     $warnings = array();
     if ($detectchanges === true) {
         if ($resetdb) {
             $warnings[] = 'Warning: unexpected database modification, resetting DB state';
         }
         $oldcfg = self::get_global_backup('CFG');
         $oldsite = self::get_global_backup('SITE');
         foreach ($CFG as $k => $v) {
             if (!property_exists($oldcfg, $k)) {
                 $warnings[] = 'Warning: unexpected new $CFG->' . $k . ' value';
             } else {
                 if ($oldcfg->{$k} !== $CFG->{$k}) {
                     $warnings[] = 'Warning: unexpected change of $CFG->' . $k . ' value';
                 }
             }
             unset($oldcfg->{$k});
         }
         if ($oldcfg) {
             foreach ($oldcfg as $k => $v) {
                 $warnings[] = 'Warning: unexpected removal of $CFG->' . $k;
             }
         }
         if ($USER->id != 0) {
             $warnings[] = 'Warning: unexpected change of $USER';
         }
         if ($COURSE->id != $oldsite->id) {
             $warnings[] = 'Warning: unexpected change of $COURSE';
         }
     }
     if (ini_get('max_execution_time') != 0) {
         // This is special warning for all resets because we do not want any
         // libraries to mess with timeouts unintentionally.
         // Our PHPUnit integration is not supposed to change it either.
         if ($detectchanges !== false) {
             $warnings[] = 'Warning: max_execution_time was changed to ' . ini_get('max_execution_time');
         }
         set_time_limit(0);
     }
     // restore original globals
     $_SERVER = self::get_global_backup('_SERVER');
     $CFG = self::get_global_backup('CFG');
     $SITE = self::get_global_backup('SITE');
     $_GET = array();
     $_POST = array();
     $_FILES = array();
     $_REQUEST = array();
     $COURSE = $SITE;
     // reinitialise following globals
     $OUTPUT = new bootstrap_renderer();
     $PAGE = new moodle_page();
     $FULLME = null;
     $ME = null;
     $SCRIPT = null;
     $SESSION = new stdClass();
     $_SESSION['SESSION'] =& $SESSION;
     // set fresh new not-logged-in user
     $user = new stdClass();
     $user->id = 0;
     $user->mnethostid = $CFG->mnet_localhost_id;
     \core\session\manager::set_user($user);
     // reset all static caches
     \core\event\manager::phpunit_reset();
     accesslib_clear_all_caches(true);
     get_string_manager()->reset_caches(true);
     reset_text_filters_cache(true);
     events_get_handlers('reset');
     core_text::reset_caches();
     get_message_processors(false, true);
     filter_manager::reset_caches();
     //TODO MDL-25290: add more resets here and probably refactor them to new core function
     // Reset course and module caches.
     if (class_exists('format_base')) {
         // If file containing class is not loaded, there is no cache there anyway.
         format_base::reset_course_cache(0);
     }
     get_fast_modinfo(0, 0, true);
     // Reset other singletons.
     if (class_exists('core_plugin_manager')) {
         core_plugin_manager::reset_caches(true);
     }
     if (class_exists('\\core\\update\\checker')) {
         \core\update\checker::reset_caches(true);
     }
     if (class_exists('\\core\\update\\deployer')) {
         \core\update\deployer::reset_caches(true);
     }
     // purge dataroot directory
     self::reset_dataroot();
     // restore original config once more in case resetting of caches changed CFG
     $CFG = self::get_global_backup('CFG');
     // inform data generator
     self::get_data_generator()->reset();
     // fix PHP settings
     error_reporting($CFG->debug);
     // verify db writes just in case something goes wrong in reset
     if (self::$lastdbwrites != $DB->perf_get_writes()) {
         error_log('Unexpected DB writes in phpunit_util::reset_all_data()');
         self::$lastdbwrites = $DB->perf_get_writes();
     }
     if ($warnings) {
         $warnings = implode("\n", $warnings);
         trigger_error($warnings, E_USER_WARNING);
     }
 }
Beispiel #24
0
 /**
  * Login as another user - no security checks here.
  * @param int $userid
  * @param \context $context
  * @return void
  */
 public static function loginas($userid, \context $context)
 {
     global $USER;
     if (self::is_loggedinas()) {
         return;
     }
     // Switch to fresh new $_SESSION.
     $_SESSION = array();
     $_SESSION['REALSESSION'] = clone $GLOBALS['SESSION'];
     $GLOBALS['SESSION'] = new \stdClass();
     $_SESSION['SESSION'] =& $GLOBALS['SESSION'];
     // Create the new $USER object with all details and reload needed capabilities.
     $_SESSION['REALUSER'] = clone $GLOBALS['USER'];
     $user = get_complete_user_data('id', $userid);
     $user->realuser = $_SESSION['REALUSER']->id;
     $user->loginascontext = $context;
     // Let enrol plugins deal with new enrolments if necessary.
     enrol_check_plugins($user);
     // Create event before $USER is updated.
     $event = \core\event\user_loggedinas::create(array('objectid' => $USER->id, 'context' => $context, 'relateduserid' => $userid, 'other' => array('originalusername' => fullname($USER, true), 'loggedinasusername' => fullname($user, true))));
     // Set up global $USER.
     \core\session\manager::set_user($user);
     $event->trigger();
 }
Beispiel #25
0
}
$PAGE->set_url($url);
if (!($chatuser = $DB->get_record('chat_users', array('sid' => $chatsid)))) {
    print_error('notlogged', 'chat');
}
// Get the minimal course.
if (!($course = $DB->get_record('course', array('id' => $chatuser->course)))) {
    print_error('invalidcourseid');
}
// Get the user theme and enough info to be used in chat_format_message() which passes it along to
// chat_format_message_manually() -- and only id and timezone are used.
// No optimisation here, it would break again in future!
if (!($user = $DB->get_record('user', array('id' => $chatuser->userid, 'deleted' => 0, 'suspended' => 0)))) {
    print_error('invaliduser');
}
\core\session\manager::set_user($user);
// Setup course, lang and theme.
$PAGE->set_course($course);
// Force deleting of timed out users if there is a silence in room or just entering.
if (time() - $chatlasttime > $CFG->chat_old_ping) {
    // Must be done before chat_get_latest_message!
    chat_delete_old_users();
}
// Time to send headers, and lay out the basic JS updater page.
header('Expires: Sun, 28 Dec 1997 09:32:45 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: text/html; charset=utf-8');
$refreshurl = "{$CFG->wwwroot}/mod/chat/gui_header_js/jsupdated.php?" . "chat_sid={$chatsid}&chat_lasttime={$chatlasttime}&chat_lastrow={$chatnewrow}&chat_lastid={$chatlastid}";
?>
 /**
  * Get recent activity for course(s)
  *
  * The passed course(s) will get populated with recent activity
  * and returned.  EG: $course->recentactivity = array(...of activity...);
  *
  * @param int $timestart Look for activity after this time
  * @param array|stdClass $courses An array of course objects or a single course object
  * @param mixed $otheruser The user who will view the list of activity.  If NULL, then currently logged in user is used.
  * @throws Exception
  * @return array
  */
 public function direct($timestart, $courses, $otheruser = NULL)
 {
     global $DB, $CFG, $USER;
     $recentactivity = array();
     // Param checks
     if (is_null($timestart) or empty($courses)) {
         return $recentactivity;
     }
     if (!is_array($courses)) {
         $courses = array($courses->id => $courses);
     }
     if (!is_null($otheruser)) {
         $currentuser = clone $USER;
         enrol_check_plugins($otheruser);
         \core\session\manager::set_user($otheruser);
     } else {
         $currentuser = false;
     }
     $timestart = clean_param($timestart, PARAM_INT);
     if ($allmods = $DB->get_records('modules')) {
         foreach ($allmods as $mod) {
             if ($mod->visible) {
                 $modnames[$mod->name] = get_string('modulename', $mod->name);
             }
         }
     } else {
         throw new Exception('No modules are installed!');
     }
     // Gather recent activity
     foreach ($courses as $course) {
         $modinfo = get_fast_modinfo($course);
         $viewfullnames = has_capability('moodle/site:viewfullnames', context_course::instance($course->id));
         $activities = array();
         $index = 0;
         $recentactivity[$course->id] = $course;
         $recentactivity[$course->id]->recentactivity = array();
         $logs = $DB->get_records_sql("SELECT l.*, u.firstname, u.lastname, u.picture\n                                            FROM {log} l\n                                 LEFT OUTER JOIN {user} u ON l.userid = u.id\n                                           WHERE time > ?\n                                             AND course = ?\n                                             AND module = 'course'\n                                             AND (action = 'add mod' OR action = 'update mod' OR action = 'delete mod')\n                                        ORDER BY id ASC", array($timestart, $course->id));
         if ($logs) {
             $changelist = array();
             $newgones = array();
             // added and later deleted items
             foreach ($logs as $key => $log) {
                 $info = explode(' ', $log->info);
                 // Labels are ignored in recent activity
                 if ($info[0] == 'label') {
                     continue;
                 }
                 // Check for incorrect entry
                 if (count($info) != 2) {
                     continue;
                 }
                 $modname = $info[0];
                 $instanceid = $info[1];
                 $userinfo = new stdClass();
                 $userinfo->id = $log->userid;
                 $userinfo->userid = $log->userid;
                 $userinfo->fullname = '';
                 $userinfo->picture = $log->picture;
                 if (!empty($log->firstname) and !empty($log->lastname)) {
                     $a = new stdClass();
                     $a->fullname = fullname($log, $viewfullnames);
                     $a->modname = get_string('modulename', $modname);
                     $userinfo->fullname = $a->fullname;
                 } else {
                     $a = false;
                 }
                 if ($log->action == 'delete mod') {
                     // unfortunately we do not know if the mod was visible
                     if (!array_key_exists($log->info, $newgones)) {
                         if ($a) {
                             $strdeleted = get_string('deletedactivity', 'local_mr', $a);
                         } else {
                             $strdeleted = get_string('deletedactivity', 'moodle', get_string('modulename', $modname));
                         }
                         $changelist[$log->info] = (object) array('cmid' => $log->cmid, 'type' => $modname, 'name' => '', 'action' => 'delete', 'timestamp' => $log->time, 'description_html' => $strdeleted, 'description_text' => $strdeleted, 'user' => $userinfo);
                     }
                 } else {
                     if (!isset($modinfo->instances[$modname][$instanceid])) {
                         if ($log->action == 'add mod') {
                             // do not display added and later deleted activities
                             $newgones[$log->info] = true;
                         }
                         continue;
                     }
                     $cm = $modinfo->instances[$modname][$instanceid];
                     if (!$cm->uservisible) {
                         continue;
                     }
                     if ($log->action == 'add mod') {
                         if ($a) {
                             $stradded = get_string('addedactivity', 'local_mr', $a);
                         } else {
                             $stradded = get_string('added', 'moodle', get_string('modulename', $modname));
                         }
                         $changelist[$log->info] = (object) array('cmid' => $cm->id, 'type' => $modname, 'name' => $cm->name, 'action' => 'add', 'timestamp' => $log->time, 'description_html' => "{$stradded}:<br /><a href=\"{$CFG->wwwroot}/mod/{$cm->modname}/view.php?id={$cm->id}\">" . format_string($cm->name, true) . '</a>', 'description_text' => "{$stradded}: " . format_string($cm->name, true), 'user' => $userinfo);
                     } else {
                         if ($log->action == 'update mod' and empty($changelist[$log->info])) {
                             if ($a) {
                                 $strupdated = get_string('updatedactivity', 'local_mr', $a);
                             } else {
                                 $strupdated = get_string('updated', 'moodle', get_string('modulename', $modname));
                             }
                             $changelist[$log->info] = (object) array('cmid' => $cm->id, 'type' => $modname, 'name' => $cm->name, 'action' => 'update', 'timestamp' => $log->time, 'description_html' => "{$strupdated}:<br /><a href=\"{$CFG->wwwroot}/mod/{$cm->modname}/view.php?id={$cm->id}\">" . format_string($cm->name, true) . '</a>', 'description_text' => "{$strupdated}: " . format_string($cm->name, true), 'user' => $userinfo);
                         }
                     }
                 }
             }
             // Add to main recentactivity array
             $recentactivity[$course->id]->recentactivity = array_values($changelist);
         }
         foreach ($modinfo->cms as $cm) {
             if (!$cm->uservisible) {
                 continue;
             }
             $lib = "{$CFG->dirroot}/mod/{$cm->modname}/lib.php";
             if (file_exists($lib)) {
                 require_once $lib;
                 $get_recent_mod_activity = "{$cm->modname}_get_recent_mod_activity";
                 if (function_exists($get_recent_mod_activity)) {
                     $get_recent_mod_activity($activities, $index, $timestart, $course->id, $cm->id, 0, 0);
                 }
             }
         }
         foreach ($activities as $activity) {
             $print_recent_mod_activity = "{$activity->type}_print_recent_mod_activity";
             if (function_exists($print_recent_mod_activity)) {
                 ob_start();
                 $print_recent_mod_activity($activity, $course->id, true, $modnames, true);
                 $description = ob_get_contents();
                 ob_end_clean();
                 $activity->description_html = $description;
                 $activity->description_text = trim(strip_tags(str_replace(array('</td>', '</div>'), array(' </td>', ' </div>'), $description)));
                 if (empty($activity->timestamp)) {
                     $activity->timestamp = 0;
                 }
                 $recentactivity[$course->id]->recentactivity[] = $activity;
             }
         }
     }
     // Sort recent activity
     foreach ($recentactivity as $courseid => $course) {
         uasort($course->recentactivity, create_function('$a, $b', 'return ($a->timestamp == $b->timestamp) ? 0 : (($a->timestamp > $b->timestamp) ? -1 : 1);'));
         $recentactivity[$courseid]->recentactivity = array_values($course->recentactivity);
     }
     if ($currentuser !== false) {
         \core\session\manager::set_user($currentuser);
     }
     return $recentactivity;
 }