Esempio n. 1
0
 /**
  * Tests constructing and using date condition as part of tree.
  */
 public function test_in_tree()
 {
     global $SITE, $USER, $CFG;
     $this->resetAfterTest();
     $this->setAdminUser();
     // Set server timezone for test. (Important as otherwise the timezone
     // could be anything - this is modified by other unit tests, too.)
     $this->setTimezone('UTC');
     // SEt user to GMT+5.
     $USER->timezone = 5;
     // Construct tree with date condition.
     $time = strtotime('2014-02-18 14:20:00 GMT');
     $structure = (object) array('op' => '|', 'show' => true, 'c' => array((object) array('type' => 'date', 'd' => '>=', 't' => $time)));
     $tree = new \core_availability\tree($structure);
     $info = new \core_availability\mock_info();
     // Check if available (when not available).
     condition::set_current_time_for_test($time - 1);
     $information = '';
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertFalse($result->is_available());
     $information = $tree->get_result_information($info, $result);
     // Note: PM is normally upper-case, but an issue with PHP on Mac means
     // that on that platform, it is reported lower-case.
     $this->assertRegExp('~from.*18 February 2014, 7:20 (PM|pm)~', $information);
     // Check if available (when available).
     condition::set_current_time_for_test($time);
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertTrue($result->is_available());
     $information = $tree->get_result_information($info, $result);
     $this->assertEquals('', $information);
 }
Esempio n. 2
0
 /**
  * Tests constructing and using condition as part of tree.
  */
 public function test_in_tree()
 {
     global $USER, $CFG;
     $this->resetAfterTest();
     $this->setAdminUser();
     // Create course with completion turned on and a Page.
     $CFG->enablecompletion = true;
     $CFG->enableavailability = true;
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('enablecompletion' => 1));
     $page = $generator->get_plugin_generator('mod_page')->create_instance(array('course' => $course->id, 'completion' => COMPLETION_TRACKING_MANUAL));
     $modinfo = get_fast_modinfo($course);
     $cm = $modinfo->get_cm($page->cmid);
     $info = new \core_availability\mock_info($course, $USER->id);
     $structure = (object) array('op' => '|', 'show' => true, 'c' => array((object) array('type' => 'completion', 'cm' => (int) $cm->id, 'e' => COMPLETION_COMPLETE)));
     $tree = new \core_availability\tree($structure);
     // Initial check (user has not completed activity).
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertFalse($result->is_available());
     // Mark activity complete.
     $completion = new completion_info($course);
     $completion->update_state($cm, COMPLETION_COMPLETE);
     // Now it's true!
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertTrue($result->is_available());
 }
Esempio n. 3
0
 /**
  * Tests constructing and using date condition as part of tree.
  */
 public function test_in_tree()
 {
     global $USER;
     $this->setAdminUser();
     $info = new \core_availability\mock_info();
     $structure = (object) array('op' => '|', 'show' => true, 'c' => array((object) array('type' => 'profile', 'op' => condition::OP_IS_EQUAL_TO, 'cf' => 'frogtype', 'v' => 'tree')));
     $tree = new \core_availability\tree($structure);
     // Initial check (user does not have custom field).
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertFalse($result->is_available());
     // Set field.
     $this->set_field($USER->id, 'tree');
     // Now it's true!
     $result = $tree->check_available(false, $info, true, $USER->id);
     $this->assertTrue($result->is_available());
 }
function content_unlock_satisfies_conditions($conditions, $courseid, $userid)
{
    global $DB;
    if (isset($conditions)) {
        $tree = new \core_availability\tree(json_decode($conditions));
        $course = $DB->get_record('course', array('id' => $courseid));
        $info = new content_unlock_conditions_info($course);
        $result = $tree->check_available(false, $info, true, $userid);
        return $result->is_available();
    }
    return true;
}
Esempio n. 5
0
/**
 * Update the module info.
 * This function doesn't check the user capabilities. It updates the course module and the module instance.
 * Then execute common action to create/update module process (trigger event, rebuild cache, save plagiarism settings...).
 *
 * @param object $cm course module
 * @param object $moduleinfo module info
 * @param object $course course of the module
 * @param object $mform - the mform is required by some specific module in the function MODULE_update_instance(). This is due to a hack in this function.
 * @return array list of course module and module info.
 */
function update_moduleinfo($cm, $moduleinfo, $course, $mform = null)
{
    global $DB, $CFG;
    // Attempt to include module library before we make any changes to DB.
    include_modulelib($moduleinfo->modulename);
    $moduleinfo->course = $course->id;
    $moduleinfo = set_moduleinfo_defaults($moduleinfo);
    if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) {
        $moduleinfo->groupmode = $cm->groupmode;
        // Keep original.
    }
    // Update course module first.
    $cm->groupmode = $moduleinfo->groupmode;
    if (isset($moduleinfo->groupingid)) {
        $cm->groupingid = $moduleinfo->groupingid;
    }
    $completion = new completion_info($course);
    if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
        // Update completion settings.
        $cm->completion = $moduleinfo->completion;
        $cm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber;
        $cm->completionview = $moduleinfo->completionview;
        $cm->completionexpected = $moduleinfo->completionexpected;
    }
    if (!empty($CFG->enableavailability)) {
        // This code is used both when submitting the form, which uses a long
        // name to avoid clashes, and by unit test code which uses the real
        // name in the table.
        if (property_exists($moduleinfo, 'availabilityconditionsjson')) {
            if ($moduleinfo->availabilityconditionsjson !== '') {
                $cm->availability = $moduleinfo->availabilityconditionsjson;
            } else {
                $cm->availability = null;
            }
        } else {
            if (property_exists($moduleinfo, 'availability')) {
                $cm->availability = $moduleinfo->availability;
            }
        }
        // If there is any availability data, verify it.
        if ($cm->availability) {
            $tree = new \core_availability\tree(json_decode($cm->availability));
            // Save time and database space by setting null if the only data
            // is an empty tree.
            if ($tree->is_empty()) {
                $cm->availability = null;
            }
        }
    }
    if (isset($moduleinfo->showdescription)) {
        $cm->showdescription = $moduleinfo->showdescription;
    } else {
        $cm->showdescription = 0;
    }
    $DB->update_record('course_modules', $cm);
    $modcontext = context_module::instance($moduleinfo->coursemodule);
    // Update embedded links and save files.
    if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true)) {
        $moduleinfo->intro = file_save_draft_area_files($moduleinfo->introeditor['itemid'], $modcontext->id, 'mod_' . $moduleinfo->modulename, 'intro', 0, array('subdirs' => true), $moduleinfo->introeditor['text']);
        $moduleinfo->introformat = $moduleinfo->introeditor['format'];
        unset($moduleinfo->introeditor);
    }
    $updateinstancefunction = $moduleinfo->modulename . "_update_instance";
    if (!$updateinstancefunction($moduleinfo, $mform)) {
        print_error('cannotupdatemod', '', course_get_url($course, $cw->section), $moduleinfo->modulename);
    }
    // Make sure visibility is set correctly (in particular in calendar).
    if (has_capability('moodle/course:activityvisibility', $modcontext)) {
        set_coursemodule_visible($moduleinfo->coursemodule, $moduleinfo->visible);
    }
    if (isset($moduleinfo->cmidnumber)) {
        // Label.
        // Set cm idnumber - uniqueness is already verified by form validation.
        set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber);
    }
    // Now that module is fully updated, also update completion data if required.
    // (this will wipe all user completion data and recalculate it)
    if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
        $completion->reset_all_state($cm);
    }
    $cm->name = $moduleinfo->name;
    \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
    $moduleinfo = edit_module_post_actions($moduleinfo, $course);
    return array($cm, $moduleinfo);
}
Esempio n. 6
0
/**
 * Update the module info.
 * This function doesn't check the user capabilities. It updates the course module and the module instance.
 * Then execute common action to create/update module process (trigger event, rebuild cache, save plagiarism settings...).
 *
 * @param object $cm course module
 * @param object $moduleinfo module info
 * @param object $course course of the module
 * @param object $mform - the mform is required by some specific module in the function MODULE_update_instance(). This is due to a hack in this function.
 * @return array list of course module and module info.
 */
function update_moduleinfo($cm, $moduleinfo, $course, $mform = null)
{
    global $DB, $CFG;
    $data = new stdClass();
    if ($mform) {
        $data = $mform->get_data();
    }
    // Attempt to include module library before we make any changes to DB.
    include_modulelib($moduleinfo->modulename);
    $moduleinfo->course = $course->id;
    $moduleinfo = set_moduleinfo_defaults($moduleinfo);
    if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) {
        $moduleinfo->groupmode = $cm->groupmode;
        // Keep original.
    }
    // Update course module first.
    $cm->groupmode = $moduleinfo->groupmode;
    if (isset($moduleinfo->groupingid)) {
        $cm->groupingid = $moduleinfo->groupingid;
    }
    $completion = new completion_info($course);
    if ($completion->is_enabled()) {
        // Completion settings that would affect users who have already completed
        // the activity may be locked; if so, these should not be updated.
        if (!empty($moduleinfo->completionunlocked)) {
            $cm->completion = $moduleinfo->completion;
            $cm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber;
            $cm->completionview = $moduleinfo->completionview;
        }
        // The expected date does not affect users who have completed the activity,
        // so it is safe to update it regardless of the lock status.
        $cm->completionexpected = $moduleinfo->completionexpected;
    }
    if (!empty($CFG->enableavailability)) {
        // This code is used both when submitting the form, which uses a long
        // name to avoid clashes, and by unit test code which uses the real
        // name in the table.
        if (property_exists($moduleinfo, 'availabilityconditionsjson')) {
            if ($moduleinfo->availabilityconditionsjson !== '') {
                $cm->availability = $moduleinfo->availabilityconditionsjson;
            } else {
                $cm->availability = null;
            }
        } else {
            if (property_exists($moduleinfo, 'availability')) {
                $cm->availability = $moduleinfo->availability;
            }
        }
        // If there is any availability data, verify it.
        if ($cm->availability) {
            $tree = new \core_availability\tree(json_decode($cm->availability));
            // Save time and database space by setting null if the only data
            // is an empty tree.
            if ($tree->is_empty()) {
                $cm->availability = null;
            }
        }
    }
    if (isset($moduleinfo->showdescription)) {
        $cm->showdescription = $moduleinfo->showdescription;
    } else {
        $cm->showdescription = 0;
    }
    $DB->update_record('course_modules', $cm);
    $modcontext = context_module::instance($moduleinfo->coursemodule);
    // Update embedded links and save files.
    if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true)) {
        $moduleinfo->intro = file_save_draft_area_files($moduleinfo->introeditor['itemid'], $modcontext->id, 'mod_' . $moduleinfo->modulename, 'intro', 0, array('subdirs' => true), $moduleinfo->introeditor['text']);
        $moduleinfo->introformat = $moduleinfo->introeditor['format'];
        unset($moduleinfo->introeditor);
    }
    // Get the a copy of the grade_item before it is modified incase we need to scale the grades.
    $oldgradeitem = null;
    $newgradeitem = null;
    if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') {
        // Fetch the grade item before it is updated.
        $oldgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course));
    }
    $updateinstancefunction = $moduleinfo->modulename . "_update_instance";
    if (!$updateinstancefunction($moduleinfo, $mform)) {
        print_error('cannotupdatemod', '', course_get_url($course, $cm->section), $moduleinfo->modulename);
    }
    // This needs to happen AFTER the grademin/grademax have already been updated.
    if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') {
        // Get the grade_item after the update call the activity to scale the grades.
        $newgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course));
        if ($newgradeitem && $oldgradeitem->gradetype == GRADE_TYPE_VALUE && $newgradeitem->gradetype == GRADE_TYPE_VALUE) {
            $params = array($course, $cm, $oldgradeitem->grademin, $oldgradeitem->grademax, $newgradeitem->grademin, $newgradeitem->grademax);
            if (!component_callback('mod_' . $moduleinfo->modulename, 'rescale_activity_grades', $params)) {
                print_error('cannotreprocessgrades', '', course_get_url($course, $cm->section), $moduleinfo->modulename);
            }
        }
    }
    // Make sure visibility is set correctly (in particular in calendar).
    if (has_capability('moodle/course:activityvisibility', $modcontext)) {
        set_coursemodule_visible($moduleinfo->coursemodule, $moduleinfo->visible);
    }
    if (isset($moduleinfo->cmidnumber)) {
        // Label.
        // Set cm idnumber - uniqueness is already verified by form validation.
        set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber);
    }
    // Update module tags.
    if (core_tag_tag::is_enabled('core', 'course_modules') && isset($moduleinfo->tags)) {
        core_tag_tag::set_item_tags('core', 'course_modules', $moduleinfo->coursemodule, $modcontext, $moduleinfo->tags);
    }
    // Now that module is fully updated, also update completion data if required.
    // (this will wipe all user completion data and recalculate it)
    if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
        $completion->reset_all_state($cm);
    }
    $cm->name = $moduleinfo->name;
    \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
    $moduleinfo = edit_module_post_actions($moduleinfo, $course);
    return array($cm, $moduleinfo);
}
Esempio n. 7
0
 /**
  * Tests the filter_users function.
  */
 public function test_filter_users()
 {
     $info = new \core_availability\mock_info();
     $checker = new capability_checker($info->get_context());
     // Don't need to create real users in database, just use these ids.
     $users = array(1 => null, 2 => null, 3 => null);
     // Test basic tree with one condition that doesn't filter.
     $structure = self::tree(array(self::mock(array())));
     $tree = new \core_availability\tree($structure);
     $result = $tree->filter_user_list($users, false, $info, $checker);
     ksort($result);
     $this->assertEquals(array(1, 2, 3), array_keys($result));
     // Now a tree with one condition that filters.
     $structure = self::tree(array(self::mock(array('filter' => array(2, 3)))));
     $tree = new \core_availability\tree($structure);
     $result = $tree->filter_user_list($users, false, $info, $checker);
     ksort($result);
     $this->assertEquals(array(2, 3), array_keys($result));
     // Tree with two conditions that both filter (|).
     $structure = self::tree(array(self::mock(array('filter' => array(3))), self::mock(array('filter' => array(1)))));
     $tree = new \core_availability\tree($structure);
     $result = $tree->filter_user_list($users, false, $info, $checker);
     ksort($result);
     $this->assertEquals(array(1, 3), array_keys($result));
     // Tree with two condition that both filter (&).
     $structure = self::tree(array(self::mock(array('filter' => array(2, 3))), self::mock(array('filter' => array(1, 2)))), '&', false, array(true, true));
     $tree = new \core_availability\tree($structure);
     $result = $tree->filter_user_list($users, false, $info, $checker);
     ksort($result);
     $this->assertEquals(array(2), array_keys($result));
     // Tree with child tree with NOT condition.
     $structure = self::tree(array(self::tree(self::mock(array('filter' => array(1))), '!&', null)));
     $tree = new \core_availability\tree($structure);
     $result = $tree->filter_user_list($users, false, $info, $checker);
     ksort($result);
     $this->assertEquals(array(2, 3), array_keys($result));
 }