/** * Tests the filter_user_list() and get_user_list_sql() functions. */ public function test_filter_user_list() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; $this->resetAfterTest(); $CFG->enableavailability = true; // Create a course with 2 sections and 2 pages and 3 users. // Availability is set up initially on the 'page/section 2' items. $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 2), array('createsections' => true)); $u1 = $generator->create_user(); $u2 = $generator->create_user(); $u3 = $generator->create_user(); $allusers = array($u1->id => $u1, $u2->id => $u2, $u3->id => $u3); $generator->enrol_user($u1->id, $course->id); $generator->enrol_user($u2->id, $course->id); $generator->enrol_user($u3->id, $course->id); $pagegen = $generator->get_plugin_generator('mod_page'); $page = $pagegen->create_instance(array('course' => $course)); $page2 = $pagegen->create_instance(array('course' => $course, 'availability' => '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u2->id . ',' . $u3->id . ']}]}')); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(1); $section2 = $modinfo->get_section_info(2); $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u1->id . ',' . $u2->id . ']}]}', array('id' => $section2->id)); moveto_module($modinfo->get_cm($page2->cmid), $section2); // With no restrictions, returns full list. $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // Set an availability restriction in database for section 1. // For the section we set it so it doesn't support filters; for the // module we have a filter. $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","a":false}]}', array('id' => $section->id)); $DB->set_field('course_modules', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u3->id . ']}]}', array('id' => $page->cmid)); rebuild_course_cache($course->id, true); $modinfo = get_fast_modinfo($course); // Now it should work (for the module). $info = new info_module($modinfo->get_cm($page->cmid)); $expected = array($u3->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); $info = new info_section($modinfo->get_section_info(1)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // With availability disabled, module returns full list too. $CFG->enableavailability = false; $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // Check the other section... $CFG->enableavailability = true; $info = new info_section($modinfo->get_section_info(2)); $expected = array($u1->id, $u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(true); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); // And the module in that section - which has combined the section and // module restrictions. $info = new info_module($modinfo->get_cm($page2->cmid)); $expected = array($u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(true); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); }
/** * Get Calendar events * * @param array $events A list of events * @param array $options various options * @return array Array of event details * @since Moodle 2.5 */ public static function get_calendar_events($events = array(), $options = array()) { global $SITE, $DB, $USER, $CFG; require_once $CFG->dirroot . "/calendar/lib.php"; // Parameter validation. $params = self::validate_parameters(self::get_calendar_events_parameters(), array('events' => $events, 'options' => $options)); $funcparam = array('courses' => array(), 'groups' => array()); $hassystemcap = has_capability('moodle/calendar:manageentries', context_system::instance()); $warnings = array(); // Let us findout courses that we can return events from. if (!$hassystemcap) { $courses = enrol_get_my_courses(); $courses = array_keys($courses); foreach ($params['events']['courseids'] as $id) { if (in_array($id, $courses)) { $funcparam['courses'][] = $id; } else { $warnings[] = array('item' => $id, 'warningcode' => 'nopermissions', 'message' => 'you do not have permissions to access this course'); } } } else { $courses = $params['events']['courseids']; $funcparam['courses'] = $courses; } // Let us findout groups that we can return events from. if (!$hassystemcap) { $groups = groups_get_my_groups(); $groups = array_keys($groups); foreach ($params['events']['groupids'] as $id) { if (in_array($id, $groups)) { $funcparam['groups'][] = $id; } else { $warnings[] = array('item' => $id, 'warningcode' => 'nopermissions', 'message' => 'you do not have permissions to access this group'); } } } else { $groups = $params['events']['groupids']; $funcparam['groups'] = $groups; } // Do we need user events? if (!empty($params['options']['userevents'])) { $funcparam['users'] = array($USER->id); } else { $funcparam['users'] = false; } // Do we need site events? if (!empty($params['options']['siteevents'])) { $funcparam['courses'][] = $SITE->id; } // We treat 0 and null as no end. if (empty($params['options']['timeend'])) { $params['options']['timeend'] = PHP_INT_MAX; } $eventlist = calendar_get_events($params['options']['timestart'], $params['options']['timeend'], $funcparam['users'], $funcparam['groups'], $funcparam['courses'], true, $params['options']['ignorehidden']); // WS expects arrays. $events = array(); foreach ($eventlist as $id => $event) { $events[$id] = (array) $event; } // We need to get events asked for eventids. $eventsbyid = calendar_get_events_by_id($params['events']['eventids']); foreach ($eventsbyid as $eventid => $eventobj) { $event = (array) $eventobj; if (isset($events[$eventid])) { continue; } if ($hassystemcap) { // User can see everything, no further check is needed. $events[$eventid] = $event; } else { if (!empty($eventobj->modulename)) { $cm = get_coursemodule_from_instance($eventobj->modulename, $eventobj->instance); if (\core_availability\info_module::is_user_visible($cm, 0, false)) { $events[$eventid] = $event; } } else { // Can the user actually see this event? $eventobj = calendar_event::load($eventobj); if ($eventobj->courseid == $SITE->id || !empty($eventobj->groupid) && in_array($eventobj->groupid, $groups) || !empty($eventobj->courseid) && in_array($eventobj->courseid, $courses) || $USER->id == $eventobj->userid || calendar_edit_event_allowed($eventid)) { $events[$eventid] = $event; } else { $warnings[] = array('item' => $eventid, 'warningcode' => 'nopermissions', 'message' => 'you do not have permissions to view this event'); } } } } return array('events' => $events, 'warnings' => $warnings); }
/** * @global object * @global object * @param object $forum * @param object $discussion * @param object $post * @param object $user * @param object $cm * @return bool */ function forum_user_can_see_post($forum, $discussion, $post, $user = NULL, $cm = NULL) { global $CFG, $USER, $DB; // Context used throughout function. $modcontext = context_module::instance($cm->id); // retrieve objects (yuk) if (is_numeric($forum)) { debugging('missing full forum', DEBUG_DEVELOPER); if (!($forum = $DB->get_record('forum', array('id' => $forum)))) { return false; } } if (is_numeric($discussion)) { debugging('missing full discussion', DEBUG_DEVELOPER); if (!($discussion = $DB->get_record('forum_discussions', array('id' => $discussion)))) { return false; } } if (is_numeric($post)) { debugging('missing full post', DEBUG_DEVELOPER); if (!($post = $DB->get_record('forum_posts', array('id' => $post)))) { return false; } } if (!isset($post->id) && isset($post->parent)) { $post->id = $post->parent; } if (!$cm) { debugging('missing cm', DEBUG_DEVELOPER); if (!($cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course))) { print_error('invalidcoursemodule'); } } if (empty($user) || empty($user->id)) { $user = $USER; } $canviewdiscussion = !empty($cm->cache->caps['mod/forum:viewdiscussion']) || has_capability('mod/forum:viewdiscussion', $modcontext, $user->id); if (!$canviewdiscussion && !has_all_capabilities(array('moodle/user:viewdetails', 'moodle/user:readuserposts'), context_user::instance($post->userid))) { return false; } if (isset($cm->uservisible)) { if (!$cm->uservisible) { return false; } } else { if (!\core_availability\info_module::is_user_visible($cm, $user->id, false)) { return false; } } if (!forum_user_can_see_timed_discussion($discussion, $user, $modcontext)) { return false; } if (!forum_user_can_see_group_discussion($discussion, $cm, $modcontext)) { return false; } if ($forum->type == 'qanda') { $firstpost = forum_get_firstpost_from_discussion($discussion->id); $userfirstpost = forum_get_user_posted_time($discussion->id, $user->id); return $userfirstpost !== false && time() - $userfirstpost >= $CFG->maxeditingtime || $firstpost->id == $post->id || $post->userid == $user->id || $firstpost->userid == $user->id || has_capability('mod/forum:viewqandawithoutposting', $modcontext, $user->id); } return true; }
/** * Gets the calendar upcoming event * * @param array $courses array of courses * @param array|int|bool $groups array of groups, group id or boolean for all/no group events * @param array|int|bool $users array of users, user id or boolean for all/no user events * @param int $daysinfuture number of days in the future we 'll look * @param int $maxevents maximum number of events * @param int $fromtime start time * @return array $output array of upcoming events */ function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxevents, $fromtime = 0) { global $CFG, $COURSE, $DB; $display = new stdClass(); $display->range = $daysinfuture; // How many days in the future we 'll look $display->maxevents = $maxevents; $output = array(); // Prepare "course caching", since it may save us a lot of queries $coursecache = array(); $processed = 0; $now = time(); // We 'll need this later $usermidnighttoday = usergetmidnight($now); if ($fromtime) { $display->tstart = $fromtime; } else { $display->tstart = $usermidnighttoday; } // This works correctly with respect to the user's DST, but it is accurate // only because $fromtime is always the exact midnight of some day! $display->tend = usergetmidnight($display->tstart + DAYSECS * $display->range + 3 * HOURSECS) - 1; // Get the events matching our criteria $events = calendar_get_events($display->tstart, $display->tend, $users, $groups, $courses); // This is either a genius idea or an idiot idea: in order to not complicate things, we use this rule: if, after // possibly removing SITEID from $courses, there is only one course left, then clicking on a day in the month // will also set the $SESSION->cal_courses_shown variable to that one course. Otherwise, we 'd need to add extra // arguments to this function. $hrefparams = array(); if (!empty($courses)) { $courses = array_diff($courses, array(SITEID)); if (count($courses) == 1) { $hrefparams['course'] = reset($courses); } } if ($events !== false) { $modinfo = get_fast_modinfo($COURSE); foreach ($events as $event) { if (!empty($event->modulename)) { if ($event->courseid == $COURSE->id) { if (isset($modinfo->instances[$event->modulename][$event->instance])) { $cm = $modinfo->instances[$event->modulename][$event->instance]; if (!$cm->uservisible) { continue; } } } else { if (!($cm = get_coursemodule_from_instance($event->modulename, $event->instance))) { continue; } if (!\core_availability\info_module::is_user_visible($cm, 0, false)) { continue; } } } if ($processed >= $display->maxevents) { break; } $event->time = calendar_format_event_time($event, $now, $hrefparams); $output[] = $event; ++$processed; } } return $output; }
/** * Displays a month in detail * * @param calendar_information $calendar * @param moodle_url $returnurl the url to return to * @return string */ public function show_month_detailed(calendar_information $calendar, moodle_url $returnurl = null) { global $CFG; if (empty($returnurl)) { $returnurl = $this->page->url; } // Get the calendar type we are using. $calendartype = \core_calendar\type_factory::get_calendar_instance(); // Store the display settings. $display = new stdClass(); $display->thismonth = false; // Get the specified date in the calendar type being used. $date = $calendartype->timestamp_to_date_array($calendar->time); $thisdate = $calendartype->timestamp_to_date_array(time()); if ($date['mon'] == $thisdate['mon'] && $date['year'] == $thisdate['year']) { $display->thismonth = true; $date = $thisdate; $calendar->time = time(); } // Get Gregorian date for the start of the month. $gregoriandate = $calendartype->convert_to_gregorian($date['year'], $date['mon'], 1); // Store the gregorian date values to be used later. list($gy, $gm, $gd, $gh, $gmin) = array($gregoriandate['year'], $gregoriandate['month'], $gregoriandate['day'], $gregoriandate['hour'], $gregoriandate['minute']); // Get the starting week day for this month. $startwday = dayofweek(1, $date['mon'], $date['year']); // Get the days in a week. $daynames = calendar_get_days(); // Store the number of days in a week. $numberofdaysinweek = $calendartype->get_num_weekdays(); $display->minwday = calendar_get_starting_weekday(); $display->maxwday = $display->minwday + ($numberofdaysinweek - 1); $display->maxdays = calendar_days_in_month($date['mon'], $date['year']); // These are used for DB queries, so we want unixtime, so we need to use Gregorian dates. $display->tstart = make_timestamp($gy, $gm, $gd, $gh, $gmin, 0); $display->tend = $display->tstart + $display->maxdays * DAYSECS - 1; // Align the starting weekday to fall in our display range // This is simple, not foolproof. if ($startwday < $display->minwday) { $startwday += $numberofdaysinweek; } // Get events from database $events = calendar_get_events($display->tstart, $display->tend, $calendar->users, $calendar->groups, $calendar->courses); if (!empty($events)) { foreach ($events as $eventid => $event) { $event = new calendar_event($event); if (!empty($event->modulename)) { $cm = get_coursemodule_from_instance($event->modulename, $event->instance); if (!\core_availability\info_module::is_user_visible($cm, 0, false)) { unset($events[$eventid]); } } } } // Extract information: events vs. time calendar_events_by_day($events, $date['mon'], $date['year'], $eventsbyday, $durationbyday, $typesbyday, $calendar->courses); $output = html_writer::start_tag('div', array('class' => 'header')); $output .= $this->course_filter_selector($returnurl, get_string('detailedmonthviewfor', 'calendar')); if (calendar_user_can_add_event($calendar->course)) { $output .= $this->add_event_button($calendar->course->id, 0, 0, 0, $calendar->time); } $output .= html_writer::end_tag('div', array('class' => 'header')); // Controls $output .= html_writer::tag('div', calendar_top_controls('month', array('id' => $calendar->courseid, 'time' => $calendar->time)), array('class' => 'controls')); $table = new html_table(); $table->attributes = array('class' => 'calendarmonth calendartable'); $table->summary = get_string('calendarheading', 'calendar', userdate($calendar->time, get_string('strftimemonthyear'))); $table->data = array(); // Get the day names as the header. $header = array(); for ($i = $display->minwday; $i <= $display->maxwday; ++$i) { $header[] = $daynames[$i % $numberofdaysinweek]['shortname']; } $table->head = $header; // For the table display. $week is the row; $dayweek is the column. $week = 1; $dayweek = $startwday; $row = new html_table_row(array()); // Paddding (the first week may have blank days in the beginning) for ($i = $display->minwday; $i < $startwday; ++$i) { $cell = new html_table_cell(' '); $cell->attributes = array('class' => 'nottoday dayblank'); $row->cells[] = $cell; } // Now display all the calendar $weekend = CALENDAR_DEFAULT_WEEKEND; if (isset($CFG->calendar_weekend)) { $weekend = intval($CFG->calendar_weekend); } $daytime = $display->tstart - DAYSECS; for ($day = 1; $day <= $display->maxdays; ++$day, ++$dayweek) { $daytime = $daytime + DAYSECS; if ($dayweek > $display->maxwday) { // We need to change week (table row) $table->data[] = $row; $row = new html_table_row(array()); $dayweek = $display->minwday; ++$week; } // Reset vars $cell = new html_table_cell(); $dayhref = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', array('view' => 'day', 'course' => $calendar->courseid)), 0, 0, 0, $daytime); $cellclasses = array(); if ($weekend & 1 << $dayweek % $numberofdaysinweek) { // Weekend. This is true no matter what the exact range is. $cellclasses[] = 'weekend'; } // Special visual fx if an event is defined if (isset($eventsbyday[$day])) { if (count($eventsbyday[$day]) == 1) { $title = get_string('oneevent', 'calendar'); } else { $title = get_string('manyevents', 'calendar', count($eventsbyday[$day])); } $cell->text = html_writer::tag('div', html_writer::link($dayhref, $day, array('title' => $title)), array('class' => 'day')); } else { $cell->text = html_writer::tag('div', $day, array('class' => 'day')); } // Special visual fx if an event spans many days $durationclass = false; if (isset($typesbyday[$day]['durationglobal'])) { $durationclass = 'duration_global'; } else { if (isset($typesbyday[$day]['durationcourse'])) { $durationclass = 'duration_course'; } else { if (isset($typesbyday[$day]['durationgroup'])) { $durationclass = 'duration_group'; } else { if (isset($typesbyday[$day]['durationuser'])) { $durationclass = 'duration_user'; } } } } if ($durationclass) { $cellclasses[] = 'duration'; $cellclasses[] = $durationclass; } // Special visual fx for today if ($display->thismonth && $day == $date['mday']) { $cellclasses[] = 'day today'; } else { $cellclasses[] = 'day nottoday'; } $cell->attributes = array('class' => join(' ', $cellclasses)); if (isset($eventsbyday[$day])) { $cell->text .= html_writer::start_tag('ul', array('class' => 'events-new')); foreach ($eventsbyday[$day] as $eventindex) { // If event has a class set then add it to the event <li> tag $attributes = array(); if (!empty($events[$eventindex]->class)) { $attributes['class'] = $events[$eventindex]->class; } $dayhref->set_anchor('event_' . $events[$eventindex]->id); $link = html_writer::link($dayhref, format_string($events[$eventindex]->name, true)); $cell->text .= html_writer::tag('li', $link, $attributes); } $cell->text .= html_writer::end_tag('ul'); } if (isset($durationbyday[$day])) { $cell->text .= html_writer::start_tag('ul', array('class' => 'events-underway')); foreach ($durationbyday[$day] as $eventindex) { $cell->text .= html_writer::tag('li', '[' . format_string($events[$eventindex]->name, true) . ']', array('class' => 'events-underway')); } $cell->text .= html_writer::end_tag('ul'); } $row->cells[] = $cell; } // Paddding (the last week may have blank days at the end) for ($i = $dayweek; $i <= $display->maxwday; ++$i) { $cell = new html_table_cell(' '); $cell->attributes = array('class' => 'nottoday dayblank'); $row->cells[] = $cell; } $table->data[] = $row; $output .= html_writer::table($table); return $output; }
function get_course_mods($id, $username = '') { global $CFG, $DB; $username = utf8_decode($username); $username = strtolower($username); if ($username) { $user = get_complete_user_data('username', $username); } $modinfo = get_fast_modinfo($id); $sections = $modinfo->get_section_info_all(); $forum = forum_get_course_forum($id, 'news'); $news_forum_id = $forum->id; $mods = get_fast_modinfo($id)->get_cms(); $modnames = get_module_types_names(); $modnamesplural = get_module_types_names(true); $modnamesused = get_fast_modinfo($id)->get_used_module_names(); $rawmods = get_course_mods($id); $context = context_course::instance($id); // Kludge to use username param to get non visible sections and modules $username_orig = $username; if ($username_orig == 'joomdle_get_not_visible') { $username = ''; } $e = array(); foreach ($sections as $section) { if ($username_orig != 'joomdle_get_not_visible') { if (!$section->visible) { continue; } } $sectionmods = explode(",", $section->sequence); foreach ($sectionmods as $modnumber) { if (empty($mods[$modnumber])) { continue; } $mod = $mods[$modnumber]; if ($username_orig != 'joomdle_get_not_visible') { if (!$mod->visible) { continue; } } $resource['completion_info'] = ''; if ($username) { $cm = get_coursemodule_from_id(false, $mod->id); if (!\core_availability\info_module::is_user_visible($cm, $user->id)) { if (empty($mod->availableinfo)) { // Mod not visible, and no completion info to show continue; } $resource['available'] = 0; $ci = new condition_info($mod); $resource['completion_info'] = $ci->get_full_information(); } else { $resource['available'] = 1; } } else { $resource['available'] = 1; } $e[$section->section]['section'] = $section->section; $e[$section->section]['name'] = $section->name; $e[$section->section]['summary'] = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php', $context->id, 'course', 'section', $section->id); $e[$section->section]['summary'] = str_replace('pluginfile.php', '/auth/joomdle/pluginfile_joomdle.php', $e[$section->section]['summary']); $resource['id'] = $mod->id; $resource['name'] = $mod->name; $resource['mod'] = $mod->modname; // Get content $resource['content'] = ''; $modname = $mod->modname; $functionname = $modname . "_get_coursemodule_info"; if (file_exists("{$CFG->dirroot}/mod/{$modname}/lib.php")) { include_once "{$CFG->dirroot}/mod/{$modname}/lib.php"; if ($hasfunction = function_exists($functionname)) { if ($info = $functionname($rawmods[$modnumber])) { $resource['content'] = $info->content; } } } // Format for mod->icon is: f/type-24 $type = substr($mod->icon, 2); $parts = explode('-', $type); $type = $parts[0]; $resource['type'] = $type; //In forum, type is unused, so we use it for forum type: news/general if ($mod->modname == 'forum') { $cm = get_coursemodule_from_id('forum', $mod->id); if ($cm->instance == $news_forum_id) { $resource['type'] = 'news'; } } /* if ($mod->modname == 'resource') { // Get display options for resource $params = array ($mod->instance); $query = "SELECT display from {$CFG->prefix}resource where id = ?"; $record = $DB->get_record_sql ($query, $params); $resource['display'] = $record->display; } else $resource['display'] = 0; */ $resource['display'] = $this->get_display($mod->modname, $mod->instance); $e[$section->section]['mods'][] = $resource; } } return $e; }
/** * Process a message received and validated by the Inbound Message processor. * * @throws \core\message\inbound\processing_failed_exception * @param \stdClass $messagedata The Inbound Message record * @param \stdClass $messagedata The message data packet * @return bool Whether the message was successfully processed. */ public function process_message(\stdClass $record, \stdClass $messagedata) { global $DB, $USER; // Load the post being replied to. $post = $DB->get_record('forum_posts', array('id' => $record->datavalue)); if (!$post) { mtrace("--> Unable to find a post matching with id {$record->datavalue}"); return false; } // Load the discussion that this post is in. $discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion)); if (!$post) { mtrace("--> Unable to find the discussion for post {$record->datavalue}"); return false; } // Load the other required data. $forum = $DB->get_record('forum', array('id' => $discussion->forum)); $course = $DB->get_record('course', array('id' => $forum->course)); $cm = get_fast_modinfo($course->id)->instances['forum'][$forum->id]; $modcontext = \context_module::instance($cm->id); $usercontext = \context_user::instance($USER->id); // Make sure user can post in this discussion. $canpost = true; if (!forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext)) { $canpost = false; } if (isset($cm->groupmode) && empty($course->groupmodeforce)) { $groupmode = $cm->groupmode; } else { $groupmode = $course->groupmode; } if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $modcontext)) { if ($discussion->groupid == -1) { $canpost = false; } else { if (!groups_is_member($discussion->groupid)) { $canpost = false; } } } if (!$canpost) { $data = new \stdClass(); $data->forum = $forum; throw new \core\message\inbound\processing_failed_exception('messageinboundnopostforum', 'mod_forum', $data); } // And check the availability. if (!\core_availability\info_module::is_user_visible($cm, $USER, true)) { $data = new \stdClass(); $data->forum = $forum; throw new \core\message\inbound\processing_failed_exception('messageinboundforumhidden', 'mod_forum', $data); } // Before we add this we must check that the user will not exceed the blocking threshold. // This should result in an appropriate reply. $thresholdwarning = forum_check_throttling($forum, $cm); if (!empty($thresholdwarning) && !$thresholdwarning->canpost) { $data = new \stdClass(); $data->forum = $forum; $data->message = get_string($thresholdwarning->errorcode, $thresholdwarning->module, $thresholdwarning->additional); throw new \core\message\inbound\processing_failed_exception('messageinboundthresholdhit', 'mod_forum', $data); } $addpost = new \stdClass(); $addpost->course = $course->id; $addpost->forum = $forum->id; $addpost->discussion = $discussion->id; $addpost->modified = $messagedata->timestamp; $addpost->subject = clean_param($messagedata->envelope->subject, PARAM_TEXT); $addpost->parent = $post->id; $addpost->itemid = file_get_unused_draft_itemid(); if (!empty($messagedata->html)) { $addpost->message = $messagedata->html; $addpost->messageformat = FORMAT_HTML; } else { $addpost->message = $messagedata->plain; $addpost->messageformat = FORMAT_PLAIN; } // We don't trust text coming from e-mail. $addpost->messagetrust = false; // Add attachments to the post. if (!empty($messagedata->attachments['attachment']) && count($messagedata->attachments['attachment'])) { $attachmentcount = count($messagedata->attachments['attachment']); if (empty($forum->maxattachments) || $forum->maxbytes == 1 || !has_capability('mod/forum:createattachment', $modcontext)) { // Attachments are not allowed. mtrace("--> User does not have permission to attach files in this forum. Rejecting e-mail."); $data = new \stdClass(); $data->forum = $forum; $data->attachmentcount = $attachmentcount; throw new \core\message\inbound\processing_failed_exception('messageinboundattachmentdisallowed', 'mod_forum', $data); } if ($forum->maxattachments < $attachmentcount) { // Too many attachments. mtrace("--> User attached {$attachmentcount} files when only {$forum->maxattachments} where allowed. " . " Rejecting e-mail."); $data = new \stdClass(); $data->forum = $forum; $data->attachmentcount = $attachmentcount; throw new \core\message\inbound\processing_failed_exception('messageinboundfilecountexceeded', 'mod_forum', $data); } $filesize = 0; $addpost->attachments = file_get_unused_draft_itemid(); foreach ($messagedata->attachments['attachment'] as $attachment) { mtrace("--> Processing {$attachment->filename} as an attachment."); $this->process_attachment('*', $usercontext, $addpost->attachments, $attachment); $filesize += $attachment->filesize; } if ($forum->maxbytes < $filesize) { // Too many attachments. mtrace("--> User attached {$filesize} bytes of files when only {$forum->maxbytes} where allowed. " . "Rejecting e-mail."); $data = new \stdClass(); $data->forum = $forum; $data->maxbytes = display_size($forum->maxbytes); $data->filesize = display_size($filesize); throw new \core\message\inbound\processing_failed_exception('messageinboundfilesizeexceeded', 'mod_forum', $data); } } // Process any files in the message itself. if (!empty($messagedata->attachments['inline'])) { foreach ($messagedata->attachments['inline'] as $attachment) { mtrace("--> Processing {$attachment->filename} as an inline attachment."); $this->process_attachment('*', $usercontext, $addpost->itemid, $attachment); // Convert the contentid link in the message. $draftfile = \moodle_url::make_draftfile_url($addpost->itemid, '/', $attachment->filename); $addpost->message = preg_replace('/cid:' . $attachment->contentid . '/', $draftfile, $addpost->message); } } // Insert the message content now. $addpost->id = forum_add_new_post($addpost, true); // Log the new post creation. $params = array( 'context' => $modcontext, 'objectid' => $addpost->id, 'other' => array( 'discussionid' => $discussion->id, 'forumid' => $forum->id, 'forumtype' => $forum->type, ) ); $event = \mod_forum\event\post_created::create($params); $event->add_record_snapshot('forum_posts', $addpost); $event->add_record_snapshot('forum_discussions', $discussion); $event->trigger(); mtrace("--> Created a post {$addpost->id} in {$discussion->id}."); return $addpost; }
/** * Internal method to retrieve any and all password conditions for the given cm. * * @param cm_info $cm * @return condition[] */ private static function get_password_conditions(cm_info $cm) { $info = new info_module($cm); $tree = $info->get_availability_tree(); return $tree->get_all_children('\\availability_password\\condition'); }
/** * Tests the filter_users() function. */ public function test_filter_users() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; $this->resetAfterTest(); $CFG->enableavailability = true; // Create a course with 2 sections and 2 pages and 3 users. // Availability is set up initially on the 'page/section 2' items. $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 2), array('createsections' => true)); $u1 = $generator->create_user(); $u2 = $generator->create_user(); $u3 = $generator->create_user(); $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST); $allusers = array($u1->id => $u1, $u2->id => $u2, $u3->id => $u3); $generator->enrol_user($u1->id, $course->id, $studentroleid); $generator->enrol_user($u2->id, $course->id, $studentroleid); $generator->enrol_user($u3->id, $course->id, $studentroleid); // Page 2 allows access to users 2 and 3, while section 2 allows access // to users 1 and 2. $pagegen = $generator->get_plugin_generator('mod_page'); $page = $pagegen->create_instance(array('course' => $course)); $page2 = $pagegen->create_instance(array('course' => $course, 'availability' => '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u2->id . ',' . $u3->id . ']}]}')); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(1); $section2 = $modinfo->get_section_info(2); $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u1->id . ',' . $u2->id . ']}]}', array('id' => $section2->id)); moveto_module($modinfo->get_cm($page2->cmid), $section2); // With no restrictions, returns full list. $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // Set an availability restriction in database for section 1. // For the section we set it so it doesn't support filters; for the // module we have a filter. $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","a":false}]}', array('id' => $section->id)); $DB->set_field('course_modules', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u3->id . ']}]}', array('id' => $page->cmid)); rebuild_course_cache($course->id, true); $modinfo = get_fast_modinfo($course); // Now it should work (for the module). $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u3->id), array_keys($info->filter_user_list($allusers))); $info = new info_section($modinfo->get_section_info(1)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // With availability disabled, module returns full list too. $CFG->enableavailability = false; $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // Check the other section... $CFG->enableavailability = true; $info = new info_section($modinfo->get_section_info(2)); $this->assertEquals(array($u1->id, $u2->id), array_keys($info->filter_user_list($allusers))); // And the module in that section - which has combined the section and // module restrictions. $info = new info_module($modinfo->get_cm($page2->cmid)); $this->assertEquals(array($u2->id), array_keys($info->filter_user_list($allusers))); // If the students have viewhiddenactivities, they get past the module // restriction. role_change_permission($studentroleid, context_module::instance($page2->cmid), 'moodle/course:viewhiddenactivities', CAP_ALLOW); $expected = array($u1->id, $u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); // If they have viewhiddensections, they also get past the section // restriction. role_change_permission($studentroleid, context_course::instance($course->id), 'moodle/course:viewhiddensections', CAP_ALLOW); $expected = array($u1->id, $u2->id, $u3->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); }
/** * Determine whether a course module is visible within a course, * this is different from instance_is_visible() - faster and visibility for user * * @global object * @global object * @uses DEBUG_DEVELOPER * @uses CONTEXT_MODULE * @param object $cm object * @param int $userid empty means current user * @return bool Success * @deprecated Since Moodle 2.7 */ function coursemodule_visible_for_user($cm, $userid = 0) { debugging('coursemodule_visible_for_user() deprecated since Moodle 2.7. ' . 'Replace with \\core_availability\\info_module::is_user_visible().'); return \core_availability\info_module::is_user_visible($cm, $userid, false); }
$groupurl = new moodle_url('/group/overview.php', array('id' => $cm->course)); $overridedeleteurl = new moodle_url('/mod/lesson/overridedelete.php'); $overrideediturl = new moodle_url('/mod/lesson/overrideedit.php'); $hasinactive = false; // Whether there are any inactive overrides. foreach ($overrides as $override) { $fields = array(); $values = array(); $active = true; // Check for inactive overrides. if (!$groupmode) { if (!is_enrolled($context, $override->userid)) { // User not enrolled. $active = false; } else { if (!\core_availability\info_module::is_user_visible($cm, $override->userid)) { // User cannot access the module. $active = false; } } } // Format available. if (isset($override->available)) { $fields[] = get_string('lessonopens', 'lesson'); $values[] = $override->available > 0 ? userdate($override->available) : get_string('noopen', 'lesson'); } // Format deadline. if (isset($override->deadline)) { $fields[] = get_string('lessoncloses', 'lesson'); $values[] = $override->deadline > 0 ? userdate($override->deadline) : get_string('noclose', 'lesson'); }
$timeend = time() + $CFG->calendar_exportlookahead * DAYSECS; break; } } else { // Parameters given but incorrect, redirect back to export page redirect($CFG->wwwroot . '/calendar/export.php'); die; } } $events = calendar_get_events($timestart, $timeend, $users, $groups, array_keys($courses), false); $ical = new iCalendar(); $ical->add_property('method', 'PUBLISH'); foreach ($events as $event) { if (!empty($event->modulename)) { $cm = get_coursemodule_from_instance($event->modulename, $event->instance); if (!\core_availability\info_module::is_user_visible($cm, 0, false)) { continue; } } $hostaddress = str_replace('http://', '', $CFG->wwwroot); $hostaddress = str_replace('https://', '', $hostaddress); $ev = new iCalendar_event(); $ev->add_property('uid', $event->id . '@' . $hostaddress); $ev->add_property('summary', $event->name); $ev->add_property('description', clean_param($event->description, PARAM_NOTAGS)); $ev->add_property('class', 'PUBLIC'); // PUBLIC / PRIVATE / CONFIDENTIAL $ev->add_property('last-modified', Bennu::timestamp_to_datetime($event->timemodified)); $ev->add_property('dtstamp', Bennu::timestamp_to_datetime()); // now $ev->add_property('dtstart', Bennu::timestamp_to_datetime($event->timestart));
/** * Get the JSON representation of the users. * * Note that when a limit is set and the exclude array is not empty, then the number of memberships * returned may be less than the limit. * * @param \mod_lti\local\ltiservice\resource_base $resource Resource handling the request * @param array $users Array of user records * @param string $id Course ID * @param object $tool Tool instance object * @param array $exclude Array of user records to be excluded from the response * @param int $limitfrom Position of first record to be returned * @param int $limitnum Maximum number of records to be returned * @param object $lti LTI instance record * @param \core_availability\info_module $info Conditional availability information for LTI instance * * @return string */ private static function users_to_json($resource, $users, $id, $tool, $exclude, $limitfrom, $limitnum, $lti, $info) { $nextpage = 'null'; if ($limitnum > 0) { $limitfrom += $limitnum; $nextpage = "\"{$resource->get_endpoint()}?limit={$limitnum}&from={$limitfrom}\""; } $json = <<<EOD { "@context" : "http://purl.imsglobal.org/ctx/lis/v2/MembershipContainer", "@type" : "Page", "@id" : "{$resource->get_endpoint()}", "nextPage" : {$nextpage}, "pageOf" : { "@type" : "LISMembershipContainer", "membershipSubject" : { "@type" : "Context", "contextId" : "{$id}", "membership" : [ EOD; $enabledcapabilities = lti_get_enabled_capabilities($tool); $sep = ' '; foreach ($users as $user) { $include = !in_array($user->id, $exclude); if ($include && !empty($info)) { $include = $info->is_user_visible($info->get_course_module(), $user->id); } if ($include) { $member = new \stdClass(); if (in_array('User.id', $enabledcapabilities)) { $member->userId = $user->id; } if (in_array('Person.sourcedId', $enabledcapabilities)) { $member->sourcedId = format_string($user->idnumber); } if (in_array('Person.name.full', $enabledcapabilities)) { $member->name = format_string("{$user->firstname} {$user->lastname}"); } if (in_array('Person.name.given', $enabledcapabilities)) { $member->givenName = format_string($user->firstname); } if (in_array('Person.name.family', $enabledcapabilities)) { $member->familyName = format_string($user->lastname); } if (in_array('Person.email.primary', $enabledcapabilities)) { $member->email = format_string($user->email); } if (in_array('Result.sourcedId', $enabledcapabilities) && !empty($lti) && !empty($lti->servicesalt)) { $member->resultSourcedId = json_encode(lti_build_sourcedid($lti->id, $user->id, $lti->servicesalt, $lti->typeid)); } $roles = explode(',', lti_get_ims_role($user->id, null, $id, true)); $membership = new \stdClass(); $membership->status = 'Active'; $membership->member = $member; $membership->role = $roles; $json .= $sep . json_encode($membership); $sep = ",\n "; } } $json .= <<<EOD ] } } } EOD; return $json; }
/** * Execute the request for this resource. * * @param mod_lti\local\ltiservice\response $response Response object for this request. */ public function execute($response) { global $CFG, $DB; $params = $this->parse_template(); $linkid = $params['link_id']; $role = optional_param('role', '', PARAM_TEXT); $limitnum = optional_param('limit', 0, PARAM_INT); $limitfrom = optional_param('from', 0, PARAM_INT); if ($limitnum <= 0) { $limitfrom = 0; } try { if (empty($linkid)) { throw new \Exception(null, 404); } if (!($lti = $DB->get_record('lti', array('id' => $linkid), 'id,course,typeid,servicesalt', IGNORE_MISSING))) { throw new \Exception(null, 404); } $tool = $DB->get_record('lti_types', array('id' => $lti->typeid)); $toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $tool->toolproxyid)); if (!$this->check_tool_proxy($toolproxy->guid, $response->get_request_data())) { throw new \Exception(null, 401); } if (!($course = $DB->get_record('course', array('id' => $lti->course), 'id', IGNORE_MISSING))) { throw new \Exception(null, 404); } if (!($context = \context_course::instance($lti->course))) { throw new \Exception(null, 404); } $modinfo = get_fast_modinfo($course); $cm = get_coursemodule_from_instance('lti', $linkid, $lti->course, false, MUST_EXIST); $cm = $modinfo->get_cm($cm->id); $info = new info_module($cm); if ($info->is_available_for_all()) { $info = null; } $json = memberships::get_users_json($this, $context, $lti->course, $tool, $role, $limitfrom, $limitnum, $lti, $info); $response->set_content_type($this->formats[0]); $response->set_body($json); } catch (\Exception $e) { $response->set_code($e->getCode()); } }
function fix_condition_targetid($labelmods, $resourcemods, $course, $cm, $targetid, $includeungraded = false, $includeresources = false, $includelabels = false, $requirecompletion = false) { global $DB; if ($targetid >= 0) { return intval($targetid); } if (!($modinfo = get_fast_modinfo($course))) { return 0; // shouldn't happen !! } // set default search values $id = 0; $modname = ''; $sectionnum = -1; $requiregraded = false; // restrict search values if ($targetid > 0) { // specific activity $id = $targetid; } else { if ($targetid == PREVIOUS_SAME_COURSE || $targetid == PREVIOUS_SAME_SECTION || $targetid == NEXT_SAME_COURSE || $targetid == NEXT_SAME_SECTION) { // same type of activity $modname = $cm->modname; } if ($targetid == PREVIOUS_ANY_SECTION || $targetid == PREVIOUS_SAME_SECTION || $targetid == NEXT_ANY_SECTION || $targetid == NEXT_SAME_SECTION) { // same section $sectionnum = $cm->sectionnum; } if ($includeungraded == false) { $requiregraded = true; } } // get grade info, if required (we just need to know if an activity has a grade or not) if ($requiregraded) { // basic SQL to get grade items for graded activities $select = 'cm.id, gi.id AS gradeitemid, gi.itemtype, gi.itemmodule, gi.iteminstance, gi.gradetype'; $from = '{grade_items} gi' . ' LEFT JOIN {modules} m ON gi.itemmodule = m.name' . ' LEFT JOIN {course_modules} cm ON m.id = cm.module AND gi.iteminstance = cm.instance'; $where = "gi.courseid = ? AND gi.itemtype = ? AND gi.gradetype <> ?"; $params = array($course->id, 'mod', GRADE_TYPE_NONE); // restrict results to single module, if we can if ($modname) { $where .= ' AND gi.itemmodule = ?'; $params[] = $modname; } // restrict results to current section, if we can if ($sectionnum >= 0) { $from .= ' LEFT JOIN {course_sections} cs ON cs.id = cm.section'; $where .= ' AND cs.section = ?'; $params[] = $sectionnum; } $gradedcms = $DB->get_records_sql("SELECT {$select} FROM {$from} WHERE {$where}", $params); } // are we searching for a PREVIOUS activity (usually we are) $previous = $targetid == PREVIOUS_ANY_COURSE || $targetid == PREVIOUS_ANY_SECTION || $targetid == PREVIOUS_SAME_COURSE || $targetid == PREVIOUS_SAME_SECTION; // get cm ids (reverse order if necessary) $coursemoduleids = array_keys($modinfo->cms); if ($previous) { $coursemoduleids = array_reverse($coursemoduleids); } // search for next, previous or specific course module $found = false; foreach ($coursemoduleids as $coursemoduleid) { if (method_exists($modinfo, 'get_cm')) { $coursemodule = $modinfo->get_cm($coursemoduleid); } else { $coursemodule = $modinfo->cms[$coursemoduleid]; } if ($id && $coursemoduleid != $id) { continue; // wrong activity } if ($sectionnum >= 0) { if ($previous) { if ($coursemodule->sectionnum > $sectionnum) { continue; // later section } if ($coursemodule->sectionnum < $sectionnum) { return 0; // previous section } } else { if ($coursemodule->sectionnum < $sectionnum) { continue; // earlier section } if ($coursemodule->sectionnum > $sectionnum) { return 0; // later section } } } if ($requirecompletion && empty($coursemodule->completion)) { continue; // cm does not have completion conditions } if ($requiregraded && empty($gradedcms[$coursemoduleid])) { continue; // skip ungraded activity } if ($modname && $coursemodule->modname != $modname) { continue; // wrong module } if ($includelabels == false && in_array($coursemodule->modname, $labelmods)) { continue; // skip labels } if ($includeresources == false && in_array($coursemodule->modname, $resourcemods)) { continue; // skip resources } if ($found || $coursemoduleid == $id) { if (class_exists('\\core_availability\\info_module')) { // Moodle >= 2.7 $is_visible = \core_availability\info_module::is_user_visible($coursemodule); } else { // Moodle <= 2.6 // Indirect modification of overloaded property // cm_info::$availableinfo has no effect // lib/datalib.php on line 1588 $is_visible = coursemodule_visible_for_user($coursemodule); } if ($is_visible) { if ($requirecompletion) { // return cm id return intval($coursemoduleid); } else { // return grade item id return intval($gradedcms[$coursemoduleid]->gradeitemid); } } if ($coursemoduleid == $id) { // required cm is not visible to this user return 0; } } if ($coursemoduleid == $cm->id) { $found = true; } } // next/prev cm not found return 0; }
/** * get_cm * * @param xxx $type * @return xxx */ public function get_cm($type) { // gets the next, previous or specific Moodle activity // get entry/exit cm id $cm_field = $type . 'cm'; $cmid = $this->{$cm_field}; if ($cmid == self::ACTIVITY_NONE) { return false; } if (!($modinfo = get_fast_modinfo($this->course))) { return false; // no modinfo - shouldn't happen !! } if (method_exists($modinfo, 'get_cm')) { if (!$modinfo->get_cm($this->cm->id)) { return false; // target cm not found - shouldn't happen !! } } else { if (!isset($modinfo->cms[$this->cm->id])) { return false; // target cm not found - shouldn't happen !! } } // set default search values $id = 0; $modname = ''; $sectionnum = -1; // restrict search values if ($cmid > 0) { $id = $cmid; } else { if ($cmid == self::ACTIVITY_COURSE_HOTPOT || $cmid == self::ACTIVITY_SECTION_HOTPOT) { $modname = 'hotpot'; } if ($cmid == self::ACTIVITY_SECTION_ANY || $cmid == self::ACTIVITY_SECTION_HOTPOT) { $sectionnum = $modinfo->get_cm($this->cm->id)->sectionnum; } } // get cm ids (reverse order if necessary) $cmids = array_keys($modinfo->cms); if ($type == 'entry') { $cmids = array_reverse($cmids); } // search for next, previous or specific course module $found = false; foreach ($cmids as $cmid) { if (method_exists($modinfo, 'get_cm')) { $cm = $modinfo->get_cm($cmid); } else { $cm = $modinfo->cms[$cmid]; } if ($id && $cm->id != $id) { continue; // wrong activity } if ($sectionnum >= 0) { if ($type == 'entry') { if ($cm->sectionnum > $sectionnum) { continue; // later section } if ($cm->sectionnum < $sectionnum) { return false; // previous section } } else { // exit (=next) if ($cm->sectionnum < $sectionnum) { continue; // earlier section } if ($cm->sectionnum > $sectionnum) { return false; // later section } } } if ($modname && $cm->modname != $modname) { continue; // wrong module } if ($cm->modname == 'label') { continue; // skip labels } if ($found || $cm->id == $id) { if (class_exists('\\core_availability\\info_module')) { // Moodle >= 2.7 $is_visible = \core_availability\info_module::is_user_visible($cm); } else { // Moodle <= 2.6 $is_visible = coursemodule_visible_for_user($cm); } if ($is_visible) { return $cm; } if ($cm->id == $id) { // required cm is not visible to this user return false; } } if ($cm->id == $this->cm->id) { $found = true; } } // next cm not found return false; }