$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);
* @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'], '');
}
/**
$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.
*/
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));
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');
}
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'])) {
'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">
* @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';
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
// If the user has never entered into the course all posts are pending
if ($course->lastaccess == 0) {
- $coursessqls[] = '(f.course = ?)';
+ $coursessqls[] = '(d.course = ?)';
$params[] = $course->id;
// Only posts created after the course last access
} else {
- $coursessqls[] = '(f.course = ? AND p.created > ?)';
+ $coursessqls[] = '(d.course = ? AND p.created > ?)';
$params[] = $course->id;
$params[] = $course->lastaccess;
}
$params[] = $USER->id;
$coursessql = implode(' OR ', $coursessqls);
- $sql = "SELECT f.id, COUNT(*) as count "
- .'FROM {forum} f '
- .'JOIN {forum_discussions} d ON d.forum = f.id '
+ $sql = "SELECT d.id, d.forum, d.course, d.groupid, COUNT(*) as count "
+ .'FROM {forum_discussions} d '
.'JOIN {forum_posts} p ON p.discussion = d.id '
."WHERE ($coursessql) "
.'AND p.userid != ? '
- .'GROUP BY f.id';
+ .'GROUP BY d.id, d.forum, d.course, d.groupid';
- if (!$new = $DB->get_records_sql($sql, $params)) {
- $new = array(); // avoid warnings
+ // Avoid warnings.
+ if (!$discussions = $DB->get_records_sql($sql, $params)) {
+ $discussions = array();
}
+ $forumsnewposts = forum_filter_user_groups_discussions($discussions);
+
// also get all forum tracking stuff ONCE.
$trackingforums = array();
foreach ($forums as $forum) {
$unread = array();
}
- if (empty($unread) and empty($new)) {
+ if (empty($unread) and empty($forumsnewposts)) {
return;
}
$thisunread = 0;
$showunread = false;
// either we have something from logs, or trackposts, or nothing.
- if (array_key_exists($forum->id, $new) && !empty($new[$forum->id])) {
- $count = $new[$forum->id]->count;
+ if (array_key_exists($forum->id, $forumsnewposts) && !empty($forumsnewposts[$forum->id])) {
+ $count = $forumsnewposts[$forum->id]->count;
}
if (array_key_exists($forum->id,$unread)) {
$thisunread = $unread[$forum->id]->count;
}
}
- $groupmode = groups_get_activity_groupmode($cm, $course);
-
- if ($groupmode) {
- if ($post->groupid == -1 or $groupmode == VISIBLEGROUPS or has_capability('moodle/site:accessallgroups', $context)) {
- // oki (Open discussions have groupid -1)
- } else {
- // separate mode
- if (isguestuser()) {
- // shortcut
- continue;
- }
-
- if (!in_array($post->groupid, $modinfo->get_groups($cm->groupingid))) {
- continue;
- }
- }
+ // Check that the user can see the discussion.
+ if (forum_is_user_group_discussion($cm, $post->groupid)) {
+ $printposts[] = $post;
}
- $printposts[] = $post;
}
unset($posts);
'questionsperpage', 'navmethod', 'shufflequestions', 'shuffleanswers',
'sumgrades', 'grade', 'timecreated',
'timemodified', 'password', 'subnet', 'browsersecurity',
- 'delay1', 'delay2', 'showuserpicture', 'showblocks'));
+ 'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'completionpass'));
// Define elements for access rule subplugin settings.
$this->add_subplugin_structure('quizaccess', $quiz, true);
<FIELD NAME="delay2" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Delay that must be left between the second and subsequent attempt, in seconds."/>
<FIELD NAME="showuserpicture" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Option to show the user's picture during the attempt and on the review page."/>
<FIELD NAME="showblocks" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether blocks should be shown on the attempt.php and review.php pages."/>
+ <FIELD NAME="completionattemptsexhausted" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
+ <FIELD NAME="completionpass" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
// Moodle v2.7.0 release upgrade line.
// Put any upgrade step following this.
+ if ($oldversion < 2014052800) {
+
+ // Define field completionattemptsexhausted to be added to quiz.
+ $table = new xmldb_table('quiz');
+ $field = new xmldb_field('completionattemptsexhausted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'showblocks');
+
+ // Conditionally launch add field completionattemptsexhausted.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ // Quiz savepoint reached.
+ upgrade_mod_savepoint(true, 2014052800, 'quiz');
+ }
+
+ if ($oldversion < 2014052801) {
+ // Define field completionpass to be added to quiz.
+ $table = new xmldb_table('quiz');
+ $field = new xmldb_field('completionpass', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionattemptsexhausted');
+
+ // Conditionally launch add field completionpass.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Quiz savepoint reached.
+ upgrade_mod_savepoint(true, 2014052801, 'quiz');
+ }
return true;
}
$string['commentorgrade'] = 'Make comment or override grade';
$string['comments'] = 'Comments';
$string['completedon'] = 'Completed on';
+$string['completionpass'] = 'Require passing grade';
+$string['completionpass_help'] = 'If enabled, this activity is considered complete when the student receives a passing grade, with the pass grade set in the gradebook.';
+$string['completionattemptsexhausted'] = 'Or all available attempts completed';
+$string['completionattemptsexhausted_help'] = 'Mark quiz complete when the student has exhausted the maximum number of attempts.';
$string['configadaptive'] = 'If you choose Yes for this option then the student will be allowed multiple responses to a question even within the same attempt at the quiz.';
$string['configattemptsallowed'] = 'Restriction on the number of attempts students are allowed at the quiz.';
$string['configdecimaldigits'] = 'Number of digits that should be shown after the decimal point when displaying grades.';
case FEATURE_GROUPMEMBERSONLY: return true;
case FEATURE_MOD_INTRO: return true;
case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
+ case FEATURE_COMPLETION_HAS_RULES: return true;
case FEATURE_GRADE_HAS_GRADE: return true;
case FEATURE_GRADE_OUTCOMES: return true;
case FEATURE_BACKUP_MOODLE2: return true;
QUIZ_NAVMETHOD_SEQ => get_string('navmethod_seq', 'quiz')
);
}
+
+
+/**
+ * Obtains the automatic completion state for this quiz on any conditions
+ * in quiz settings, such as if all attempts are used or a certain grade is achieved.
+ *
+ * @param object $course Course
+ * @param object $cm Course-module
+ * @param int $userid User ID
+ * @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
+ * @return bool True if completed, false if not. (If no conditions, then return
+ * value depends on comparison type)
+ */
+function quiz_get_completion_state($course, $cm, $userid, $type) {
+ global $DB;
+ global $CFG;
+
+ $quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST);
+ if (!$quiz->completionattemptsexhausted && !$quiz->completionpass) {
+ return $type;
+ }
+
+ // Check if the user has used up all attempts.
+ if ($quiz->completionattemptsexhausted) {
+ $attempts = quiz_get_user_attempts($quiz->id, $userid, 'finished', true);
+ if ($attempts) {
+ $lastfinishedattempt = end($attempts);
+ $context = context_module::instance($cm->id);
+ $quizobj = quiz::create($quiz->id, $userid);
+ $accessmanager = new quiz_access_manager($quizobj, time(),
+ has_capability('mod/quiz:ignoretimelimits', $context, $userid, false));
+ if ($accessmanager->is_finished(count($attempts), $lastfinishedattempt)) {
+ return true;
+ }
+ }
+ }
+
+ // Check for passing grade.
+ if ($quiz->completionpass) {
+ require_once($CFG->libdir . '/gradelib.php');
+ $item = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod',
+ 'itemmodule' => 'quiz', 'iteminstance' => $cm->instance));
+ if ($item) {
+ $grades = grade_grade::fetch_users_grades($item, array($userid), false);
+ if (!empty($grades[$userid])) {
+ return $grades[$userid]->is_passed($item);
+ }
+ }
+ }
+ return false;
+}
return true;
}
+ // Update completion state.
+ $completion = new completion_info($course);
+ if ($completion->is_enabled($cm) && ($quiz->completionattemptsexhausted || $quiz->completionpass)) {
+ $completion->update_state($cm, COMPLETION_COMPLETE, $event->userid);
+ }
return quiz_send_notification_messages($course, $quiz, $attempt,
context_module::instance($cm->id), $cm);
}
return $errors;
}
+
+ /**
+ * Display module-specific activity completion rules.
+ * Part of the API defined by moodleform_mod
+ * @return array Array of string IDs of added items, empty array if none
+ */
+ public function add_completion_rules() {
+ $mform = $this->_form;
+ $items = array();
+
+ $group = array();
+ $group[] = $mform->createElement('advcheckbox', 'completionpass', null, get_string('completionpass', 'quiz'),
+ array('group' => 'cpass'));
+
+ $group[] = $mform->createElement('advcheckbox', 'completionattemptsexhausted', null,
+ get_string('completionattemptsexhausted', 'quiz'),
+ array('group' => 'cattempts'));
+ $mform->disabledIf('completionattemptsexhausted', 'completionpass', 'notchecked');
+ $mform->addGroup($group, 'completionpassgroup', get_string('completionpass', 'quiz'), ' ', false);
+ $mform->addHelpButton('completionpassgroup', 'completionpass', 'quiz');
+ $items[] = 'completionpassgroup';
+ return $items;
+ }
+
+ /**
+ * Called during validation. Indicates whether a module-specific completion rule is selected.
+ *
+ * @param array $data Input data (not yet validated)
+ * @return bool True if one or more rules is enabled, false if none are.
+ */
+ public function completion_rule_enabled($data) {
+ return !empty($data['completionattemptsexhausted']) || !empty($data['completionpass']);
+ }
}
--- /dev/null
+@mod @mod_quiz
+Feature: Set a quiz to be marked complete when the student uses all attempts allowed
+ In order to ensure a student has learned the material before being marked complete
+ As a teacher
+ I need to set a quiz to complete when the student receives a passing grade, or completed_fail if they use all attempts without passing
+
+ Background:
+ Given the following "users" exist:
+ | username | firstname | lastname | email |
+ | student1 | Student | 1 | student1@asd.com |
+ | teacher1 | Teacher | 1 | teacher1@asd.com |
+ And the following "courses" exist:
+ | fullname | shortname | category |
+ | Course 1 | C1 | 0 |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | teacher1 | C1 | editingteacher |
+ | student1 | C1 | student |
+ And I log in as "admin"
+ And I set the following administration settings values:
+ | Enable completion tracking | 1 |
+ And I expand "Grades" node
+ And I follow "Grade item settings"
+ And I set the field "Advanced grade item options" to "hiddenuntil"
+ And I press "Save changes"
+ And I log out
+
+ Scenario: student1 uses up both attempts without passing
+ When I log in as "teacher1"
+ And I follow "Course 1"
+ And I turn editing mode on
+ And I click on "Edit settings" "link" in the "Administration" "block"
+ And I set the following fields to these values:
+ | Enable completion tracking | Yes |
+ And I press "Save changes"
+ And I add a "Quiz" to section "1" and I fill the form with:
+ | Name | Test quiz name |
+ | Description | Test quiz description |
+ | Completion tracking | Show activity as complete when conditions are met |
+ | Attempts allowed | 2 |
+ | Require passing grade | 1 |
+ | Or all available attempts completed | 1 |
+ And I add a "True/False" question to the "Test quiz name" quiz with:
+ | Question name | First question |
+ | Question text | Answer the first question |
+ | General feedback | Thank you, this is the general feedback |
+ | Correct answer | True |
+ | Feedback for the response 'True'. | So you think it is true |
+ | Feedback for the response 'False'. | So you think it is false |
+ And I follow "Course 1"
+ And I follow "Grades"
+ And I follow "Simple view"
+ And I follow "Edit quiz Test quiz name"
+ Then I should see "Edit grade item"
+ And I set the field "gradepass" to "5"
+ And I press "Save changes"
+ And I should see "Simple view"
+ Then I log out
+
+ And I log in as "student1"
+ And I follow "Course 1"
+ And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I follow "Test quiz name"
+ And I press "Attempt quiz now"
+ And I should see "Question 1"
+ And I should see "Answer the first question"
+ And I set the field "False" to "1"
+ And I press "Next"
+ And I should see "Answer saved"
+ And I press "Submit all and finish"
+ And I follow "C1"
+ And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I follow "Test quiz name"
+ And I press "Re-attempt quiz"
+ Then I should see "Question 1"
+ And I should see "Answer the first question"
+ And I set the field "False" to "1"
+ And I press "Next"
+ And I should see "Answer saved"
+ And I press "Submit all and finish"
+ And I follow "C1"
+ And "//img[contains(@alt, 'Completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I log out
+ And I log in as "teacher1"
+ And I follow "Course 1"
+ And I follow "Activity completion"
+ Then "//img[contains(@title,'Test quiz name') and @alt='Completed']" "xpath_element" should exist in the "Student 1" "table_row"
+
--- /dev/null
+@mod @mod_quiz
+Feature: Set a quiz to be marked complete when the student passes
+ In order to ensure a student has learned the material before being marked complete
+ As a teacher
+ I need to set a quiz to complete when the student recieves a passing grade
+
+ Background:
+ Given the following "users" exist:
+ | username | firstname | lastname | email |
+ | student1 | Student | 1 | student1@asd.com |
+ | teacher1 | Teacher | 1 | teacher1@asd.com |
+ And the following "courses" exist:
+ | fullname | shortname | category |
+ | Course 1 | C1 | 0 |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | teacher1 | C1 | editingteacher |
+ | student1 | C1 | student |
+ And I log in as "admin"
+ And I set the following administration settings values:
+ | Enable completion tracking | 1 |
+ And I expand "Grades" node
+ And I follow "Grade item settings"
+ And I set the field "Advanced grade item options" to "hiddenuntil"
+ And I press "Save changes"
+ And I log out
+
+ Scenario: student1 passes on the first try
+ When I log in as "teacher1"
+ And I follow "Course 1"
+ And I turn editing mode on
+ And I click on "Edit settings" "link" in the "Administration" "block"
+ And I set the following fields to these values:
+ | Enable completion tracking | Yes |
+ And I press "Save changes"
+ And I add a "Quiz" to section "1" and I fill the form with:
+ | Name | Test quiz name |
+ | Description | Test quiz description |
+ | Completion tracking | Show activity as complete when conditions are met |
+ | Attempts allowed | 4 |
+ | Require passing grade | 1 |
+ And I add a "True/False" question to the "Test quiz name" quiz with:
+ | Question name | First question |
+ | Question text | Answer the first question |
+ | General feedback | Thank you, this is the general feedback |
+ | Correct answer | True |
+ | Feedback for the response 'True'. | So you think it is true |
+ | Feedback for the response 'False'. | So you think it is false |
+ And I follow "Course 1"
+ And I follow "Grades"
+ And I set the field "jump" to "Simple view"
+ And I press "Go"
+ And I follow "Edit quiz Test quiz name"
+ Then I should see "Edit grade item"
+ And I set the field "gradepass" to "5"
+ And I press "Save changes"
+ Then I should see "Simple view"
+ And I log out
+
+ And I log in as "student1"
+ And I follow "Course 1"
+ And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I follow "Test quiz name"
+ And I press "Attempt quiz now"
+ Then I should see "Question 1"
+ And I should see "Answer the first question"
+ And I set the field "False" to "1"
+ And I press "Next"
+ And I should see "Answer saved"
+ And I press "Submit all and finish"
+ And I follow "C1"
+ And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I follow "Test quiz name"
+ And I press "Re-attempt quiz"
+ Then I should see "Question 1"
+ And I should see "Answer the first question"
+ And I set the field "True" to "1"
+ And I press "Next"
+ And I should see "Answer saved"
+ And I press "Submit all and finish"
+ And I follow "C1"
+ And "//img[contains(@alt, 'Completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
+ And I log out
+ And I log in as "teacher1"
+ And I follow "Course 1"
+ And I follow "Activity completion"
+ Then "//img[contains(@title,'Test quiz name') and @alt='Completed']" "xpath_element" should exist in the "Student 1" "table_row"
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2014051200; // The current module version (Date: YYYYMMDDXX).
+$plugin->version = 2014052801; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2014050800; // Requires this Moodle version.
$plugin->component = 'mod_quiz'; // Full name of the plugin (used for diagnostics).
$plugin->cron = 60;
-<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-if (isset($userdata->status)) {
- if ($userdata->status == '') {
- $userdata->entry = 'ab-initio';
- } else {
- if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
- $userdata->entry = 'resume';
- } else {
- $userdata->entry = '';
- }
- }
-}
-if (!isset($currentorg)) {
- $currentorg = '';
-}
-?>
//
// SCORM 1.2 API Implementation
//
-function AICCapi() {
+function AICCapi(def, cmiobj, scormauto, cfgwwwroot, scormid, scoid, attempt, viewmode, currentorg, sesskey, cmid) {
+
+ var prerequrl = cfgwwwroot + "/mod/scorm/prereqs.php?a="+scormid+"&scoid="+scoid+"&attempt="+attempt+"&mode="+viewmode+"¤torg="+currentorg+"&sesskey="+sesskey;
+ var datamodelurl = cfgwwwroot + "/mod/scorm/datamodel.php";
+ var datamodelurlparams = "id="+cmid+"&a="+scormid+"&sesskey="+sesskey+"&attempt="+attempt+"&scoid="+scoid;
+
// Standard Data Type Definition
CMIString256 = '^.{0,255}$';
CMIString4096 = '^.{0,4096}$';
'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'},
'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'},
'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'},
- 'cmi.core.student_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.student_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.lesson_location':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_location'})?$userdata->{'cmi.core.lesson_location'}:'' ?>', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
- 'cmi.core.credit':{'defaultvalue':'<?php echo $userdata->credit ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.lesson_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_status'})?$userdata->{'cmi.core.lesson_status'}:'' ?>', 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'},
- 'cmi.core.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.exit'})?$userdata->{'cmi.core.exit'}:'' ?>', 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
- 'cmi.core.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r', 'writeerror':'403'},
+ 'cmi.core.student_id':{'defaultvalue':def['cmi.core.student_id'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.core.student_name':{'defaultvalue':def['cmi.core.student_name'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.core.lesson_location':{'defaultvalue':def['cmi.core.lesson_location'], 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.credit':{'defaultvalue':def['cmi.core.credit'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.core.lesson_status':{'defaultvalue':def['cmi.core.lesson_status'], 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.exit':{'defaultvalue':def['cmi.core.exit'], 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
+ 'cmi.core.entry':{'defaultvalue':def['cmi.core.entry'], 'mod':'r', 'writeerror':'403'},
'cmi.core.score._children':{'defaultvalue':score_children, 'mod':'r', 'writeerror':'402'},
- 'cmi.core.score.raw':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.raw'})?$userdata->{'cmi.core.score.raw'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
- 'cmi.core.score.max':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.max'})?$userdata->{'cmi.core.score.max'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
- 'cmi.core.score.min':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.min'})?$userdata->{'cmi.core.score.min'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.score.raw':{'defaultvalue':def['cmi.core.score.raw'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.score.max':{'defaultvalue':def['cmi.core.score.max'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.score.min':{'defaultvalue':def['cmi.core.score.min'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'},
- 'cmi.core.total_time':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.total_time'})?$userdata->{'cmi.core.total_time'}:'00:00:00' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.lesson_mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.suspend_data':{'defaultvalue':'<?php echo isset($userdata->{'cmi.suspend_data'})?$userdata->{'cmi.suspend_data'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
- 'cmi.launch_data':{'defaultvalue':'<?php echo isset($userdata->datafromlms)?$userdata->datafromlms:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.comments':{'defaultvalue':'<?php echo isset($userdata->{'cmi.comments'})?$userdata->{'cmi.comments'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.core.total_time':{'defaultvalue':def['cmi.core.total_time'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.core.lesson_mode':{'defaultvalue':def['cmi.core.lesson_mode'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.suspend_data':{'defaultvalue':def['cmi.suspend_data'], 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
+ 'cmi.launch_data':{'defaultvalue':def['cmi.launch_data'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.comments':{'defaultvalue':def['cmi.comments'], 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
// deprecated evaluation attributes
'cmi.evaluation.comments._count':{'defaultvalue':'0', 'mod':'r', 'writeerror':'402'},
'cmi.evaluation.comments._children':{'defaultvalue':comments_children, 'mod':'r', 'writeerror':'402'},
'cmi.objectives.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
'cmi.objectives.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
'cmi.student_data._children':{'defaultvalue':student_data_children, 'mod':'r', 'writeerror':'402'},
- 'cmi.student_data.attempt_number':{'defaultvalue':'<?php echo isset($userdata->{'cmi.student_data.attempt_number'})?$userdata->{'cmi.student_data.attempt_number'}:'' ?>', 'mod':'r', 'writeerror':'402'},
+ 'cmi.student_data.attempt_number':{'defaultvalue':def['cmi.student_data.attempt_number'], 'mod':'r', 'writeerror':'402'},
'cmi.student_data.tries.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
'cmi.student_data.tries.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
'cmi.student_data.tries.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
'cmi.student_data.tries.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
'cmi.student_data.tries.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
- 'cmi.student_data.mastery_score':{'defaultvalue':'<?php echo isset($userdata->mastery_score)?$userdata->mastery_score:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.student_data.max_time_allowed':{'defaultvalue':'<?php echo isset($userdata->max_time_allowed)?$userdata->max_time_allowed:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.student_data.time_limit_action':{'defaultvalue':'<?php echo isset($userdata->time_limit_action)?$userdata->time_limit_action:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.student_data.tries_during_lesson':{'defaultvalue':'<?php echo isset($userdata->{'cmi.student_data.tries_during_lesson'})?$userdata->{'cmi.student_data.tries_during_lesson'}:'' ?>', 'mod':'r', 'writeerror':'402'},
+ 'cmi.student_data.mastery_score':{'defaultvalue':def['cmi.student_data.mastery_score'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.student_data.max_time_allowed':{'defaultvalue':def['cmi.student_data.max_time_allowed'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.student_data.time_limit_action':{'defaultvalue':def['cmi.student_data.time_limit_action'], 'mod':'r', 'writeerror':'403'},
+ 'cmi.student_data.tries_during_lesson':{'defaultvalue':def['cmi.student_data.tries_during_lesson'], 'mod':'r', 'writeerror':'402'},
'cmi.student_preference._children':{'defaultvalue':student_preference_children, 'mod':'r', 'writeerror':'402'},
'cmi.student_preference.audio':{'defaultvalue':'0', 'format':CMISInteger, 'range':audio_range, 'mod':'rw', 'writeerror':'405'},
'cmi.student_preference.language':{'defaultvalue':'', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
}
}
-<?php
-$current_objective = '';
-$count = 0;
-$objectives = '';
-foreach ($userdata as $element => $value) {
- if (substr($element, 0, 14) == 'cmi.objectives') {
- $element = preg_replace('/\.(\d+)\./', "_\$1.", $element);
- preg_match('/\_(\d+)\./', $element, $matches);
- if (count($matches) > 0 && $current_objective != $matches[1]) {
- $current_objective = $matches[1];
- $count++;
- $end = strpos($element, $matches[1])+strlen($matches[1]);
- $subelement = substr($element, 0, $end);
- echo ' '.$subelement." = new Object();\n";
- echo ' '.$subelement.".score = new Object();\n";
- echo ' '.$subelement.".score._children = score_children;\n";
- echo ' '.$subelement.".score.raw = '';\n";
- echo ' '.$subelement.".score.min = '';\n";
- echo ' '.$subelement.".score.max = '';\n";
- }
- echo ' '.$element.' = \''.$value."';\n";
- }
-}
-if ($count > 0) {
- echo ' cmi.objectives._count = '.$count.";\n";
-}
-?>
+ eval(cmiobj);
if (cmi.core.lesson_status == '') {
cmi.core.lesson_status = 'not attempted';
setTimeout('mod_scorm_launch_prev_sco();',500);
}
} else {
- if (<?php echo $scorm->auto ?> == 1) {
+ if (scormauto == 1) {
setTimeout('mod_scorm_launch_next_sco();',500);
}
}
// trigger TOC update
- var sURL = "<?php echo $CFG->wwwroot; ?>" + "/mod/scorm/prereqs.php?a=<?php echo $scorm->id ?>&scoid=<?php echo $scoid ?>&attempt=<?php echo $attempt ?>&mode=<?php echo $mode ?>¤torg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
var callback = M.mod_scorm.connectPrereqCallback;
YUI().use('io-base', function(Y) {
Y.on('io:complete', callback.success, Y);
- Y.io(sURL);
+ Y.io(prerequrl);
});
return "true";
} else {
} else {
datastring = CollectData(data,'cmi');
}
- datastring += '&attempt=<?php echo $attempt ?>';
- datastring += '&scoid=<?php echo $scoid ?>';
//popupwin(datastring);
var myRequest = NewHttpReq();
- result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
+ result = DoRequest(myRequest,datamodelurl,datamodelurlparams+datastring);
results = String(result).split('\n');
errorCode = results[1];
return results[0];
this.LMSGetDiagnostic = LMSGetDiagnostic;
}
-var API = new AICCapi();
+M.scorm_api = {};
+
+M.scorm_api.init = function(Y, def, cmiobj, scormauto, cfgwwwroot, scormid, scoid, attempt, viewmode, currentorg, sesskey, cmid) {
+ window.API = new AICCapi(def, cmiobj, scormauto, cfgwwwroot, scormid, scoid, attempt, viewmode, currentorg, sesskey, cmid);
+}
--- /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/>.
+
+require_once($CFG->dirroot.'/mod/scorm/locallib.php');
+
+$userdata = new stdClass();
+$def = get_scorm_default($userdata, $scorm, $scoid, $attempt, $mode);
+
+if (!isset($currentorg)) {
+ $currentorg = '';
+}
+
+$cmiobj = '';
+$currentobj = '';
+$count = 0;
+foreach ($userdata as $element => $value) {
+ if (substr($element, 0, 14) == 'cmi.objectives') {
+ $element = preg_replace('/\.(\d+)\./', "_\$1.", $element);
+ preg_match('/\_(\d+)\./', $element, $matches);
+ if (count($matches) > 0 && $currentobj != $matches[1]) {
+ $currentobj = $matches[1];
+ $count++;
+ $end = strpos($element, $matches[1])+strlen($matches[1]);
+ $subelement = substr($element, 0, $end);
+ $cmiobj .= ' '.$subelement." = new Object();\n";
+ $cmiobj .= ' '.$subelement.".score = new Object();\n";
+ $cmiobj .= ' '.$subelement.".score._children = score_children;\n";
+ $cmiobj .= ' '.$subelement.".score.raw = '';\n";
+ $cmiobj .= ' '.$subelement.".score.min = '';\n";
+ $cmiobj .= ' '.$subelement.".score.max = '';\n";
+ }
+ $cmiobj .= ' '.$element.' = \''.$value."';\n";
+ }
+}
+if ($count > 0) {
+ $cmiobj .= ' cmi.objectives._count = '.$count.";\n";
+}
+
+$PAGE->requires->js_init_call('M.scorm_api.init', array($def, $cmiobj, $scorm->auto, $CFG->wwwroot, $scorm->id, $scoid, $attempt,
+ $mode, $currentorg, sesskey(), $id));
* Sets up AICC packages
* Called whenever package changes
* @param object $scorm instance - fields are updated and changes saved into database
-
* @return bool
*/
function scorm_parse_aicc(&$scorm) {
$id = $DB->insert_record('scorm_scoes', $sco);
}
return $id;
-}
\ No newline at end of file
+}
+
+/**
+ * Sets up $userdata array and default values for AICC package.
+ *
+ * @param stdClass $userdata an empty stdClass variable that should be set up with user values
+ * @param object $scorm package record
+ * @param string $scoid SCO Id
+ * @param string $attempt attempt number for the user
+ * @param string $mode scorm display mode type
+ * @return array The default values that should be used for AICC package
+ */
+function get_scorm_default (&$userdata, $scorm, $scoid, $attempt, $mode) {
+ global $USER;
+
+ $userdata->student_id = $USER->username;
+ $userdata->student_name = $USER->lastname .', '. $USER->firstname;
+
+ if ($usertrack = scorm_get_tracks($scoid, $USER->id, $attempt)) {
+ foreach ($usertrack as $key => $value) {
+ $userdata->$key = $value;
+ }
+ } else {
+ $userdata->status = '';
+ $userdata->score_raw = '';
+ }
+
+ if ($scodatas = scorm_get_sco($scoid, SCO_DATA)) {
+ foreach ($scodatas as $key => $value) {
+ $userdata->$key = $value;
+ }
+ } else {
+ print_error('cannotfindsco', 'scorm');
+ }
+ if (!$sco = scorm_get_sco($scoid)) {
+ print_error('cannotfindsco', 'scorm');
+ }
+
+ $userdata->mode = 'normal';
+ if (!empty($mode)) {
+ $userdata->mode = $mode;
+ }
+ if ($userdata->mode == 'normal') {
+ $userdata->credit = 'credit';
+ } else {
+ $userdata->credit = 'no-credit';
+ }
+
+ if (isset($userdata->status)) {
+ if ($userdata->status == '') {
+ $userdata->entry = 'ab-initio';
+ } else {
+ if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
+ $userdata->entry = 'resume';
+ } else {
+ $userdata->entry = '';
+ }
+ }
+ }
+
+ $def = array();
+ $def['cmi.core.student_id'] = $userdata->student_id;
+ $def['cmi.core.student_name'] = $userdata->student_name;
+ $def['cmi.core.credit'] = $userdata->credit;
+ $def['cmi.core.entry'] = $userdata->entry;
+ $def['cmi.launch_data'] = scorm_isset($userdata, 'datafromlms');
+ $def['cmi.core.lesson_mode'] = $userdata->mode;
+ $def['cmi.student_data.attempt_number'] = scorm_isset($userdata, 'cmi.student_data.attempt_number');
+ $def['cmi.student_data.mastery_score'] = scorm_isset($userdata, 'mastery_score');
+ $def['cmi.student_data.max_time_allowed'] = scorm_isset($userdata, 'max_time_allowed');
+ $def['cmi.student_data.time_limit_action'] = scorm_isset($userdata, 'time_limit_action');
+ $def['cmi.student_data.tries_during_lesson'] = scorm_isset($userdata, 'cmi.student_data.tries_during_lesson');
+
+ $def['cmi.core.lesson_location'] = scorm_isset($userdata, 'cmi.core.lesson_location');
+ $def['cmi.core.lesson_status'] = scorm_isset($userdata, 'cmi.core.lesson_status');
+ $def['cmi.core.exit'] = scorm_isset($userdata, 'cmi.core.exit');
+ $def['cmi.core.score.raw'] = scorm_isset($userdata, 'cmi.core.score.raw');
+ $def['cmi.core.score.max'] = scorm_isset($userdata, 'cmi.core.score.max');
+ $def['cmi.core.score.min'] = scorm_isset($userdata, 'cmi.core.score.min');
+ $def['cmi.core.total_time'] = scorm_isset($userdata, 'cmi.core.total_time', '00:00:00');
+ $def['cmi.suspend_data'] = scorm_isset($userdata, 'cmi.suspend_data');
+ $def['cmi.comments'] = scorm_isset($userdata, 'cmi.comments');
+
+ return $def;
+}
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+echo html_writer::start_tag('script');
?>
<!--// hopefully fool ie IE proof way of getting DOM element
if (getLoggingActive() == "A") {
AppendToLog("Moodle Logging Deactivated", 0);
setLoggingActive('N');
- logButton.innerHTML = '--><?php echo addslashes_js(get_string('scormloggingoff', 'scorm')); ?>';
+ logButton.innerHTML = '-><?php echo addslashes_js(get_string('scormloggingoff', 'scorm')); ?>';
} else {
setLoggingActive('A');
AppendToLog("Moodle Logging Activated", 0);
var content = safeGetElement(document, 'scormpage');
content.insertBefore(logButton, content.firstChild);
}
+-->
+
+<?php
+echo html_writer::end_tag('script');
-<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-require_once($CFG->dirroot.'/mod/scorm/locallib.php');
-
-if (isset($userdata->status)) {
- if ($userdata->status == '') {
- $userdata->entry = 'ab-initio';
- } else {
- if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
- $userdata->entry = 'resume';
- } else {
- $userdata->entry = '';
- }
- }
-}
-if (!isset($currentorg)) {
- $currentorg = '';
-}
-
-// If SCORM 1.2 standard mode is disabled allow higher datamodel limits.
-if (intval(get_config("scorm", "scorm12standard"))) {
- $cmistring256 = '^[\\u0000-\\uFFFF]{0,255}$';
- $cmistring4096 = '^[\\u0000-\\uFFFF]{0,4096}$';
-} else {
- $cmistring256 = '^[\\u0000-\\uFFFF]{0,64000}$';
- $cmistring4096 = $cmistring256;
-}
-?>
//
// SCORM 1.2 API Implementation
//
-function SCORMapi1_2() {
+function SCORMapi1_2(def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg) {
+
+ var prerequrl = cfgwwwroot + "/mod/scorm/prereqs.php?a="+scormid+"&scoid="+scoid+"&attempt="+attempt+"&mode="+viewmode+"¤torg="+currentorg+"&sesskey="+sesskey;
+ var datamodelurl = cfgwwwroot + "/mod/scorm/datamodel.php";
+ var datamodelurlparams = "id="+cmid+"&a="+scormid+"&sesskey="+sesskey+"&attempt="+attempt+"&scoid="+scoid;
+
// Standard Data Type Definition
- CMIString256 = '<?php echo $cmistring256 ?>';
- CMIString4096 = '<?php echo $cmistring4096 ?>';
+ CMIString256 = cmistring256;
+ CMIString4096 = cmistring4096;
CMITime = '^([0-2]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{1,2})?$';
CMITimespan = '^([0-9]{2,4}):([0-9]{2}):([0-9]{2})(\.[0-9]{1,2})?$';
CMIInteger = '^\\d+$';
'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'},
'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'},
'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'},
- 'cmi.core.student_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.student_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.core.lesson_location':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_location'})?$userdata->{'cmi.core.lesson_location'}:'' ?>', 'format':CMIString256, 'mod':'rw', 'wri