MDL-46099 session: fix use of references for session globals

This reverses the references used for global $USER and $SESSION,
the reason is that PHP does not allow references to references.
$USER is a reference to $GLOBALS['USER'] which means we cannot
put any references to it. Solution is to store the current user and session
objects in $GLOBALS['USER'] and $GLOBALS['SESSIOn'] are reference
them in $_SESSION.

This patch makes the session code behave the same way in CLI,
phpunit and normal web requests - this allows use to finally
unit test most aspects of the session code in Moodle.
This commit is contained in:
Petr Skoda
2014-07-01 08:38:00 +12:00
parent 7a4832ecb9
commit 2e00d01db4
13 changed files with 431 additions and 92 deletions
+115 -9
View File
@@ -41,38 +41,122 @@ class core_session_manager_testcase extends advanced_testcase {
$this->assertDebuggingCalled('Session was already started!', DEBUG_DEVELOPER);
}
public function test_init_empty_session() {
global $SESSION, $USER;
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$SESSION->test = true;
$this->assertTrue($GLOBALS['SESSION']->test);
$this->assertTrue($_SESSION['SESSION']->test);
\core\session\manager::set_user($user);
$this->assertSame($user, $USER);
$this->assertSame($user, $GLOBALS['USER']);
$this->assertSame($user, $_SESSION['USER']);
\core\session\manager::init_empty_session();
$this->assertInstanceOf('stdClass', $SESSION);
$this->assertEmpty((array)$SESSION);
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$this->assertInstanceOf('stdClass', $USER);
$this->assertEquals(array('id' => 0, 'mnethostid' => 1), (array)$USER, '', 0, 10, true);
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
// Now test how references work.
$GLOBALS['SESSION'] = new \stdClass();
$GLOBALS['SESSION']->test = true;
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$SESSION = new \stdClass();
$SESSION->test2 = true;
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$_SESSION['SESSION'] = new stdClass();
$_SESSION['SESSION']->test3 = true;
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$GLOBALS['USER'] = new \stdClass();
$GLOBALS['USER']->test = true;
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
$USER = new \stdClass();
$USER->test2 = true;
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
$_SESSION['USER'] = new stdClass();
$_SESSION['USER']->test3 = true;
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
}
public function test_set_user() {
global $USER;
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$this->setUser(0);
$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);
}
public function test_login_user() {
global $USER;
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$this->setUser(0);
$this->assertEquals(0, $USER->id);
$user = $this->getDataGenerator()->create_user();
@\core\session\manager::login_user($user); // Ignore header error messages.
$this->assertEquals($user->id, $USER->id);
$this->assertObjectNotHasAttribute('description', $user);
$this->assertObjectNotHasAttribute('password', $user);
$this->assertSame($user, $GLOBALS['USER']);
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
}
public function test_terminate_current() {
global $USER;
global $USER, $SESSION;
$this->resetAfterTest();
// This can not be tested much without real session...
$this->setAdminUser();
\core\session\manager::terminate_current();
$this->assertEquals(0, $USER->id);
$this->assertInstanceOf('stdClass', $SESSION);
$this->assertEmpty((array)$SESSION);
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$this->assertInstanceOf('stdClass', $USER);
$this->assertEquals(array('id' => 0, 'mnethostid' => 1), (array)$USER, '', 0, 10, true);
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
}
public function test_write_close() {
@@ -84,6 +168,9 @@ class core_session_manager_testcase extends advanced_testcase {
$userid = $USER->id;
\core\session\manager::write_close();
$this->assertSame($userid, $USER->id);
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
}
public function test_session_exists() {
@@ -293,22 +380,37 @@ class core_session_manager_testcase extends advanced_testcase {
* @copyright 2103 Rajesh Taneja <[email protected]>
*/
public function test_loginas() {
global $USER;
global $USER, $SESSION;
$this->resetAfterTest();
// Set current user as Admin user and save it for later use.
$this->setAdminUser();
$adminuser = $USER;
// Create a new user and try admin loginas this user.
$adminsession = $SESSION;
$user = $this->getDataGenerator()->create_user();
$_SESSION['extra'] = true;
// Try admin loginas this user in system context.
$this->assertObjectNotHasAttribute('realuser', $USER);
\core\session\manager::loginas($user->id, context_system::instance());
$this->assertSame($user->id, $USER->id);
$this->assertSame(context_system::instance(), $USER->loginascontext);
$this->assertSame($adminuser->id, $USER->realuser);
$this->assertSame($GLOBALS['USER'], $_SESSION['USER']);
$this->assertSame($GLOBALS['USER'], $USER);
$this->assertNotSame($adminuser, $_SESSION['REALUSER']);
$this->assertEquals($adminuser, $_SESSION['REALUSER']);
$this->assertSame($GLOBALS['SESSION'], $_SESSION['SESSION']);
$this->assertSame($GLOBALS['SESSION'], $SESSION);
$this->assertNotSame($adminsession, $_SESSION['REALSESSION']);
$this->assertEquals($adminsession, $_SESSION['REALSESSION']);
$this->assertArrayNotHasKey('extra', $_SESSION);
// Set user as current user and login as admin user in course context.
\core\session\manager::init_empty_session();
$this->setUser($user);
$this->assertNotEquals($adminuser->id, $USER->id);
$course = $this->getDataGenerator()->create_course();
@@ -358,6 +460,9 @@ class core_session_manager_testcase extends advanced_testcase {
$user2 = $this->getDataGenerator()->create_user();
$this->setUser($user1);
$normal = \core\session\manager::get_realuser();
$this->assertSame($GLOBALS['USER'], $normal);
\core\session\manager::loginas($user2->id, context_system::instance());
$real = \core\session\manager::get_realuser();
@@ -370,5 +475,6 @@ class core_session_manager_testcase extends advanced_testcase {
unset($user1->sesskey);
$this->assertEquals($real, $user1);
$this->assertSame($_SESSION['REALUSER'], $real);
}
}