function filter($text, array $options = array())
 {
     $coursectx = $this->context->get_course_context(false);
     if (!$coursectx) {
         return $text;
     }
     $courseid = $coursectx->instanceid;
     // Initialise/invalidate our trivial cache if dealing with a different course
     if (!isset(self::$cachedcourseid) || self::$cachedcourseid !== (int) $courseid) {
         self::$activitylist = null;
     }
     self::$cachedcourseid = (int) $courseid;
     /// It may be cached
     if (is_null(self::$activitylist)) {
         self::$activitylist = array();
         $modinfo = get_fast_modinfo($courseid);
         if (!empty($modinfo->cms)) {
             self::$activitylist = array();
             // We will store all the created filters here.
             // Create array of visible activities sorted by the name length (we are only interested in properties name and url).
             $sortedactivities = array();
             foreach ($modinfo->cms as $cm) {
                 // Exclude labels, hidden activities and activities for group members only.
                 if ($cm->visible and empty($cm->groupmembersonly) and $cm->has_view()) {
                     $sortedactivities[] = (object) array('name' => $cm->name, 'url' => $cm->url, 'id' => $cm->id, 'namelen' => strlen($cm->name));
                 }
             }
             core_collator::asort_objects_by_property($sortedactivities, 'namelen', SORT_NUMERIC);
             foreach ($sortedactivities as $cm) {
                 $title = s(trim(strip_tags($cm->name)));
                 $currentname = trim($cm->name);
                 $entitisedname = s($currentname);
                 // Avoid empty or unlinkable activity names.
                 if (!empty($title)) {
                     $href_tag_begin = html_writer::start_tag('a', array('class' => 'autolink', 'title' => $title, 'href' => $cm->url));
                     self::$activitylist[$cm->id] = new filterobject($currentname, $href_tag_begin, '</a>', false, true);
                     if ($currentname != $entitisedname) {
                         // If name has some entity (&amp; &quot; &lt; &gt;) add that filter too. MDL-17545.
                         self::$activitylist[$cm->id . '-e'] = new filterobject($entitisedname, $href_tag_begin, '</a>', false, true);
                     }
                 }
             }
         }
     }
     $filterslist = array();
     if (self::$activitylist) {
         $cmid = $this->context->instanceid;
         if ($this->context->contextlevel == CONTEXT_MODULE && isset(self::$activitylist[$cmid])) {
             // remove filterobjects for the current module
             $filterslist = array_values(array_diff_key(self::$activitylist, array($cmid => 1, $cmid . '-e' => 1)));
         } else {
             $filterslist = array_values(self::$activitylist);
         }
     }
     if ($filterslist) {
         return $text = filter_phrases($text, $filterslist);
     } else {
         return $text;
     }
 }
/**
 * Set the global activated state for a text filter.
 *
 * @param string $filtername The filter name, for example 'tex'.
 * @param int $state One of the values TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED.
 * @param int $move -1 means up, 0 means the same, 1 means down
 */
function filter_set_global_state($filtername, $state, $move = 0)
{
    global $DB;
    // Check requested state is valid.
    if (!in_array($state, array(TEXTFILTER_ON, TEXTFILTER_OFF, TEXTFILTER_DISABLED))) {
        throw new coding_exception("Illegal option '{$state}' passed to filter_set_global_state. " . "Must be one of TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED.");
    }
    if ($move > 0) {
        $move = 1;
    } else {
        if ($move < 0) {
            $move = -1;
        }
    }
    if (strpos($filtername, 'filter/') === 0) {
        //debugging("Old filtername '$filtername' parameter used in filter_set_global_state()", DEBUG_DEVELOPER);
        $filtername = substr($filtername, 7);
    } else {
        if (strpos($filtername, '/') !== false) {
            throw new coding_exception("Invalid filter name '{$filtername}' used in filter_set_global_state()");
        }
    }
    $transaction = $DB->start_delegated_transaction();
    $syscontext = context_system::instance();
    $filters = $DB->get_records('filter_active', array('contextid' => $syscontext->id), 'sortorder ASC');
    $on = array();
    $off = array();
    foreach ($filters as $f) {
        if ($f->active == TEXTFILTER_DISABLED) {
            $off[$f->filter] = $f;
        } else {
            $on[$f->filter] = $f;
        }
    }
    // Update the state or add new record.
    if (isset($on[$filtername])) {
        $filter = $on[$filtername];
        if ($filter->active != $state) {
            add_to_config_log('filter_active', $filter->active, $state, $filtername);
            $filter->active = $state;
            $DB->update_record('filter_active', $filter);
            if ($filter->active == TEXTFILTER_DISABLED) {
                unset($on[$filtername]);
                $off = array($filter->filter => $filter) + $off;
            }
        }
    } else {
        if (isset($off[$filtername])) {
            $filter = $off[$filtername];
            if ($filter->active != $state) {
                add_to_config_log('filter_active', $filter->active, $state, $filtername);
                $filter->active = $state;
                $DB->update_record('filter_active', $filter);
                if ($filter->active != TEXTFILTER_DISABLED) {
                    unset($off[$filtername]);
                    $on[$filter->filter] = $filter;
                }
            }
        } else {
            add_to_config_log('filter_active', '', $state, $filtername);
            $filter = new stdClass();
            $filter->filter = $filtername;
            $filter->contextid = $syscontext->id;
            $filter->active = $state;
            $filter->sortorder = 99999;
            $filter->id = $DB->insert_record('filter_active', $filter);
            $filters[$filter->id] = $filter;
            if ($state == TEXTFILTER_DISABLED) {
                $off[$filter->filter] = $filter;
            } else {
                $on[$filter->filter] = $filter;
            }
        }
    }
    // Move only active.
    if ($move != 0 and isset($on[$filter->filter])) {
        $i = 1;
        foreach ($on as $f) {
            $f->newsortorder = $i;
            $i++;
        }
        $filter->newsortorder = $filter->newsortorder + $move;
        foreach ($on as $f) {
            if ($f->id == $filter->id) {
                continue;
            }
            if ($f->newsortorder == $filter->newsortorder) {
                if ($move == 1) {
                    $f->newsortorder = $f->newsortorder - 1;
                } else {
                    $f->newsortorder = $f->newsortorder + 1;
                }
            }
        }
        core_collator::asort_objects_by_property($on, 'newsortorder', core_collator::SORT_NUMERIC);
    }
    // Inactive are sorted by filter name.
    core_collator::asort_objects_by_property($off, 'filter', core_collator::SORT_NATURAL);
    // Update records if necessary.
    $i = 1;
    foreach ($on as $f) {
        if ($f->sortorder != $i) {
            $DB->set_field('filter_active', 'sortorder', $i, array('id' => $f->id));
        }
        $i++;
    }
    foreach ($off as $f) {
        if ($f->sortorder != $i) {
            $DB->set_field('filter_active', 'sortorder', $i, array('id' => $f->id));
        }
        $i++;
    }
    $transaction->allow_commit();
}
Exemple #3
0
 /**
  * Returns the children associated with this category.
  *
  * @return part_of_admin_tree[]
  */
 public function get_children()
 {
     // If we should sort and it hasn't already been sorted.
     if ($this->sort && !$this->sorted) {
         if ($this->sortsplit) {
             $categories = array();
             $pages = array();
             foreach ($this->children as $child) {
                 if ($child instanceof admin_category) {
                     $categories[] = $child;
                 } else {
                     $pages[] = $child;
                 }
             }
             core_collator::asort_objects_by_property($categories, 'visiblename');
             core_collator::asort_objects_by_property($pages, 'visiblename');
             if (!$this->sortasc) {
                 $categories = array_reverse($categories);
                 $pages = array_reverse($pages);
             }
             $this->children = array_merge($pages, $categories);
         } else {
             core_collator::asort_objects_by_property($this->children, 'visiblename');
             if (!$this->sortasc) {
                 $this->children = array_reverse($this->children);
             }
         }
         $this->sorted = true;
     }
     return $this->children;
 }
 /**
  * Resort the courses within this category by the given field.
  *
  * @param string $field One of fullname, shortname, idnumber or descending values of each (appended desc)
  * @param bool $cleanup
  * @return bool True for success.
  * @throws coding_exception
  */
 public function resort_courses($field, $cleanup = true)
 {
     global $DB;
     $desc = false;
     if (substr($field, -4) === "desc") {
         $desc = true;
         $field = substr($field, 0, -4);
         // Remove "desc" from field name.
     }
     if ($field !== 'fullname' && $field !== 'shortname' && $field !== 'idnumber' && $field !== 'timecreated') {
         // This is ultra important as we use $field in an SQL statement below this.
         throw new coding_exception('Invalid field requested');
     }
     $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
     $sql = "SELECT c.id, c.sortorder, c.{$field}, {$ctxfields}\n                  FROM {course} c\n             LEFT JOIN {context} ctx ON ctx.instanceid = c.id\n                 WHERE ctx.contextlevel = :ctxlevel AND\n                       c.category = :categoryid";
     $params = array('ctxlevel' => CONTEXT_COURSE, 'categoryid' => $this->id);
     $courses = $DB->get_records_sql($sql, $params);
     if (count($courses) > 0) {
         foreach ($courses as $courseid => $course) {
             context_helper::preload_from_record($course);
             if ($field === 'idnumber') {
                 $course->sortby = $course->idnumber;
             } else {
                 // It'll require formatting.
                 $options = array('context' => context_course::instance($course->id));
                 // We format the string first so that it appears as the user would see it.
                 // This ensures the sorting makes sense to them. However it won't necessarily make
                 // sense to everyone if things like multilang filters are enabled.
                 // We then strip any tags as we don't want things such as image tags skewing the
                 // sort results.
                 $course->sortby = strip_tags(format_string($course->{$field}, true, $options));
             }
             // We set it back here rather than using references as there is a bug with using
             // references in a foreach before passing as an arg by reference.
             $courses[$courseid] = $course;
         }
         // Sort the courses.
         core_collator::asort_objects_by_property($courses, 'sortby', core_collator::SORT_NATURAL);
         if (!empty($desc)) {
             $courses = array_reverse($courses);
         }
         $i = 1;
         foreach ($courses as $course) {
             $DB->set_field('course', 'sortorder', $this->sortorder + $i, array('id' => $course->id));
             $i++;
         }
         if ($cleanup) {
             // This should not be needed but we do it just to be safe.
             fix_course_sortorder();
             cache_helper::purge_by_event('changesincourse');
         }
     }
     return true;
 }
Exemple #5
0
/**
 * Retrieve the messages between two users
 *
 * @param object $user1 the current user
 * @param object $user2 the other user
 * @param int $limitnum the maximum number of messages to retrieve
 * @param bool $viewingnewmessages are we currently viewing new messages?
 */
function message_get_history($user1, $user2, $limitnum=0, $viewingnewmessages=false) {
    global $DB, $CFG;

    $messages = array();

    //we want messages sorted oldest to newest but if getting a subset of messages we need to sort
    //desc to get the last $limitnum messages then flip the order in php
    $sort = 'asc';
    if ($limitnum>0) {
        $sort = 'desc';
    }

    $notificationswhere = null;
    //we have just moved new messages to read. If theyre here to see new messages dont hide notifications
    if (!$viewingnewmessages && $CFG->messaginghidereadnotifications) {
        $notificationswhere = 'AND notification=0';
    }

    //prevent notifications of your own actions appearing in your own message history
    $ownnotificationwhere = ' AND NOT (useridfrom=? AND notification=1)';

    $sql = "((useridto = ? AND useridfrom = ? AND timeusertodeleted = 0) OR
        (useridto = ? AND useridfrom = ? AND timeuserfromdeleted = 0))";
    if ($messages_read = $DB->get_records_select('message_read', $sql . $notificationswhere . $ownnotificationwhere,
                                                    array($user1->id, $user2->id, $user2->id, $user1->id, $user1->id),
                                                    "timecreated $sort", '*', 0, $limitnum)) {
        foreach ($messages_read as $message) {
            $messages[] = $message;
        }
    }
    if ($messages_new = $DB->get_records_select('message', $sql . $ownnotificationwhere,
                                                    array($user1->id, $user2->id, $user2->id, $user1->id, $user1->id),
                                                    "timecreated $sort", '*', 0, $limitnum)) {
        foreach ($messages_new as $message) {
            $messages[] = $message;
        }
    }

    $result = core_collator::asort_objects_by_property($messages, 'timecreated', core_collator::SORT_NUMERIC);

    //if we only want the last $limitnum messages
    $messagecount = count($messages);
    if ($limitnum > 0 && $messagecount > $limitnum) {
        $messages = array_slice($messages, $messagecount - $limitnum, $limitnum, true);
    }

    return $messages;
}
Exemple #6
0
 /**
  * Tests the static asort_objects_by_method method.
  */
 public function test_asort_objects_by_property()
 {
     $objects = array('b' => new string_test_class('ab'), 1 => new string_test_class('aa'), 0 => new string_test_class('cc'));
     $result = core_collator::asort_objects_by_property($objects, 'publicname');
     $this->assertSame(array(1, 'b', 0), array_keys($objects));
     $this->assertSame(array('aa', 'ab', 'cc'), $this->get_ordered_names($objects, 'publicname'));
     $this->assertTrue($result);
     $objects = array('b' => new string_test_class('a20'), 1 => new string_test_class('a1'), 0 => new string_test_class('a100'));
     $result = core_collator::asort_objects_by_property($objects, 'publicname', core_collator::SORT_NATURAL);
     $this->assertSame(array(1, 'b', 0), array_keys($objects));
     $this->assertSame(array('a1', 'a20', 'a100'), $this->get_ordered_names($objects, 'publicname'));
     $this->assertTrue($result);
 }
Exemple #7
0
    }
    if ($swapcategory and $movecategory) {
        $DB->set_field('course_categories', 'sortorder', $swapcategory->sortorder, array('id' => $movecategory->id));
        $DB->set_field('course_categories', 'sortorder', $movecategory->sortorder, array('id' => $swapcategory->id));
        cache_helper::purge_by_event('changesincoursecat');
        add_to_log(SITEID, "category", "move", "editcategory.php?id=$movecategory->id", $movecategory->id);
    }

    // Finally reorder courses.
    fix_course_sortorder();
}

if ($coursecat->id && $canmanage && $resort && confirm_sesskey()) {
    // Resort the category.
    if ($courses = get_courses($coursecat->id, '', 'c.id,c.fullname,c.sortorder')) {
        core_collator::asort_objects_by_property($courses, 'fullname', core_collator::SORT_NATURAL);
        $i = 1;
        foreach ($courses as $course) {
            $DB->set_field('course', 'sortorder', $coursecat->sortorder + $i, array('id' => $course->id));
            $i++;
        }
        // This should not be needed but we do it just to be safe.
        fix_course_sortorder();
        cache_helper::purge_by_event('changesincourse');
    }
}

if (!empty($moveto) && ($data = data_submitted()) && confirm_sesskey()) {
    // Move a specified course to a new category.
    // User must have category update in both cats to perform this.
    require_capability('moodle/category:manage', $context);
Exemple #8
0
/**
 * Given a course and a time, this module should find recent activity
 * that has occurred in workshop activities and print it out.
 * Return true if there was output, or false is there was none.
 *
 * @param stdClass $course
 * @param bool $viewfullnames
 * @param int $timestart
 * @return boolean
 */
function workshop_print_recent_activity($course, $viewfullnames, $timestart) {
    global $CFG, $USER, $DB, $OUTPUT;

    $authoramefields = get_all_user_name_fields(true, 'author', null, 'author');
    $reviewerfields = get_all_user_name_fields(true, 'reviewer', null, 'reviewer');

    $sql = "SELECT s.id AS submissionid, s.title AS submissiontitle, s.timemodified AS submissionmodified,
                   author.id AS authorid, $authoramefields, a.id AS assessmentid, a.timemodified AS assessmentmodified,
                   reviewer.id AS reviewerid, $reviewerfields, cm.id AS cmid
              FROM {workshop} w
        INNER JOIN {course_modules} cm ON cm.instance = w.id
        INNER JOIN {modules} md ON md.id = cm.module
        INNER JOIN {workshop_submissions} s ON s.workshopid = w.id
        INNER JOIN {user} author ON s.authorid = author.id
         LEFT JOIN {workshop_assessments} a ON a.submissionid = s.id
         LEFT JOIN {user} reviewer ON a.reviewerid = reviewer.id
             WHERE cm.course = ?
                   AND md.name = 'workshop'
                   AND s.example = 0
                   AND (s.timemodified > ? OR a.timemodified > ?)
          ORDER BY s.timemodified";

    $rs = $DB->get_recordset_sql($sql, array($course->id, $timestart, $timestart));

    $modinfo = get_fast_modinfo($course); // reference needed because we might load the groups

    $submissions = array(); // recent submissions indexed by submission id
    $assessments = array(); // recent assessments indexed by assessment id
    $users       = array();

    foreach ($rs as $activity) {
        if (!array_key_exists($activity->cmid, $modinfo->cms)) {
            // this should not happen but just in case
            continue;
        }

        $cm = $modinfo->cms[$activity->cmid];
        if (!$cm->uservisible) {
            continue;
        }

        // remember all user names we can use later
        if (empty($users[$activity->authorid])) {
            $u = new stdclass();
            $users[$activity->authorid] = username_load_fields_from_object($u, $activity, 'author');
        }
        if ($activity->reviewerid and empty($users[$activity->reviewerid])) {
            $u = new stdclass();
            $users[$activity->reviewerid] = username_load_fields_from_object($u, $activity, 'reviewer');
        }

        $context = context_module::instance($cm->id);
        $groupmode = groups_get_activity_groupmode($cm, $course);

        if ($activity->submissionmodified > $timestart and empty($submissions[$activity->submissionid])) {
            $s = new stdclass();
            $s->title = $activity->submissiontitle;
            $s->authorid = $activity->authorid;
            $s->timemodified = $activity->submissionmodified;
            $s->cmid = $activity->cmid;
            if ($activity->authorid == $USER->id || has_capability('mod/workshop:viewauthornames', $context)) {
                $s->authornamevisible = true;
            } else {
                $s->authornamevisible = false;
            }

            // the following do-while wrapper allows to break from deeply nested if-statements
            do {
                if ($s->authorid === $USER->id) {
                    // own submissions always visible
                    $submissions[$activity->submissionid] = $s;
                    break;
                }

                if (has_capability('mod/workshop:viewallsubmissions', $context)) {
                    if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
                        if (isguestuser()) {
                            // shortcut - guest user does not belong into any group
                            break;
                        }

                        // this might be slow - show only submissions by users who share group with me in this cm
                        if (!$modinfo->get_groups($cm->groupingid)) {
                            break;
                        }
                        $authorsgroups = groups_get_all_groups($course->id, $s->authorid, $cm->groupingid);
                        if (is_array($authorsgroups)) {
                            $authorsgroups = array_keys($authorsgroups);
                            $intersect = array_intersect($authorsgroups, $modinfo->get_groups($cm->groupingid));
                            if (empty($intersect)) {
                                break;
                            } else {
                                // can see all submissions and shares a group with the author
                                $submissions[$activity->submissionid] = $s;
                                break;
                            }
                        }

                    } else {
                        // can see all submissions from all groups
                        $submissions[$activity->submissionid] = $s;
                    }
                }
            } while (0);
        }

        if ($activity->assessmentmodified > $timestart and empty($assessments[$activity->assessmentid])) {
            $a = new stdclass();
            $a->submissionid = $activity->submissionid;
            $a->submissiontitle = $activity->submissiontitle;
            $a->reviewerid = $activity->reviewerid;
            $a->timemodified = $activity->assessmentmodified;
            $a->cmid = $activity->cmid;
            if ($activity->reviewerid == $USER->id || has_capability('mod/workshop:viewreviewernames', $context)) {
                $a->reviewernamevisible = true;
            } else {
                $a->reviewernamevisible = false;
            }

            // the following do-while wrapper allows to break from deeply nested if-statements
            do {
                if ($a->reviewerid === $USER->id) {
                    // own assessments always visible
                    $assessments[$activity->assessmentid] = $a;
                    break;
                }

                if (has_capability('mod/workshop:viewallassessments', $context)) {
                    if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
                        if (isguestuser()) {
                            // shortcut - guest user does not belong into any group
                            break;
                        }

                        // this might be slow - show only submissions by users who share group with me in this cm
                        if (!$modinfo->get_groups($cm->groupingid)) {
                            break;
                        }
                        $reviewersgroups = groups_get_all_groups($course->id, $a->reviewerid, $cm->groupingid);
                        if (is_array($reviewersgroups)) {
                            $reviewersgroups = array_keys($reviewersgroups);
                            $intersect = array_intersect($reviewersgroups, $modinfo->get_groups($cm->groupingid));
                            if (empty($intersect)) {
                                break;
                            } else {
                                // can see all assessments and shares a group with the reviewer
                                $assessments[$activity->assessmentid] = $a;
                                break;
                            }
                        }

                    } else {
                        // can see all assessments from all groups
                        $assessments[$activity->assessmentid] = $a;
                    }
                }
            } while (0);
        }
    }
    $rs->close();

    $shown = false;

    if (!empty($submissions)) {
        $shown = true;
        echo $OUTPUT->heading(get_string('recentsubmissions', 'workshop'), 3);
        foreach ($submissions as $id => $submission) {
            $link = new moodle_url('/mod/workshop/submission.php', array('id'=>$id, 'cmid'=>$submission->cmid));
            if ($submission->authornamevisible) {
                $author = $users[$submission->authorid];
            } else {
                $author = null;
            }
            print_recent_activity_note($submission->timemodified, $author, $submission->title, $link->out(), false, $viewfullnames);
        }
    }

    if (!empty($assessments)) {
        $shown = true;
        echo $OUTPUT->heading(get_string('recentassessments', 'workshop'), 3);
        core_collator::asort_objects_by_property($assessments, 'timemodified');
        foreach ($assessments as $id => $assessment) {
            $link = new moodle_url('/mod/workshop/assessment.php', array('asid' => $id));
            if ($assessment->reviewernamevisible) {
                $reviewer = $users[$assessment->reviewerid];
            } else {
                $reviewer = null;
            }
            print_recent_activity_note($assessment->timemodified, $reviewer, $assessment->submissiontitle, $link->out(), false, $viewfullnames);
        }
    }

    if ($shown) {
        return true;
    }

    return false;
}
Exemple #9
0
/**
 * Get the users recent conversations meaning all the people they've recently
 * sent or received a message from plus the most recent message sent to or received from each other user
 *
 * @param object|int $userorid the current user or user id
 * @param int $limitfrom can be used for paging
 * @param int $limitto can be used for paging
 * @return array
 */
function message_get_recent_conversations($userorid, $limitfrom = 0, $limitto = 100) {
    global $DB;

    if (is_object($userorid)) {
        $user = $userorid;
    } else {
        $userid = $userorid;
        $user = new stdClass();
        $user->id = $userid;
    }

    $userfields = user_picture::fields('otheruser', array('lastaccess'));

    // This query retrieves the most recent message received from or sent to
    // seach other user.
    //
    // If two messages have the same timecreated, we take the one with the
    // larger id.
    //
    // There is a separate query for read and unread messages as they are stored
    // in different tables. They were originally retrieved in one query but it
    // was so large that it was difficult to be confident in its correctness.
    $uniquefield = $DB->sql_concat('message.useridfrom', "'-'", 'message.useridto');
    $sql = "SELECT $uniquefield, $userfields,
                   message.id as mid, message.notification, message.useridfrom, message.useridto,
                   message.smallmessage, message.fullmessage, message.fullmessagehtml,
                   message.fullmessageformat, message.timecreated,
                   contact.id as contactlistid, contact.blocked
              FROM {message_read} message
              JOIN (
                        SELECT MAX(id) AS messageid,
                               matchedmessage.useridto,
                               matchedmessage.useridfrom
                         FROM {message_read} matchedmessage
                   INNER JOIN (
                               SELECT MAX(recentmessages.timecreated) timecreated,
                                      recentmessages.useridfrom,
                                      recentmessages.useridto
                                 FROM {message_read} recentmessages
                                WHERE (
                                      (recentmessages.useridfrom = :userid1 AND recentmessages.timeuserfromdeleted = 0) OR
                                      (recentmessages.useridto = :userid2   AND recentmessages.timeusertodeleted = 0)
                                      )
                             GROUP BY recentmessages.useridfrom, recentmessages.useridto
                              ) recent ON matchedmessage.useridto     = recent.useridto
                           AND matchedmessage.useridfrom   = recent.useridfrom
                           AND matchedmessage.timecreated  = recent.timecreated
                           WHERE (
                                 (matchedmessage.useridfrom = :userid6 AND matchedmessage.timeuserfromdeleted = 0) OR
                                 (matchedmessage.useridto = :userid7   AND matchedmessage.timeusertodeleted = 0)
                                 )
                      GROUP BY matchedmessage.useridto, matchedmessage.useridfrom
                   ) messagesubset ON messagesubset.messageid = message.id
              JOIN {user} otheruser ON (message.useridfrom = :userid4 AND message.useridto = otheruser.id)
                OR (message.useridto   = :userid5 AND message.useridfrom   = otheruser.id)
         LEFT JOIN {message_contacts} contact ON contact.userid  = :userid3 AND contact.contactid = otheruser.id
             WHERE otheruser.deleted = 0 AND message.notification = 0
          ORDER BY message.timecreated DESC";
    $params = array(
            'userid1' => $user->id,
            'userid2' => $user->id,
            'userid3' => $user->id,
            'userid4' => $user->id,
            'userid5' => $user->id,
            'userid6' => $user->id,
            'userid7' => $user->id
        );
    $read = $DB->get_records_sql($sql, $params, $limitfrom, $limitto);

    // We want to get the messages that have not been read. These are stored in the 'message' table. It is the
    // exact same query as the one above, except for the table we are querying. So, simply replace references to
    // the 'message_read' table with the 'message' table.
    $sql = str_replace('{message_read}', '{message}', $sql);
    $unread = $DB->get_records_sql($sql, $params, $limitfrom, $limitto);

    $unreadcountssql = 'SELECT useridfrom, count(*) as count
                          FROM {message}
                         WHERE useridto = :userid
                           AND timeusertodeleted = 0
                           AND notification = 0
                      GROUP BY useridfrom';
    $unreadcounts = $DB->get_records_sql($unreadcountssql, array('userid' => $user->id));

    // Union the 2 result sets together looking for the message with the most
    // recent timecreated for each other user.
    // $conversation->id (the array key) is the other user's ID.
    $conversations = array();
    $conversation_arrays = array($unread, $read);
    foreach ($conversation_arrays as $conversation_array) {
        foreach ($conversation_array as $conversation) {
            // Only consider it unread if $user has unread messages.
            if (isset($unreadcounts[$conversation->useridfrom])) {
                $conversation->isread = 0;
                $conversation->unreadcount = $unreadcounts[$conversation->useridfrom]->count;
            } else {
                $conversation->isread = 1;
            }

            if (!isset($conversations[$conversation->id])) {
                $conversations[$conversation->id] = $conversation;
            } else {
                $current = $conversations[$conversation->id];
                // We need to maintain the isread and unreadcount values from existing
                // parts of the conversation if we're replacing it.
                $conversation->isread = ($conversation->isread && $current->isread);
                if (isset($current->unreadcount) && !isset($conversation->unreadcount)) {
                    $conversation->unreadcount = $current->unreadcount;
                }

                if ($current->timecreated < $conversation->timecreated) {
                    $conversations[$conversation->id] = $conversation;
                } else if ($current->timecreated == $conversation->timecreated) {
                    if ($current->mid < $conversation->mid) {
                        $conversations[$conversation->id] = $conversation;
                    }
                }
            }
        }
    }

    // Sort the conversations by $conversation->timecreated, newest to oldest
    // There may be multiple conversations with the same timecreated
    // The conversations array contains both read and unread messages (different tables) so sorting by ID won't work
    $result = core_collator::asort_objects_by_property($conversations, 'timecreated', core_collator::SORT_NUMERIC);
    $conversations = array_reverse($conversations);

    return $conversations;
}
Exemple #10
0
        $settingspath = $path . '/settings.php';
        if (file_exists($settingspath)) {
            $settings = new admin_settingpage('cachestore_' . $plugin . '_settings', new lang_string('pluginname', 'cachestore_' . $plugin), 'moodle/site:config');
            include $settingspath;
            $ADMIN->add('cachestores', $settings);
        }
    }
}
// Add Calendar type settings.
if ($hassiteconfig) {
    $ADMIN->add('modules', new admin_category('calendartype', new lang_string('calendartypes', 'calendar')));
    $plugins = core_plugin_manager::instance()->get_plugins_of_type('calendartype');
    core_collator::asort_objects_by_property($plugins, 'displayname');
    foreach ($plugins as $plugin) {
        /** @var \core\plugininfo\calendartype $plugin */
        $plugin->load_settings($ADMIN, 'calendartype', $hassiteconfig);
    }
}
/// Add all local plugins - must be always last!
if ($hassiteconfig) {
    $ADMIN->add('modules', new admin_category('localplugins', new lang_string('localplugins')));
    $ADMIN->add('localplugins', new admin_externalpage('managelocalplugins', new lang_string('localpluginsmanage'), $CFG->wwwroot . '/' . $CFG->admin . '/localplugins.php'));
}
// Extend settings for each local plugin. Note that their settings may be in any part of the
// settings tree and may be visible not only for administrators.
$plugins = core_plugin_manager::instance()->get_plugins_of_type('local');
core_collator::asort_objects_by_property($plugins, 'displayname');
foreach ($plugins as $plugin) {
    /** @var \core\plugininfo\local $plugin */
    $plugin->load_settings($ADMIN, null, $hassiteconfig);
}
Exemple #11
0
/**
 * Retrieve all metadata for the requested modules
 *
 * @param object $course The Course
 * @param array $modnames An array containing the list of modules and their
 * names
 * @param int $sectionreturn The section to return to
 * @return array A list of stdClass objects containing metadata about each
 * module
 */
function get_module_metadata($course, $modnames, $sectionreturn = null)
{
    global $OUTPUT;
    // get_module_metadata will be called once per section on the page and courses may show
    // different modules to one another
    static $modlist = array();
    if (!isset($modlist[$course->id])) {
        $modlist[$course->id] = array();
    }
    $return = array();
    $urlbase = new moodle_url('/course/mod.php', array('id' => $course->id, 'sesskey' => sesskey()));
    if ($sectionreturn !== null) {
        $urlbase->param('sr', $sectionreturn);
    }
    foreach ($modnames as $modname => $modnamestr) {
        if (!course_allowed_module($course, $modname)) {
            continue;
        }
        if (isset($modlist[$course->id][$modname])) {
            // This module is already cached
            $return += $modlist[$course->id][$modname];
            continue;
        }
        $modlist[$course->id][$modname] = array();
        // Create an object for a default representation of this module type in the activity chooser. It will be used
        // if module does not implement callback get_shortcuts() and it will also be passed to the callback if it exists.
        $defaultmodule = new stdClass();
        $defaultmodule->title = $modnamestr;
        $defaultmodule->name = $modname;
        $defaultmodule->link = new moodle_url($urlbase, array('add' => $modname));
        $defaultmodule->icon = $OUTPUT->pix_icon('icon', '', $defaultmodule->name, array('class' => 'icon'));
        $sm = get_string_manager();
        if ($sm->string_exists('modulename_help', $modname)) {
            $defaultmodule->help = get_string('modulename_help', $modname);
            if ($sm->string_exists('modulename_link', $modname)) {
                // Link to further info in Moodle docs.
                $link = get_string('modulename_link', $modname);
                $linktext = get_string('morehelp');
                $defaultmodule->help .= html_writer::tag('div', $OUTPUT->doc_link($link, $linktext, true), array('class' => 'helpdoclink'));
            }
        }
        $defaultmodule->archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
        // Legacy support for callback get_types() - do not use any more, use get_shortcuts() instead!
        $typescallbackexists = component_callback_exists($modname, 'get_types');
        // Each module can implement callback modulename_get_shortcuts() in its lib.php and return the list
        // of elements to be added to activity chooser.
        $items = component_callback($modname, 'get_shortcuts', array($defaultmodule), null);
        if ($items !== null) {
            foreach ($items as $item) {
                // Add all items to the return array. All items must have different links, use them as a key in the return array.
                if (!isset($item->archetype)) {
                    $item->archetype = $defaultmodule->archetype;
                }
                if (!isset($item->icon)) {
                    $item->icon = $defaultmodule->icon;
                }
                // If plugin returned the only one item with the same link as default item - cache it as $modname,
                // otherwise append the link url to the module name.
                $item->name = count($items) == 1 && $item->link->out() === $defaultmodule->link->out() ? $modname : $modname . ':' . $item->link;
                // If the module provides the helptext property, append it to the help text to match the look and feel
                // of the default course modules.
                if (isset($item->help) && isset($item->helplink)) {
                    $linktext = get_string('morehelp');
                    $item->help .= html_writer::tag('div', $OUTPUT->doc_link($item->helplink, $linktext, true), array('class' => 'helpdoclink'));
                }
                $modlist[$course->id][$modname][$item->name] = $item;
            }
            $return += $modlist[$course->id][$modname];
            if ($typescallbackexists) {
                debugging('Both callbacks get_shortcuts() and get_types() are found in module ' . $modname . '. Callback get_types() will be completely ignored', DEBUG_DEVELOPER);
            }
            // If get_shortcuts() callback is defined, the default module action is not added.
            // It is a responsibility of the callback to add it to the return value unless it is not needed.
            continue;
        }
        if ($typescallbackexists) {
            debugging('Callback get_types() is found in module ' . $modname . ', this functionality is deprecated, ' . 'please use callback get_shortcuts() instead', DEBUG_DEVELOPER);
        }
        $types = component_callback($modname, 'get_types', array(), MOD_SUBTYPE_NO_CHILDREN);
        if ($types !== MOD_SUBTYPE_NO_CHILDREN) {
            // Legacy support for deprecated callback get_types(). To be removed in Moodle 3.5. TODO MDL-53697.
            if (is_array($types) && count($types) > 0) {
                $grouptitle = $modnamestr;
                $icon = $OUTPUT->pix_icon('icon', '', $modname, array('class' => 'icon'));
                foreach ($types as $type) {
                    if ($type->typestr === '--') {
                        continue;
                    }
                    if (strpos($type->typestr, '--') === 0) {
                        $grouptitle = str_replace('--', '', $type->typestr);
                        continue;
                    }
                    // Set the Sub Type metadata.
                    $subtype = new stdClass();
                    $subtype->title = get_string('activitytypetitle', '', (object) ['activity' => $grouptitle, 'type' => $type->typestr]);
                    $subtype->type = str_replace('&amp;', '&', $type->type);
                    $typename = preg_replace('/.*type=/', '', $subtype->type);
                    $subtype->archetype = $type->modclass;
                    if (!empty($type->help)) {
                        $subtype->help = $type->help;
                    } else {
                        if (get_string_manager()->string_exists('help' . $subtype->name, $modname)) {
                            $subtype->help = get_string('help' . $subtype->name, $modname);
                        }
                    }
                    $subtype->link = new moodle_url($urlbase, array('add' => $modname, 'type' => $typename));
                    $subtype->name = $modname . ':' . $subtype->link;
                    $subtype->icon = $icon;
                    $modlist[$course->id][$modname][$subtype->name] = $subtype;
                }
                $return += $modlist[$course->id][$modname];
            }
        } else {
            // Neither get_shortcuts() nor get_types() callbacks found, use the default item for the activity chooser.
            $modlist[$course->id][$modname][$modname] = $defaultmodule;
            $return[$modname] = $defaultmodule;
        }
    }
    core_collator::asort_objects_by_property($return, 'title');
    return $return;
}
Exemple #12
0
 /**
  * The list of block types that may be added to this page.
  *
  * @return array block name => record from block table.
  */
 public function get_addable_blocks()
 {
     $this->check_is_loaded();
     if (!is_null($this->addableblocks)) {
         return $this->addableblocks;
     }
     // Lazy load.
     $this->addableblocks = array();
     $allblocks = blocks_get_record();
     if (empty($allblocks)) {
         return $this->addableblocks;
     }
     $unaddableblocks = self::get_undeletable_block_types();
     $requiredbythemeblocks = self::get_required_by_theme_block_types();
     $pageformat = $this->page->pagetype;
     foreach ($allblocks as $block) {
         if (!($bi = block_instance($block->name))) {
             continue;
         }
         if ($block->visible && !in_array($block->name, $unaddableblocks) && !in_array($block->name, $requiredbythemeblocks) && ($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) && blocks_name_allowed_in_format($block->name, $pageformat) && $bi->user_can_addto($this->page)) {
             $block->title = $bi->get_title();
             $this->addableblocks[$block->name] = $block;
         }
     }
     core_collator::asort_objects_by_property($this->addableblocks, 'title');
     return $this->addableblocks;
 }
Exemple #13
0
require_capability('moodle/course:managegroups', $context);
$strgroups = get_string('groups');
$strparticipants = get_string('participants');
$stroverview = get_string('overview', 'group');
$strgrouping = get_string('grouping', 'group');
$strgroup = get_string('group', 'group');
$strnotingrouping = get_string('notingrouping', 'group');
$strfiltergroups = get_string('filtergroups', 'group');
$strnogroups = get_string('nogroups', 'group');
$strdescription = get_string('description');
// Get all groupings and sort them by formatted name.
$groupings = $DB->get_records('groupings', array('courseid' => $courseid), 'name');
foreach ($groupings as $gid => $grouping) {
    $groupings[$gid]->formattedname = format_string($grouping->name, true, array('context' => $context));
}
core_collator::asort_objects_by_property($groupings, 'formattedname');
$members = array();
foreach ($groupings as $grouping) {
    $members[$grouping->id] = array();
}
$members[-1] = array();
//groups not in a grouping
// Get all groups
$groups = $DB->get_records('groups', array('courseid' => $courseid), 'name');
$params = array('courseid' => $courseid);
if ($groupid) {
    $groupwhere = "AND g.id = :groupid";
    $params['groupid'] = $groupid;
} else {
    $groupwhere = "";
}
Exemple #14
0
 /**
  * Reorder observers to allow quick lookup of observer for each event.
  */
 protected static function order_all_observers()
 {
     foreach (self::$allobservers as $classname => $observers) {
         \core_collator::asort_objects_by_property($observers, 'priority', \core_collator::SORT_NUMERIC);
         self::$allobservers[$classname] = array_reverse($observers);
     }
 }
 /**
  * Import the provided tour JSON.
  *
  * @param   string      $json           The tour configuration.
  * @return  tour
  */
 public static function import_tour_from_json($json)
 {
     $tourconfig = json_decode($json);
     // We do not use this yet - we may do in the future.
     unset($tourconfig->version);
     $steps = $tourconfig->steps;
     unset($tourconfig->steps);
     $tourconfig->id = null;
     $tourconfig->sortorder = null;
     $tour = tour::load_from_record($tourconfig, true);
     $tour->persist(true);
     // Ensure that steps are orderered by their sortorder.
     \core_collator::asort_objects_by_property($steps, 'sortorder', \core_collator::SORT_NUMERIC);
     foreach ($steps as $stepconfig) {
         $stepconfig->id = null;
         $stepconfig->tourid = $tour->get_id();
         $step = step::load_from_record($stepconfig, true);
         $step->persist(true);
     }
     return $tour;
 }