public function get_description($full, $not, \core_availability\info $info)
 {
     // Get name for module.
     $modinfo = $info->get_modinfo();
     if (!isset($this->expectedpublicprivate)) {
         $modname = get_string('missing', 'availability_publicprivate');
     }
     //        // Work out which lang string to use.
     //        if ($not) {
     //            // Convert NOT strings to use the equivalent where possible.
     //            switch ($this->expectedpublicprivate) {
     //                case COMPLETION_INCOMPLETE:
     //                    $str = 'requires_' . self::get_lang_string_keyword(COMPLETION_COMPLETE);
     //                    break;
     //                case COMPLETION_COMPLETE:
     //                    $str = 'requires_' . self::get_lang_string_keyword(COMPLETION_INCOMPLETE);
     //                    break;
     //                default:
     //                    // The other two cases do not have direct opposites.
     //                    $str = 'requires_not_' . self::get_lang_string_keyword($this->expectedpublicprivate);
     //                    break;
     //            }
     //        } else {
     //            $str = 'requires_' . self::get_lang_string_keyword($this->expectedpublicprivate);
     //        }
     if ($this->expectedpublicprivate === PUBLICPRIVATE_PRIVATE) {
         $str = 'requires_private';
     } else {
         $str = 'requires_public';
     }
     return get_string($str, 'availability_publicprivate');
 }
 /**
  * Determines whether a particular item is currently available
  * according to this availability condition.
  *
  * @param bool $not Set true if we are inverting the condition.
  * @param info $info Item we're checking.
  * @param bool $grabthelot Performance hint: if true, caches information
  *   required for all course-modules, to make the front page and similar
  *   pages work more quickly (works only for current user).
  * @param int $userid User ID to check availability for.
  * @return bool True if available.
  */
 public function is_available($not, \core_availability\info $info, $grabthelot, $userid)
 {
     $available = false;
     if ($this->requiredlvl > 0) {
         $currentlvl = $this->get_user_level($info->get_course()->id, $userid);
         if ($currentlvl >= $this->requiredlvl) {
             $available = true;
         } else {
             $available = false;
         }
         if ($not) {
             $available = !$available;
         }
     }
     return $available;
 }
 public function get_description($full, $not, \core_availability\info $info)
 {
     $course = $info->get_course();
     // String depends on type of requirement. We are coy about
     // the actual numbers, in case grades aren't released to
     // students.
     if (is_null($this->min) && is_null($this->max)) {
         $string = 'any';
     } else {
         if (is_null($this->max)) {
             $string = 'min';
         } else {
             if (is_null($this->min)) {
                 $string = 'max';
             } else {
                 $string = 'range';
             }
         }
     }
     if ($not) {
         // The specific strings don't make as much sense with 'not'.
         if ($string === 'any') {
             $string = 'notany';
         } else {
             $string = 'notgeneral';
         }
     }
     $name = self::get_cached_grade_name($course->id, $this->gradeitemid);
     return get_string('requires_' . $string, 'availability_grade', $name);
 }
 public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name)
 {
     // Update the date, if restoring with changed date.
     $dateoffset = \core_availability\info::get_restore_date_offset($restoreid);
     if ($dateoffset) {
         $this->time += $dateoffset;
         return true;
     }
     return false;
 }
Example #5
0
 /**
  * Tests the is_available and get_description functions.
  */
 public function test_usage()
 {
     global $CFG, $DB;
     require_once $CFG->dirroot . '/mod/assign/locallib.php';
     $this->resetAfterTest();
     // Create course with completion turned on.
     $CFG->enablecompletion = true;
     $CFG->enableavailability = true;
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('enablecompletion' => 1));
     $user = $generator->create_user();
     $generator->enrol_user($user->id, $course->id);
     $this->setUser($user);
     // Create a Page with manual completion for basic checks.
     $page = $generator->get_plugin_generator('mod_page')->create_instance(array('course' => $course->id, 'name' => 'Page!', 'completion' => COMPLETION_TRACKING_MANUAL));
     // Create an assignment - we need to have something that can be graded
     // so as to test the PASS/FAIL states. Set it up to be completed based
     // on its grade item.
     $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Assign!', 'completion' => COMPLETION_TRACKING_AUTOMATIC));
     $DB->set_field('course_modules', 'completiongradeitemnumber', 0, array('id' => $assignrow->cmid));
     $assign = new assign(context_module::instance($assignrow->cmid), false, false);
     // Get basic details.
     $modinfo = get_fast_modinfo($course);
     $pagecm = $modinfo->get_cm($page->cmid);
     $assigncm = $assign->get_course_module();
     $info = new \core_availability\mock_info($course, $user->id);
     // COMPLETE state (false), positive and NOT.
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // INCOMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     // Mark page complete.
     $completion = new completion_info($course);
     $completion->update_state($pagecm, COMPLETION_COMPLETE);
     // COMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     // INCOMPLETE state (false).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // We are going to need the grade item so that we can get pass/fails.
     $gradeitem = $assign->get_grade_item();
     grade_object::set_properties($gradeitem, array('gradepass' => 50.0));
     $gradeitem->update();
     // With no grade, it should return true for INCOMPLETE and false for
     // the other three.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Check $information for COMPLETE_PASS and _FAIL as we haven't yet.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Change the grade to be complete and failed.
     self::set_grade($assignrow, $user->id, 40);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and failed~', $information);
     // Now change it to pass.
     self::set_grade($assignrow, $user->id, 60);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and passed~', $information);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Simulate deletion of an activity by using an invalid cmid. These
     // conditions always fail, regardless of NOT flag or INCOMPLETE.
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~(Missing activity).*is marked complete~', $information);
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
 }
 /**
  * Obtains a string describing this restriction (whether or not
  * it actually applies).
  *
  * @param bool $full Set true if this is the 'full information' view
  * @param bool $not Set true if we are inverting the condition
  * @param info $info Item we're checking
  * @return string Information string (for admin) about all restrictions on
  *   this item
  */
 public function get_description($full, $not, \core_availability\info $info)
 {
     global $USER;
     $logmanager = get_log_manager();
     if (!($readers = $logmanager->get_readers('core\\log\\sql_reader'))) {
         // Should be using 2.8, use old class.
         $readers = $logmanager->get_readers('core\\log\\sql_select_reader');
     }
     $reader = array_pop($readers);
     $context = $info->get_context();
     $viewscount = $reader->get_events_select_count('contextid = :context AND userid = :userid AND crud = :crud', array('context' => $context->id, 'userid' => $USER->id, 'crud' => 'r'));
     $a = new \stdclass();
     $a->viewslimit = $this->viewslimit;
     $a->viewscount = $viewscount;
     if ($not) {
         return get_string('eithernotdescription', 'availability_maxviews', $a);
     } else {
         return get_string('eitherdescription', 'availability_maxviews', $a);
     }
 }
Example #7
0
 /**
  * Process the legacy availability fields table record. This table does not
  * exist in Moodle 2.7+ but we still support restore.
  *
  * @param stdClass $data Record data
  */
 protected function process_availability_field($data)
 {
     global $DB;
     $data = (object) $data;
     // Mark it is as passed by default
     $passed = true;
     $customfieldid = null;
     // If a customfield has been used in order to pass we must be able to match an existing
     // customfield by name (data->customfield) and type (data->customfieldtype)
     if (!empty($data->customfield) xor !empty($data->customfieldtype)) {
         // xor is sort of uncommon. If either customfield is null or customfieldtype is null BUT not both.
         // If one is null but the other isn't something clearly went wrong and we'll skip this condition.
         $passed = false;
     } else {
         if (!empty($data->customfield)) {
             $params = array('shortname' => $data->customfield, 'datatype' => $data->customfieldtype);
             $customfieldid = $DB->get_field('user_info_field', 'id', $params);
             $passed = $customfieldid !== false;
         }
     }
     if ($passed) {
         // Create the object to insert into the database
         $availfield = new stdClass();
         $availfield->coursemoduleid = $this->task->get_moduleid();
         // Lets add the availability cmid
         $availfield->userfield = $data->userfield;
         $availfield->customfieldid = $customfieldid;
         $availfield->operator = $data->operator;
         $availfield->value = $data->value;
         // Get showavailability option.
         $showrec = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'module_showavailability', $availfield->coursemoduleid);
         if (!$showrec) {
             // Should not happen.
             throw new coding_exception('No matching showavailability record');
         }
         $show = $showrec->info->showavailability;
         // The $availfieldobject is now in the format used in the old
         // system. Interpret this and convert to new system.
         $currentvalue = $DB->get_field('course_modules', 'availability', array('id' => $availfield->coursemoduleid), MUST_EXIST);
         $newvalue = \core_availability\info::add_legacy_availability_field_condition($currentvalue, $availfield, $show);
         $DB->set_field('course_modules', 'availability', $newvalue, array('id' => $availfield->coursemoduleid));
     }
 }
 public function get_description($full, $not, \core_availability\info $info)
 {
     // Get name for module.
     $modinfo = $info->get_modinfo();
     if (!array_key_exists($this->cmid, $modinfo->cms)) {
         $modname = get_string('missing', 'availability_completion');
     } else {
         $modname = '<AVAILABILITY_CMNAME_' . $modinfo->cms[$this->cmid]->id . '/>';
     }
     // Work out which lang string to use.
     if ($not) {
         // Convert NOT strings to use the equivalent where possible.
         switch ($this->expectedcompletion) {
             case COMPLETION_INCOMPLETE:
                 $str = 'requires_' . self::get_lang_string_keyword(COMPLETION_COMPLETE);
                 break;
             case COMPLETION_COMPLETE:
                 $str = 'requires_' . self::get_lang_string_keyword(COMPLETION_INCOMPLETE);
                 break;
             default:
                 // The other two cases do not have direct opposites.
                 $str = 'requires_not_' . self::get_lang_string_keyword($this->expectedcompletion);
                 break;
         }
     } else {
         $str = 'requires_' . self::get_lang_string_keyword($this->expectedcompletion);
     }
     return get_string($str, 'availability_completion', $modname);
 }
Example #9
0
 /**
  * Renders HTML to show course module availability information (for someone who isn't allowed
  * to see the activity itself, or for staff)
  *
  * @param cm_info $mod
  * @param array $displayoptions
  * @return string
  */
 public function course_section_cm_availability(cm_info $mod, $displayoptions = array())
 {
     global $CFG;
     if (!$mod->uservisible) {
         // this is a student who is not allowed to see the module but might be allowed
         // to see availability info (i.e. "Available from ...")
         if (!empty($mod->availableinfo)) {
             $formattedinfo = \core_availability\info::format_info($mod->availableinfo, $mod->get_course());
             $output = html_writer::tag('div', $formattedinfo, array('class' => 'availabilityinfo'));
         }
         return $output;
     }
     // this is a teacher who is allowed to see module but still should see the
     // information that module is not available to all/some students
     $modcontext = context_module::instance($mod->id);
     $canviewhidden = has_capability('moodle/course:viewhiddenactivities', $modcontext);
     if ($canviewhidden && !empty($CFG->enableavailability)) {
         // Don't add availability information if user is not editing and activity is hidden.
         if ($mod->visible || $this->page->user_is_editing()) {
             $hidinfoclass = '';
             if (!$mod->visible) {
                 $hidinfoclass = 'hide';
             }
             $ci = new \core_availability\info_module($mod);
             $fullinfo = $ci->get_full_information();
             if ($fullinfo) {
                 $formattedinfo = \core_availability\info::format_info($fullinfo, $mod->get_course());
                 return html_writer::div($formattedinfo, 'availabilityinfo ' . $hidinfoclass);
             }
         }
     }
     return '';
 }
Example #10
0
 public function filter_user_list(array $users, $not, \core_availability\info $info, \core_availability\capability_checker $checker)
 {
     global $CFG, $DB;
     require_once $CFG->libdir . '/grouplib.php';
     $course = $info->get_course();
     // List users for this course who match the condition.
     if ($this->groupid) {
         $groupusers = groups_get_members($this->groupid, 'u.id', 'u.id ASC');
     } else {
         $groupusers = $DB->get_records_sql("\n                    SELECT DISTINCT gm.userid\n                      FROM {groups} g\n                      JOIN {groups_members} gm ON gm.groupid = g.id\n                     WHERE g.courseid = ?", array($course->id));
     }
     // List users who have access all groups.
     $aagusers = $checker->get_users_by_capability('moodle/site:accessallgroups');
     // Filter the user list.
     $result = array();
     foreach ($users as $id => $user) {
         // Always include users with access all groups.
         if (array_key_exists($id, $aagusers)) {
             $result[$id] = $user;
             continue;
         }
         // Other users are included or not based on group membership.
         $allow = array_key_exists($id, $groupusers);
         if ($not) {
             $allow = !$allow;
         }
         if ($allow) {
             $result[$id] = $user;
         }
     }
     return $result;
 }
 public function get_description($full, $not, \core_availability\info $info)
 {
     global $DB;
     $context = \context_course::instance($info->get_course()->id);
     $role = $DB->get_record('role', array('id' => $this->roleid));
     if (!$role) {
         $missing = get_string('missing', 'availability_role');
         return get_string($not ? 'requires_notrole' : 'requires_role', 'availability_role', $missing);
     } else {
         $name = role_get_name($role, $context);
         return get_string($not ? 'requires_notrole' : 'requires_role', 'availability_role', $name);
     }
 }
 public function __construct($course = null)
 {
     global $SITE;
     if (!$course) {
         $course = $SITE;
     }
     parent::__construct($course, true, null);
 }
 /**
  * Renders HTML to show course module availability information
  *
  * @param cm_info $mod
  * @param array $displayoptions
  * @return string
  */
 public function course_section_cm_availability(cm_info $mod, $displayoptions = array())
 {
     // If we have available info, always spit it out.
     if (!empty($mod->availableinfo)) {
         $availinfo = $mod->availableinfo;
     } else {
         $ci = new \core_availability\info_module($mod);
         $availinfo = $ci->get_full_information();
     }
     if ($availinfo) {
         $formattedinfo = \core_availability\info::format_info($availinfo, $mod->get_course());
         return html_writer::div($formattedinfo, 'availabilityinfo');
     }
     return '';
 }
Example #14
0
 public function get_description($full, $not, \core_availability\info $info)
 {
     $course = $info->get_course();
     // Display the fieldname into current lang.
     if ($this->customfield) {
         // Is a custom profile field (will use multilang).
         $customfields = self::get_custom_profile_fields();
         if (array_key_exists($this->customfield, $customfields)) {
             $translatedfieldname = $customfields[$this->customfield]->name;
         } else {
             $translatedfieldname = get_string('missing', 'availability_profile', $this->customfield);
         }
     } else {
         $translatedfieldname = get_user_field_name($this->standardfield);
     }
     $context = \context_course::instance($course->id);
     $a = new \stdClass();
     $a->field = format_string($translatedfieldname, true, array('context' => $context));
     $a->value = s($this->value);
     if ($not) {
         // When doing NOT strings, we replace the operator with its inverse.
         // Some of them don't have inverses, so for those we use a new
         // identifier which is only used for this lang string.
         switch ($this->operator) {
             case self::OP_CONTAINS:
                 $opname = self::OP_DOES_NOT_CONTAIN;
                 break;
             case self::OP_DOES_NOT_CONTAIN:
                 $opname = self::OP_CONTAINS;
                 break;
             case self::OP_ENDS_WITH:
                 $opname = 'notendswith';
                 break;
             case self::OP_IS_EMPTY:
                 $opname = self::OP_IS_NOT_EMPTY;
                 break;
             case self::OP_IS_EQUAL_TO:
                 $opname = 'notisequalto';
                 break;
             case self::OP_IS_NOT_EMPTY:
                 $opname = self::OP_IS_EMPTY;
                 break;
             case self::OP_STARTS_WITH:
                 $opname = 'notstartswith';
                 break;
             default:
                 throw new \coding_exception('Unexpected operator: ' . $this->operator);
         }
     } else {
         $opname = $this->operator;
     }
     return get_string('requires_' . $opname, 'availability_profile', $a);
 }
 protected function process_module($data)
 {
     global $CFG, $DB;
     $data = (object) $data;
     $oldid = $data->id;
     $this->task->set_old_moduleversion($data->version);
     // Get the current course module data.
     $newitemid = $this->task->get_moduleid();
     $params = array('id' => $newitemid);
     $cmdata = $DB->get_record('course_modules', $params, '*', MUST_EXIST);
     // Group mode and Grouping.
     $cmdata->groupmode = $data->groupmode;
     $cmdata->groupingid = $this->get_mappingid('grouping', $data->groupingid);
     // Idnumber uniqueness.
     if (!grade_verify_idnumber($data->idnumber, $this->get_courseid())) {
         $data->idnumber = '';
     }
     $cmdata->idnumber = $data->idnumber;
     // Completion.
     if (!empty($CFG->enablecompletion)) {
         $cmdata->completion = $data->completion;
         $cmdata->completiongradeitemnumber = $data->completiongradeitemnumber;
         $cmdata->completionview = $data->completionview;
         $cmdata->completionexpected = $this->apply_date_offset($data->completionexpected);
     }
     // Availability.
     if (empty($CFG->enableavailability)) {
         $data->availability = null;
     }
     if (empty($data->availability)) {
         // If there are legacy availablility data fields (and no new format data),
         // convert the old fields.
         $data->availability = \core_availability\info::convert_legacy_fields($data, false);
     } else {
         if (!empty($data->groupmembersonly)) {
             // There is current availability data, but it still has groupmembersonly
             // as well (2.7 backups), convert just that part.
             require_once $CFG->dirroot . '/lib/db/upgradelib.php';
             $data->availability = upgrade_group_members_only($data->groupingid, $data->availability);
         }
     }
     $cmdata->availability = $data->availability;
     // Backups that did not include showdescription, set it to default 0
     // (this is not totally necessary as it has a db default, but just to
     // be explicit).
     if (!isset($data->showdescription)) {
         $data->showdescription = 0;
     }
     $cmdata->showdescription = $data->showdescription;
     // Course_module record ready, update it.
     $DB->update_record('course_modules', $cmdata);
     // Save mapping.
     $this->set_mapping('course_module', $oldid, $newitemid);
     // Set the new course_module id in the task.
     $this->task->set_moduleid($newitemid);
     // We can now create the context safely.
     $ctxid = context_module::instance($newitemid)->id;
     // Set the new context id in the task.
     $this->task->set_contextid($ctxid);
     // If there is the legacy showavailability data, store this for later use.
     // (This data is not present when restoring 'new' backups.)
     if (isset($cmdata->showavailability)) {
         // Cache the showavailability flag using the backup_ids data field.
         restore_dbops::set_backup_ids_record($this->get_restoreid(), 'module_showavailability', $newitemid, 0, null, (object) array('showavailability' => $cmdata->showavailability));
     }
 }
 /**
  * If section is not visible, display the message about that ('Not available
  * until...', that sort of thing). Otherwise, returns blank.
  *
  * For users with the ability to view hidden sections, it shows the
  * information even though you can view the section and also may include
  * slightly fuller information (so that teachers can tell when sections
  * are going to be unavailable etc). This logic is the same as for
  * activities.
  *
  * @param stdClass $section The course_section entry from DB
  * @param bool $canviewhidden True if user can view hidden sections
  * @return string HTML to output
  */
 protected function section_availability_message($section, $canviewhidden)
 {
     global $CFG;
     $o = '';
     if (!$section->uservisible) {
         // Note: We only get to this function if availableinfo is non-empty,
         // so there is definitely something to print.
         $formattedinfo = \core_availability\info::format_info($section->availableinfo, $section->course);
         $o .= html_writer::div($formattedinfo, 'availabilityinfo');
     } else {
         if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) {
             $ci = new \core_availability\info_section($section);
             $fullinfo = $ci->get_full_information();
             if ($fullinfo) {
                 $formattedinfo = \core_availability\info::format_info($fullinfo, $section->course);
                 $o .= html_writer::div($formattedinfo, 'availabilityinfo');
             }
         }
     }
     return $o;
 }
Example #17
0
 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive)
 {
     global $DB;
     // Build suitable SQL depending on custom or standard field.
     if ($this->customfield) {
         $customfields = self::get_custom_profile_fields();
         if (!array_key_exists($this->customfield, $customfields)) {
             // If the field isn't found, nobody matches.
             return array('SELECT id FROM {user} WHERE 0 = 1', array());
         }
         $customfield = $customfields[$this->customfield];
         $mainparams = array();
         $tablesql = "LEFT JOIN {user_info_data} uid ON uid.fieldid = " . self::unique_sql_parameter($mainparams, $customfield->id) . " AND uid.userid = userids.id";
         list($condition, $conditionparams) = $this->get_condition_sql('uid.data');
         $mainparams = array_merge($mainparams, $conditionparams);
         // If default is true, then allow that too.
         if ($this->is_field_condition_met($this->operator, $customfield->defaultdata, $this->value)) {
             $where = "((uid.data IS NOT NULL AND {$condition}) OR (uid.data IS NULL))";
         } else {
             $where = "(uid.data IS NOT NULL AND {$condition})";
         }
     } else {
         $tablesql = "JOIN {user} u ON u.id = userids.id";
         list($where, $mainparams) = $this->get_condition_sql('u.' . $this->standardfield);
     }
     // Handle NOT.
     if ($not) {
         $where = 'NOT (' . $where . ')';
     }
     // Get enrolled user SQL and combine with this query.
     list($enrolsql, $enrolparams) = get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
     $sql = "SELECT userids.id\n                  FROM ({$enrolsql}) userids\n                       {$tablesql}\n                 WHERE {$where}";
     $params = array_merge($enrolparams, $mainparams);
     return array($sql, $params);
 }
 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive)
 {
     global $DB;
     // Get enrolled users with access all groups. These always are allowed.
     list($aagsql, $aagparams) = get_enrolled_sql($info->get_context(), 'moodle/site:accessallgroups', 0, $onlyactive);
     // Get all enrolled users.
     list($enrolsql, $enrolparams) = get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
     // Condition for specified or any group.
     $matchparams = array();
     $matchsql = "SELECT 1\n                       FROM {groups_members} gm\n                       JOIN {groupings_groups} gg ON gg.groupid = gm.groupid\n                      WHERE gm.userid = userids.id\n                            AND gg.groupingid = " . self::unique_sql_parameter($matchparams, $this->get_grouping_id($info));
     // Overall query combines all this.
     $condition = $not ? 'NOT' : '';
     $sql = "SELECT userids.id\n                  FROM ({$enrolsql}) userids\n                 WHERE (userids.id IN ({$aagsql})) OR {$condition} EXISTS ({$matchsql})";
     return array($sql, array_merge($enrolparams, $aagparams, $matchparams));
 }
Example #19
0
 /**
  * Obtains SQL that returns a list of enrolled users that has been filtered
  * by the conditions applied in the availability API, similar to calling
  * get_enrolled_users and then filter_user_list. As for filter_user_list,
  * this ONLY filteres out users with conditions that are marked as applying
  * to user lists. For example, group conditions are included but date
  * conditions are not included.
  *
  * The returned SQL is a query that returns a list of user IDs. It does not
  * include brackets, so you neeed to add these to make it into a subquery.
  * You would normally use it in an SQL phrase like "WHERE u.id IN ($sql)".
  *
  * The SQL will be complex and may be slow. It uses named parameters (sorry,
  * I know they are annoying, but it was unavoidable here).
  *
  * If there are no conditions, the returned result is array('', array()).
  *
  * @param bool $not True if this condition is applying in negative mode
  * @param \core_availability\info $info Item we're checking
  * @param bool $onlyactive If true, only returns active enrolments
  * @return array Array with two elements: SQL subquery and parameters array
  * @throws \coding_exception If called on a condition that doesn't apply to user lists
  */
 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive)
 {
     if (!$this->is_applied_to_user_lists()) {
         throw new \coding_exception('Not implemented (do not call unless ' . 'is_applied_to_user_lists is true)');
     }
     // Handle situation where plugin does not implement this, by returning a
     // default (all enrolled users). This ensures compatibility with 2.7
     // plugins and behaviour. Plugins should be updated to support this
     // new function (if they return true to is_applied_to_user_lists).
     debugging('Availability plugins that return true to is_applied_to_user_lists ' . 'should also now implement get_user_list_sql: ' . get_class($this), DEBUG_DEVELOPER);
     return get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
 }
Example #20
0
 public function get_description($full, $not, \core_availability\info $info)
 {
     global $DB;
     $course = $info->get_course();
     // Need to get the name for the grouping. Unfortunately this requires
     // a database query. To save queries, get all groupings for course at
     // once in a static cache.
     $groupingid = $this->get_grouping_id($info);
     if (!array_key_exists($groupingid, self::$groupingnames)) {
         $coursegroupings = $DB->get_records('groupings', array('courseid' => $course->id), '', 'id, name');
         foreach ($coursegroupings as $rec) {
             self::$groupingnames[$rec->id] = $rec->name;
         }
     }
     // If it still doesn't exist, it must have been misplaced.
     if (!array_key_exists($groupingid, self::$groupingnames)) {
         $name = get_string('missing', 'availability_grouping');
     } else {
         $context = \context_course::instance($course->id);
         $name = format_string(self::$groupingnames[$groupingid], true, array('context' => $context));
     }
     return get_string($not ? 'requires_notgrouping' : 'requires_grouping', 'availability_grouping', $name);
 }
Example #21
0
 /**
  * This function converts all of the base settings for an instance of
  * the old setaskment to the new format. Then it calls each of the plugins
  * to see if they can help upgrade this setaskment.
  * @param int $oldsetaskmentid (don't rely on the old setaskment type even being installed)
  * @param string $log This string gets appended to during the conversion process
  * @return bool true or false
  */
 public function upgrade_setaskment($oldsetaskmentid, &$log)
 {
     global $DB, $CFG, $USER;
     // Steps to upgrade an setaskment.
     core_php_time_limit::raise(ASSIGN_MAX_UPGRADE_TIME_SECS);
     // Get the module details.
     $oldmodule = $DB->get_record('modules', array('name' => 'setaskment'), '*', MUST_EXIST);
     $params = array('module' => $oldmodule->id, 'instance' => $oldsetaskmentid);
     $oldcoursemodule = $DB->get_record('course_modules', $params, '*', MUST_EXIST);
     $oldcontext = context_module::instance($oldcoursemodule->id);
     // We used to check for admin capability, but since Moodle 2.7 this is called
     // during restore of a mod_setaskment module.
     // Also note that we do not check for any mod_setaskment capabilities, because they can
     // be removed so that users don't add new instances of the broken old thing.
     if (!has_capability('mod/setask:addinstance', $oldcontext)) {
         $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask');
         return false;
     }
     // First insert an setask instance to get the id.
     $oldsetaskment = $DB->get_record('setaskment', array('id' => $oldsetaskmentid), '*', MUST_EXIST);
     $oldversion = get_config('setaskment_' . $oldsetaskment->setaskmenttype, 'version');
     $data = new stdClass();
     $data->course = $oldsetaskment->course;
     $data->name = $oldsetaskment->name;
     $data->intro = $oldsetaskment->intro;
     $data->introformat = $oldsetaskment->introformat;
     $data->alwaysshowdescription = 1;
     $data->sendnotifications = $oldsetaskment->emailteachers;
     $data->sendlatenotifications = $oldsetaskment->emailteachers;
     $data->duedate = $oldsetaskment->timedue;
     $data->allowsubmissionsfromdate = $oldsetaskment->timeavailable;
     $data->grade = $oldsetaskment->grade;
     $data->submissiondrafts = $oldsetaskment->resubmit;
     $data->requiresubmissionstatement = 0;
     $data->markingworkflow = 0;
     $data->markingallocation = 0;
     $data->cutoffdate = 0;
     // New way to specify no late submissions.
     if ($oldsetaskment->preventlate) {
         $data->cutoffdate = $data->duedate;
     }
     $data->teamsubmission = 0;
     $data->requireallteammemberssubmit = 0;
     $data->teamsubmissiongroupingid = 0;
     $data->blindmarking = 0;
     $data->attemptreopenmethod = 'none';
     $data->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS;
     $newsetaskment = new setask(null, null, null);
     if (!$newsetaskment->add_instance($data, false)) {
         $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask');
         return false;
     }
     // Now create a new coursemodule from the old one.
     $newmodule = $DB->get_record('modules', array('name' => 'setask'), '*', MUST_EXIST);
     $newcoursemodule = $this->duplicate_course_module($oldcoursemodule, $newmodule->id, $newsetaskment->get_instance()->id);
     if (!$newcoursemodule) {
         $log = get_string('couldnotcreatenewcoursemodule', 'mod_setask');
         return false;
     }
     // Convert the base database tables (setaskment, submission, grade).
     // These are used to store information in case a rollback is required.
     $gradingarea = null;
     $gradingdefinitions = null;
     $gradeidmap = array();
     $completiondone = false;
     $gradesdone = false;
     // From this point we want to rollback on failure.
     $rollback = false;
     try {
         $newsetaskment->set_context(context_module::instance($newcoursemodule->id));
         // The course module has now been created - time to update the core tables.
         // Copy intro files.
         $newsetaskment->copy_area_files_for_upgrade($oldcontext->id, 'mod_setaskment', 'intro', 0, $newsetaskment->get_context()->id, 'mod_setask', 'intro', 0);
         // Get the plugins to do their bit.
         foreach ($newsetaskment->get_submission_plugins() as $plugin) {
             if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                 $plugin->enable();
                 if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) {
                     $rollback = true;
                 }
             } else {
                 $plugin->disable();
             }
         }
         foreach ($newsetaskment->get_feedback_plugins() as $plugin) {
             if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                 $plugin->enable();
                 if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) {
                     $rollback = true;
                 }
             } else {
                 $plugin->disable();
             }
         }
         // See if there is advanced grading upgrades required.
         $gradingarea = $DB->get_record('grading_areas', array('contextid' => $oldcontext->id, 'areaname' => 'submission'), '*', IGNORE_MISSING);
         if ($gradingarea) {
             $params = array('id' => $gradingarea->id, 'contextid' => $newsetaskment->get_context()->id, 'component' => 'mod_setask', 'areaname' => 'submissions');
             $DB->update_record('grading_areas', $params);
             $gradingdefinitions = $DB->get_records('grading_definitions', array('areaid' => $gradingarea->id));
         }
         // Upgrade availability data.
         \core_availability\info::update_dependency_id_across_course($newcoursemodule->course, 'course_modules', $oldcoursemodule->id, $newcoursemodule->id);
         // Upgrade completion data.
         $DB->set_field('course_modules_completion', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid' => $oldcoursemodule->id));
         $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $oldcoursemodule->id));
         foreach ($allcriteria as $criteria) {
             $criteria->module = 'setask';
             $criteria->moduleinstance = $newcoursemodule->id;
             $DB->update_record('course_completion_criteria', $criteria);
         }
         $completiondone = true;
         // Migrate log entries so we don't lose them.
         $logparams = array('cmid' => $oldcoursemodule->id, 'course' => $oldcoursemodule->course);
         $DB->set_field('log', 'module', 'setask', $logparams);
         $DB->set_field('log', 'cmid', $newcoursemodule->id, $logparams);
         // Copy all the submission data (and get plugins to do their bit).
         $oldsubmissions = $DB->get_records('setaskment_submissions', array('setaskment' => $oldsetaskmentid));
         foreach ($oldsubmissions as $oldsubmission) {
             $submission = new stdClass();
             $submission->setaskment = $newsetaskment->get_instance()->id;
             $submission->userid = $oldsubmission->userid;
             $submission->timecreated = $oldsubmission->timecreated;
             $submission->timemodified = $oldsubmission->timemodified;
             $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
             // Because in mod_setaskment there could only be one submission per student, it is always the latest.
             $submission->latest = 1;
             $submission->id = $DB->insert_record('setask_submission', $submission);
             if (!$submission->id) {
                 $log .= get_string('couldnotinsertsubmission', 'mod_setask', $submission->userid);
                 $rollback = true;
             }
             foreach ($newsetaskment->get_submission_plugins() as $plugin) {
                 if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                     if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $submission, $log)) {
                         $rollback = true;
                     }
                 }
             }
             if ($oldsubmission->timemarked) {
                 // Submission has been graded - create a grade record.
                 $grade = new stdClass();
                 $grade->setaskment = $newsetaskment->get_instance()->id;
                 $grade->userid = $oldsubmission->userid;
                 $grade->grader = $oldsubmission->teacher;
                 $grade->timemodified = $oldsubmission->timemarked;
                 $grade->timecreated = $oldsubmission->timecreated;
                 $grade->grade = $oldsubmission->grade;
                 if ($oldsubmission->mailed) {
                     // The mailed flag goes in the flags table.
                     $flags = new stdClass();
                     $flags->userid = $oldsubmission->userid;
                     $flags->setaskment = $newsetaskment->get_instance()->id;
                     $flags->mailed = 1;
                     $DB->insert_record('setask_user_flags', $flags);
                 }
                 $grade->id = $DB->insert_record('setask_grades', $grade);
                 if (!$grade->id) {
                     $log .= get_string('couldnotinsertgrade', 'mod_setask', $grade->userid);
                     $rollback = true;
                 }
                 // Copy any grading instances.
                 if ($gradingarea) {
                     $gradeidmap[$grade->id] = $oldsubmission->id;
                     foreach ($gradingdefinitions as $definition) {
                         $params = array('definitionid' => $definition->id, 'itemid' => $oldsubmission->id);
                         $DB->set_field('grading_instances', 'itemid', $grade->id, $params);
                     }
                 }
                 foreach ($newsetaskment->get_feedback_plugins() as $plugin) {
                     if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) {
                         if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $grade, $log)) {
                             $rollback = true;
                         }
                     }
                 }
             }
         }
         $newsetaskment->update_calendar($newcoursemodule->id);
         // Reassociate grade_items from the old setaskment instance to the new setask instance.
         // This includes outcome linked grade_items.
         $params = array('setask', $newsetaskment->get_instance()->id, 'setaskment', $oldsetaskment->id);
         $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?';
         $DB->execute($sql, $params);
         // Create a mapping record to map urls from the old to the new setaskment.
         $mapping = new stdClass();
         $mapping->oldcmid = $oldcoursemodule->id;
         $mapping->oldinstance = $oldsetaskment->id;
         $mapping->newcmid = $newcoursemodule->id;
         $mapping->newinstance = $newsetaskment->get_instance()->id;
         $mapping->timecreated = time();
         $DB->insert_record('setaskment_upgrade', $mapping);
         $gradesdone = true;
     } catch (Exception $exception) {
         $rollback = true;
         $log .= get_string('conversionexception', 'mod_setask', $exception->getMessage());
     }
     if ($rollback) {
         // Roll back the grades changes.
         if ($gradesdone) {
             // Reassociate grade_items from the new setask instance to the old setaskment instance.
             $params = array('setaskment', $oldsetaskment->id, 'setask', $newsetaskment->get_instance()->id);
             $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?';
             $DB->execute($sql, $params);
         }
         // Roll back the completion changes.
         if ($completiondone) {
             $DB->set_field('course_modules_completion', 'coursemoduleid', $oldcoursemodule->id, array('coursemoduleid' => $newcoursemodule->id));
             $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $newcoursemodule->id));
             foreach ($allcriteria as $criteria) {
                 $criteria->module = 'setaskment';
                 $criteria->moduleinstance = $oldcoursemodule->id;
                 $DB->update_record('course_completion_criteria', $criteria);
             }
         }
         // Roll back the log changes.
         $logparams = array('cmid' => $newcoursemodule->id, 'course' => $newcoursemodule->course);
         $DB->set_field('log', 'module', 'setaskment', $logparams);
         $DB->set_field('log', 'cmid', $oldcoursemodule->id, $logparams);
         // Roll back the advanced grading update.
         if ($gradingarea) {
             foreach ($gradeidmap as $newgradeid => $oldsubmissionid) {
                 foreach ($gradingdefinitions as $definition) {
                     $DB->set_field('grading_instances', 'itemid', $oldsubmissionid, array('definitionid' => $definition->id, 'itemid' => $newgradeid));
                 }
             }
             $params = array('id' => $gradingarea->id, 'contextid' => $oldcontext->id, 'component' => 'mod_setaskment', 'areaname' => 'submission');
             $DB->update_record('grading_areas', $params);
         }
         $newsetaskment->delete_instance();
         return false;
     }
     // Delete the old setaskment (use object delete).
     $cm = get_coursemodule_from_id('', $oldcoursemodule->id, $oldcoursemodule->course);
     if ($cm) {
         course_delete_module($cm->id);
     }
     rebuild_course_cache($oldcoursemodule->course);
     return true;
 }
 /**
  * Obtains a string describing this restriction (whether or not
  * it actually applies). Used to obtain information that is displayed to
  * students if the activity is not available to them, and for staff to see
  * what conditions are.
  *
  * The $full parameter can be used to distinguish between 'staff' cases
  * (when displaying all information about the activity) and 'student' cases
  * (when displaying only conditions they don't meet).
  *
  * If implementations require a course or modinfo, they should use
  * the get methods in $info.
  *
  * The special string <AVAILABILITY_CMNAME_123/> can be returned, where
  * 123 is any number. It will be replaced with the correctly-formatted
  * name for that activity.
  *
  * @param bool $full Set true if this is the 'full information' view
  * @param bool $not Set true if we are inverting the condition
  * @param info $info Item we're checking
  * @return string Information string (for admin) about all restrictions on
  *   this item
  */
 public function get_description($full, $not, info $info)
 {
     global $USER, $PAGE;
     static $jsadded = false;
     if (!$info instanceof info_module) {
         return '';
         // Should only be possible against activities, not sections.
     }
     $cm = $info->get_course_module();
     if ($not) {
         $str = get_string('requires_nopassword', 'availability_password');
     } else {
         $str = get_string('requires_password', 'availability_password');
     }
     if (!$full || !$this->is_available($not, $info, false, $USER->id)) {
         $url = new \moodle_url('/availability/condition/password/index.php', array('id' => $cm->id));
         $str = \html_writer::link($url, $str, array('class' => 'availability_password-popup'));
         if (!$jsadded) {
             $PAGE->requires->strings_for_js(['enterpassword', 'wrongpassword', 'passwordintro'], 'availability_password');
             $PAGE->requires->strings_for_js(['submit', 'cancel'], 'core');
             $jsadded = true;
             $PAGE->requires->yui_module('moodle-availability_password-popup', 'M.availability_password.popup.init');
         }
     }
     return $str;
 }
 /**
  * Tests the add_legacy_availability_field_condition function used in restore.
  */
 public function test_add_legacy_availability_field_condition()
 {
     // User field, normal operator.
     $rec = (object) array('userfield' => 'email', 'shortname' => null, 'operator' => 'contains', 'value' => '@');
     $this->assertEquals('{"op":"&","showc":[true],"c":[' . '{"type":"profile","op":"contains","sf":"email","v":"@"}]}', info::add_legacy_availability_field_condition(null, $rec, true));
     // User field, non-value operator.
     $rec = (object) array('userfield' => 'email', 'shortname' => null, 'operator' => 'isempty', 'value' => '');
     $this->assertEquals('{"op":"&","showc":[true],"c":[' . '{"type":"profile","op":"isempty","sf":"email"}]}', info::add_legacy_availability_field_condition(null, $rec, true));
     // Custom field.
     $rec = (object) array('userfield' => null, 'shortname' => 'frogtype', 'operator' => 'isempty', 'value' => '');
     $this->assertEquals('{"op":"&","showc":[true],"c":[' . '{"type":"profile","op":"isempty","cf":"frogtype"}]}', info::add_legacy_availability_field_condition(null, $rec, true));
 }
Example #24
0
 public function get_user_list_sql($not, \core_availability\info $info, $onlyactive)
 {
     global $DB;
     // The data for this condition is not really stored in the database,
     // so we return SQL that contains the hard-coded user list.
     list($enrolsql, $enrolparams) = get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
     $condition = $not ? 'NOT' : '';
     list($matchsql, $matchparams) = $DB->get_in_or_equal($this->filter, SQL_PARAMS_NAMED);
     $sql = "SELECT userids.id\n                  FROM ({$enrolsql}) userids\n                 WHERE {$condition} (userids.id {$matchsql})";
     return array($sql, array_merge($enrolparams, $matchparams));
 }