$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
//check if the site is registered on Moodle.org
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
+// Check if there are any cache warnings.
+$cachewarnings = cache_helper::warnings();
admin_externalpage_setup('adminnotifications');
+/* @var core_admin_renderer $output */
$output = $PAGE->get_renderer('core', 'admin');
-echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
- $cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
- $registered);
+
+echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
+ $maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
+ $registered, $cachewarnings);
* @param bool $buggyiconvnomb warn iconv problems
* @param array|null $availableupdates array of \core\update\info objects or null
* @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
+ * @param string[] $cachewarnings An array containing warnings from the Cache API.
*
* @return string HTML to output.
*/
public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
- $buggyiconvnomb, $registered) {
+ $buggyiconvnomb, $registered, array $cachewarnings = array()) {
global $CFG;
$output = '';
$output .= $this->cron_overdue_warning($cronoverdue);
$output .= $this->db_problems($dbproblems);
$output .= $this->maintenance_mode_warning($maintenancemode);
+ $output .= $this->cache_warnings($cachewarnings);
$output .= $this->registration_warning($registered);
//////////////////////////////////////////////////////////////////////////////////////////////////
return $this->warning($dbproblems);
}
+ /**
+ * Renders cache warnings if there are any.
+ *
+ * @param string[] $cachewarnings
+ * @return string
+ */
+ public function cache_warnings(array $cachewarnings) {
+ if (!count($cachewarnings)) {
+ return '';
+ }
+ return join("\n", array_map(array($this, 'warning'), $cachewarnings));
+ }
+
/**
* Render an appropriate message if the site in in maintenance mode.
* @param bool $maintenancemode
$ADMIN->add('accounts', new admin_externalpage('editusers', new lang_string('userlist','admin'), "$CFG->wwwroot/$CFG->admin/user.php", array('moodle/user:update', 'moodle/user:delete')));
$ADMIN->add('accounts', new admin_externalpage('userbulk', new lang_string('userbulk','admin'), "$CFG->wwwroot/$CFG->admin/user/user_bulk.php", array('moodle/user:update', 'moodle/user:delete')));
$ADMIN->add('accounts', new admin_externalpage('addnewuser', new lang_string('addnewuser'), "$securewwwroot/user/editadvanced.php?id=-1", 'moodle/user:create'));
+
+ // "User default preferences" settingpage.
+ $temp = new admin_settingpage('userdefaultpreferences', new lang_string('userdefaultpreferences', 'admin'));
+ if ($ADMIN->fulltree) {
+ $choices = array();
+ $choices['0'] = new lang_string('emaildisplayno');
+ $choices['1'] = new lang_string('emaildisplayyes');
+ $choices['2'] = new lang_string('emaildisplaycourse');
+ $temp->add(new admin_setting_configselect('defaultpreference_maildisplay', new lang_string('emaildisplay'),
+ '', 2, $choices));
+
+ $choices = array();
+ $choices['0'] = new lang_string('textformat');
+ $choices['1'] = new lang_string('htmlformat');
+ $temp->add(new admin_setting_configselect('defaultpreference_mailformat', new lang_string('emailformat'), '', 1, $choices));
+
+ $choices = array();
+ $choices['0'] = new lang_string('emaildigestoff');
+ $choices['1'] = new lang_string('emaildigestcomplete');
+ $choices['2'] = new lang_string('emaildigestsubjects');
+ $temp->add(new admin_setting_configselect('defaultpreference_maildigest', new lang_string('emaildigest'),
+ new lang_string('emaildigest_help'), 0, $choices));
+
+
+ $choices = array();
+ $choices['1'] = new lang_string('autosubscribeyes');
+ $choices['0'] = new lang_string('autosubscribeno');
+ $temp->add(new admin_setting_configselect('defaultpreference_autosubscribe', new lang_string('autosubscribe'),
+ '', 1, $choices));
+
+ if (!empty($CFG->forum_trackreadposts)) {
+ $choices = array();
+ $choices['0'] = new lang_string('trackforumsno');
+ $choices['1'] = new lang_string('trackforumsyes');
+ $temp->add(new admin_setting_configselect('defaultpreference_trackforums', new lang_string('trackforums'),
+ '', 0, $choices));
+ }
+ }
+ $ADMIN->add('accounts', $temp);
+
$ADMIN->add('accounts', new admin_externalpage('profilefields', new lang_string('profilefields','admin'), "$CFG->wwwroot/user/profile/index.php", 'moodle/site:config'));
$ADMIN->add('accounts', new admin_externalpage('cohorts', new lang_string('cohorts', 'cohort'), $CFG->wwwroot . '/cohort/index.php', array('moodle/cohort:manage', 'moodle/cohort:view')));
When I set the field "First name" to "Field value"
And I set the field "Text editor" to "Plain text area"
And I set the field "Unmask" to "1"
+ And I expand all fieldsets
Then the field "First name" matches value "Field value"
And the "Text editor" select box should contain "Plain text area"
And the field "Unmask" matches value "1"
$choices = array(0 => get_string('emaildisplayno'), 1 => get_string('emaildisplayyes'), 2 => get_string('emaildisplaycourse'));
$mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices);
- $mform->setDefault('maildisplay', 2);
+ $mform->setDefault('maildisplay', $CFG->defaultpreference_maildisplay);
$choices = array(0 => get_string('textformat'), 1 => get_string('htmlformat'));
$mform->addElement('select', 'mailformat', get_string('emailformat'), $choices);
- $mform->setDefault('mailformat', 1);
+ $mform->setDefault('mailformat', $CFG->defaultpreference_mailformat);
$mform->setAdvanced('mailformat');
$choices = array(0 => get_string('emaildigestoff'), 1 => get_string('emaildigestcomplete'), 2 => get_string('emaildigestsubjects'));
$mform->addElement('select', 'maildigest', get_string('emaildigest'), $choices);
- $mform->setDefault('maildigest', 0);
+ $mform->setDefault('maildigest', $CFG->defaultpreference_maildigest);
$mform->setAdvanced('maildigest');
$choices = array(1 => get_string('autosubscribeyes'), 0 => get_string('autosubscribeno'));
$mform->addElement('select', 'autosubscribe', get_string('autosubscribe'), $choices);
- $mform->setDefault('autosubscribe', 1);
+ $mform->setDefault('autosubscribe', $CFG->defaultpreference_autosubscribe);
$mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="25"');
$mform->setType('city', PARAM_TEXT);
return;
}
+ // If the multi-authentication setting is used, check for the param before connecting to CAS.
+ if ($this->config->multiauth) {
+ $authCAS = optional_param('authCAS', '', PARAM_RAW);
+ if ($authCAS == 'NOCAS') {
+ return;
+ }
+ // Show authentication form for multi-authentication.
+ // Test pgtIou parameter for proxy mode (https connection in background from CAS server to the php server).
+ if ($authCAS != 'CAS' && !isset($_GET['pgtIou'])) {
+ $PAGE->set_url('/login/index.php');
+ $PAGE->navbar->add($CASform);
+ $PAGE->set_title("$site->fullname: $CASform");
+ $PAGE->set_heading($site->fullname);
+ echo $OUTPUT->header();
+ include($CFG->dirroot.'/auth/cas/cas_form.html');
+ echo $OUTPUT->footer();
+ exit();
+ }
+ }
+
// Connection to CAS server
$this->connectCAS();
return;
}
- if ($this->config->multiauth) {
- $authCAS = optional_param('authCAS', '', PARAM_RAW);
- if ($authCAS == 'NOCAS') {
- return;
- }
-
- // Show authentication form for multi-authentication
- // test pgtIou parameter for proxy mode (https connection
- // in background from CAS server to the php server)
- if ($authCAS != 'CAS' && !isset($_GET['pgtIou'])) {
- $PAGE->set_url('/login/index.php');
- $PAGE->navbar->add($CASform);
- $PAGE->set_title("$site->fullname: $CASform");
- $PAGE->set_heading($site->fullname);
- echo $OUTPUT->header();
- include($CFG->dirroot.'/auth/cas/cas_form.html');
- echo $OUTPUT->footer();
- exit();
- }
- }
-
// Force CAS authentication (if needed).
if (!phpCAS::isAuthenticated()) {
phpCAS::setLang($this->config->language);
// If we have data, insert it, else something went wrong in the restore_logs_processor
if ($data) {
- $DB->insert_record('log', $data);
+ if (empty($data->url)) {
+ $data->url = '';
+ }
+ if (empty($data->info)) {
+ $data->info = '';
+ }
+ // Store the data in the legacy log table if we are still using it.
+ $manager = get_log_manager();
+ if (method_exists($manager, 'legacy_add_to_log')) {
+ $manager->legacy_add_to_log($data->course, $data->module, $data->action, $data->url,
+ $data->info, $data->cmid, $data->userid);
+ }
}
}
}
// If we have data, insert it, else something went wrong in the restore_logs_processor
if ($data) {
- $DB->insert_record('log', $data);
+ if (empty($data->url)) {
+ $data->url = '';
+ }
+ if (empty($data->info)) {
+ $data->info = '';
+ }
+ // Store the data in the legacy log table if we are still using it.
+ $manager = get_log_manager();
+ if (method_exists($manager, 'legacy_add_to_log')) {
+ $manager->legacy_add_to_log($data->course, $data->module, $data->action, $data->url,
+ $data->info, $data->cmid, $data->userid);
+ }
}
}
}
}
// Arrived here log is empty, no rule was able to perform the conversion, log the problem
if (empty($newlog)) {
- self::$task->log('Log module-action "' . $keyname . ' process problem. Not restored', backup::LOG_DEBUG);
+ self::$task->log('Log module-action "' . $keyname . '" process problem. Not restored', backup::LOG_DEBUG);
}
} else { // Action not found log the problem
- self::$task->log('Log module-action "' . $keyname . ' unknown. Not restored', backup::LOG_DEBUG);
+ self::$task->log('Log module-action "' . $keyname . '" unknown. Not restored', backup::LOG_DEBUG);
$newlog = false;
}
* @param string $label
*/
public function set_label($label) {
- if ((string)$label === '' || $label !== clean_param($label, PARAM_TEXT)) {
+ $label = (string)$label;
+ if ($label === '' || $label !== clean_param($label, PARAM_TEXT)) {
throw new base_setting_ui_exception('setting_invalid_ui_label');
}
$this->label = $label;
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$mform->addElement('textarea', 'description', get_string('description', 'badges'), 'wrap="virtual" rows="8" cols="70"');
- $mform->setType('description', PARAM_CLEANHTML);
+ $mform->setType('description', PARAM_NOTAGS);
$mform->addRule('description', null, 'required');
$str = $action == 'new' ? get_string('badgeimage', 'badges') : get_string('newimage', 'badges');
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(dirname(__FILE__)).'/config.php');
-include_once('lib.php');
-include_once('locallib.php');
+require_once('lib.php');
+require_once('locallib.php');
$action = required_param('action', PARAM_ALPHA);
$id = optional_param('entryid', 0, PARAM_INT);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
-$modid = optional_param('modid', 0, PARAM_INT); // To associate the entry with a module instance
-$courseid = optional_param('courseid', 0, PARAM_INT); // To associate the entry with a course
-
-$PAGE->set_url('/blog/edit.php', array('action' => $action, 'entryid' => $id, 'confirm' => $confirm, 'modid' => $modid, 'courseid' => $courseid));
+$modid = optional_param('modid', 0, PARAM_INT); // To associate the entry with a module instance.
+$courseid = optional_param('courseid', 0, PARAM_INT); // To associate the entry with a course.
-// If action is add, we ignore $id to avoid any further problems
-if (!empty($id) && $action == 'add') {
- $id = null;
+if ($action == 'edit') {
+ $id = required_param('entryid', PARAM_INT);
}
-$returnurl = new moodle_url('/blog/index.php');
+$PAGE->set_url('/blog/edit.php', array('action' => $action,
+ 'entryid' => $id,
+ 'confirm' => $confirm,
+ 'modid' => $modid,
+ 'courseid' => $courseid));
-if (!empty($courseid) && empty($modid)) {
- $returnurl->param('courseid', $courseid);
-}
-
-// If a modid is given, guess courseid
-if (!empty($modid)) {
- $returnurl->param('modid', $modid);
- $courseid = $DB->get_field('course_modules', 'course', array('id' => $modid));
- $returnurl->param('courseid', $courseid);
+// If action is add, we ignore $id to avoid any further problems.
+if (!empty($id) && $action == 'add') {
+ $id = null;
}
// Blogs are always in system context.
$sitecontext = context_system::instance();
$PAGE->set_context($sitecontext);
-
-$blogheaders = blog_get_headers();
-
require_login($courseid);
-if ($action == 'edit') {
- $id = required_param('entryid', PARAM_INT);
-}
-
if (empty($CFG->enableblogs)) {
print_error('blogdisable', 'blog');
}
print_error('noguestentry', 'blog');
}
+$returnurl = new moodle_url('/blog/index.php');
+
+if (!empty($courseid) && empty($modid)) {
+ $returnurl->param('courseid', $courseid);
+}
+
+// If a modid is given, guess courseid.
+if (!empty($modid)) {
+ $returnurl->param('modid', $modid);
+ $courseid = $DB->get_field('course_modules', 'course', array('id' => $modid));
+ $returnurl->param('courseid', $courseid);
+}
+
+$blogheaders = blog_get_headers();
+
if (!has_capability('moodle/blog:create', $sitecontext) && !has_capability('moodle/blog:manageentries', $sitecontext)) {
print_error('cannoteditentryorblog');
}
-// Make sure that the person trying to edit has access right
+// Make sure that the person trying to edit has access right.
if ($id) {
if (!$entry = new blog_entry($id)) {
print_error('wrongentryid', 'blog');
} else {
if (!has_capability('moodle/blog:create', $sitecontext)) {
- print_error('noentry', 'blog'); // manageentries is not enough for adding
+ print_error('noentry', 'blog'); // The capability "manageentries" is not enough for adding.
}
$entry = new stdClass();
$entry->id = null;
// Blog renderer.
$output = $PAGE->get_renderer('blog');
-$strblogs = get_string('blogs','blog');
+$strblogs = get_string('blogs', 'blog');
-if ($action === 'delete'){
+if ($action === 'delete') {
if (empty($entry->id)) {
print_error('wrongentryid', 'blog');
}
if (data_submitted() && $confirm && confirm_sesskey()) {
- // Make sure the current user is the author of the blog entry, or has some deleteanyentry capability
+ // Make sure the current user is the author of the blog entry, or has some deleteanyentry capability.
if (!blog_user_can_edit_entry($entry)) {
print_error('nopermissionstodeleteentry', 'blog');
} else {
echo $output->render($entry);
echo '<br />';
- echo $OUTPUT->confirm(get_string('blogdeleteconfirm', 'blog'), new moodle_url('edit.php', $optionsyes),new moodle_url( 'index.php', $optionsno));
+ echo $OUTPUT->confirm(get_string('blogdeleteconfirm', 'blog'),
+ new moodle_url('edit.php', $optionsyes),
+ new moodle_url('index.php', $optionsno));
echo $OUTPUT->footer();
die;
}
'subdirs'=>file_area_contains_subdirs($sitecontext, 'blog', 'post', $entry->id));
$attachmentoptions = array('subdirs'=>false, 'maxfiles'=> 99, 'maxbytes'=>$CFG->maxbytes);
-$blogeditform = new blog_edit_form(null, compact('entry', 'summaryoptions', 'attachmentoptions', 'sitecontext', 'courseid', 'modid'));
+$blogeditform = new blog_edit_form(null, compact('entry',
+ 'summaryoptions',
+ 'attachmentoptions',
+ 'sitecontext',
+ 'courseid',
+ 'modid'));
$entry = file_prepare_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id);
-$entry = file_prepare_standard_filemanager($entry, 'attachment', $attachmentoptions, $sitecontext, 'blog', 'attachment', $entry->id);
+$entry = file_prepare_standard_filemanager($entry,
+ 'attachment',
+ $attachmentoptions,
+ $sitecontext,
+ 'blog',
+ 'attachment',
+ $entry->id);
if (!empty($CFG->usetags) && !empty($entry->id)) {
include_once($CFG->dirroot.'/tag/lib.php');
}
$entry->action = $action;
-// set defaults
+// Set defaults.
$blogeditform->set_data($entry);
if ($blogeditform->is_cancelled()) {
redirect($returnurl);
-} else if ($data = $blogeditform->get_data()){
+} else if ($data = $blogeditform->get_data()) {
switch ($action) {
case 'add':
}
-// gui setup
+// GUI setup.
switch ($action) {
case 'add':
- // prepare new empty form
+ // Prepare new empty form.
$entry->publishstate = 'site';
$strformheading = get_string('addnewentry', 'blog');
$entry->action = $action;
if ($CFG->useblogassociations) {
- //pre-select the course for associations
+ // Pre-select the course for associations.
if ($courseid) {
$context = context_course::instance($courseid);
$entry->courseassoc = $context->id;
}
- //pre-select the mod for associations
+ // Pre-select the mod for associations.
if ($modid) {
$context = context_module::instance($modid);
$entry->modassoc = $context->id;
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
if (!defined('MOODLE_INTERNAL')) {
- die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
}
require_once($CFG->libdir.'/formslib.php');
class blog_edit_form extends moodleform {
public $modnames = array();
- function definition() {
+ /**
+ * Blog form definition.
+ */
+ public function definition() {
global $CFG, $DB;
$mform =& $this->_form;
$mform->addElement('filemanager', 'attachment_filemanager', get_string('attachment', 'forum'), null, $attachmentoptions);
- //disable publishstate options that are not allowed
+ // Disable publishstate options that are not allowed.
$publishstates = array();
$i = 0;
foreach (blog_entry::get_applicable_publish_states() as $state => $desc) {
- $publishstates[$state] = $desc; //no maximum was set
+ $publishstates[$state] = $desc; // No maximum was set.
$i++;
}
}
$mform->addElement('header', 'assochdr', get_string('associations', 'blog'));
- $mform->addElement('advcheckbox', 'courseassoc', get_string('associatewithcourse', 'blog', $a), null, null, array(0, $contextid));
+ $mform->addElement('advcheckbox',
+ 'courseassoc',
+ get_string('associatewithcourse', 'blog', $a),
+ null,
+ null,
+ array(0, $contextid));
$mform->setDefault('courseassoc', $contextid);
} else if ((!empty($entry->modassoc) || !empty($modid))) {
}
$mform->addElement('header', 'assochdr', get_string('associations', 'blog'));
- $mform->addElement('advcheckbox', 'modassoc', get_string('associatewithmodule', 'blog', $a), null, null, array(0, $context->id));
+ $mform->addElement('advcheckbox',
+ 'modassoc',
+ get_string('associatewithmodule', 'blog', $a),
+ null,
+ null,
+ array(0, $context->id));
$mform->setDefault('modassoc', $context->id);
}
}
$mform->setDefault('courseid', $courseid);
}
- function validation($data, $files) {
+ /**
+ * Validate the blog form data.
+ * @param array $data Data to be validated
+ * @param array $files unused
+ * @return array|bool
+ */
+ public function validation($data, $files) {
global $CFG, $DB, $USER;
$errors = array();
- // validate course association
+ // Validate course association.
if (!empty($data['courseassoc'])) {
$coursecontext = context::instance_by_id($data['courseassoc']);
}
}
- // validate mod association
+ // Validate mod association.
if (!empty($data['modassoc'])) {
$modcontextid = $data['modassoc'];
$modcontext = context::instance_by_id($modcontextid);
if ($modcontext->contextlevel == CONTEXT_MODULE) {
- // get context of the mod's course
+ // Get context of the mod's course.
$coursecontext = $modcontext->get_course_context(true);
- // ensure only one course is associated
+ // Ensure only one course is associated.
if (!empty($data['courseassoc'])) {
if ($data['courseassoc'] != $coursecontext->id) {
$errors['modassoc'] = get_string('onlyassociateonecourse', 'blog');
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
$context = context_system::instance();
require_capability('moodle/blog:manageexternal', $context);
-// TODO redirect if $CFG->useexternalblogs is off, $CFG->maxexternalblogsperuser == 0, or if user doesn't have caps to manage external blogs
+// TODO redirect if $CFG->useexternalblogs is off,
+// $CFG->maxexternalblogsperuser == 0,
+// or if user doesn't have caps to manage external blogs.
$id = optional_param('id', null, PARAM_INT);
$url = new moodle_url('/blog/external_blog_edit.php');
$external = new stdClass();
-// Check that this id exists
+// Check that this id exists.
if (!empty($id) && !$DB->record_exists('blog_external', array('id' => $id))) {
print_error('wrongexternalid', 'blog');
-} elseif (!empty($id)) {
+} else if (!empty($id)) {
$external = $DB->get_record('blog_external', array('id' => $id));
}
$strformheading = ($action == 'edit') ? get_string('editexternalblog', 'blog') : get_string('addnewexternalblog', 'blog');
-$strexternalblogs = get_string('externalblogs','blog');
-$strblogs = get_string('blogs','blog');
+$strexternalblogs = get_string('externalblogs', 'blog');
+$strblogs = get_string('blogs', 'blog');
$externalblogform = new blog_edit_external_form();
-if ($externalblogform->is_cancelled()){
+if ($externalblogform->is_cancelled()) {
redirect($returnurl);
} else if ($data = $externalblogform->get_data()) {
- //save stuff in db
+ // Save stuff in db.
switch ($action) {
case 'add':
$rss = new moodle_simplepie($data->url);
$newexternal->description = (empty($data->description)) ? $rss->get_description() : $data->description;
$newexternal->userid = $USER->id;
$newexternal->url = $data->url;
- $newexternal->filtertags = $data->filtertags;
+ $newexternal->filtertags = (!empty($data->filtertags)) ? $data->filtertags : null;
$newexternal->timemodified = time();
$newexternal->id = $DB->insert_record('blog_external', $newexternal);
blog_sync_external_entries($newexternal);
- tag_set('blog_external', $newexternal->id, explode(',', $data->autotags), 'core',
- context_user::instance($newexternal->userid)->id);
+ if ($CFG->usetags) {
+ $autotags = (!empty($data->autotags)) ? $data->autotags : null;
+ tag_set('blog_external', $newexternal->id, explode(',', $autotags), 'core',
+ context_user::instance($newexternal->userid)->id);
+ }
break;
$external->description = (empty($data->description)) ? $rss->get_description() : $data->description;
$external->userid = $USER->id;
$external->url = $data->url;
- $external->filtertags = $data->filtertags;
+ $external->filtertags = (!empty($data->filtertags)) ? $data->filtertags : null;
$external->timemodified = time();
$DB->update_record('blog_external', $external);
- tag_set('blog_external', $external->id, explode(',', $data->autotags), 'core',
- context_user::instance($newexternal->userid)->id);
-
+ if ($CFG->usetags) {
+ $autotags = (!empty($data->autotags)) ? $data->autotags : null;
+ tag_set('blog_external', $external->id, explode(',', $autotags), 'core',
+ context_user::instance($external->userid)->id);
+ }
} else {
print_error('wrongexternalid', 'blog');
}
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
*/
if (!defined('MOODLE_INTERNAL')) {
- die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
}
require_once($CFG->libdir.'/formslib.php');
if ($id = $mform->getElementValue('id')) {
$mform->setDefault('autotags', implode(',', tag_get_tags_array('blog_external', $id)));
$mform->freeze('url');
- $mform->freeze('filtertags');
+ if ($mform->elementExists('filtertags')) {
+ $mform->freeze('filtertags');
+ }
// TODO change the filtertags element to a multiple select, using the tags of the external blog
- // Use $rss->get_channel_tags()
+ // Use $rss->get_channel_tags().
}
}
}
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
$delete = optional_param('delete', null, PARAM_INT);
-$strexternalblogs = get_string('externalblogs','blog');
-$straddnewexternalblog = get_string('addnewexternalblog','blog');
-$strblogs = get_string('blogs','blog');
+$strexternalblogs = get_string('externalblogs', 'blog');
+$straddnewexternalblog = get_string('addnewexternalblog', 'blog');
+$strblogs = get_string('blogs', 'blog');
$message = null;
if ($delete && confirm_sesskey()) {
$externalbloguserid = $DB->get_field('blog_external', 'userid', array('id' => $delete));
if ($externalbloguserid == $USER->id) {
- // Delete the external blog
+ // Delete the external blog.
$DB->delete_records('blog_external', array('id' => $delete));
- // Delete the external blog's posts
+ // Delete the external blog's posts.
$deletewhere = 'module = :module
AND userid = :userid
AND ' . $DB->sql_isnotempty('post', 'uniquehash', false, false) . '
AND ' . $DB->sql_compare_text('content') . ' = ' . $DB->sql_compare_text(':delete');
- $DB->delete_records_select('post', $deletewhere, array('module' => 'blog_external', 'userid' => $USER->id, 'delete' => $delete));
+ $DB->delete_records_select('post', $deletewhere, array('module' => 'blog_external',
+ 'userid' => $USER->id,
+ 'delete' => $delete));
$message = get_string('externalblogdeleted', 'blog');
}
$table = new html_table();
$table->cellpadding = 4;
$table->attributes['class'] = 'generaltable boxaligncenter';
- $table->head = array(get_string('name'), get_string('url', 'blog'), get_string('timefetched', 'blog'), get_string('valid', 'blog'), get_string('actions'));
+ $table->head = array(get_string('name'),
+ get_string('url', 'blog'),
+ get_string('timefetched', 'blog'),
+ get_string('valid', 'blog'),
+ get_string('actions'));
foreach ($blogs as $blog) {
if ($blog->failedlastsync) {
$deletelink = new moodle_url('/blog/external_blogs.php', array('delete' => $blog->id, 'sesskey'=>sesskey()));
$deleteicon = $OUTPUT->action_icon($deletelink, new pix_icon('t/delete', get_string('deleteexternalblog', 'blog')));
- $table->data[] = new html_table_row(array($blog->name, $blog->url, userdate($blog->timefetched), $validicon, $editicon . ' '. $deleteicon));
+ $table->data[] = new html_table_row(array($blog->name,
+ $blog->url,
+ userdate($blog->timefetched),
+ $validicon,
+ $editicon . ' '. $deleteicon));
}
echo html_writer::table($table);
}
<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* file index.php
}
$PAGE->set_url('/blog/index.php', $url_params);
-if (empty($CFG->enableblogs)) {
- print_error('blogdisable', 'blog');
-}
-
-//correct tagid if a text tag is provided as a param
+// Correct tagid if a text tag is provided as a param.
if (!empty($tag)) {
if ($tagrec = $DB->get_record('tag', array('name' => $tag))) {
$tagid = $tagrec->id;
}
}
-// add courseid if modid or groupid is specified: This is used for navigation and title
-if (!empty($modid) && empty($courseid)) {
- $courseid = $DB->get_field('course_modules', 'course', array('id'=>$modid));
-}
-
-if (!empty($groupid) && empty($courseid)) {
- $courseid = $DB->get_field('groups', 'courseid', array('id'=>$groupid));
-}
-
$sitecontext = context_system::instance();
// Blogs are always in system context.
$PAGE->set_context($sitecontext);
-// check basic permissions
+// Check basic permissions.
if ($CFG->bloglevel == BLOG_GLOBAL_LEVEL) {
- // everybody can see anything - no login required unless site is locked down using forcelogin
+ // Everybody can see anything - no login required unless site is locked down using forcelogin.
if ($CFG->forcelogin) {
require_login();
}
} else if ($CFG->bloglevel == BLOG_SITE_LEVEL) {
- // users must log in and can not be guests
+ // Users must log in and can not be guests.
require_login();
if (isguestuser()) {
- // they must have entered the url manually...
+ // They must have entered the url manually.
print_error('blogdisable', 'blog');
}
} else if ($CFG->bloglevel == BLOG_USER_LEVEL) {
- // users can see own blogs only! with the exception of ppl with special cap
+ // Users can see own blogs only! with the exception of people with special cap.
require_login();
} else {
- // weird!
+ // Weird!
print_error('blogdisable', 'blog');
}
+if (empty($CFG->enableblogs)) {
+ print_error('blogdisable', 'blog');
+}
+
+// Add courseid if modid or groupid is specified: This is used for navigation and title.
+if (!empty($modid) && empty($courseid)) {
+ $courseid = $DB->get_field('course_modules', 'course', array('id' => $modid));
+}
+
+if (!empty($groupid) && empty($courseid)) {
+ $courseid = $DB->get_field('groups', 'courseid', array('id' => $groupid));
+}
+
if (!$userid && has_capability('moodle/blog:view', $sitecontext) && $CFG->bloglevel > BLOG_USER_LEVEL) {
if ($entryid) {
}
$rsstitle = $blogheaders['heading'];
- //check we haven't started output by outputting an error message
+ // Check we haven't started output by outputting an error message.
if ($PAGE->state == moodle_page::STATE_BEFORE_HEADER) {
blog_rss_add_http_header($rsscontext, $rsstitle, $filtertype, $thingid, $tagid);
}
-
- //this works but there isn't a great place to put the link
- //blog_rss_print_link($rsscontext, $filtertype, $thingid, $tagid);
}
echo $OUTPUT->header();
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
defined('MOODLE_INTERNAL') || die();
-/**
+/*
* Library of functions and constants for blog
*/
require_once($CFG->dirroot .'/blog/rsslib.php');
$sitecontext = context_system::instance();
if (has_capability('moodle/blog:manageentries', $sitecontext)) {
- return true; // can edit any blog entry
+ return true; // Can edit any blog entry.
}
if ($blogentry->userid == $USER->id && has_capability('moodle/blog:create', $sitecontext)) {
- return true; // can edit own when having blog:create capability
+ return true; // Can edit own when having blog:create capability.
}
return false;
if (empty($rss->data)) {
return null;
}
- //used to identify blog posts that have been deleted from the source feed
+ // Used to identify blog posts that have been deleted from the source feed.
$oldesttimestamp = null;
$uniquehashes = array();
foreach ($rss->get_items() as $entry) {
- // If filtertags are defined, use them to filter the entries by RSS category
+ // If filtertags are defined, use them to filter the entries by RSS category.
if (!empty($externalblog->filtertags)) {
$containsfiltertag = false;
$categories = $entry->get_categories();
$newentry->uniquehash = $entry->get_permalink();
$newentry->publishstate = 'site';
$newentry->format = FORMAT_HTML;
- // Clean subject of html, just in case
+ // Clean subject of html, just in case.
$newentry->subject = clean_param($entry->get_title(), PARAM_TEXT);
- // Observe 128 max chars in DB
- // TODO: +1 to raise this to 255
+ // Observe 128 max chars in DB.
+ // TODO: +1 to raise this to 255.
if (core_text::strlen($newentry->subject) > 128) {
$newentry->subject = core_text::substr($newentry->subject, 0, 125) . '...';
}
$newentry->summary = $entry->get_description();
- //used to decide whether to insert or update
- //uses enty permalink plus creation date if available
+ // Used to decide whether to insert or update.
+ // Uses enty permalink plus creation date if available.
$existingpostconditions = array('uniquehash' => $entry->get_permalink());
- //our DB doesnt allow null creation or modified timestamps so check the external blog supplied one
+ // Our DB doesnt allow null creation or modified timestamps so check the external blog supplied one.
$entrydate = $entry->get_date('U');
if (!empty($entrydate)) {
$existingpostconditions['created'] = $entrydate;
}
- //the post ID or false if post not found in DB
+ // The post ID or false if post not found in DB.
$postid = $DB->get_field('post', 'id', $existingpostconditions);
$timestamp = null;
$timestamp = $entrydate;
}
- //only set created if its a new post so we retain the original creation timestamp if the post is edited
+ // Only set created if its a new post so we retain the original creation timestamp if the post is edited.
if ($postid === false) {
$newentry->created = $timestamp;
}
$newentry->lastmodified = $timestamp;
if (empty($oldesttimestamp) || $timestamp < $oldesttimestamp) {
- //found an older post
+ // Found an older post.
$oldesttimestamp = $timestamp;
}
if ($postid === false) {
$id = $DB->insert_record('post', $newentry);
- // Set tags
+ // Set tags.
if ($tags = tag_get_tags_array('blog_external', $externalblog->id)) {
tag_set('post', $id, $tags, 'core', context_user::instance($externalblog->userid)->id);
}
$dbposts = $DB->get_records_sql($sql, array('blogid' => $externalblog->id, 'ts' => $oldesttimestamp));
$todelete = array();
- foreach($dbposts as $dbpost) {
+ foreach ($dbposts as $dbpost) {
if ( !in_array($dbpost->uniquehash, $uniquehashes) ) {
$todelete[] = $dbpost->id;
}
$options = array();
- // If blogs are enabled and the user is logged in and not a guest
+ // If blogs are enabled and the user is logged in and not a guest.
if (blog_is_enabled_for_user()) {
- // If the context is the user then assume we want to load for the users context
+ // If the context is the user then assume we want to load for the users context.
if (is_null($userid) && $page->context->contextlevel == CONTEXT_USER) {
$userid = $page->context->instanceid;
}
- // Check the userid var
+ // Check the userid var.
if (!is_null($userid) && $userid!==$USER->id) {
// Load the user from the userid... it MUST EXIST throw a wobbly if it doesn't!
$user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
}
if ($CFG->useblogassociations && $page->cm !== null) {
- // Load for the module associated with the page
+ // Load for the module associated with the page.
$options[CONTEXT_MODULE] = blog_get_options_for_module($page->cm, $user);
} else if ($CFG->useblogassociations && $page->course->id != SITEID) {
- // Load the options for the course associated with the page
+ // Load the options for the course associated with the page.
$options[CONTEXT_COURSE] = blog_get_options_for_course($page->course, $user);
}
- // Get the options for the user
+ // Get the options for the user.
if ($user !== null and !isguestuser($user)) {
- // Load for the requested user
+ // Load for the requested user.
$options[CONTEXT_USER+1] = blog_get_options_for_user($user);
}
- // Load for the current user
+ // Load for the current user.
if (isloggedin() and !isguestuser()) {
$options[CONTEXT_USER] = blog_get_options_for_user();
}
}
- // If blog level is global then display a link to view all site entries
- if (!empty($CFG->enableblogs) && $CFG->bloglevel >= BLOG_GLOBAL_LEVEL && has_capability('moodle/blog:view', context_system::instance())) {
+ // If blog level is global then display a link to view all site entries.
+ if (!empty($CFG->enableblogs)
+ && $CFG->bloglevel >= BLOG_GLOBAL_LEVEL
+ && has_capability('moodle/blog:view', context_system::instance())) {
+
$options[CONTEXT_SYSTEM] = array('viewsite' => array(
'string' => get_string('viewsiteentries', 'blog'),
'link' => new moodle_url('/blog/index.php')
));
}
- // Return the options
+ // Return the options.
return $options;
}
*/
function blog_get_options_for_user(stdClass $user=null) {
global $CFG, $USER;
- // Cache
+ // Cache.
static $useroptions = array();
$options = array();
- // Blogs must be enabled and the user must be logged in
+ // Blogs must be enabled and the user must be logged in.
if (!blog_is_enabled_for_user()) {
return $options;
}
- // Sort out the user var
+ // Sort out the user var.
if ($user === null || $user->id == $USER->id) {
$user = $USER;
$iscurrentuser = true;
$iscurrentuser = false;
}
- // If we've already generated serve from the cache
+ // If we've already generated serve from the cache.
if (array_key_exists($user->id, $useroptions)) {
return $useroptions[$user->id];
}
$canview = has_capability('moodle/blog:view', $sitecontext);
if (!$iscurrentuser && $canview && ($CFG->bloglevel >= BLOG_SITE_LEVEL)) {
- // Not the current user, but we can view and its blogs are enabled for SITE or GLOBAL
+ // Not the current user, but we can view and its blogs are enabled for SITE or GLOBAL.
$options['userentries'] = array(
'string' => get_string('viewuserentries', 'blog', fullname($user)),
'link' => new moodle_url('/blog/index.php', array('userid'=>$user->id))
);
} else {
- // It's the current user
+ // It's the current user.
if ($canview) {
- // We can view our own blogs .... BIG surprise
+ // We can view our own blogs .... BIG surprise.
$options['view'] = array(
'string' => get_string('viewallmyentries', 'blog'),
'link' => new moodle_url('/blog/index.php', array('userid'=>$USER->id))
);
}
if (has_capability('moodle/blog:create', $sitecontext)) {
- // We can add to our own blog
+ // We can add to our own blog.
$options['add'] = array(
'string' => get_string('addnewentry', 'blog'),
'link' => new moodle_url('/blog/edit.php', array('action'=>'add'))
$options['rss'] = array(
'string' => get_string('rssfeed', 'blog'),
'link' => new moodle_url(rss_get_url($sitecontext->id, $USER->id, 'blog', 'user/'.$user->id))
- );
+ );
}
- // Cache the options
+ // Cache the options.
$useroptions[$user->id] = $options;
- // Return the options
+ // Return the options.
return $options;
}
*/
function blog_get_options_for_course(stdClass $course, stdClass $user=null) {
global $CFG, $USER;
- // Cache
+ // Cache.
static $courseoptions = array();
$options = array();
- // User must be logged in and blogs must be enabled
+ // User must be logged in and blogs must be enabled.
if (!blog_is_enabled_for_user()) {
return $options;
}
- // Check that the user can associate with the course
+ // Check that the user can associate with the course.
$sitecontext = context_system::instance();
- // Generate the cache key
+ // Generate the cache key.
$key = $course->id.':';
if (!empty($user)) {
$key .= $user->id;
} else {
$key .= $USER->id;
}
- // Serve from the cache if we've already generated for this course
+ // Serve from the cache if we've already generated for this course.
if (array_key_exists($key, $courseoptions)) {
return $courseoptions[$key];
}
-
if (has_capability('moodle/blog:view', $sitecontext)) {
// We can view!
if ($CFG->bloglevel >= BLOG_SITE_LEVEL) {
- // View entries about this course
+ // View entries about this course.
$options['courseview'] = array(
'string' => get_string('viewcourseblogs', 'blog'),
'link' => new moodle_url('/blog/index.php', array('courseid' => $course->id))
);
}
- // View MY entries about this course
+ // View MY entries about this course.
$options['courseviewmine'] = array(
'string' => get_string('viewmyentriesaboutcourse', 'blog'),
'link' => new moodle_url('/blog/index.php', array('courseid' => $course->id, 'userid' => $USER->id))
);
if (!empty($user) && ($CFG->bloglevel >= BLOG_SITE_LEVEL)) {
- // View the provided users entries about this course
+ // View the provided users entries about this course.
$options['courseviewuser'] = array(
'string' => get_string('viewentriesbyuseraboutcourse', 'blog', fullname($user)),
'link' => new moodle_url('/blog/index.php', array('courseid' => $course->id, 'userid' => $user->id))
}
if (has_capability('moodle/blog:create', $sitecontext)) {
- // We can blog about this course
+ // We can blog about this course.
$options['courseadd'] = array(
'string' => get_string('blogaboutthiscourse', 'blog'),
'link' => new moodle_url('/blog/edit.php', array('action' => 'add', 'courseid' => $course->id))
);
}
-
- // Cache the options for this course
+ // Cache the options for this course.
$courseoptions[$key] = $options;
- // Return the options
+ // Return the options.
return $options;
}
*/
function blog_get_options_for_module($module, $user=null) {
global $CFG, $USER;
- // Cache
+ // Cache.
static $moduleoptions = array();
$options = array();
- // User must be logged in, blogs must be enabled
+ // User must be logged in, blogs must be enabled.
if (!blog_is_enabled_for_user()) {
return $options;
}
$sitecontext = context_system::instance();
- // Generate the cache key
+ // Generate the cache key.
$key = $module->id.':';
if (!empty($user)) {
$key .= $user->id;
$key .= $USER->id;
}
if (array_key_exists($key, $moduleoptions)) {
- // Serve from the cache so we don't have to regenerate
+ // Serve from the cache so we don't have to regenerate.
return $moduleoptions[$key];
}
-
if (has_capability('moodle/blog:view', $sitecontext)) {
// Save correct module name for later usage.
$modulename = get_string('modulename', $module->modname);
// We can view!
if ($CFG->bloglevel >= BLOG_SITE_LEVEL) {
- // View all entries about this module
+ // View all entries about this module.
$a = new stdClass;
$a->type = $modulename;
$options['moduleview'] = array(
'link' => new moodle_url('/blog/index.php', array('modid'=>$module->id))
);
}
- // View MY entries about this module
+ // View MY entries about this module.
$options['moduleviewmine'] = array(
'string' => get_string('viewmyentriesaboutmodule', 'blog', $modulename),
'link' => new moodle_url('/blog/index.php', array('modid'=>$module->id, 'userid'=>$USER->id))
);
if (!empty($user) && ($CFG->bloglevel >= BLOG_SITE_LEVEL)) {
- // View the given users entries about this module
+ // View the given users entries about this module.
$a = new stdClass;
$a->mod = $modulename;
$a->user = fullname($user);
}
if (has_capability('moodle/blog:create', $sitecontext)) {
- // The user can blog about this module
+ // The user can blog about this module.
$options['moduleadd'] = array(
'string' => get_string('blogaboutthismodule', 'blog', $modulename),
'link' => new moodle_url('/blog/edit.php', array('action'=>'add', 'modid'=>$module->id))
);
}
- // Cache the options
+ // Cache the options.
$moduleoptions[$key] = $options;
- // Return the options
+ // Return the options.
return $options;
}
$action = optional_param('action', null, PARAM_ALPHA);
$confirm = optional_param('confirm', false, PARAM_BOOL);
- // Ignore userid when action == add
+ // Ignore userid when action == add.
if ($action == 'add' && $userid) {
unset($userid);
$PAGE->url->remove_params(array('userid'));
$site = $DB->get_record('course', array('id' => SITEID));
$sitecontext = context_system::instance();
- // Common Lang strings
+ // Common Lang strings.
$strparticipants = get_string("participants");
$strblogentries = get_string("blogentries", 'blog');
- // Prepare record objects as needed
+ // Prepare record objects as needed.
if (!empty($courseid)) {
$headers['filters']['course'] = $courseid;
$course = $DB->get_record('course', array('id' => $courseid));
$user = $DB->get_record('user', array('id' => $userid));
}
- if (!empty($groupid)) { // groupid always overrides courseid
+ if (!empty($groupid)) { // The groupid always overrides courseid.
$headers['filters']['group'] = $groupid;
$group = $DB->get_record('groups', array('id' => $groupid));
$course = $DB->get_record('course', array('id' => $group->courseid));
$PAGE->set_pagelayout('standard');
- // modid always overrides courseid, so the $course object may be reset here
+ // The modid always overrides courseid, so the $course object may be reset here.
if (!empty($modid) && $CFG->useblogassociations) {
$headers['filters']['module'] = $modid;
- // A groupid param may conflict with this coursemod's courseid. Ignore groupid in that case
+ // A groupid param may conflict with this coursemod's courseid. Ignore groupid in that case.
$courseid = $DB->get_field('course_modules', 'course', array('id'=>$modid));
$course = $DB->get_record('course', array('id' => $courseid));
$cm = $DB->get_record('course_modules', array('id' => $modid));
}
// Case 1: No entry, mod, course or user params: all site entries to be shown (filtered by search and tag/tagid)
- // Note: if action is set to 'add' or 'edit', we do this at the end
+ // Note: if action is set to 'add' or 'edit', we do this at the end.
if (empty($entryid) && empty($modid) && empty($courseid) && empty($userid) && !in_array($action, array('edit', 'add'))) {
$shortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$PAGE->navbar->add($strblogentries, $blogurl);
$PAGE->set_title("$shortname: " . get_string('blog', 'blog'));
$PAGE->set_heading("$shortname: " . get_string('blog', 'blog'));
$headers['heading'] = get_string('siteblog', 'blog', $shortname);
- // $headers['strview'] = get_string('viewsiteentries', 'blog');
}
- // Case 2: only entryid is requested, ignore all other filters. courseid is used to give more contextual information
+ // Case 2: only entryid is requested, ignore all other filters. courseid is used to give more contextual information.
if (!empty($entryid)) {
$headers['filters']['entry'] = $entryid;
$sql = 'SELECT u.* FROM {user} u, {post} p WHERE p.id = ? AND p.userid = u.id';
$PAGE->set_heading("$shortname: " . fullname($user) . ": $entry->subject");
$headers['heading'] = get_string('blogentrybyuser', 'blog', fullname($user));
- // We ignore tag and search params
+ // We ignore tag and search params.
if (empty($action) || !$CFG->useblogassociations) {
$headers['url'] = $blogurl;
return $headers;
}
}
- // Case 3: A user's blog entries
if (!empty($userid) && empty($entryid) && ((empty($courseid) && empty($modid)) || !$CFG->useblogassociations)) {
+ // Case 3: A user's blog entries.
+
$shortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$blogurl->param('userid', $userid);
$PAGE->set_title("$shortname: " . fullname($user) . ": " . get_string('blog', 'blog'));
$headers['heading'] = get_string('userblog', 'blog', fullname($user));
$headers['strview'] = get_string('viewuserentries', 'blog', fullname($user));
- } else
+ } else if (!$CFG->useblogassociations && empty($userid) && !in_array($action, array('edit', 'add'))) {
+ // Case 4: No blog associations, no userid.
- // Case 4: No blog associations, no userid
- if (!$CFG->useblogassociations && empty($userid) && !in_array($action, array('edit', 'add'))) {
$shortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$PAGE->set_title("$shortname: " . get_string('blog', 'blog'));
$PAGE->set_heading("$shortname: " . get_string('blog', 'blog'));
$headers['heading'] = get_string('siteblog', 'blog', $shortname);
- } else
+ } else if (!empty($userid) && !empty($modid) && empty($entryid)) {
+ // Case 5: Blog entries associated with an activity by a specific user (courseid ignored).
- // Case 5: Blog entries associated with an activity by a specific user (courseid ignored)
- if (!empty($userid) && !empty($modid) && empty($entryid)) {
$shortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$blogurl->param('userid', $userid);
$blogurl->param('modid', $modid);
- // Course module navigation is handled by build_navigation as the second param
+ // Course module navigation is handled by build_navigation as the second param.
$headers['cm'] = $cm;
$PAGE->navbar->add(fullname($user), "$CFG->wwwroot/user/view.php?id=$user->id");
$PAGE->navbar->add($strblogentries, $blogurl);
$headers['heading'] = get_string('blogentriesbyuseraboutmodule', 'blog', $a);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewallmodentries', 'blog', $a);
- } else
+ } else if (!empty($userid) && !empty($courseid) && empty($modid) && empty($entryid)) {
+ // Case 6: Blog entries associated with a course by a specific user.
- // Case 6: Blog entries associated with a course by a specific user
- if (!empty($userid) && !empty($courseid) && empty($modid) && empty($entryid)) {
$siteshortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$blogurl->param('userid', $userid);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewblogentries', 'blog', $a);
- // Remove the userid from the URL to inform the blog_menu block correctly
+ // Remove the userid from the URL to inform the blog_menu block correctly.
$blogurl->remove_params(array('userid'));
- } else
+ } else if (!empty($groupid) && empty($modid) && empty($entryid)) {
+ // Case 7: Blog entries by members of a group, associated with that group's course.
- // Case 7: Blog entries by members of a group, associated with that group's course
- if (!empty($groupid) && empty($modid) && empty($entryid)) {
$siteshortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$blogurl->param('courseid', $course->id);
$headers['heading'] = get_string('blogentriesbygroupaboutcourse', 'blog', $a);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewblogentries', 'blog', $a);
- } else
+ } else if (!empty($groupid) && !empty($modid) && empty($entryid)) {
+ // Case 8: Blog entries by members of a group, associated with an activity in that course.
- // Case 8: Blog entries by members of a group, associated with an activity in that course
- if (!empty($groupid) && !empty($modid) && empty($entryid)) {
$siteshortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$headers['cm'] = $cm;
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewallmodentries', 'blog', $a);
- } else
+ } else if (!empty($modid) && empty($userid) && empty($groupid) && empty($entryid)) {
+ // Case 9: All blog entries associated with an activity.
- // Case 9: All blog entries associated with an activity
- if (!empty($modid) && empty($userid) && empty($groupid) && empty($entryid)) {
$siteshortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$PAGE->set_cm($cm, $course);
$a->type = get_string('modulename', $cm->modname);
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewallmodentries', 'blog', $a);
- } else
+ } else if (!empty($courseid) && empty($userid) && empty($groupid) && empty($modid) && empty($entryid)) {
+ // Case 10: All blog entries associated with a course.
- // Case 10: All blog entries associated with a course
- if (!empty($courseid) && empty($userid) && empty($groupid) && empty($modid) && empty($entryid)) {
$siteshortname = format_string($site->shortname, true, array('context' => context_course::instance(SITEID)));
$courseshortname = format_string($course->shortname, true, array('context' => context_course::instance($course->id)));
$blogurl->param('courseid', $courseid);
$PAGE->set_heading("$siteshortname: $courseshortname: " . get_string('blogentries', 'blog'));
$a = new stdClass();
$a->type = get_string('course');
- $headers['heading'] = get_string('blogentriesabout', 'blog', format_string($course->fullname, true, array('context' => context_course::instance($course->id))));
+ $headers['heading'] = get_string('blogentriesabout',
+ 'blog',
+ format_string($course->fullname,
+ true,
+ array('context' => context_course::instance($course->id))));
$headers['stradd'] = get_string('blogaboutthis', 'blog', $a);
$headers['strview'] = get_string('viewblogentries', 'blog', $a);
$blogurl->remove_params(array('userid'));
}
if (!in_array($action, array('edit', 'add'))) {
- // Append Tag info
+ // Append Tag info.
if (!empty($tagid)) {
$headers['filters']['tag'] = $tagid;
$blogurl->param('tagid', $tagid);
$tagrec = $DB->get_record('tag', array('id'=>$tagid));
$PAGE->navbar->add($tagrec->name, $blogurl);
- } elseif (!empty($tag)) {
+ } else if (!empty($tag)) {
if ($tagrec = $DB->get_record('tag', array('name' => $tag))) {
$tagid = $tagrec->id;
$headers['filters']['tag'] = $tagid;
}
}
- // Append Search info
+ // Append Search info.
if (!empty($search)) {
$headers['filters']['search'] = $search;
$blogurl->param('search', $search);
}
}
- // Append edit mode info
+ // Append edit mode info.
if (!empty($action) && $action == 'add') {
} else if (!empty($action) && $action == 'edit') {
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class blog_entry implements renderable {
- // Public Database fields
+ // Public Database fields.
public $id;
public $userid;
public $subject;
public $attachment;
public $publishstate;
- // Locked Database fields (Don't touch these)
+ // Locked Database fields (Don't touch these).
public $courseid = 0;
public $groupid = 0;
public $module = 'blog';
public $created;
public $usermodified;
- // Other class variables
+ // Other class variables.
public $form;
public $tags = array();
/** @var StdClass Data needed to render the entry */
public $renderable;
- // Methods
/**
* Constructor. If given an id, will fetch the corresponding record from the DB.
*
if ($externalblog = $DB->get_record('blog_external', array('id' => $this->content))) {
$urlparts = parse_url($externalblog->url);
$this->renderable->externalblogtext = get_string('retrievedfrom', 'blog') . get_string('labelsep', 'langconfig');
- $this->renderable->externalblogtext .= html_writer::link($urlparts['scheme'] . '://'.$urlparts['host'], $externalblog->name);
+ $this->renderable->externalblogtext .= html_writer::link($urlparts['scheme'] . '://' . $urlparts['host'],
+ $externalblog->name);
}
}
- // Retrieve associations
+ // Retrieve associations.
$this->renderable->unassociatedentry = false;
if (!empty($CFG->useblogassociations)) {
// Course associations.
if ($context->contextlevel == CONTEXT_COURSE) {
- $instancename = $DB->get_field('course', 'shortname', array('id' => $context->instanceid)); //TODO: performance!!!!
+ // TODO: performance!!!!
+ $instancename = $DB->get_field('course', 'shortname', array('id' => $context->instanceid));
- $associations[$key]->url = $assocurl = new moodle_url('/course/view.php', array('id' => $context->instanceid));
+ $associations[$key]->url = $assocurl = new moodle_url('/course/view.php',
+ array('id' => $context->instanceid));
$associations[$key]->text = $instancename;
$associations[$key]->icon = new pix_icon('i/course', $associations[$key]->text);
}
// Mod associations.
if ($context->contextlevel == CONTEXT_MODULE) {
- // Getting the activity type and the activity instance id
+ // Getting the activity type and the activity instance id.
$sql = 'SELECT cm.instance, m.name FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module
WHERE cm.id = :cmid';
$modinfo = $DB->get_record_sql($sql, array('cmid' => $context->instanceid));
- $instancename = $DB->get_field($modinfo->name, 'name', array('id' => $modinfo->instance)); //TODO: performance!!!!
+ // TODO: performance!!!!
+ $instancename = $DB->get_field($modinfo->name, 'name', array('id' => $modinfo->instance));
$associations[$key]->type = get_string('modulename', $modinfo->name);
- $associations[$key]->url = new moodle_url('/mod/' . $modinfo->name . '/view.php', array('id' => $context->instanceid));
+ $associations[$key]->url = new moodle_url('/mod/' . $modinfo->name . '/view.php',
+ array('id' => $context->instanceid));
$associations[$key]->text = $instancename;
$associations[$key]->icon = new pix_icon('icon', $associations[$key]->text, $modinfo->name);
}
* Gets the entry attachments list
* @return array List of blog_entry_attachment instances
*/
- function get_attachments() {
+ public function get_attachments() {
global $CFG;
}
$entry = file_postupdate_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id);
- $entry = file_postupdate_standard_filemanager($entry, 'attachment', $attachmentoptions, $sitecontext, 'blog', 'attachment', $entry->id);
+ $entry = file_postupdate_standard_filemanager($entry,
+ 'attachment',
+ $attachmentoptions,
+ $sitecontext,
+ 'blog',
+ 'attachment',
+ $entry->id);
if (!empty($CFG->useblogassociations)) {
$entry->add_associations();
if ($otags = optional_param('otags', '', PARAM_INT)) {
foreach ($otags as $tagid) {
- // TODO : make this use the tag name in the form
+ // TODO : make this use the tag name in the form.
if ($tag = tag_get('id', $tagid)) {
$tags[] = $tag->name;
}
$sitecontext = context_system::instance();
if (has_capability('moodle/blog:manageentries', $sitecontext)) {
- return true; // can edit any blog entry
+ return true; // Can edit any blog entry.
}
if ($this->userid == $userid && has_capability('moodle/blog:create', $sitecontext)) {
- return true; // can edit own when having blog:create capability
+ return true; // Can edit own when having blog:create capability.
}
return false;
$sitecontext = context_system::instance();
if (empty($CFG->enableblogs) || !has_capability('moodle/blog:view', $sitecontext)) {
- return false; // blog system disabled or user has no blog view capability
+ return false; // Blog system disabled or user has no blog view capability.
}
if (isloggedin() && $USER->id == $targetuserid) {
- return true; // can view own entries in any case
+ return true; // Can view own entries in any case.
}
if (has_capability('moodle/blog:manageentries', $sitecontext)) {
- return true; // can manage all entries
+ return true; // Can manage all entries.
}
- // coming for 1 entry, make sure it's not a draft
+ // Coming for 1 entry, make sure it's not a draft.
if ($this->publishstate == 'draft' && !has_capability('moodle/blog:viewdrafts', $sitecontext)) {
- return false; // can not view draft of others
+ return false; // Can not view draft of others.
}
- // coming for 1 entry, make sure user is logged in, if not a public blog
+ // Coming for 1 entry, make sure user is logged in, if not a public blog.
if ($this->publishstate != 'public' && !isloggedin()) {
return false;
}
break;
case BLOG_SITE_LEVEL:
- if (isloggedin()) { // not logged in viewers forbidden
+ if (isloggedin()) { // Not logged in viewers forbidden.
return true;
}
return false;
global $CFG;
$options = array();
- // everyone gets draft access
+ // Everyone gets draft access.
if ($CFG->bloglevel >= BLOG_USER_LEVEL) {
$options['draft'] = get_string('publishtonoone', 'blog');
}
* @param array $filters An associative array of filtername => filterid
*/
public function __construct($filters=array()) {
- // Unset filters overridden by more specific filters
+ // Unset filters overridden by more specific filters.
foreach ($filters as $type => $id) {
if (!empty($type) && !empty($id)) {
$this->filters[$type] = blog_filter::get_instance($id, $type);
public function get_entry_fetch_sql($count=false, $sort='lastmodified DESC', $userid = false) {
global $DB, $USER, $CFG;
- if(!$userid) {
+ if (!$userid) {
$userid = $USER->id;
}
$allnamefields = get_all_user_name_fields(true, 'u');
// The query used to locate blog entries is complicated. It will be built from the following components:
- $requiredfields = "p.*, $allnamefields, u.email"; // the SELECT clause
- $tables = array('p' => 'post', 'u' => 'user'); // components of the FROM clause (table_id => table_name)
- $conditions = array('u.deleted = 0', 'p.userid = u.id', '(p.module = \'blog\' OR p.module = \'blog_external\')'); // components of the WHERE clause (conjunction)
+ $requiredfields = "p.*, $allnamefields, u.email"; // The SELECT clause.
+ $tables = array('p' => 'post', 'u' => 'user'); // Components of the FROM clause (table_id => table_name).
+ // Components of the WHERE clause (conjunction).
+ $conditions = array('u.deleted = 0', 'p.userid = u.id', '(p.module = \'blog\' OR p.module = \'blog_external\')');
- // build up a clause for permission constraints
+ // Build up a clause for permission constraints.
$params = array();
- // fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs
- // admins can see all blogs regardless of publish states, as described on the help page
+ // Fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs.
+ // Admins can see all blogs regardless of publish states, as described on the help page.
if (has_capability('moodle/user:readuserblogs', context_system::instance())) {
- // don't add permission constraints
+ // Don't add permission constraints.
- } else if(!empty($this->filters['user']) && has_capability('moodle/user:readuserblogs',
- context_user::instance((empty($this->filters['user']->id) ? 0 : $this->filters['user']->id)))) {
- // don't add permission constraints
+ } else if (!empty($this->filters['user'])
+ && has_capability('moodle/user:readuserblogs',
+ context_user::instance((empty($this->filters['user']->id) ? 0 : $this->filters['user']->id)))) {
+ // Don't add permission constraints.
} else {
if (isloggedin() and !isguestuser()) {
- $assocexists = $DB->record_exists('blog_association', array()); //dont check association records if there aren't any
+ // Dont check association records if there aren't any.
+ $assocexists = $DB->record_exists('blog_association', array());
- //begin permission sql clause
+ // Begin permission sql clause.
$permissionsql = '(p.userid = ? ';
$params[] = $userid;
- if ($CFG->bloglevel >= BLOG_SITE_LEVEL) { // add permission to view site-level entries
+ if ($CFG->bloglevel >= BLOG_SITE_LEVEL) { // Add permission to view site-level entries.
$permissionsql .= " OR p.publishstate = 'site' ";
}
- if ($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { // add permission to view global entries
+ if ($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { // Add permission to view global entries.
$permissionsql .= " OR p.publishstate = 'public' ";
}
- $permissionsql .= ') '; //close permissions sql clause
- } else { // default is access to public entries
+ $permissionsql .= ') '; // Close permissions sql clause.
+ } else { // Default is access to public entries.
$permissionsql = "p.publishstate = 'public'";
}
- $conditions[] = $permissionsql; //add permission constraints
+ $conditions[] = $permissionsql; // Add permission constraints.
}
foreach ($this->filters as $type => $blogfilter) {
$tables = array_merge($tables, $blogfilter->tables);
}
- $tablessql = ''; // build up the FROM clause
+ $tablessql = ''; // Build up the FROM clause.
foreach ($tables as $tablename => $table) {
$tablessql .= ($tablessql ? ', ' : '').'{'.$table.'} '.$tablename;
}
global $CFG, $USER, $DB, $OUTPUT, $PAGE;
$sitecontext = context_system::instance();
- // Blog renderer
+ // Blog renderer.
$output = $PAGE->get_renderer('blog');
$page = optional_param('blogpage', 0, PARAM_INT);
echo $OUTPUT->render($pagingbar);
if (has_capability('moodle/blog:create', $sitecontext)) {
- //the user's blog is enabled and they are viewing their own blog
+ // The user's blog is enabled and they are viewing their own blog.
$userid = optional_param('userid', null, PARAM_INT);
if (empty($userid) || (!empty($userid) && $userid == $USER->id)) {
foreach ($entries as $entry) {
$blogentry = new blog_entry(null, $entry);
- // Get the required blog entry data to render it
+ // Get the required blog entry data to render it.
$blogentry->prepare_render();
echo $output->render($blogentry);
}
}
- /// Find the base url from $_GET variables, for print_paging_bar
+ // Find the base url from $_GET variables, for print_paging_bar.
public function get_baseurl() {
$getcopy = $_GET;
$this->type = $type;
}
- $this->availabletypes = array('site' => get_string('site'), 'course' => get_string('course'), 'module' => get_string('activity'));
+ $this->availabletypes = array('site' => get_string('site'),
+ 'course' => get_string('course'),
+ 'module' => get_string('activity'));
switch ($this->type) {
case 'course': // Careful of site course!
- // Ignore course filter if blog associations are not enabled
+ // Ignore course filter if blog associations are not enabled.
if ($this->id != $SITE->id && !empty($CFG->useblogassociations)) {
$this->overrides = array('site');
$context = context_course::instance($this->id);
$this->conditions[] = 'ba.contextid = '.$context->id;
break;
} else {
- // We are dealing with the site course, do not break from the current case
+ // We are dealing with the site course, do not break from the current case.
}
case 'site':
- // No special constraints
+ // No special constraints.
break;
case 'module':
if (!empty($CFG->useblogassociations)) {
$this->params = array($this->id);
$this->overrides = array('group');
- } elseif ($this->type == 'group') {
+ } else if ($this->type == 'group') {
$this->overrides = array('course', 'site');
$this->tables['gm'] = 'groups_members';
$this->conditions[] = 'gm.groupid = ?';
$this->params[] = $this->id;
- if (!empty($CFG->useblogassociations)) { // only show blog entries associated with this course
+ if (!empty($CFG->useblogassociations)) { // Only show blog entries associated with this course.
$coursecontext = context_course::instance($DB->get_field('groups', 'courseid', array('id' => $this->id)));
$this->tables['ba'] = 'blog_association';
$this->conditions[] = 'gm.groupid = ?';
$this->file = $file;
$this->filename = $file->get_filename();
- $this->url = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.SYSCONTEXTID.'/blog/attachment/'.$entryid.'/'.$this->filename);
+ $this->url = file_encode_url($CFG->wwwroot . '/pluginfile.php',
+ '/' . SYSCONTEXTID . '/blog/attachment/' . $entryid . '/' . $this->filename);
}
}
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// The preference is site wide not blog specific. Hence user should have permissions in site level.
require_capability('moodle/blog:view', $sitecontext);
-/// If data submitted, then process and store.
+// If data submitted, then process and store.
$mform = new blog_preferences_form('preferences.php');
$mform->set_data(array('pagesize' => get_user_preferences('blogpagesize')));
set_user_preference('blogpagesize', $pagesize);
}
-if ($mform->is_cancelled()){
+if ($mform->is_cancelled()) {
redirect($CFG->wwwroot . '/blog/index.php');
}
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
*/
if (!defined('MOODLE_INTERNAL')) {
- die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
}
require_once($CFG->libdir.'/formslib.php');
$o .= $this->output->container_start('topic starter header clearfix');
// Title.
- $titlelink = html_writer::link(new moodle_url('/blog/index.php', array('entryid' => $entry->id)), format_string($entry->subject));
+ $titlelink = html_writer::link(new moodle_url('/blog/index.php',
+ array('entryid' => $entry->id)),
+ format_string($entry->subject));
$o .= $this->output->container($titlelink, 'subject');
// Post by.
$o = html_writer::empty_tag('img', $attrs);
$class = 'attachedimages';
} else {
- $image = $this->output->pix_icon(file_file_icon($attachment->file), $attachment->filename, 'moodle', array('class'=>'icon'));
+ $image = $this->output->pix_icon(file_file_icon($attachment->file),
+ $attachment->filename,
+ 'moodle',
+ array('class' => 'icon'));
$o = html_writer::link($attachment->url, $image);
- $o .= format_text(html_writer::link($attachment->url, $attachment->filename), FORMAT_HTML, array('context' => $syscontext));
+ $o .= format_text(html_writer::link($attachment->url, $attachment->filename),
+ FORMAT_HTML,
+ array('context' => $syscontext));
$class = 'attachments';
}
<?php
-
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
function blog_rss_add_http_header($context, $title, $filtertype, $filterselect=0, $tagid=0) {
global $PAGE, $USER, $CFG;
- //$componentname = 'blog';
- //rss_add_http_header($context, $componentname, $filterselect, $title);
-
if (!isloggedin()) {
$userid = $CFG->siteguest;
} else {
if ($CFG->bloglevel == BLOG_SITE_LEVEL) {
if (isguestuser()) {
- debugging(get_string('nopermissiontoshow','error'));
+ debugging(get_string('nopermissiontoshow', 'error'));
return '';
}
}
}
$type = clean_param($args[3], PARAM_ALPHA);
- $id = clean_param($args[4], PARAM_INT); // could be groupid / courseid / userid depending on $type
+ $id = clean_param($args[4], PARAM_INT); // Could be groupid / courseid / userid depending on $type.
$tagid=0;
if ($args[5] != 'rss.xml') {
if (file_exists($filename)) {
if (filemtime($filename) + 3600 > time()) {
- return $filename; // It's already done so we return cached version
+ return $filename; // It's already done so we return cached version.
}
}
$courseid = $groupid = $userid = null;
switch ($type) {
case 'site':
- //$siteid = $id;
break;
case 'course':
$courseid = $id;
break;
}
- // Get all the entries from the database
+ // Get all the entries from the database.
require_once($CFG->dirroot .'/blog/locallib.php');
$blogheaders = blog_get_headers($courseid, $groupid, $userid, $tagid);
$bloglisting = new blog_listing($blogheaders['filters']);
$blogentries = $bloglisting->get_entries();
- // Now generate an array of RSS items
+ // Now generate an array of RSS items.
if ($blogentries) {
$items = array();
- foreach ($blogentries as $blog_entry) {
- $item = NULL;
- $item->author = fullname($DB->get_record('user', array('id'=>$blog_entry->userid))); // TODO: this is slow
- $item->title = $blog_entry->subject;
- $item->pubdate = $blog_entry->lastmodified;
- $item->link = $CFG->wwwroot.'/blog/index.php?entryid='.$blog_entry->id;
- $summary = file_rewrite_pluginfile_urls($blog_entry->summary, 'pluginfile.php',
- $sitecontext->id, 'blog', 'post', $blog_entry->id);
- $item->description = format_text($summary, $blog_entry->format);
- if ( !empty($CFG->usetags) && ($blogtags = tag_get_tags_array('post', $blog_entry->id)) ) {
+ foreach ($blogentries as $blogentry) {
+ $item = null;
+ $item->author = fullname($DB->get_record('user', array('id' => $blogentry->userid))); // TODO: this is slow.
+ $item->title = $blogentry->subject;
+ $item->pubdate = $blogentry->lastmodified;
+ $item->link = $CFG->wwwroot.'/blog/index.php?entryid='.$blogentry->id;
+ $summary = file_rewrite_pluginfile_urls($blogentry->summary, 'pluginfile.php',
+ $sitecontext->id, 'blog', 'post', $blogentry->id);
+ $item->description = format_text($summary, $blogentry->format);
+ if ( !empty($CFG->usetags) && ($blogtags = tag_get_tags_array('post', $blogentry->id)) ) {
if ($blogtags) {
$item->tags = $blogtags;
}
}
$items[] = $item;
}
- $articles = rss_add_items($items); /// Change structure to XML
+ $articles = rss_add_items($items); // Change structure to XML.
} else {
$articles = '';
}
-/// Get header and footer information
+ // Get header and footer information.
switch ($type) {
case 'user':
break;
case 'group':
$group = groups_get_group($id);
- $info = $group->name; //TODO: $DB->get_field('groups', 'name', array('id'=>$id))
+ $info = $group->name; // TODO: $DB->get_field('groups', 'name', array('id'=>$id)).
break;
default:
$info = '';
$info .= ': '.$DB->get_field('tags', 'text', array('id'=>$tagid));
}
- $header = rss_standard_header(get_string($type.'blog','blog', $info),
+ $header = rss_standard_header(get_string($type.'blog', 'blog', $info),
$CFG->wwwroot.'/blog/index.php',
- get_string('intro','blog'));
+ get_string('intro', 'blog'));
$footer = rss_standard_footer();
// Save the XML contents to file.
$rssdata = $header.$articles.$footer;
- if (blog_rss_save_file($type,$id,$tagid,$rssdata)) {
+ if (blog_rss_save_file($type, $id, $tagid, $rssdata)) {
return $filename;
} else {
- return false; // Couldn't find it or make it
+ return false; // Couldn't find it or make it.
}
}
$status = true;
- //blog creates some additional dirs within the rss cache so make sure they all exist
+ // Blog creates some additional dirs within the rss cache so make sure they all exist.
make_cache_directory('rss/blog');
make_cache_directory('rss/blog/'.$type);
$filename = blog_rss_file_name($type, $id, $tagid);
- $expandfilename = false; //we're supplying a full file path
+ $expandfilename = false; // We are supplying a full file path.
$status = rss_save_file('blog', $filename, $contents, $expandfilename);
return $status;
*/
class core_bloglib_testcase extends advanced_testcase {
- private $courseid; // To store important ids to be used in tests
+ private $courseid;
private $cmid;
private $groupid;
private $userid;
$this->resetAfterTest();
- // Create default course
+ // Create default course.
$course = $this->getDataGenerator()->create_course(array('category'=>1, 'shortname'=>'ANON'));
$this->assertNotEmpty($course);
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
$this->assertNotEmpty($page);
- // Create default group
+ // Create default group.
$group = new stdClass();
$group->courseid = $course->id;
$group->name = 'ANON';
$group->id = $DB->insert_record('groups', $group);
- // Create default user
+ // Create default user.
$user = $this->getDataGenerator()->create_user(array('username'=>'testuser', 'firstname'=>'Jimmy', 'lastname'=>'Kinnon'));
- // Create default tag
+ // Create default tag.
$tag = new stdClass();
$tag->userid = $user->id;
$tag->name = 'testtagname';
$tag->tagtype = 'official';
$tag->id = $DB->insert_record('tag', $tag);
- // Create default post
+ // Create default post.
$post = new stdClass();
$post->userid = $user->id;
$post->groupid = $group->id;
$post->content = 'test post content text';
$post->id = $DB->insert_record('post', $post);
- // Grab important ids
+ // Grab important ids.
$this->courseid = $course->id;
$this->cmid = $page->cmid;
$this->groupid = $group->id;
public function test_overrides() {
global $SITE;
- // Try all the filters at once: Only the entry filter is active
+ // Try all the filters at once: Only the entry filter is active.
$filters = array('site' => $SITE->id, 'course' => $this->courseid, 'module' => $this->cmid,
'group' => $this->groupid, 'user' => $this->userid, 'tag' => $this->tagid, 'entry' => $this->postid);
$blog_listing = new blog_listing($filters);
$this->assertFalse(array_key_exists('tag', $blog_listing->filters));
$this->assertTrue(array_key_exists('entry', $blog_listing->filters));
- // Again, but without the entry filter: This time, the tag, user and module filters are active
+ // Again, but without the entry filter: This time, the tag, user and module filters are active.
$filters = array('site' => $SITE->id, 'course' => $this->courseid, 'module' => $this->cmid,
'group' => $this->groupid, 'user' => $this->userid, 'tag' => $this->postid);
$blog_listing = new blog_listing($filters);
$this->assertTrue(array_key_exists('user', $blog_listing->filters));
$this->assertTrue(array_key_exists('tag', $blog_listing->filters));
- // We should get the same result by removing the 3 inactive filters: site, course and group:
+ // We should get the same result by removing the 3 inactive filters: site, course and group.
$filters = array('module' => $this->cmid, 'user' => $this->userid, 'tag' => $this->tagid);
$blog_listing = new blog_listing($filters);
$this->assertFalse(array_key_exists('site', $blog_listing->filters));
public function test_blog_get_headers_case_1() {
global $CFG, $PAGE, $OUTPUT;
- $blog_headers = blog_get_headers();
- $this->assertEquals($blog_headers['heading'], get_string('siteblog', 'blog', 'phpunit'));
+ $blogheaders = blog_get_headers();
+ $this->assertEquals($blogheaders['heading'], get_string('siteblog', 'blog', 'phpunit'));
}
public function test_blog_get_headers_case_6() {
global $CFG, $PAGE, $OUTPUT;
- $blog_headers = blog_get_headers($this->courseid, NULL, $this->userid);
- $this->assertNotEquals($blog_headers['heading'], '');
+ $blogheaders = blog_get_headers($this->courseid, null, $this->userid);
+ $this->assertNotEquals($blogheaders['heading'], '');
}
public function test_blog_get_headers_case_7() {
global $CFG, $PAGE, $OUTPUT;
- $blog_headers = blog_get_headers(NULL, $this->groupid);
- $this->assertNotEquals($blog_headers['heading'], '');
+ $blogheaders = blog_get_headers(null, $this->groupid);
+ $this->assertNotEquals($blogheaders['heading'], '');
}
public function test_blog_get_headers_case_10() {
global $CFG, $PAGE, $OUTPUT;
- $blog_headers = blog_get_headers($this->courseid);
- $this->assertNotEquals($blog_headers['heading'], '');
+ $blogheaders = blog_get_headers($this->courseid);
+ $this->assertNotEquals($blogheaders['heading'], '');
}
/**
$title = new lang_string('cacheadmin', 'cache');
$mform = null;
-$notification = null;
+$notifications = array();
$notifysuccess = true;
if (!empty($action) && confirm_sesskey()) {
if (!array_key_exists($store, $stores)) {
$notifysuccess = false;
- $notification = get_string('invalidstore', 'cache');
+ $notifications[] = array(get_string('invalidstore', 'cache'), false);
} else if ($stores[$store]['mappings'] > 0) {
$notifysuccess = false;
- $notification = get_string('deletestorehasmappings', 'cache');
+ $notifications[] = array(get_string('deletestorehasmappings', 'cache'), false);
}
if ($notifysuccess) {
$confirm = optional_param('confirm', false, PARAM_BOOL);
if (!array_key_exists($lock, $locks)) {
$notifysuccess = false;
- $notification = get_string('invalidlock', 'cache');
+ $notifications[] = array(get_string('invalidlock', 'cache'), false);
} else if ($locks[$lock]['uses'] > 0) {
$notifysuccess = false;
- $notification = get_string('deletelockhasuses', 'cache');
+ $notifications[] = array(get_string('deletelockhasuses', 'cache'), false);
}
if ($notifysuccess) {
if (!$confirm) {
}
}
+$notifications = array_merge($notifications, cache_helper::warnings($stores));
+
$PAGE->set_title($title);
$PAGE->set_heading($SITE->fullname);
/* @var core_cache_renderer $renderer */
echo $renderer->header();
echo $renderer->heading($title);
-
-if (!is_null($notification)) {
- echo $renderer->notification($notification, ($notifysuccess)?'notifysuccess' : 'notifyproblem');
-}
+echo $renderer->notifications($notifications);
if ($mform instanceof moodleform) {
$mform->display();
}
return $stores;
}
+
+ /**
+ * Returns an array of warnings from the cache API.
+ *
+ * The warning returned here are for things like conflicting store instance configurations etc.
+ * These get shown on the admin notifications page for example.
+ *
+ * @param array|null $stores An array of stores to get warnings for, or null for all.
+ * @return string[]
+ */
+ public static function warnings(array $stores = null) {
+ global $CFG;
+ if ($stores === null) {
+ require_once($CFG->dirroot.'/cache/locallib.php');
+ $stores = cache_administration_helper::get_store_instance_summaries();
+ }
+ $warnings = array();
+ foreach ($stores as $store) {
+ if (!empty($store['warnings'])) {
+ $warnings = array_merge($warnings, $store['warnings']);
+ }
+ }
+ return $warnings;
+ }
}
public static function initialise_unit_test_instance(cache_definition $definition) {
return static::initialise_test_instance($definition);
}
+
+ /**
+ * Can be overridden to return any warnings this store instance should make to the admin.
+ *
+ * This should be used to notify things like configuration conflicts etc.
+ * The warnings returned here will be displayed on the cache configuration screen.
+ *
+ * @return array[] Returns an array of arrays with the format:
+ * $notifications = array(
+ * array('This is a success message', true),
+ * array('This is a failure message', false),
+ * );
+ */
+ public function get_warnings() {
+ return array();
+ }
}
'nativelocking' => ($store instanceof cache_is_lockable),
'keyawareness' => ($store instanceof cache_is_key_aware),
'searchable' => ($store instanceof cache_is_searchable)
- )
+ ),
+ 'warnings' => $store->get_warnings()
);
if (empty($details['default'])) {
$return[$name] = $record;
);
$table->data = array();
+ core_collator::asort_array_of_arrays_by_key($definitions, 'name');
+
$none = new lang_string('none', 'cache');
foreach ($definitions as $id => $definition) {
$actions = cache_administration_helper::get_definition_actions($context, $definition);
$html .= html_writer::end_tag('div');
return $html;
}
+
+ /**
+ * Renders an array of notifications for the cache configuration screen.
+ *
+ * Takes an array of notifications with the form:
+ * $notifications = array(
+ * array('This is a success message', true),
+ * array('This is a failure message', false),
+ * );
+ *
+ * @param array $notifications
+ * @return string
+ */
+ public function notifications(array $notifications = array()) {
+ if (count($notifications) === 0) {
+ // There are no notifications to render.
+ return '';
+ }
+ $html = html_writer::start_div('notifications');
+ foreach ($notifications as $notification) {
+ list($message, $notifysuccess) = $notification;
+ $html .= $this->notification($message, ($notifysuccess) ? 'notifysuccess' : 'notifyproblem');
+ }
+ $html .= html_writer::end_div();
+ return $html;
+ }
}
\ No newline at end of file
server.url.com
ipaddress:port
</pre>';
+$string['sessionhandlerconflict'] = 'Warning: A memcache instance ({$a}) has being configured to use the same memcached server as sessions. Purging all caches will lead to sessions also being purged.';
$string['testservers'] = 'Test servers';
$string['testservers_desc'] = 'The test servers get used for unit tests and for performance tests. It is entirely optional to set up test servers. Servers should be defined one per line and consist of a server address and optionally a port and weight.
If no port is provided then the default port (11211) is used.';
\ No newline at end of file
public function my_name() {
return $this->name;
}
+
+ /**
+ * Used to notify of configuration conflicts.
+ *
+ * The warnings returned here will be displayed on the cache configuration screen.
+ *
+ * @return string[] Returns an array of warnings (strings)
+ */
+ public function get_warnings() {
+ global $CFG;
+ $warnings = array();
+ if (isset($CFG->session_memcached_save_path) && count($this->servers)) {
+ $bits = explode(':', $CFG->session_memcached_save_path, 3);
+ $host = array_shift($bits);
+ $port = (count($bits)) ? array_shift($bits) : '11211';
+ foreach ($this->servers as $server) {
+ if ($server[0] === $host && $server[1] === $port) {
+ $warnings[] = get_string('sessionhandlerconflict', 'cachestore_memcache', $this->my_name());
+ break;
+ }
+ }
+ }
+ return $warnings;
+ }
}
server.url.com
ipaddress:port
</pre>';
+$string['sessionhandlerconflict'] = 'Warning: A memcached instance ({$a}) has being configured to use the same memcached server as sessions. Purging all caches will lead to sessions also being purged.';
$string['testservers'] = 'Test servers';
$string['testservers_desc'] = 'The test servers get used for unit tests and for performance tests. It is entirely optional to set up test servers. Servers should be defined one per line and consist of a server address and optionally a port and weight.
If no port is provided then the default port (11211) is used.';
public function my_name() {
return $this->name;
}
+
+ /**
+ * Used to notify of configuration conflicts.
+ *
+ * The warnings returned here will be displayed on the cache configuration screen.
+ *
+ * @return string[] Returns an array of warnings (strings)
+ */
+ public function get_warnings() {
+ global $CFG;
+ $warnings = array();
+ if (isset($CFG->session_memcached_save_path) && count($this->servers)) {
+ $bits = explode(':', $CFG->session_memcached_save_path, 3);
+ $host = array_shift($bits);
+ $port = (count($bits)) ? array_shift($bits) : '11211';
+
+ foreach ($this->servers as $server) {
+ if ((string)$server[0] === $host && (string)$server[1] === $port) {
+ $warnings[] = get_string('sessionhandlerconflict', 'cachestore_memcached', $this->my_name());
+ break;
+ }
+ }
+ }
+ return $warnings;
+ }
}
$group[] =& $mform->createElement('radio', 'duration', null, get_string('durationuntil', 'calendar'), 1);
$group[] =& $mform->createElement('date_time_selector', 'timedurationuntil', '');
$group[] =& $mform->createElement('radio', 'duration', null, get_string('durationminutes', 'calendar'), 2);
- $group[] =& $mform->createElement('text', 'timedurationminutes', null);
+ $group[] =& $mform->createElement('text', 'timedurationminutes', get_string('durationminutes', 'calendar'));
$mform->addGroup($group, 'durationgroup', '', '<br />', false);
mtrace("Updating calendar subscription {$sub->name} in course {$sub->courseid}");
try {
$log = calendar_update_subscription_events($sub->id);
+ mtrace(trim(strip_tags($log)));
} catch (moodle_exception $ex) {
-
+ mtrace('Error updating calendar subscription: ' . $ex->getMessage());
}
- mtrace(trim(strip_tags($log)));
}
mtrace('Finished updating calendar subscriptions.');
*/
class core_calendar_lib_testcase extends advanced_testcase {
- public function test_calendar_get_course_cached() {
+ protected function setUp() {
$this->resetAfterTest(true);
+ }
+ public function test_calendar_get_course_cached() {
// Setup some test courses.
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$this->assertEquals($course3->shortname, $cachedcourse3->shortname);
$this->assertEquals($course3->fullname, $cachedcourse3->fullname);
}
+
+ /**
+ * Test calendar cron with a working subscription URL.
+ */
+ public function test_calendar_cron_working_url() {
+ global $CFG;
+ require_once($CFG->dirroot . '/lib/cronlib.php');
+
+ // Moodle ICal URL (moodle.org events).
+ $presetwhat = 'all';
+ $presettime = 'recentupcoming';
+ $userid = 1;
+ $authtoken = 'a8bcfee2fb868a05357f650bd65dc0699b026524';
+ $subscriptionurl = 'https://moodle.org/calendar/export_execute.php'
+ . '?preset_what='.$presetwhat.'&preset_time='.$presettime.'&userid='.$userid.'&authtoken='.$authtoken;
+
+ $subscription = new stdClass();
+ $subscription->eventtype = 'site';
+ $subscription->name = 'test';
+ $subscription->url = $subscriptionurl;
+ $subscription->pollinterval = 86400;
+ $subscription->lastupdated = 0;
+ calendar_add_subscription($subscription);
+
+ $this->expectOutputRegex('/Events imported: .* Events updated:/');
+ calendar_cron();
+ }
+
+ /**
+ * Test calendar cron with a broken subscription URL.
+ */
+ public function test_calendar_cron_broken_url() {
+ global $CFG;
+ require_once($CFG->dirroot . '/lib/cronlib.php');
+
+ $subscription = new stdClass();
+ $subscription->eventtype = 'site';
+ $subscription->name = 'test';
+ $subscription->url = 'brokenurl';
+ $subscription->pollinterval = 86400;
+ $subscription->lastupdated = 0;
+ calendar_add_subscription($subscription);
+
+ $this->expectOutputRegex('/Error updating calendar subscription: The given iCal URL is invalid/');
+ calendar_cron();
+ }
}
$actions['resortbyname'] = array(
'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'name')),
'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
- 'string' => new \lang_string('resortsubcategoriesbyname', 'moodle')
+ 'string' => new \lang_string('resortsubcategoriesby', 'moodle' , get_string('categoryname'))
+ );
+ $actions['resortbynamedesc'] = array(
+ 'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'namedesc')),
+ 'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
+ 'string' => new \lang_string('resortsubcategoriesbyreverse', 'moodle', get_string('categoryname'))
);
$actions['resortbyidnumber'] = array(
'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'idnumber')),
'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
- 'string' => new \lang_string('resortsubcategoriesbyidnumber', 'moodle')
+ 'string' => new \lang_string('resortsubcategoriesby', 'moodle', get_string('idnumbercoursecategory'))
+ );
+ $actions['resortbyidnumberdesc'] = array(
+ 'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'idnumberdesc')),
+ 'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
+ 'string' => new \lang_string('resortsubcategoriesbyreverse', 'moodle', get_string('idnumbercoursecategory'))
);
}
$form .= html_writer::div(
html_writer::select(
array(
- 'name' => get_string('sortcategoriesbyname'),
- 'idnumber' => get_string('sortcategoriesbyidnumber'),
+ 'name' => get_string('sortbyx', 'moodle', get_string('categoryname')),
+ 'namedesc' => get_string('sortbyxreverse', 'moodle', get_string('categoryname')),
+ 'idnumber' => get_string('sortbyx', 'moodle', get_string('idnumbercoursecategory')),
+ 'idnumberdesc' => get_string('sortbyxreverse' , 'moodle' , get_string('idnumbercoursecategory')),
'none' => get_string('dontsortcategories')
),
'resortcategoriesby',
$form .= html_writer::div(
html_writer::select(
array(
- 'fullname' => get_string('sortcoursesbyfullname'),
- 'shortname' => get_string('sortcoursesbyshortname'),
- 'idnumber' => get_string('sortcoursesbyidnumber'),
+ 'fullname' => get_string('sortbyx', 'moodle', get_string('fullnamecourse')),
+ 'fullnamedesc' => get_string('sortbyxreverse', 'moodle', get_string('fullnamecourse')),
+ 'shortname' => get_string('sortbyx', 'moodle', get_string('shortnamecourse')),
+ 'shortnamedesc' => get_string('sortbyxreverse', 'moodle', get_string('shortnamecourse')),
+ 'idnumber' => get_string('sortbyx', 'moodle', get_string('idnumbercourse')),
+ 'idnumberdesc' => get_string('sortbyxreverse', 'moodle', get_string('idnumbercourse')),
+ 'timecreated' => get_string('sortbyx', 'moodle', get_string('timecreatedcourse')),
+ 'timecreateddesc' => get_string('sortbyxreverse', 'moodle', get_string('timecreatedcourse')),
'none' => get_string('dontsortcourses')
),
'resortcoursesby',
$params['sesskey'] = sesskey();
$baseurl = new moodle_url('/course/management.php', $params);
$fullnameurl = new moodle_url($baseurl, array('resort' => 'fullname'));
+ $fullnameurldesc = new moodle_url($baseurl, array('resort' => 'fullnamedesc'));
$shortnameurl = new moodle_url($baseurl, array('resort' => 'shortname'));
+ $shortnameurldesc = new moodle_url($baseurl, array('resort' => 'shortnamedesc'));
$idnumberurl = new moodle_url($baseurl, array('resort' => 'idnumber'));
+ $idnumberdescurl = new moodle_url($baseurl, array('resort' => 'idnumberdesc'));
+ $timecreatedurl = new moodle_url($baseurl, array('resort' => 'timecreated'));
+ $timecreateddescurl = new moodle_url($baseurl, array('resort' => 'timecreateddesc'));
$menu = new action_menu(array(
- new action_menu_link_secondary($fullnameurl, null, get_string('resortbyfullname')),
- new action_menu_link_secondary($shortnameurl, null, get_string('resortbyshortname')),
- new action_menu_link_secondary($idnumberurl, null, get_string('resortbyidnumber'))
+ new action_menu_link_secondary($fullnameurl,
+ null,
+ get_string('sortbyx', 'moodle', get_string('fullnamecourse'))),
+ new action_menu_link_secondary($fullnameurldesc,
+ null,
+ get_string('sortbyxreverse', 'moodle', get_string('fullnamecourse'))),
+ new action_menu_link_secondary($shortnameurl,
+ null,
+ get_string('sortbyx', 'moodle', get_string('shortnamecourse'))),
+ new action_menu_link_secondary($shortnameurldesc,
+ null,
+ get_string('sortbyxreverse', 'moodle', get_string('shortnamecourse'))),
+ new action_menu_link_secondary($idnumberurl,
+ null,
+ get_string('sortbyx', 'moodle', get_string('idnumbercourse'))),
+ new action_menu_link_secondary($idnumberdescurl,
+ null,
+ get_string('sortbyxreverse', 'moodle', get_string('idnumbercourse'))),
+ new action_menu_link_secondary($timecreatedurl,
+ null,
+ get_string('sortbyx', 'moodle', get_string('timecreatedcourse'))),
+ new action_menu_link_secondary($timecreateddescurl,
+ null,
+ get_string('sortbyxreverse', 'moodle', get_string('timecreatedcourse')))
));
$menu->set_menu_trigger(get_string('resortcourses'));
$actions[] = $this->render($menu);
return html_writer::span(join('', $actions), 'course-item-actions item-actions');
}
+ /**
+ * Renders html to display a course search form
+ *
+ * @param string $value default value to populate the search field
+ * @param string $format display format - 'plain' (default), 'short' or 'navbar'
+ * @return string
+ */
+ public function course_search_form($value = '', $format = 'plain') {
+ static $count = 0;
+ $formid = 'coursesearch';
+ if ((++$count) > 1) {
+ $formid .= $count;
+ }
+
+ switch ($format) {
+ case 'navbar' :
+ $formid = 'coursesearchnavbar';
+ $inputid = 'navsearchbox';
+ $inputsize = 20;
+ break;
+ case 'short' :
+ $inputid = 'shortsearchbox';
+ $inputsize = 12;
+ break;
+ default :
+ $inputid = 'coursesearchbox';
+ $inputsize = 30;
+ }
+
+ $strsearchcourses = get_string("searchcourses");
+ $searchurl = new moodle_url('/course/management.php');
+
+ $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get'));
+ $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset'));
+ $output .= html_writer::tag('label', $strsearchcourses.': ', array('for' => $inputid));
+ $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid,
+ 'size' => $inputsize, 'name' => 'search', 'value' => s($value)));
+ $output .= html_writer::empty_tag('input', array('type' => 'submit',
+ 'value' => get_string('go')));
+ $output .= html_writer::end_tag('fieldset');
+ $output .= html_writer::end_tag('form');
+
+ return $output;
+ }
+
/**
* Creates access hidden skip to links for the displayed sections.
*
}
}
- $data->timecreated = time();
+ // Check if timecreated is given.
+ $data->timecreated = !empty($data->timecreated) ? $data->timecreated : time();
$data->timemodified = $data->timecreated;
// place at beginning of any category
// They're not sorting anything.
break;
}
- if (!in_array($sortcategoriesby, array('idnumber', 'name'))) {
+ if (!in_array($sortcategoriesby, array('idnumber', 'idnumberdesc',
+ 'name', 'namedesc'))) {
$sortcategoriesby = false;
}
- if (!in_array($sortcoursesby, array('idnumber', 'fullname', 'shortname'))) {
+ if (!in_array($sortcoursesby, array('timecreated', 'timecreateddesc',
+ 'idnumber', 'idnumberdesc',
+ 'fullname', 'fullnamedesc',
+ 'shortname', 'shortnamedesc'))) {
$sortcoursesby = false;
}
// End of the management form.
echo $renderer->management_form_end();
+echo $renderer->course_search_form($search);
+
echo $renderer->footer();
foreach ($moduleshtml as $modnumber => $modulehtml) {
if ($ismoving) {
$movingurl = new moodle_url('/course/mod.php', array('moveto' => $modnumber, 'sesskey' => sesskey()));
- $sectionoutput .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix)),
- array('class' => 'movehere', 'title' => $strmovefull));
+ $sectionoutput .= html_writer::tag('li',
+ html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
+ array('class' => 'movehere'));
}
$sectionoutput .= $modulehtml;
if ($ismoving) {
$movingurl = new moodle_url('/course/mod.php', array('movetosection' => $section->id, 'sesskey' => sesskey()));
- $sectionoutput .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix)),
- array('class' => 'movehere', 'title' => $strmovefull));
+ $sectionoutput .= html_writer::tag('li',
+ html_writer::link($movingurl, $this->output->render($movingpix), array('title' => $strmovefull)),
+ array('class' => 'movehere'));
}
}
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "Sort categories by name" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "Sort categories by ID number" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Category name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Category ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
Scenario Outline: Test bulk sorting current category.
Given the following "categories" exist:
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "Sort categories by name" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "Sort categories by ID number" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Category name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Category ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
Scenario Outline: Test resorting subcategories.
Given the following "categories" exist:
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "resortbynamedesc" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyidnumberdesc" | "Applied sciences" | "Social studies" | "Extended social studies" |
@javascript
Scenario Outline: Test resorting subcategories with JS enabled.
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "resortbynamedesc" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyidnumberdesc" | "Applied sciences" | "Social studies" | "Extended social studies" |
# The scenario below this is the same but with JS enabled.
Scenario: Test moving categories up and down by one.
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "Sort categories by name" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "Sort categories by ID number" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Category name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Category ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Category ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
@javascript
Scenario Outline: Sub categories are displayed correctly when resorted
Examples:
| sortby | cat1 | cat2 | cat3 |
- | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyname" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "resortbynamedesc" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "resortbyidnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "resortbyidnumberdesc" | "Applied sciences" | "Social studies" | "Extended social studies" |
@javascript
Scenario Outline: Test courses are displayed correctly after being resorted.
| name | category 0| idnumber |
| Cat 1 | 0 | CAT1 |
And the following "courses" exist:
- | category | fullname | shortname | idnumber | sortorder |
- | CAT1 | Social studies | Senior school | Ext003 | 1 |
- | CAT1 | Applied sciences | Middle school | Sci001 | 2 |
- | CAT1 | Extended social studies | Junior school | Ext002 | 3 |
+ | category | fullname | shortname | idnumber | sortorder | timecreated |
+ | CAT1 | Social studies | Senior school | Ext003 | 1 | 10000000001 |
+ | CAT1 | Applied sciences | Middle school | Sci001 | 2 | 10000000002 |
+ | CAT1 | Extended social studies | Junior school | Ext002 | 3 | 10000000003 |
And I log in as "admin"
And I go to the courses management page
# Redirect.
And I should see the "Course categories and courses" management page
And I click on "Sort courses" "link"
- And I should see "By fullname" in the ".course-listing-actions" "css_element"
- And I should see "By shortname" in the ".course-listing-actions" "css_element"
- And I should see "By idnumber" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created descending" in the ".course-listing-actions" "css_element"
And I click on <sortby> "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
Examples:
| sortby | course1 | course2 | course3 |
- | "By fullname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "By shortname" | "Extended social studies" | "Applied sciences" | "Social studies" |
- | "By idnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course full name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Course full name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Course short name ascending" | "Extended social studies" | "Applied sciences" | "Social studies" |
+ | "Sort by Course short name descending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
+ | "Sort by Course time created ascending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course time created descending" | "Extended social studies" | "Applied sciences" | "Social studies" |
@javascript
Scenario: Test course pagination
# Redirect.
And I should see the "Course categories and courses" management page
And I click on "Sort courses" "link"
- And I click on "By idnumber" "link" in the ".course-listing-actions" "css_element"
+ And I click on "Sort by Course ID number ascending" "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see "Per page: 20" in the ".course-listing-actions" "css_element"
And I should see course listing "Course 1" before "Course 2"
# Redirect.
And I should see the "Course categories and courses" management page
And I click on "Sort courses" "link"
- And I click on "By idnumber" "link" in the ".course-listing-actions" "css_element"
+ And I click on "Sort by Course ID number ascending" "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see "Per page: 20" in the ".course-listing-actions" "css_element"
And I should see course listing "Course 1" before "Course 2"
# Redirect.
And I should see the "Course categories and courses" management page
And I click on "Sort courses" "link"
- And I click on "By idnumber" "link" in the ".course-listing-actions" "css_element"
+ And I click on "Sort by Course ID number ascending" "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
And I should see "Per page: 20" in the ".course-listing-actions" "css_element"
| name | category 0| idnumber |
| Cat 1 | 0 | CAT1 |
And the following "courses" exist:
- | category | fullname | shortname | idnumber | sortorder |
- | CAT1 | Social studies | Senior school | Ext003 | 1 |
- | CAT1 | Applied sciences | Middle school | Sci001 | 2 |
- | CAT1 | Extended social studies | Junior school | Ext002 | 3 |
+ | category | fullname | shortname | idnumber | sortorder | timecreated |
+ | CAT1 | Social studies | Senior school | Ext003 | 1 | 10000000001 |
+ | CAT1 | Applied sciences | Middle school | Sci001 | 2 | 10000000002 |
+ | CAT1 | Extended social studies | Junior school | Ext002 | 3 | 10000000003 |
And I log in as "admin"
And I go to the courses management page
# Redirect.
And I should see the "Course categories and courses" management page
And I should see "Sort courses" in the ".course-listing-actions" "css_element"
- And I should see "By fullname" in the ".course-listing-actions" "css_element"
- And I should see "By shortname" in the ".course-listing-actions" "css_element"
- And I should see "By idnumber" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created descending" in the ".course-listing-actions" "css_element"
And I click on <sortby> "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
Examples:
| sortby | course1 | course2 | course3 |
- | "By fullname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "By shortname" | "Extended social studies" | "Applied sciences" | "Social studies" |
- | "By idnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course full name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Course full name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Course short name ascending" | "Extended social studies" | "Applied sciences" | "Social studies" |
+ | "Sort by Course short name descending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
+ | "Sort by Course time created ascending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course time created descending" | "Extended social studies" | "Applied sciences" | "Social studies" |
@javascript
Scenario Outline: Resort courses with JavaScript enabled.
| name | category 0| idnumber |
| Cat 1 | 0 | CAT1 |
And the following "courses" exist:
- | category | fullname | shortname | idnumber | sortorder |
- | CAT1 | Social studies | Senior school | Ext003 | 1 |
- | CAT1 | Applied sciences | Middle school | Sci001 | 2 |
- | CAT1 | Extended social studies | Junior school | Ext002 | 3 |
+ | category | fullname | shortname | idnumber | sortorder | timecreated |
+ | CAT1 | Social studies | Senior school | Ext003 | 1 | 10000000001 |
+ | CAT1 | Applied sciences | Middle school | Sci001 | 2 | 10000000002 |
+ | CAT1 | Extended social studies | Junior school | Ext002 | 3 | 10000000003 |
And I log in as "admin"
And I go to the courses management page
# Redirect.
And I should see the "Course categories and courses" management page
And I should see "Sort courses" in the ".course-listing-actions" "css_element"
- And I should not see "By fullname" in the ".course-listing-actions" "css_element"
- And I should not see "By shortname" in the ".course-listing-actions" "css_element"
- And I should not see "By idnumber" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course full name ascending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course full name descending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course short name ascending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course short name descending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course ID number ascending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course ID number descending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course time created ascending" in the ".course-listing-actions" "css_element"
+ And I should not see "Sort by Course time created descending" in the ".course-listing-actions" "css_element"
And I click on "Sort courses" "link"
- And I should see "By fullname" in the ".course-listing-actions" "css_element"
- And I should see "By shortname" in the ".course-listing-actions" "css_element"
- And I should see "By idnumber" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course full name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course short name descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course ID number descending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created ascending" in the ".course-listing-actions" "css_element"
+ And I should see "Sort by Course time created descending" in the ".course-listing-actions" "css_element"
And I click on <sortby> "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
Examples:
| sortby | course1 | course2 | course3 |
- | "By fullname" | "Applied sciences" | "Extended social studies" | "Social studies" |
- | "By shortname" | "Extended social studies" | "Applied sciences" | "Social studies" |
- | "By idnumber" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course full name ascending" | "Applied sciences" | "Extended social studies" | "Social studies" |
+ | "Sort by Course full name descending" | "Social studies" | "Extended social studies" | "Applied sciences" |
+ | "Sort by Course short name ascending" | "Extended social studies" | "Applied sciences" | "Social studies" |
+ | "Sort by Course short name descending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course ID number ascending" | "Extended social studies" | "Social studies" | "Applied sciences" |
+ | "Sort by Course ID number descending" | "Applied sciences" | "Social studies" | "Extended social studies" |
+ | "Sort by Course time created ascending" | "Social studies" | "Applied sciences" | "Extended social studies" |
+ | "Sort by Course time created descending" | "Extended social studies" | "Applied sciences" | "Social studies" |
Scenario: Test moving courses up and down by one.
Given the following "categories" exist:
And I should see "Course categories" in the "#category-listing h3" "css_element"
And I should see "Cat 1" in the "#category-listing" "css_element"
And I click on "Sort courses" "link"
- And I click on "By idnumber" "link" in the ".course-listing-actions" "css_element"
+ And I click on "Sort by Course ID number ascending" "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
And I should see course listing "Course 1" before "Course 2"
And I should see "Course categories" in the "#category-listing h3" "css_element"
And I should see "Cat 1" in the "#category-listing" "css_element"
And I click on "Sort courses" "link"
- And I click on "By idnumber" "link" in the ".course-listing-actions" "css_element"
+ And I click on "Sort by Course ID number ascending" "link" in the ".course-listing-actions" "css_element"
# Redirect.
And I should see the "Course categories and courses" management page
And I should see course listing "Course 1" before "Course 2"
* @param string $tagcontents The raw contents of the XML element
*/
protected function process_group_tag($tagcontents) {
- global $DB;
+ global $DB, $CFG;
// Get configs.
$truncatecoursecodes = $this->get_config('truncatecoursecodes');
$createnewcourses = $this->get_config('createnewcourses');
$createnewcategories = $this->get_config('createnewcategories');
+ if ($createnewcourses) {
+ require_once("$CFG->dirroot/course/lib.php");
+ }
// Process tag contents.
$group = new stdClass();
if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)) {
<div class="fp-tb-message"></div>
</div>
<div class="fp-viewbar">
- <a title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
+ <a role="button" title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
<img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" />
</a>
- <a title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
+ <a role="button" title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
<img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" />
</a>
- <a title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
+ <a role="button" title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
<img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" />
</a>
</div>
'name' => $cm->name,
'url' => $cm->url,
'id' => $cm->id,
- 'namelen' => strlen($cm->name),
+ 'namelen' => -strlen($cm->name), // Negative value for reverse sorting.
);
}
}
- core_collator::asort_objects_by_property($sortedactivities, 'namelen', SORT_NUMERIC);
+ // Sort activities by the length of the activity name in reverse order.
+ core_collator::asort_objects_by_property($sortedactivities, 'namelen', core_collator::SORT_NUMERIC);
foreach ($sortedactivities as $cm) {
$title = s(trim(strip_tags($cm->name)));
default:
print_error('unknoworder');
}
- $users = groups_get_potential_members($data->courseid, $data->roleid, $data->cohortid, $orderby);
+ $users = groups_get_potential_members($data->courseid, $data->roleid, $data->cohortid, $orderby, !empty($data->notingroup));
$usercnt = count($users);
if ($data->allocateby == 'random') {
$mform->addElement('checkbox', 'nosmallgroups', get_string('nosmallgroups', 'group'));
$mform->disabledIf('nosmallgroups', 'groupby', 'noteq', 'members');
+ $mform->addElement('checkbox', 'notingroup', get_string('notingroup', 'group'));
+
$mform->addElement('header', 'groupinghdr', get_string('grouping', 'group'));
$options = array('0' => get_string('nogrouping', 'group'),
* @param int $roleid The role to select users from
* @param int $cohortid restrict to cohort id
* @param string $orderby The column to sort users by
+ * @param int $notingroup restrict to users not in existing groups
* @return array An array of the users
*/
-function groups_get_potential_members($courseid, $roleid = null, $cohortid = null, $orderby = 'lastname ASC, firstname ASC') {
+function groups_get_potential_members($courseid, $roleid = null, $cohortid = null,
+ $orderby = 'lastname ASC, firstname ASC',
+ $notingroup = null) {
global $DB;
$context = context_course::instance($courseid);
list($esql, $params) = get_enrolled_sql($context);
+ $notingroupsql = "";
+ if ($notingroup) {
+ // We want to eliminate users that are already associated with a course group.
+ $notingroupsql = "u.id NOT IN (SELECT userid
+ FROM {groups_members}
+ WHERE groupid IN (SELECT id
+ FROM {groups}
+ WHERE courseid = :courseid))";
+ $params['courseid'] = $courseid;
+ }
+
if ($roleid) {
// We are looking for all users with this role assigned in this context or higher.
- list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
+ list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true),
+ SQL_PARAMS_NAMED,
+ 'relatedctx');
$params = array_merge($params, $relatedctxparams, array('roleid' => $roleid));
$where = "WHERE u.id IN (SELECT userid
FROM {role_assignments}
WHERE roleid = :roleid AND contextid $relatedctxsql)";
+ $where .= $notingroup ? "AND $notingroupsql" : "";
+ } else if ($notingroup) {
+ $where = "WHERE $notingroupsql";
} else {
$where = "";
}
And I should see "Group B" in the ".generaltable" "css_element"
And I should see "5" in the "Group A" "table_row"
And I should see "5" in the "Group B" "table_row"
+
+ @javascript
+ Scenario: Split automatically the course users in groups that are not in groups
+ Given I press "Cancel"
+ And I press "Create group"
+ And I set the following fields to these values:
+ | Group name | Group 1 |
+ And I press "Save changes"
+ And I press "Create group"
+ And I set the following fields to these values:
+ | Group name | Group 2 |
+ And I press "Save changes"
+ When I add "Student 0" user to "Group 1" group members
+ And I add "Student 1" user to "Group 1" group members
+ And I add "Student 2" user to "Group 2" group members
+ And I add "Student 3" user to "Group 2" group members
+ And I press "Auto-create groups"
+ And I expand all fieldsets
+ And I set the field "Auto create based on" to "Number of groups"
+ And I set the field "Group/member count" to "2"
+ And I set the field "Grouping of auto-created groups" to "No grouping"
+ And I set the field "Ignore users in groups" to "1"
+ And I press "Submit"
+ And the "groups" select box should contain "Group A (3)"
+ And the "groups" select box should contain "Group B (3)"
\ No newline at end of file
--- /dev/null
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package installer
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$string['language'] = 'Taal';
$string['availablelangs'] = 'Доступные языковые пакеты';
$string['chooselanguagehead'] = 'Выберите язык';
$string['chooselanguagesub'] = 'Сейчас необходимо выбрать язык ТОЛЬКО для сообщений во время установки. Язык сайта и пользовательских интерфейсов можно будет указать далее в процессе установки.';
-$string['clialreadyconfigured'] = 'Файл config.php уже существует. Если Вы хотите установить этот сайт, используйте admin/cli/install_database.php.';
-$string['clialreadyinstalled'] = 'Файл config.php уже существует. Если Вы хотите обновить сайт, то используйте скрипт admin/cli/upgrade.php.';
+$string['clialreadyconfigured'] = 'Файл config.php уже существует. Если Вы хотите установить Moodle на этот сайт, используйте admin/cli/install_database.php.';
+$string['clialreadyinstalled'] = 'Файл config.php уже существует. Если Вы хотите обновить сайт Moodle, то используйте скрипт admin/cli/upgrade.php.';
$string['cliinstallheader'] = 'Программа установки Moodle {$a} в режиме командной строки';
$string['databasehost'] = 'Сервер баз данных';
$string['databasename'] = 'Название базы данных';
$string['user'] = 'User';
$string['userbulk'] = 'Bulk user actions';
$string['userlist'] = 'Browse list of users';
+$string['userdefaultpreferences'] = 'User default preferences';
$string['userpreference'] = 'User preference';
$string['userpolicies'] = 'User policies';
$string['users'] = 'Users';
$string['nogroupsassigned'] = 'No groups assigned';
$string['nopermissionforcreation'] = 'Can\'t create group "{$a}" as you don\'t have the required permissions';
$string['nosmallgroups'] = 'Prevent last small group';
+$string['notingroup'] = 'Ignore users in groups';
$string['notingrouping'] = '[Not in a grouping]';
$string['nousersinrole'] = 'There are no suitable users in the selected role';
$string['number'] = 'Group/member count';
$string['resetstatus'] = 'Status';
$string['resettask'] = 'Task';
$string['resettodefaults'] = 'Reset to defaults';
-$string['resortsubcategoriesbyname'] = 'Sort subcategories by name';
-$string['resortsubcategoriesbyidnumber'] = 'Sort subcategories by idnumber';
+$string['resortsubcategoriesby'] = 'Sort subcategories by {$a} ascending';
+$string['resortsubcategoriesbyreverse'] = 'Sort subcategories by {$a} descending';
$string['resortcourses'] = 'Sort courses';
-$string['resortbyshortname'] = 'By shortname';
-$string['resortbyfullname'] = 'By fullname';
-$string['resortbyidnumber'] = 'By idnumber';
$string['resource'] = 'Resource';
$string['resourcedisplayauto'] = 'Automatic';
$string['resourcedisplaydownload'] = 'Force download';
$string['sortby'] = 'Sort by';
$string['sortbyx'] = 'Sort by {$a} ascending';
$string['sortbyxreverse'] = 'Sort by {$a} descending';
-$string['sortcategoriesbyname'] = 'Sort categories by name';
-$string['sortcategoriesbyidnumber'] = 'Sort categories by ID number';
-$string['sortcoursesbyfullname'] = 'Sort courses by full name';
-$string['sortcoursesbyshortname'] = 'Sort courses by short name';
-$string['sortcoursesbyidnumber'] = 'Sort courses by ID number';
$string['sorting'] = 'Sorting';
$string['sourcerole'] = 'Source role';
$string['specifyname'] = 'You must specify a name.';
$string['thiscategory'] = 'This category';
$string['thiscategorycontains'] = 'This category contains';
$string['time'] = 'Time';
+$string['timecreatedcourse'] = 'Course time created';
$string['timezone'] = 'Timezone';
$string['to'] = 'To';
$string['tocreatenewaccount'] = 'Skip to create new account';
$string['trysearching'] = 'Try searching instead.';
$string['turneditingoff'] = 'Turn editing off';
$string['turneditingon'] = 'Turn editing on';
+$string['unauthorisedlogin'] = 'The user account "{$a}" is not available on this site';
$string['undecided'] = 'Undecided';
$string['unfinished'] = 'Unfinished';
$string['unknowncategory'] = 'Unknown category';
/** Can not login because user is locked out. */
define('AUTH_LOGIN_LOCKOUT', 4);
+/** Can not login becauser user is not authorised. */
+define('AUTH_LOGIN_UNAUTHORISED', 5);
/**
* Abstract authentication plugin.
return $result;
}
+ /**
+ * Locale aware sort of array of arrays.
+ *
+ * Given an array like:
+ * $array = array(
+ * array('name' => 'bravo'),
+ * array('name' => 'charlie'),
+ * array('name' => 'alpha')
+ * );
+ *
+ * If you call:
+ * core_collator::asort_array_of_arrays_by_key($array, 'name')
+ *
+ * You will be returned $array sorted by the name key of the subarrays. e.g.
+ * $array = array(
+ * array('name' => 'alpha'),
+ * array('name' => 'bravo'),
+ * array('name' => 'charlie')
+ * );
+ *
+ * @param array $array An array of objects to sort (handled by reference)
+ * @param string $key The key to use for comparison
+ * @param int $sortflag One of
+ * core_collator::SORT_NUMERIC,
+ * core_collator::SORT_STRING,
+ * core_collator::SORT_NATURAL,
+ * core_collator::SORT_REGULAR
+ * optionally "|" core_collator::CASE_SENSITIVE
+ * @return bool True on success
+ */
+ public static function asort_array_of_arrays_by_key(array &$array, $key, $sortflag = core_collator::SORT_STRING) {
+ $original = $array;
+ foreach ($array as $initkey => $item) {
+ $array[$initkey] = $item[$key];
+ }
+ $result = self::asort($array, $sortflag);
+ self::restore_array($array, $original);
+ return $result;
+ }
+
/**
* Locale aware sorting, the key associations are kept, keys are sorted alphabetically.
*
*/
protected function init() {
$this->data['crud'] = 'r';
- $this->data['edulevel'] = self::LEVEL_OTHER;
+ $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
/**
$this->customdata = json_encode($customdata);
}
+ /**
+ * Alternate setter for $customdata. Expects the data as a json_encoded string.
+ * @param string $customdata json_encoded string
+ */
+ public function set_custom_data_as_string($customdata) {
+ $this->customdata = $customdata;
+ }
+
/**
* Getter for $customdata.
* @return mixed (anything that can be handled by json_decode).
return json_decode($this->customdata);
}
+ /**
+ * Alternate getter for $customdata.
+ * @return string this is the raw json encoded version.
+ */
+ public function get_custom_data_as_string() {
+ return $this->customdata;
+ }
+
+
}
$record->blocking = $task->is_blocking();
$record->nextruntime = $task->get_next_run_time();
$record->faildelay = $task->get_fail_delay();
- $record->customdata = $task->get_custom_data();
+ $record->customdata = $task->get_custom_data_as_string();
return $record;
}
$task->set_fail_delay($record->faildelay);
}
if (isset($record->customdata)) {
- $task->set_custom_data($record->customdata);
+ $task->set_custom_data_as_string($record->customdata);
}
return $task;
/**
* Get incomplete course completion criteria
*
+ * @deprecated since Moodle 2.8 MDL-46290.
+ * @todo MDL-46294 This will be deleted in Moodle 3.0.
* @return array
*/
public function get_incomplete_criteria() {
+ debugging('completion_info->get_incomplete_criteria() is deprecated.', DEBUG_DEVELOPER);
$incomplete = array();
foreach ($this->get_criteria() as $criteria) {
return $coursecat;
} else {
if ($strictness == MUST_EXIST) {
- throw new moodle_exception('unknowcategory');
+ throw new moodle_exception('unknowncategory');
}
}
return null;
/**
* Resorts the sub categories of this category by the given field.
*
- * @param string $field
+ * @param string $field One of name, idnumber or descending values of each (appended desc)
* @param bool $cleanup If true cleanup will be done, if false you will need to do it manually later.
* @return bool True on success.
* @throws coding_exception
*/
public function resort_subcategories($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 !== 'name' && $field !== 'idnumber') {
throw new coding_exception('Invalid field requested');
}
$children = $this->get_children();
core_collator::asort_objects_by_property($children, $field, core_collator::SORT_NATURAL);
+ if (!empty($desc)) {
+ $children = array_reverse($children);
+ }
$i = 1;
foreach ($children as $cat) {
$i++;
/**
* Resort the courses within this category by the given field.
*
- * @param string $field One of fullname, shortname or idnumber
+ * @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;
- if ($field !== 'fullname' && $field !== 'shortname' && $field !== 'idnumber') {
+ $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');
}
FROM {course} c
LEFT JOIN {context} ctx ON ctx.instanceid = c.id
WHERE ctx.contextlevel = :ctxlevel AND
- c.category = :categoryid
- ORDER BY c.{$field}, c.sortorder";
+ c.category = :categoryid";
$params = array(
'ctxlevel' => CONTEXT_COURSE,
'categoryid' => $this->id
}
// 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));
* @param string $tofile store the downloaded content to file instead of returning it.
* @param bool $calctimeout false by default, true enables an extra head request to try and determine
* filesize and appropriately larger timeout based on $CFG->curltimeoutkbitrate
- * @return mixed false if request failed or content of the file as string if ok. True if file downloaded into $tofile successfully.
+ * @return stdClass|string|bool stdClass object if $fullresponse is true, false if request failed, true
+ * if file downloaded into $tofile successfully or the file content as a string.
*/
function download_file_content($url, $headers=null, $postdata=null, $fullresponse=false, $timeout=300, $connecttimeout=20, $skipcertverify=false, $tofile=NULL, $calctimeout=false) {
global $CFG;
var labelid = 'fm-dialog-label_'+ this.selectnode.get('id');
this.selectui = new M.core.dialogue({
draggable : true,
- headerContent: '<span id="' + labelid +'">' + M.str.moodle.edit + '</span>',
+ headerContent: '<h3 id="' + labelid +'">' + M.str.moodle.edit + '</h3>',
bodyContent : this.selectnode,
centered : true,
width : '480px',
}
+/**
+ * Validates RTMP defined by Adobe
+ */
+class HTMLPurifier_URIScheme_rtmp extends HTMLPurifier_URIScheme {
+
+ public $browsable = false;
+ public $hierarchical = true;
+
+ public function doValidate(&$uri, $config, $context) {
+ $uri->userinfo = null;
+ return true;
+ }
+
+}
+
+
/**
* Validates IRC defined by IETF Draft
*/
*
* A NULL value will delete the entry.
*
+ * NOTE: this function is called from lib/db/upgrade.php
+ *
* @param string $name the key to set
* @param string $value the value to set (without magic quotes)
* @param string $plugin (optional) the plugin scope, default null
* If called with 2 parameters it will return a string single
* value or false if the value is not found.
*
+ * NOTE: this function is called from lib/db/upgrade.php
+ *
* @static string|false $siteidentifier The site identifier is not cached. We use this static cache so
* that we need only fetch it once per request.
* @param string $plugin full component name
/**
* Removes a key from global configuration.
*
+ * NOTE: this function is called from lib/db/upgrade.php
+ *
* @param string $name the key to set
* @param string $plugin (optional) the plugin scope
* @return boolean whether the operation succeeded.
return false;
}
- // Do not try to authenticate non-existent accounts when user creation is disabled.
- if (!empty($CFG->authpreventaccountcreation)) {
- $failurereason = AUTH_LOGIN_NOUSER;
-
- // Trigger login failed event.
- $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
- 'reason' => $failurereason)));
- $event->trigger();
-
- error_log('[client '.getremoteaddr()."] $CFG->wwwroot Unknown user, can not create new accounts: $username ".
- $_SERVER['HTTP_USER_AGENT']);
- return false;
- }
-
// User does not exist.
$auths = $authsenabled;
$user = new stdClass();
$user = update_user_record_by_id($user->id);
}
} else {
- // Create account, we verified above that user creation is allowed.
- $user = create_user_record($username, $password, $auth);
+ // The user is authenticated but user creation may be disabled.
+ if (!empty($CFG->authpreventaccountcreation)) {
+ $failurereason = AUTH_LOGIN_UNAUTHORISED;
+
+ // Trigger login failed event.
+ $event = \core\event\user_login_failed::create(array('other' => array('username' => $username,
+ 'reason' => $failurereason)));
+ $event->trigger();
+
+ error_log('[client '.getremoteaddr()."] $CFG->wwwroot Unknown user, can not create new accounts: $username ".
+ $_SERVER['HTTP_USER_AGENT']);
+ return false;
+ } else {
+ $user = create_user_record($username, $password, $auth);
+ }
}
$authplugin->sync_roles($user);
// A quick query to check whether the user has new messages.
$messagecount = $DB->count_records('message', array('useridto' => $USER->id));
- if ($messagecount<1) {
+ if ($messagecount < 1) {
return;
}
- // Got unread messages so now do another query that joins with the user table.
+ // There are unread messages so now do a more complex but slower query.
$namefields = get_all_user_name_fields(true, 'u');
- $messagesql = "SELECT m.id, m.smallmessage, m.fullmessageformat, m.notification, $namefields
+ $messagesql = "SELECT m.id, m.smallmessage, m.fullmessageformat, m.notification, m.useridto, m.useridfrom, $namefields, c.blocked
FROM {message} m
JOIN {message_working} mw ON m.id=mw.unreadmessageid
JOIN {message_processors} p ON mw.processorid=p.id
JOIN {user} u ON m.useridfrom=u.id
+ LEFT JOIN {message_contacts} c ON c.contactid = m.useridfrom
+ AND c.userid = m.useridto
WHERE m.useridto = :userid
AND p.name='popup'";
$messageusers = $DB->get_records_sql($messagesql, array('userid' => $USER->id, 'lastpopuptime' => $USER->message_lastpopup));
- // If we have new messages to notify the user about.
- if (!empty($messageusers)) {
+ $validmessages = 0;
+ foreach($messageusers as $message) {
+ if ($message->blocked) {
+ // Message is from a user who has since been blocked so just mark it read.
+ message_mark_message_read($message, time());
+ } else {
+ $validmessages++;
+ }
+ }
- $strmessages = get_string('unreadnewmessages', 'message', count($messageusers));
+ if ($validmessages > 0) {
+ $strmessages = get_string('unreadnewmessages', 'message', $validmessages);
$strgomessage = get_string('gotomessages', 'message');
$strstaymessage = get_string('ignore', 'admin');
*/
public $class = 'userpicture';
+ /**
+ * @var bool Whether to be visible to screen readers.
+ */
+ public $visibletoscreenreaders = true;
+
/**
* User picture constructor.
*
* - popup=false (open in popup)
* - alttext=true (add image alt attribute)
* - class = image class attribute (default 'userpicture')
+ * - visibletoscreenreaders=true (whether to be visible to screen readers)
* @return string HTML fragment
*/
public function user_picture(stdClass $user, array $options = null) {
$src = $userpicture->get_url($this->page, $this);
$attributes = array('src'=>$src, 'alt'=>$alt, 'title'=>$alt, 'class'=>$class, 'width'=>$size, 'height'=>$size);
+ if (!$userpicture->visibletoscreenreaders) {
+ $attributes['role'] = 'presentation';
+ }
// get the image html output fisrt
$output = html_writer::empty_tag('img', $attributes);
}
$attributes = array('href'=>$url);
+ if (!$userpicture->visibletoscreenreaders) {
+ $attributes['role'] = 'presentation';
+ $attributes['tabindex'] = '-1';
+ $attributes['aria-hidden'] = 'true';
+ }
if ($userpicture->popup) {
$id = html_writer::random_id('userpicture');
}
if (!isset($record['maildisplay'])) {
- $record['maildisplay'] = 1;
+ $record['maildisplay'] = $CFG->defaultpreference_maildisplay;
+ }
+
+ if (!isset($record['mailformat'])) {
+ $record['mailformat'] = $CFG->defaultpreference_mailformat;
+ }
+
+ if (!isset($record['maildigest'])) {
+ $record['maildigest'] = $CFG->defaultpreference_maildigest;
+ }
+
+ if (!isset($record['autosubscribe'])) {
+ $record['autosubscribe'] = $CFG->defaultpreference_autosubscribe;
+ }
+
+ if (!isset($record['trackforums'])) {
+ $record['trackforums'] = $CFG->defaultpreference_trackforums;
}
if (!isset($record['deleted'])) {
$this->assertTrue($result);
}
+ /**
+ * Tests the sorting of an array of arrays by key.
+ */
+ public function test_asort_array_of_arrays_by_key() {
+ $array = array(
+ 'a' => array('name' => 'bravo'),
+ 'b' => array('name' => 'charlie'),
+ 'c' => array('name' => 'alpha')
+ );
+ $this->assertSame(array('a', 'b', 'c'), array_keys($array));
+ $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
+ $this->assertSame(array('c', 'a', 'b'), array_keys($array));
+
+ $array = array(
+ 'a' => array('name' => 'b'),
+ 'b' => array('name' => 1),
+ 'c' => array('name' => 0)
+ );
+ $this->assertSame(array('a', 'b', 'c'), array_keys($array));
+ $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
+ $this->assertSame(array('c', 'b', 'a'), array_keys($array));
+
+ $array = array(
+ 'a' => array('name' => 'áb'),
+ 'b' => array('name' => 'ab'),
+ 1 => array('name' => 'aa'),
+ 'd' => array('name' => 'cc'),
+ 0 => array('name' => 'Áb')
+ );
+ $this->assertSame(array('a', 'b', 1, 'd', 0), array_keys($array));
+ $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
+ $this->assertSame(array(1, 'b', 'a', 0, 'd'), array_keys($array));
+ $this->assertSame(array(
+ 1 => array('name' => 'aa'),
+ 'b' => array('name' => 'ab'),
+ 'a' => array('name' => 'áb'),
+ 0 => array('name' => 'Áb'),
+ 'd' => array('name' => 'cc')
+ ), $array);
+
+ }
+
/**
* Returns an array of sorted names.
* @param array $objects
'category' => $category->id,
'idnumber' => '006-01',
'shortname' => 'Biome Study',
- 'fullname' => '<span lang="ar" class="multilang">'.'دراسة منطقة إحيائية'.'</span><span lang="en" class="multilang">Biome Study</span>'
+ 'fullname' => '<span lang="ar" class="multilang">'.'دراسة منطقة إحيائية'.'</span><span lang="en" class="multilang">Biome Study</span>',
+ 'timecreated' => '10000000001'
));
$course2 = $generator->create_course(array(
'category' => $category->id,
'idnumber' => '007-02',
'shortname' => 'Chemistry Revision',
- 'fullname' => 'Chemistry Revision'
+ 'fullname' => 'Chemistry Revision',
+ 'timecreated' => '10000000002'
));
$course3 = $generator->create_course(array(
'category' => $category->id,
'idnumber' => '007-03',
'shortname' => 'Swiss Rolls and Sunflowers',
- 'fullname' => 'Aarkvarks guide to Swiss Rolls and Sunflowers'
+ 'fullname' => 'Aarkvarks guide to Swiss Rolls and Sunflowers',
+ 'timecreated' => '10000000003'
));
$course4 = $generator->create_course(array(
'category' => $category->id,
'idnumber' => '006-04',
'shortname' => 'Scratch',
- 'fullname' => '<a href="test.php">Basic Scratch</a>'
+ 'fullname' => '<a href="test.php">Basic Scratch</a>',
+ 'timecreated' => '10000000004'
));
$c1 = (int)$course1->id;
$c2 = (int)$course2->id;
$this->assertTrue($coursecat->resort_courses('shortname'));
$this->assertSame(array($c1, $c2, $c4, $c3), array_keys($coursecat->get_courses()));
+ $this->assertTrue($coursecat->resort_courses('timecreated'));
+ $this->assertSame(array($c1, $c2, $c3, $c4), array_keys($coursecat->get_courses()));
try {
// Enable the multilang filter and set it to apply to headings and content.
$text = '<a href="rtsp://www.example.com/movie.mov">link</a>';
$this->assertSame($text, purify_html($text));
+ $text = '<a href="rtmp://www.example.com/video.f4v">link</a>';
+ $this->assertSame($text, purify_html($text));
+
$text = '<a href="teamspeak://speak.example.com/?par=val?par2=val2">link</a>';
$this->assertSame($text, purify_html($text));
If you have a renderable class named like "blah_renderable" and have a method on a renderer named "render_blah_renderable"
you will need to change the name of your render method to "render_blah" instead, as renderable at the end is no longer accepted.
+DEPRECATIONS:
+* completion_info->get_incomplete_criteria() is deprecated and will be removed in Moodle 3.0.
+
=== 2.6.4 / 2.7.1 ===
+
* setnew_password_and_mail() and update_internal_user_password() will trigger
\core\event\user_password_updated. Previously they used to generate
\core\event\user_updated event.
'nntp' => true,
'news' => true,
'rtsp' => true,
+ 'rtmp' => true,
'teamspeak' => true,
'gopher' => true,
'mms' => true,
}
if (this.get('position') === 'right') {
- panel.get('node').setStyle('left', -panel.get('offsetWidth')+'px');
+ panel.get('node').setStyle('left', '-' + panel.get('node').get('offsetWidth') + 'px');
} else if (this.get('position') === 'top') {
dockx = this.get('dockNode').getX();
$frm = false;
} else {
if (empty($errormsg)) {
- $user = authenticate_user_login($frm->username, $frm->password);
+ $user = authenticate_user_login($frm->username, $frm->password, false, $errorcode);
}
}
} else {
if (empty($errormsg)) {
- $errormsg = get_string("invalidlogin");
- $errorcode = 3;
+ if ($errorcode == AUTH_LOGIN_UNAUTHORISED) {
+ $errormsg = get_string("unauthorisedlogin", "", $frm->username);
+ } else {
+ $errormsg = get_string("invalidlogin");
+ $errorcode = 3;
+ }
}
}
}
<div class="form-label"><label for="password"><?php print_string("password") ?></label></div>
<div class="form-input">
<input type="password" name="password" id="password" size="15" value="" <?php echo $autocomplete; ?> />
- <input type="submit" id="loginbtn" value="<?php print_string("login") ?>" />
</div>
</div>
<div class="clearer"><!-- --></div>
</div>
<?php } ?>
<div class="clearer"><!-- --></div>
+ <input type="submit" id="loginbtn" value="<?php print_string("login") ?>" />
<div class="forgetpass"><a href="forgot_password.php"><?php print_string("forgotten") ?></a></div>
</form>
<div class="desc">
function message_get_recent_conversations($user, $limitfrom=0, $limitto=100) {
global $DB;
- $userfields = user_picture::fields('u', array('lastaccess'));
- //This query retrieves the last message received from and sent to each user
- //It unions that data then, within that set, it finds the most recent message you've exchanged with each user over all
- //It then joins with some other tables to get some additional data we need
-
- //message ID is used instead of timecreated as it should sort the same and will be much faster
-
- //There is a separate query for read and unread queries 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
- $sql = "SELECT $userfields, mr.id as mid, mr.notification, mr.smallmessage, mr.fullmessage, mr.fullmessagehtml, mr.fullmessageformat, mr.timecreated, mc.id as contactlistid, mc.blocked
- FROM {message_read} mr
- JOIN (
- SELECT messages.userid AS userid, MAX(messages.mid) AS mid
- FROM (
- SELECT mr1.useridto AS userid, MAX(mr1.id) AS mid
- FROM {message_read} mr1
- WHERE mr1.useridfrom = :userid1
- AND mr1.notification = 0
- GROUP BY mr1.useridto
- UNION
- SELECT mr2.useridfrom AS userid, MAX(mr2.id) AS mid
- FROM {message_read} mr2
- WHERE mr2.useridto = :userid2
- AND mr2.notification = 0
- GROUP BY mr2.useridfrom
- ) messages
- GROUP BY messages.userid
- ) messages2 ON mr.id = messages2.mid AND (mr.useridto = messages2.userid OR mr.useridfrom = messages2.userid)
- JOIN {user} u ON u.id = messages2.userid
- LEFT JOIN {message_contacts} mc ON mc.userid = :userid3 AND mc.contactid = u.id
- WHERE u.deleted = '0'
- ORDER BY mr.id DESC";
- $params = array('userid1' => $user->id, 'userid2' => $user->id, 'userid3' => $user->id);
- $read = $DB->get_records_sql($sql, $params, $limitfrom, $limitto);
-
- $sql = "SELECT $userfields, m.id as mid, m.notification, m.smallmessage, m.fullmessage, m.fullmessagehtml, m.fullmessageformat, m.timecreated, mc.id as contactlistid, mc.blocked
- FROM {message} m
- JOIN (
- SELECT messages.userid AS userid, MAX(messages.mid) AS mid
- FROM (
- SELECT m1.useridto AS userid, MAX(m1.id) AS mid
- FROM {message} m1
- WHERE m1.useridfrom = :userid1
- AND m1.notification = 0
- GROUP BY m1.useridto
- UNION
- SELECT m2.useridfrom AS userid, MAX(m2.id) AS mid
- FROM {message} m2
- WHERE m2.useridto = :userid2
- AND m2.notification = 0
- GROUP BY m2.useridfrom
- ) messages
- GROUP BY messages.userid
- ) messages2 ON m.id = messages2.mid AND (m.useridto = messages2.userid OR m.useridfrom = messages2.userid)
- JOIN {user} u ON u.id = messages2.userid
- LEFT JOIN {message_contacts} mc ON mc.userid = :userid3 AND mc.contactid = u.id
- WHERE u.deleted = '0'
- ORDER BY m.id DESC";
- $unread = $DB->get_records_sql($sql, $params, $limitfrom, $limitto);
+ $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.
+ $sql = "SELECT $userfields,
+ message.id as mid, message.notification, message.smallmessage, message.fullmessage,
+ message.fullmessagehtml, message.fullmessageformat, message.timecreated,
+ contact.id as contactlistid, contact.blocked
+
+ FROM {message_read} message
+ JOIN {user} otheruser ON otheruser.id = CASE
+ WHEN message.useridto = :userid1 THEN message.useridfrom
+ ELSE message.useridto END
+ LEFT JOIN {message_contacts} contact ON contact.userid = :userid2 AND contact.contactid = otheruser.id
+
+ WHERE otheruser.deleted = 0
+ AND (message.useridto = :userid3 OR message.useridfrom = :userid4)
+ AND message.notification = 0
+ AND NOT EXISTS (
+ SELECT 1
+ FROM {message_read} othermessage
+ WHERE ((othermessage.useridto = :userid5 AND othermessage.useridfrom = otheruser.id) OR
+ (othermessage.useridfrom = :userid6 AND othermessage.useridto = otheruser.id))
+ AND (othermessage.timecreated > message.timecreated OR (
+ othermessage.timecreated = message.timecreated AND othermessage.id > message.id))
+ )
+
+ 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);
+ $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);
$conversations = array();
- //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
+ // 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.
$conversation_arrays = array($unread, $read);
foreach ($conversation_arrays as $conversation_array) {
foreach ($conversation_array as $conversation) {
FROM {message_read} mr
JOIN {user} u ON u.id=mr.useridfrom
WHERE mr.useridto = :userid1 AND u.deleted = '0' AND mr.notification = :notification
- ORDER BY mr.id DESC";//ordering by id should give the same result as ordering by timecreated but will be faster
+ ORDER BY mr.timecreated DESC";
$params = array('userid1' => $user->id, 'notification' => 1);
$notifications = $DB->get_records_sql($sql, $params, $limitfrom, $limitto);
* @param int $fromuserid the id of the message sender
* @return void
*/
-function message_mark_messages_read($touserid, $fromuserid){
+function message_mark_messages_read($touserid, $fromuserid) {
global $DB;
$sql = 'SELECT m.* FROM {message} m WHERE m.useridto=:useridto AND m.useridfrom=:useridfrom';
* @param stdClass $userfrom user object of the one sending the message.
* @param stdClass $userto user object of the one receiving the message.
* @param string $message message to send.
+ * @return int the id of the message
*/
protected function send_fake_message($userfrom, $userto, $message = 'Hello world!') {
global $DB;
$record->subject = 'No subject';
$record->fullmessage = $message;
$record->timecreated = time();
- $insert = $DB->insert_record('message', $record);
+
+ return $DB->insert_record('message', $record);
}
/**
$this->assertEquals(false, message_search(array('Message'), true, true, 2));
$this->assertCount(5, message_search(array('Message'), true, true, SITEID));
}
+
+ /**
+ * Test message_get_recent_conversations.
+ */
+ public function test_message_get_recent_conversations() {
+ global $DB, $USER;
+
+ // Set this user as the admin.
+ $this->setAdminUser();
+
+ // Create user's to send messages to/from.
+ $user1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'user1'));
+ $user2 = $this->getDataGenerator()->create_user(array('firstname' => 'Test2', 'lastname' => 'user2'));
+
+ // Add a few messages that have been read and some that are unread.
+ $m1 = $this->send_fake_message($USER, $user1, 'Message 1'); // An unread message.
+ $m2 = $this->send_fake_message($user1, $USER, 'Message 2'); // An unread message.
+ $m3 = $this->send_fake_message($USER, $user1, 'Message 3'); // An unread message.
+ $m4 = message_post_message($USER, $user2, 'Message 4', FORMAT_PLAIN);
+ $m5 = message_post_message($user2, $USER, 'Message 5', FORMAT_PLAIN);
+ $m6 = message_post_message($USER, $user2, 'Message 6', FORMAT_PLAIN);
+
+ // We want to alter the timecreated values so we can ensure message_get_recent_conversations orders by timecreated.
+ $updatemessage = new stdClass();
+ $updatemessage->id = $m3;
+ $updatemessage->timecreated = 0;
+ $DB->update_record('message', $updatemessage);
+
+ $updatemessage->id = $m6;
+ $DB->update_record('message_read', $updatemessage);
+
+ // Get the recent conversations for the current user.
+ $conversations = message_get_recent_conversations($USER);
+
+ // Confirm that we have received the messages with the maximum timecreated, rather than the max id.
+ $this->assertEquals('Message 2', $conversations[0]->fullmessage);
+ $this->assertEquals('Message 5', $conversations[1]->smallmessage);
+ }
+
+ /**
+ * Test message_get_recent_notifications.
+ */
+ public function test_message_get_recent_notifications() {
+ global $DB, $USER;
+
+ // Set this user as the admin.
+ $this->setAdminUser();
+
+ // Create a user to send messages from.
+ $user1 = $this->getDataGenerator()->create_user(array('firstname' => 'Test1', 'lastname' => 'user1'));
+
+ // Add two messages - will mark them as notifications later.
+ $m1 = message_post_message($user1, $USER, 'Message 1', FORMAT_PLAIN);
+ $m2 = message_post_message($user1, $USER, 'Message 2', FORMAT_PLAIN);
+
+ // Mark the second message as a notification.
+ $updatemessage = new stdClass();
+ $updatemessage->id = $m2;
+ $updatemessage->notification = 1;
+ $DB->update_record('message_read', $updatemessage);
+
+ // Mark the first message as a notification and change the timecreated to 0.
+ $updatemessage->id = $m1;
+ $updatemessage->notification = 1;
+ $updatemessage->timecreated = 0;
+ $DB->update_record('message_read', $updatemessage);
+
+ $notifications = message_get_recent_notifications($USER);
+
+ // Get the messages.
+ $firstmessage = array_shift($notifications);
+ $secondmessage = array_shift($notifications);
+
+ // Confirm that we have received the notifications with the maximum timecreated, rather than the max id.
+ $this->assertEquals('Message 2', $firstmessage->smallmessage);
+ $this->assertEquals('Message 1', $secondmessage->smallmessage);
+ }
}
if ($assignment->get_instance()->teamsubmission) {
$columns[] = 'team';
$headers[] = get_string('submissionteam', 'assign');
-
- $columns[] = 'teamstatus';
- $headers[] = get_string('teamsubmissionstatus', 'assign');
}
// Allocated marker.
if ($this->assignment->get_instance()->markingallocation &&
if ($assignment->get_instance()->teamsubmission) {
$this->no_sorting('team');
- $this->no_sorting('teamstatus');
}
$plugincolumnindex = 0;
return '';
}
if ($this->is_downloading()) {
- return $markers[$row->allocatedmarker];
+ if (isset($markers[$row->allocatedmarker])) {
+ return fullname($markers[$row->allocatedmarker]);
+ } else {
+ return '';
+ }
}
if ($this->quickgrading && has_capability('mod/assign:manageallocations', $this->assignment->get_context()) &&
}
}
-
- /**
- * Get the team status for this user.
- *
- * @param stdClass $row
- * @return string The team name
- */
- public function col_teamstatus(stdClass $row) {
- $submission = false;
- $group = false;
- $this->get_group_and_submission($row->id, $group, $submission, -1);
-
- $status = '';
- if ($submission) {
- $status = $submission->status;
- }
- return get_string('submissionstatus_' . $status, 'assign');
- }
-
-
/**
* Format a list of outcomes.
*
public function col_timesubmitted(stdClass $row) {
$o = '-';
- if ($row->timesubmitted) {
+ $group = false;
+ $submission = false;
+ $this->get_group_and_submission($row->id, $group, $submission, -1);
+ if ($group && $submission && $submission->timemodified) {
+ $o = userdate($submission->timemodified);
+ } else if ($row->timesubmitted) {
$o = userdate($row->timesubmitted);
}
$due = $row->extensionduedate;
}
+ $group = false;
+ $submission = false;
+ $this->get_group_and_submission($row->id, $group, $submission, -1);
+ if ($group && $submission) {
+ $timesubmitted = $submission->timemodified;
+ $status = $submission->status;
+ } else {
+ $timesubmitted = $row->timesubmitted;
+ $status = $row->status;
+ }
+
if ($this->assignment->is_any_submission_plugin_enabled()) {
- $o .= $this->output->container(get_string('submissionstatus_' . $row->status, 'assign'),
- array('class'=>'submissionstatus' .$row->status));
- if ($due && $row->timesubmitted > $due) {
- $usertime = format_time($row->timesubmitted - $due);
+ $o .= $this->output->container(get_string('submissionstatus_' . $status, 'assign'),
+ array('class'=>'submissionstatus' .$status));
+ if ($due && $timesubmitted > $due) {
+ $usertime = format_time($timesubmitted - $due);
$latemessage = get_string('submittedlateshort',
'assign',
$usertime);
$o .= $this->col_workflowstatus($row);
} else if ($row->grade !== null && $row->grade >= 0) {
$o .= $this->output->container(get_string('graded', 'assign'), 'submissiongraded');
- }
-
- if (!$row->timesubmitted) {
+ } else if (!$timesubmitted) {
$now = time();
if ($due && ($now > $due)) {
$overduestr = get_string('overdue', 'assign', format_time($now - $due));
$o .= $this->output->container($overduestr, 'overduesubmission');
}
}
+
if ($row->extensionduedate) {
$userdate = userdate($row->extensionduedate);
$extensionstr = get_string('userextensiondate', 'assign', $userdate);
$string['quickgradingresult'] = 'Quick grading';
$string['quickgradingchangessaved'] = 'The grade changes were saved';
$string['quickgrading_help'] = 'Quick grading allows you to assign grades (and outcomes) directly in the submissions table. Quick grading is not compatible with advanced grading and is not recommended when there are multiple markers.';
+$string['reopenuntilpassincompatiblewithblindmarking'] = 'Reopen until pass option is incompatible with blind marking, because the grades are not released to the gradebook until the student identities are revealed.';
$string['requiresubmissionstatement'] = 'Require that students accept the submission statement';
$string['requiresubmissionstatement_help'] = 'Require that students accept the submission statement for all submissions to this assignment.';
$string['requireallteammemberssubmit'] = 'Require all group members submit';
$string['teamsubmission_help'] = 'If enabled students will be divided into groups based on the default set of groups or a custom grouping. A group submission will be shared among group members and all members of the group will see each others changes to the submission.';
$string['teamsubmissiongroupingid'] = 'Grouping for student groups';
$string['teamsubmissiongroupingid_help'] = 'This is the grouping that the assignment will use to find groups for student groups. If not set - the default set of groups will be used.';
-$string['teamsubmissionstatus'] = 'Group submission status';
$string['textinstructions'] = 'Assignment instructions';
$string['timemodified'] = 'Last modified';
$string['timeremaining'] = 'Time remaining';
}
/**
- * Display a continue page.
+ * Display a continue page after grading.
*
- * @param string $message - The message to display
+ * @param string $message - The message to display.
* @return string
*/
protected function view_savegrading_result($message) {
return $o;
}
/**
- * Display a grading error.
+ * Display a continue page after quickgrading.
*
- * @param string $message - The description of the result
+ * @param string $message - The message to display.
* @return string
*/
protected function view_quickgrading_result($message) {
$shouldreopen = false;
if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
// Check the gradetopass from the gradebook.
- $gradinginfo = grade_get_grades($this->get_course()->id,
- 'mod',
- 'assign',
- $instance->id,
- $userid);
+ $gradeitem = $this->get_grade_item();
+ if ($gradeitem) {
+ $gradegrade = grade_grade::fetch(array('userid' => $userid, 'itemid' => $gradeitem->id));
- // What do we do if the grade has not been added to the gradebook (e.g. blind marking)?
- $gradingitem = null;
- $gradebookgrade = null;
- if (isset($gradinginfo->items[0])) {
- $gradingitem = $gradinginfo->items[0];
- $gradebookgrade = $gradingitem->grades[$userid];
- }
-
- if ($gradebookgrade) {
- // TODO: This code should call grade_grade->is_passed().
- $shouldreopen = true;
- if (is_null($gradebookgrade->grade)) {
- $shouldreopen = false;
- }
- if (empty($gradingitem->gradepass) || $gradingitem->gradepass == $gradingitem->grademin) {
- $shouldreopen = false;
- }
- if ($gradebookgrade->grade >= $gradingitem->gradepass) {
- $shouldreopen = false;
+ if ($gradegrade && !$gradegrade->is_passed()) {
+ $shouldreopen = true;
}
}
}
$errors['cutoffdate'] = get_string('cutoffdatefromdatevalidation', 'assign');
}
}
+ if ($data['blindmarking'] && $data['attemptreopenmethod'] == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
+ $errors['attemptreopenmethod'] = get_string('reopenuntilpassincompatiblewithblindmarking', 'assign');
+ }
return $errors;
}
public $message = '';
/** @var int $coursemoduleid */
public $coursemoduleid = 0;
+ /** @var int $gradingerror should be set true if there was a problem grading */
+ public $gradingerror = null;
/**
* Constructor
* @param string $heading This is the heading to display
* @param string $message This is the message to display
+ * @param bool $gradingerror Set to true to display the message as an error.
* @param int $coursemoduleid
*/
- public function __construct($heading, $message, $coursemoduleid) {
+ public function __construct($heading, $message, $coursemoduleid, $gradingerror = false) {
$this->heading = $heading;
$this->message = $message;
$this->coursemoduleid = $coursemoduleid;
+ $this->gradingerror = $gradingerror;
}
}
public function render_assign_gradingmessage(assign_gradingmessage $result) {
$urlparams = array('id' => $result->coursemoduleid, 'action'=>'grading');
$url = new moodle_url('/mod/assign/view.php', $urlparams);
+ $classes = $result->gradingerror ? 'notifyproblem' : 'notifysuccess';
$o = '';
$o .= $this->output->heading($result->heading, 4);
- $o .= $this->output->notification($result->message);
+ $o .= $this->output->notification($result->message, $classes);
$o .= $this->output->continue_button($url);
return $o;
}
$row->cells = array($cell1, $cell2);
$t->data[] = $row;
+ $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
$duedate = $status->duedate;
if ($duedate > 0) {
// Due date.
$row = new html_table_row();
$cell1 = new html_table_cell(get_string('timeremaining', 'assign'));
if ($duedate - $time <= 0) {
- if (!$status->submission ||
- $status->submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
+ if (!$submission ||
+ $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
if ($status->submissionsenabled) {
$overduestr = get_string('overdue', 'assign', format_time($time - $duedate));
$cell2 = new html_table_cell($overduestr);
$cell2 = new html_table_cell(get_string('duedatereached', 'assign'));
}
} else {
- if ($status->submission->timemodified > $duedate) {
+ if ($submission->timemodified > $duedate) {
$latestr = get_string('submittedlate',
'assign',
- format_time($status->submission->timemodified - $duedate));
+ format_time($submission->timemodified - $duedate));
$cell2 = new html_table_cell($latestr);
$cell2->attributes = array('class'=>'latesubmission');
} else {
$earlystr = get_string('submittedearly',
'assign',
- format_time($status->submission->timemodified - $duedate));
+ format_time($submission->timemodified - $duedate));
$cell2 = new html_table_cell($earlystr);
$cell2->attributes = array('class'=>'earlysubmission');
}
}
// Last modified.
- $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
if ($submission) {
$row = new html_table_row();
$cell1 = new html_table_cell(get_string('timemodified', 'assign'));
$this->editingteachers[0]->ignoresesskey = false;
}
+ /**
+ * Test submissions with extension date.
+ */
+ public function test_gradingtable_extension_due_date() {
+ global $PAGE;
+
+ // Setup the assignment.
+ $this->create_extra_users();
+ $this->setUser($this->editingteachers[0]);
+ $assign = $this->create_instance(array(
+ 'assignsubmission_onlinetext_enabled'=>1,
+ 'duedate' => time() - 4 * 24 * 60 * 60,
+ ));
+ $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
+ 'id' => $assign->get_course_module()->id,
+ 'action' => 'grading',
+ )));
+
+ // Check that the assignment is late.
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
+ $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output);
+
+ // Grant an extension.
+ $assign->testable_save_user_extension($this->students[0]->id, time() + 2 * 24 * 60 * 60);
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
+ $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() + 2*24*60*60)), $output);
+
+ // Simulate a submission.
+ $this->setUser($this->students[0]);
+ $submission = $assign->get_user_submission($this->students[0]->id, true);
+ $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+ $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
+ $data = new stdClass();
+ $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+ 'text'=>'Submission text',
+ 'format'=>FORMAT_MOODLE);
+ $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+ $plugin->save($submission, $data);
+
+ // Verify output.
+ $this->setUser($this->editingteachers[0]);
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
+ $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() + 2*24*60*60)), $output);
+ }
+
+ /**
+ * Test that late submissions with extension date calculate correctly.
+ */
+ public function test_gradingtable_extension_date_calculation_for_lateness() {
+ global $PAGE;
+
+ // Setup the assignment.
+ $this->create_extra_users();
+ $this->setUser($this->editingteachers[0]);
+ $assign = $this->create_instance(array(
+ 'assignsubmission_onlinetext_enabled'=>1,
+ 'duedate' => time() - 4 * 24 * 60 * 60,
+ ));
+ $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
+ 'id' => $assign->get_course_module()->id,
+ 'action' => 'grading',
+ )));
+
+ // Check that the assignment is late.
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
+ $this->assertContains(get_string('overdue', 'assign', format_time(4*24*60*60)), $output);
+
+ // Grant an extension that is in the past.
+ $assign->testable_save_user_extension($this->students[0]->id, time() - 2 * 24 * 60 * 60);
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_', 'assign'), $output);
+ $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() - 2*24*60*60)), $output);
+ $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60)), $output);
+
+ // Simulate a submission.
+ $this->setUser($this->students[0]);
+ $submission = $assign->get_user_submission($this->students[0]->id, true);
+ $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+ $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
+ $data = new stdClass();
+ $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+ 'text'=>'Submission text',
+ 'format'=>FORMAT_MOODLE);
+ $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+ $plugin->save($submission, $data);
+
+ // Verify output.
+ $this->setUser($this->editingteachers[0]);
+ $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $this->assertContains(get_string('submissionstatus_submitted', 'assign'), $output);
+ $this->assertContains(get_string('userextensiondate', 'assign', userdate(time() - 2*24*60*60)), $output);
+ $this->assertContains(get_string('submittedlateshort', 'assign', format_time(2*24*60*60)), $output);
+ }
+
+ /**
+ * Check that group submission information is rendered correctly in the
+ * grading table.
+ */
+ public function test_gradingtable_group_submissions_rendering() {
+ global $PAGE;
+
+ $this->create_extra_users();
+ // Now verify group assignments.
+ $this->setUser($this->teachers[0]);
+ $assign = $this->create_instance(array(
+ 'teamsubmission' => 1,
+ 'assignsubmission_onlinetext_enabled' => 1,
+ 'submissiondrafts' => 1,
+ 'requireallteammemberssubmit' => 0,
+ ));
+ $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
+ 'id' => $assign->get_course_module()->id,
+ 'action' => 'grading',
+ )));
+
+ // Add a submission.
+ $this->setUser($this->extrastudents[0]);
+ $data = new stdClass();
+ $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+ 'text'=>'Submission text',
+ 'format'=>FORMAT_MOODLE);
+ $notices = array();
+ $assign->save_submission($data, $notices);
+
+ $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
+ $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+ $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
+
+ // Check output.
+ $this->setUser($this->teachers[0]);
+ $gradingtable = new assign_grading_table($assign, 4, '', 0, true);
+ $output = $assign->get_renderer()->render($gradingtable);
+ $document = new DOMDocument();
+ $document->loadHTML($output);
+ $xpath = new DOMXPath($document);
+
+ // Check status.
+ $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c4"]/div[@class="submissionstatussubmitted"])'));
+ $this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])'));
+
+ // Check submission last modified date
+ $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')));
+ $this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])')));
+
+ // Check group.
+ $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])'));
+ $this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])'));
+
+ // Check submission text.
+ $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)'));
+ $this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)'));
+
+ // Check comments can be made.
+ $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)'));
+ $this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)'));
+ }
+
public function test_show_intro() {
// Test whether we are showing the intro at the correct times.
$this->setUser($this->editingteachers[0]);
$this->assertEquals(null, $gradinginfo->items[0]->grades[$this->extrastudents[0]->id]->datesubmitted);
}
- public function test_group_submissions_submit_for_marking() {
+ public function test_group_submissions_submit_for_marking_requireallteammemberssubmit() {
global $PAGE;
$this->create_extra_users();
'requireallteammemberssubmit'=>1));
$PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
- $this->setUser($this->extrastudents[0]);
// Add a submission.
+ $this->setUser($this->extrastudents[0]);
$data = new stdClass();
$data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
'text'=>'Submission text',
$this->assertNotContains(get_string('submitassignment', 'assign'), $output);
}
+ public function test_group_submissions_submit_for_marking() {
+ global $PAGE;
+
+ $this->create_extra_users();
+ // Now verify group assignments.
+ $this->setUser($this->editingteachers[0]);
+ $assign = $this->create_instance(array('teamsubmission'=>1,
+ 'assignsubmission_onlinetext_enabled'=>1,
+ 'submissiondrafts'=>1,
+ 'requireallteammemberssubmit'=>0,
+ 'duedate' => time() - 2*24*60*60));
+ $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id)));
+
+ $this->setUser($this->extrastudents[0]);
+ // Add a submission.
+ $data = new stdClass();
+ $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+ 'text'=>'Submission text',
+ 'format'=>FORMAT_MOODLE);
+
+ $notices = array();
+ $assign->save_submission($data, $notices);
+
+ // Check we can see the submit button.
+ $output = $assign->view_student_summary($this->extrastudents[0], true);
+ $this->assertContains(get_string('submitassignment', 'assign'), $output);
+ $this->assertContains(get_string('timeremaining', 'assign'), $output);
+ $this->assertContains(get_string('overdue', 'assign', format_time(2*24*60*60)), $output);
+
+ $submission = $assign->get_group_submission($this->extrastudents[0]->id, 0, true);
+ $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+ $assign->testable_update_submission($submission, $this->extrastudents[0]->id, true, true);
+
+ // Check that the student does not see "Submit" button.
+ $output = $assign->view_student_summary($this->extrastudents[0], true);
+ $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
+
+ // Change to another user in the same group.
+ $this->setUser($this->extrastudents[self::GROUP_COUNT]);
+ $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
+ $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
+
+ // Check that time remaining is not overdue.
+ $this->assertContains(get_string('timeremaining', 'assign'), $output);
+ $this->assertContains(get_string('submittedlate', 'assign', format_time(2*24*60*60)), $output);
+
+ $submission = $assign->get_group_submission($this->extrastudents[self::GROUP_COUNT]->id, 0, true);
+ $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+ $assign->testable_update_submission($submission, $this->extrastudents[self::GROUP_COUNT]->id, true, true);
+ $output = $assign->view_student_summary($this->extrastudents[self::GROUP_COUNT], true);
+ $this->assertNotContains(get_string('submitassignment', 'assign'), $output);
+ }
+
public function test_submissions_open() {
$this->setUser($this->editingteachers[0]);
$data = $analysed_item->data;
if (is_array($data)) {
if (isset($data[0])) {
- $worksheet->write_string($row_offset, 2, $data[0], $xls_formats->value_bold);
+ $worksheet->write_string($row_offset, 2, htmlspecialchars_decode($data[0], ENT_QUOTES), $xls_formats->value_bold);
}
$row_offset++;
$sizeofdata = count($data);
for ($i = 1; $i < $sizeofdata; $i++) {
- $worksheet->write_string($row_offset, 2, $data[$i], $xls_formats->default);
+ $worksheet->write_string($row_offset, 2, htmlspecialchars_decode($data[$i], ENT_QUOTES), $xls_formats->default);
$row_offset++;
}
}
$worksheet->write_string($row_offset, 1, $item->name, $xls_formats->head2);
$data = $analysed_item->data;
if (is_array($data)) {
- $worksheet->write_string($row_offset, 2, $data[0], $xls_formats->value_bold);
+ $worksheet->write_string($row_offset, 2, htmlspecialchars_decode($data[0], ENT_QUOTES), $xls_formats->value_bold);
$row_offset++;
$sizeofdata = count($data);
for ($i = 1; $i < $sizeofdata; $i++) {
- $worksheet->write_string($row_offset, 2, $data[$i], $xls_formats->default);
+ $worksheet->write_string($row_offset, 2, htmlspecialchars_decode($data[$i], ENT_QUOTES), $xls_formats->default);
$row_offset++;
}
}
*/
protected function init() {
$this->data['crud'] = 'r';
- $this->data['edulevel'] = self::LEVEL_OTHER;
+ $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
/**
}
}
+/**
+ * Filters the forum discussions according to groups membership and config.
+ *
+ * @since Moodle 2.8, 2.7.1, 2.6.4
+ * @param array $discussions Discussions with new posts array
+ * @return array Forums with the number of new posts
+ */
+function forum_filter_user_groups_discussions($discussions) {
+
+ // Group the remaining discussions posts by their forumid.
+ $filteredforums = array();
+
+ // Discard not visible groups.
+ foreach ($discussions as $discussion) {
+
+ // Course data is already cached.
+ $instances = get_fast_modinfo($discussion->course)->get_instances();
+ $forum = $instances['forum'][$discussion->forum];
+
+ // Continue if the user should not see this discussion.
+ if (!forum_is_user_group_discussion($forum, $discussion->groupid)) {
+ continue;
+ }
+
+ // Grouping results by forum.
+ if (empty($filteredforums[$forum->instance])) {
+ $filteredforums[$forum->instance] = new stdClass();
+ $filteredforums[$forum->instance]->id = $forum->id;
+ $filteredforums[$forum->instance]->count = 0;
+ }
+ $filteredforums[$forum->instance]->count += $discussion->count;
+ }
+
+ return $filteredforums;
+}
+
+/**
+ * Returns whether the discussion group is visible by the current user or not.
+ *
+ * @since Moodle 2.8, 2.7.1, 2.6.4
+ * @param cm_info $cm The discussion course module
+ * @param int $discussiongroupid The discussion groupid
+ * @return bool
+ */
+function forum_is_user_group_discussion(cm_info $cm, $discussiongroupid) {
+
+ if ($discussiongroupid == -1 || $cm->effectivegroupmode != SEPARATEGROUPS) {
+ return true;
+ }
+ if (isguestuser()) {
+ return false;
+ }
+ if (has_capability('moodle/site:accessallgroups', context_module::instance($cm->id)) ||
+ in_array($discussiongroupid, $cm->get_modinfo()->get_groups($cm->groupingid))) {
+ return true;
+ }
+ return false;
+}
/**
* @global object