Skip to content

Commit

Permalink
Merge branch 'MDL-63902-34' of git://github.com/andrewnicols/moodle i…
Browse files Browse the repository at this point in the history
…nto MOODLE_34_STABLE
  • Loading branch information
junpataleta committed Nov 8, 2018
2 parents ce6f4fe + 0878ecb commit d59a7b7
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 21 deletions.
24 changes: 15 additions & 9 deletions admin/tool/dataprivacy/classes/expired_contexts_manager.php
Expand Up @@ -786,11 +786,13 @@ public static function is_context_expired(\context $context) : bool {
$parents = $context->get_parent_contexts(true);
foreach ($parents as $parent) {
if ($parent instanceof \context_course) {
// This is a context within a course. Check whether _this context_ is expired as a function of a course.
return self::is_course_context_expired($context);
}

if ($parent instanceof \context_user) {
return self::are_user_context_dependencies_expired($context);
// This is a context within a user. Check whether the _user_ has expired.
return self::are_user_context_dependencies_expired($parent);
}
}

Expand All @@ -810,12 +812,13 @@ protected static function is_course_expired(\stdClass $course) : bool {
}

/**
* Determine whether the supplied course context has expired.
* Determine whether the supplied course-related context has expired.
* Note: This is not necessarily a _course_ context, but a context which is _within_ a course.
*
* @param \context_course $context
* @param \context $context
* @return bool
*/
protected static function is_course_context_expired(\context_course $context) : bool {
protected static function is_course_context_expired(\context $context) : bool {
$expiryrecords = self::get_nested_expiry_info_for_courses($context->path);

return !empty($expiryrecords[$context->path]) && $expiryrecords[$context->path]->info->is_fully_expired();
Expand Down Expand Up @@ -890,25 +893,28 @@ public static function is_context_expired_or_unprotected_for_user(\context $cont
$parents = $context->get_parent_contexts(true);
foreach ($parents as $parent) {
if ($parent instanceof \context_course) {
return self::is_course_context_expired_or_unprotected_for_user($parent, $user);
// This is a context within a course. Check whether _this context_ is expired as a function of a course.
return self::is_course_context_expired_or_unprotected_for_user($context, $user);
}

if ($parent instanceof \context_user) {
return self::are_user_context_dependencies_expired($context);
// This is a context within a user. Check whether the _user_ has expired.
return self::are_user_context_dependencies_expired($parent);
}
}

return false;
}

/**
* Determine whether the supplied course context has expired, or is unprotected.
* Determine whether the supplied course-related context has expired, or is unprotected.
* Note: This is not necessarily a _course_ context, but a context which is _within_ a course.
*
* @param \context_course $context
* @param \context $context
* @param \stdClass $user
* @return bool
*/
protected static function is_course_context_expired_or_unprotected_for_user(\context_course $context, \stdClass $user) {
protected static function is_course_context_expired_or_unprotected_for_user(\context $context, \stdClass $user) {
$expiryrecords = self::get_nested_expiry_info_for_courses($context->path);

$info = $expiryrecords[$context->path]->info;
Expand Down
81 changes: 69 additions & 12 deletions admin/tool/dataprivacy/tests/expired_contexts_test.php
Expand Up @@ -97,7 +97,7 @@ protected function create_and_set_purpose_for_contextlevel(string $retention, in
api::set_contextlevel($record);
} else {
list($purposevar, ) = data_registry::var_names_from_context(
\context_helper::get_class_for_level(CONTEXT_COURSE)
\context_helper::get_class_for_level($contextlevel)
);
set_config($purposevar, $purpose->get('id'), 'tool_dataprivacy');
}
Expand Down Expand Up @@ -1719,18 +1719,17 @@ public function test_process_course_context_updated() {
$manager->set_progress(new \null_progress_trace());
$manager->method('get_privacy_manager')->willReturn($mockprivacymanager);

$purposes->course->set('retentionperiod', 'P5Y');
$purposes->course->save();
// Changing the retention period to a longer period will remove the expired_context record.
$purposes->activity->set('retentionperiod', 'P5Y');
$purposes->activity->save();

list($processedcourses, $processedusers) = $manager->process_approved_deletions();

$this->assertEquals(0, $processedcourses);
$this->assertEquals(0, $processedusers);

$this->expectException('dml_missing_record_exception');
$updatedcontext = new expired_context($expiredcontext->get('id'));

// No change - we just can't process it until the children have finished.
$this->assertEquals(expired_context::STATUS_APPROVED, $updatedcontext->get('status'));
}

/**
Expand Down Expand Up @@ -2186,8 +2185,6 @@ protected function get_last_block_on_page($page) {
* Test the is_context_expired functions when supplied with the system context.
*/
public function test_is_context_expired_system() {
global $DB;

$this->resetAfterTest();
$this->setup_basics('PT1H', 'PT1H', 'P1D');
$user = $this->getDataGenerator()->create_user(['lastaccess' => time() - YEARSECS]);
Expand All @@ -2197,12 +2194,38 @@ public function test_is_context_expired_system() {
expired_contexts_manager::is_context_expired_or_unprotected_for_user(\context_system::instance(), $user));
}

/**
* Test the is_context_expired functions when supplied with a block in the user context.
*
* Children of a user context always follow the user expiry rather than any context level defaults (e.g. at the
* block level.
*/
public function test_is_context_expired_user_block() {
$this->resetAfterTest();

$purposes = $this->setup_basics('PT1H', 'PT1H', 'P1D');
$purposes->block = $this->create_and_set_purpose_for_contextlevel('P5Y', CONTEXT_BLOCK);

$user = $this->getDataGenerator()->create_user(['lastaccess' => time() - YEARSECS]);
$this->setUser($user);
$block = $this->create_user_block('Title', 'Content', FORMAT_PLAIN);
$blockcontext = \context_block::instance($block->instance->id);
$this->setUser();

// Protected flags have no bearing on expiry of user subcontexts.
$this->assertTrue(expired_contexts_manager::is_context_expired($blockcontext));

$purposes->block->set('protected', 1)->save();
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($blockcontext, $user));

$purposes->block->set('protected', 0)->save();
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($blockcontext, $user));
}

/**
* Test the is_context_expired functions when supplied with an expired course.
*/
public function test_is_context_expired_course_expired() {
global $DB;

$this->resetAfterTest();

$purposes = $this->setup_basics('PT1H', 'PT1H', 'P1D');
Expand All @@ -2226,8 +2249,6 @@ public function test_is_context_expired_course_expired() {
* Test the is_context_expired functions when supplied with an unexpired course.
*/
public function test_is_context_expired_course_unexpired() {
global $DB;

$this->resetAfterTest();

$purposes = $this->setup_basics('PT1H', 'PT1H', 'P1D');
Expand All @@ -2247,6 +2268,42 @@ public function test_is_context_expired_course_unexpired() {
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($coursecontext, $user));
}

/**
* Test the is_context_expired functions when supplied with an unexpired course and a child context in the course which is protected.
*
* When a child context has a specific purpose set, then that purpose should be respected with respect to the
* course.
*
* If the course is still within the expiry period for the child context, then that child's protected flag should be
* respected, even when the course may have expired.
*/
public function test_is_child_context_expired_course_unexpired_with_child() {
$this->resetAfterTest();

$purposes = $this->setup_basics('PT1H', 'PT1H', 'P1D', 'P1D');
$purposes->course->set('protected', 0)->save();
$purposes->activity->set('protected', 1)->save();

$user = $this->getDataGenerator()->create_user(['lastaccess' => time() - YEARSECS]);
$course = $this->getDataGenerator()->create_course(['startdate' => time() - YEARSECS, 'enddate' => time() + WEEKSECS]);
$forum = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);

$coursecontext = \context_course::instance($course->id);
$cm = get_coursemodule_from_instance('forum', $forum->id);
$forumcontext = \context_module::instance($cm->id);

$this->getDataGenerator()->enrol_user($user->id, $course->id, 'student');

$this->assertFalse(expired_contexts_manager::is_context_expired($coursecontext));
$this->assertFalse(expired_contexts_manager::is_context_expired($forumcontext));

$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($coursecontext, $user));
$this->assertFalse(expired_contexts_manager::is_context_expired_or_unprotected_for_user($forumcontext, $user));

$purposes->activity->set('protected', 0)->save();
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($forumcontext, $user));
}

/**
* Test the is_context_expired functions when supplied with an expired course which has role overrides.
*/
Expand Down

0 comments on commit d59a7b7

Please sign in to comment.