$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);
$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();
+ }
}
<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['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) {
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
*/
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'])) {
$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,
$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;
+ }
}
}
}
* @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['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';
$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', '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.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.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.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.core.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.exit'})?$userdata->{'cmi.core.exit'}:'' ?>', 'format':CMIExit, 'mod':'w', 'readerror':'404', '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.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.core.exit':{'defaultvalue':def['cmi.core.exit'], 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'},
- '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.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.mastery_score':{'defaultvalue':'<?php echo isset($userdata->masteryscore)?$userdata->masteryscore:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.student_data.max_time_allowed':{'defaultvalue':'<?php echo isset($userdata->maxtimeallowed)?$userdata->maxtimeallowed:'' ?>', 'mod':'r', 'writeerror':'403'},
- 'cmi.student_data.time_limit_action':{'defaultvalue':'<?php echo isset($userdata->timelimitaction)?$userdata->timelimitaction:'' ?>', 'mod':'r', 'writeerror':'403'},
+ '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_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
- // reconstitute objectives
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.objectives', array('score'));
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.interactions', array('objectives', 'correct_responses'));
- ?>
+ eval(cmiobj);
+ eval(cmiint);
if (cmi.core.lesson_status == '') {
cmi.core.lesson_status = 'not attempted';
if (!Initialized) {
Initialized = true;
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSInitialize", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSInitialize", param, "", errorCode);
+ }
return "true";
} else {
errorCode = "101";
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSInitialize", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSInitialize", param, "", errorCode);
+ }
return "false";
}
setTimeout('mod_scorm_launch_prev_sco();',500);
}
} else {
- if (<?php echo $scorm->auto ?> == 1) {
+ if (scormauto == 1) {
setTimeout('mod_scorm_launch_next_sco();',500);
}
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSFinish", "AJAXResult", result, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSFinish", "AJAXResult", result, 0);
+ }
result = ('true' == result) ? 'true' : 'false';
errorCode = (result == 'true')? '0' : '101';
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSFinish", "result", result, 0);';
- echo 'LogAPICall("LMSFinish", param, "", 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSFinish", "result", result, 0);
+ LogAPICall("LMSFinish", param, "", 0);
+ }
// 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 result;
} else {
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSFinish", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSFinish", param, "", errorCode);
+ }
return "false";
}
}
if (subelement == element) {
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetValue", element, eval(element), 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSGetValue", element, eval(element), 0);
+ }
return eval(element);
} else {
errorCode = "0"; // Need to check if it is the right errorCode
} else {
errorCode = "301";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetValue", element, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSGetValue", element, "", errorCode);
+ }
return "";
}
if ((value >= ranges[0]) && (value <= ranges[1])) {
eval(element+'=value;');
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSSetValue", element, value, errorCode);
+ }
return "true";
} else {
errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
eval(element+'=value;');
}
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSSetValue", element, value, errorCode);
+ }
return "true";
}
}
} else {
errorCode = "301";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
+ if (scormdebugging) {
+ LogAPICall("LMSSetValue", element, value, errorCode);
}
- ?>
return "false";
}
if (Initialized) {
result = StoreData(cmi,false);
// 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);
});
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Commit", param, "", 0);';
- }
- ?>
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSCommit", "AJAXResult", result, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Commit", param, "", 0);
+ }
+ if (scormdebugging) {
+ LogAPICall("LMSCommit", "AJAXResult", result, 0);
+ }
result = ('true' == result) ? 'true' : 'false';
errorCode = (result =='true')? '0' : '101';
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSCommit", "result", result, 0);';
- echo 'LogAPICall("LMSCommit", "errorCode", errorCode, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSCommit", "result", result, 0);
+ LogAPICall("LMSCommit", "errorCode", errorCode, 0);
+ }
return result;
} else {
errorCode = "301";
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSCommit", param, "", 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSCommit", param, "", 0);
+ }
return "false";
}
function LMSGetLastError () {
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetLastError", "", "", errorCode);';
+ if (scormdebugging) {
+ LogAPICall("LMSGetLastError", "", "", errorCode);
}
- ?>
return errorCode;
}
errorString["403"] = "Element is read only";
errorString["404"] = "Element is write only";
errorString["405"] = "Incorrect data type";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetErrorString", param, errorString[param], 0);';
+ if (scormdebugging) {
+ LogAPICall("LMSGetErrorString", param, errorString[param], 0);
}
- ?>
return errorString[param];
} else {
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetErrorString", param, "No error string found!", 0);';
+ if (scormdebugging) {
+ LogAPICall("LMSGetErrorString", param, "No error string found!", 0);
}
- ?>
return "";
}
}
if (param == "") {
param = errorCode;
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("LMSGetDiagnostic", param, param, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("LMSGetDiagnostic", param, param, 0);
+ }
return param;
}
} else {
datastring = CollectData(data,'cmi');
}
- datastring += '&attempt=<?php echo $attempt ?>';
- datastring += '&scoid=<?php echo $scoid ?>';
var myRequest = NewHttpReq();
//alert('going to:' + "<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php" + "id=<?php p($id) ?>&a=<?php p($a) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
- result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&a=<?php p($a) ?>&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 SCORMapi1_2();
+M.scorm_api = {};
-<?php
-// pull in the debugging utilities
-if (scorm_debugging($scorm)) {
- include_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
- echo 'AppendToLog("Moodle SCORM 1.2 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);';
+M.scorm_api.init = function(Y, def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg) {
+ window.API = new SCORMapi1_2(def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg);
}
-
--- /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');
+
+// Set some vars to use as default values.
+$userdata = new stdClass();
+$def = get_scorm_default($userdata, $scorm, $scoid, $attempt, $mode);
+
+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;
+}
+
+// reconstitute objectives
+$cmiobj = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.objectives', array('score'));
+$cmiint = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.interactions', array('objectives', 'correct_responses'));
+
+$PAGE->requires->js_init_call('M.scorm_api.init', array($def, $cmiobj, $cmiint, $cmistring256, $cmistring4096,
+ scorm_debugging($scorm), $scorm->auto, $scorm->id, $CFG->wwwroot,
+ sesskey(), $scoid, $attempt, $mode, $id, $currentorg));
+
+// pull in the debugging utilities
+if (scorm_debugging($scorm)) {
+ require_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
+ echo html_writer::script('AppendToLog("Moodle SCORM 1.2 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);');
+}
\ No newline at end of file
}
return eval('return '.implode($stack).';');
}
+
+/**
+ * Sets up $userdata array and default values for SCORM 1.2 .
+ *
+ * @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 SCORM 1.2 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');
+ }
+
+ 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 = '';
+ }
+ }
+ }
+
+ $userdata->mode = 'normal';
+ if (!empty($mode)) {
+ $userdata->mode = $mode;
+ }
+ if ($userdata->mode == 'normal') {
+ $userdata->credit = 'credit';
+ } else {
+ $userdata->credit = 'no-credit';
+ }
+
+ $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.core.lesson_mode'] = $userdata->mode;
+ $def['cmi.launch_data'] = scorm_isset($userdata, 'datafromlms');
+ $def['cmi.student_data.mastery_score'] = scorm_isset($userdata, 'masteryscore');
+ $def['cmi.student_data.max_time_allowed'] = scorm_isset($userdata, 'maxtimeallowed');
+ $def['cmi.student_data.time_limit_action'] = scorm_isset($userdata, 'timelimitaction');
+ $def['cmi.core.total_time'] = scorm_isset($userdata, 'cmi.core.total_time', '00:00:00');
+
+ // Now handle standard userdata items:
+ $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.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.exit'] = scorm_isset($userdata, 'cmi.core.exit');
+ $def['cmi.suspend_data'] = scorm_isset($userdata, 'cmi.suspend_data');
+ $def['cmi.comments'] = scorm_isset($userdata, 'cmi.comments');
+ $def['cmi.student_preference.language'] = scorm_isset($userdata, 'cmi.student_preference.language');
+ $def['cmi.student_preference.audio'] = scorm_isset($userdata, 'cmi.student_preference.audio', '0');
+ $def['cmi.student_preference.speed'] = scorm_isset($userdata, 'cmi.student_preference.speed', '0');
+ $def['cmi.student_preference.text'] = scorm_isset($userdata, 'cmi.student_preference.text', '0');
+ return $def;
+}
-<?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 (!isset($userdata->{'cmi.exit'}) || (($userdata->{'cmi.exit'} == 'time-out') || ($userdata->{'cmi.exit'} == 'normal'))) {
- $userdata->entry = 'ab-initio';
- } else {
- if (isset($userdata->{'cmi.exit'}) && (($userdata->{'cmi.exit'} == 'suspend') || ($userdata->{'cmi.exit'} == 'logout'))) {
- $userdata->entry = 'resume';
- } else {
- $userdata->entry = '';
- }
- }
-}
-if (!isset($currentorg)) {
- $currentorg = '';
-}
-?>
-
// Used need to debug cmi content (if you uncomment this, you must comment the definition inside SCORMapi1_3)
//var cmi = new Object();
//
// SCORM 1.3 API Implementation
//
-function SCORMapi1_3() {
+function SCORMapi1_3(def, cmiobj, cmiint, cmicommentsuser, cmicommentslms, 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
// language key has to be checked for language dependent strings
'cmi.comments_from_lms.n.comment':{'format':CMILangString4000, 'mod':'r'},
'cmi.comments_from_lms.n.location':{'format':CMIString250, 'mod':'r'},
'cmi.comments_from_lms.n.timestamp':{'format':CMITime, 'mod':'r'},
- 'cmi.completion_status':{'defaultvalue':'<?php echo !empty($userdata->{'cmi.completion_status'})?$userdata->{'cmi.completion_status'}:'unknown' ?>', 'format':CMICStatus, 'mod':'rw'},
- 'cmi.completion_threshold':{'defaultvalue':<?php echo !empty($userdata->threshold)?'\''.$userdata->threshold.'\'':'null' ?>, 'mod':'r'},
- 'cmi.credit':{'defaultvalue':'<?php echo !empty($userdata->credit)?$userdata->credit:'' ?>', 'mod':'r'},
- 'cmi.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r'},
- 'cmi.exit':{'defaultvalue':'<?php echo !empty($userdata->{'cmi.exit'})?$userdata->{'cmi.exit'}:'' ?>', 'format':CMIExit, 'mod':'w'},
+ 'cmi.completion_status':{'defaultvalue':def['cmi.completion_status'], 'format':CMICStatus, 'mod':'rw'},
+ 'cmi.completion_threshold':{'defaultvalue':def['cmi.completion_threshold'], 'mod':'r'},
+ 'cmi.credit':{'defaultvalue':def['cmi.credit'], 'mod':'r'},
+ 'cmi.entry':{'defaultvalue':def['cmi.entry'], 'mod':'r'},
+ 'cmi.exit':{'defaultvalue':def['cmi.exit'], 'format':CMIExit, 'mod':'w'},
'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r'},
'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0'},
'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMILongIdentifier, 'mod':'rw'},
'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'rw'},
'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'rw'},
'cmi.interactions.n.description':{'pattern':CMIIndex, 'format':CMILangString250, 'mod':'rw'},
- 'cmi.launch_data':{'defaultvalue':<?php echo !empty($userdata->datafromlms)?'\''.$userdata->datafromlms.'\'':'null' ?>, 'mod':'r'},
- 'cmi.learner_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r'},
- 'cmi.learner_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r'},
+ 'cmi.launch_data':{'defaultvalue':def['cmi.exit'], 'mod':'r'},
+ 'cmi.learner_id':{'defaultvalue':def['cmi.learner_id'], 'mod':'r'},
+ 'cmi.learner_name':{'defaultvalue':def['cmi.learner_name'], 'mod':'r'},
'cmi.learner_preference._children':{'defaultvalue':student_preference_children, 'mod':'r'},
- 'cmi.learner_preference.audio_level':{'defaultvalue':<?php echo !empty($userdata->{'cmi.learner_preference.audio_level'})?'\''.$userdata->{'cmi.learner_preference.audio_level'}.'\'':'\'1\'' ?>, 'format':CMIDecimal, 'range':audio_range, 'mod':'rw'},
- 'cmi.learner_preference.language':{'defaultvalue':<?php echo !empty($userdata->{'cmi.learner_preference.language'})?'\''.$userdata->{'cmi.learner_preference.language'}.'\'':'\'\'' ?>, 'format':CMILang, 'mod':'rw'},
- 'cmi.learner_preference.delivery_speed':{'defaultvalue':<?php echo !empty($userdata->{'cmi.learner_preference.delivery_speed'})?'\''.$userdata->{'cmi.learner_preference.delivery_speed'}.'\'':'\'1\'' ?>, 'format':CMIDecimal, 'range':speed_range, 'mod':'rw'},
- 'cmi.learner_preference.audio_captioning':{'defaultvalue':<?php echo !empty($userdata->{'cmi.learner_preference.audio_captioning'})?'\''.$userdata->{'cmi.learner_preference.audio_captioning'}.'\'':'\'0\'' ?>, 'format':CMISInteger, 'range':text_range, 'mod':'rw'},
- 'cmi.location':{'defaultvalue':<?php echo !empty($userdata->{'cmi.location'})?'\''.$userdata->{'cmi.location'}.'\'':'null' ?>, 'format':CMIString1000, 'mod':'rw'},
- 'cmi.max_time_allowed':{'defaultvalue':<?php echo !empty($userdata->attemptAbsoluteDurationLimit)?'\''.$userdata->attemptAbsoluteDurationLimit.'\'':'null' ?>, 'mod':'r'},
- 'cmi.mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r'},
+ 'cmi.learner_preference.audio_level':{'defaultvalue':def['cmi.learner_preference.audio_level'], 'format':CMIDecimal, 'range':audio_range, 'mod':'rw'},
+ 'cmi.learner_preference.language':{'defaultvalue':def['cmi.learner_preference.language'], 'format':CMILang, 'mod':'rw'},
+ 'cmi.learner_preference.delivery_speed':{'defaultvalue':def['cmi.learner_preference.delivery_speed'], 'format':CMIDecimal, 'range':speed_range, 'mod':'rw'},
+ 'cmi.learner_preference.audio_captioning':{'defaultvalue':def['cmi.learner_preference.audio_captioning'], 'format':CMISInteger, 'range':text_range, 'mod':'rw'},
+ 'cmi.location':{'defaultvalue':def['cmi.location'], 'format':CMIString1000, 'mod':'rw'},
+ 'cmi.max_time_allowed':{'defaultvalue':def['cmi.max_time_allowed'], 'mod':'r'},
+ 'cmi.mode':{'defaultvalue':def['cmi.mode'], 'mod':'r'},
'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r'},
'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0'},
'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMILongIdentifier, 'mod':'rw'},
'cmi.objectives.n.completion_status':{'defaultvalue':'unknown', 'pattern':CMIIndex, 'format':CMICStatus, 'mod':'rw'},
'cmi.objectives.n.progress_measure':{'defaultvalue':null, 'format':CMIDecimal, 'range':progress_range, 'mod':'rw'},
'cmi.objectives.n.description':{'pattern':CMIIndex, 'format':CMILangString250, 'mod':'rw'},
- 'cmi.progress_measure':{'defaultvalue':<?php echo !empty($userdata->{'cmi.progress_measure'})?'\''.$userdata->{'cmi.progress_measure'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':progress_range, 'mod':'rw'},
- 'cmi.scaled_passing_score':{'defaultvalue':<?php echo !empty($userdata->{'cmi.scaled_passing_score'})?'\''.$userdata->{'cmi.scaled_passing_score'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':scaled_range, 'mod':'r'},
+ 'cmi.progress_measure':{'defaultvalue':def['cmi.progress_measure'], 'format':CMIDecimal, 'range':progress_range, 'mod':'rw'},
+ 'cmi.scaled_passing_score':{'defaultvalue':def['cmi.scaled_passing_score'], 'format':CMIDecimal, 'range':scaled_range, 'mod':'r'},
'cmi.score._children':{'defaultvalue':score_children, 'mod':'r'},
- 'cmi.score.scaled':{'defaultvalue':<?php echo !empty($userdata->{'cmi.score.scaled'})?'\''.$userdata->{'cmi.score.scaled'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':scaled_range, 'mod':'rw'},
- 'cmi.score.raw':{'defaultvalue':<?php echo !empty($userdata->{'cmi.score.raw'})?'\''.$userdata->{'cmi.score.raw'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
- 'cmi.score.min':{'defaultvalue':<?php echo !empty($userdata->{'cmi.score.min'})?'\''.$userdata->{'cmi.score.min'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
- 'cmi.score.max':{'defaultvalue':<?php echo !empty($userdata->{'cmi.score.max'})?'\''.$userdata->{'cmi.score.max'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
+ 'cmi.score.scaled':{'defaultvalue':def['cmi.score.scaled'], 'format':CMIDecimal, 'range':scaled_range, 'mod':'rw'},
+ 'cmi.score.raw':{'defaultvalue':def['cmi.score.raw'], 'format':CMIDecimal, 'mod':'rw'},
+ 'cmi.score.min':{'defaultvalue':def['cmi.score.min'], 'format':CMIDecimal, 'mod':'rw'},
+ 'cmi.score.max':{'defaultvalue':def['cmi.score.max'], 'format':CMIDecimal, 'mod':'rw'},
'cmi.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'PT0H0M0S'},
- 'cmi.success_status':{'defaultvalue':'<?php echo !empty($userdata->{'cmi.success_status'})?$userdata->{'cmi.success_status'}:'unknown' ?>', 'format':CMISStatus, 'mod':'rw'},
- 'cmi.suspend_data':{'defaultvalue':<?php echo !empty($userdata->{'cmi.suspend_data'})?'\''.$userdata->{'cmi.suspend_data'}.'\'':'null' ?>, 'format':CMIString64000, 'mod':'rw'},
- 'cmi.time_limit_action':{'defaultvalue':<?php echo !empty($userdata->timelimitaction)?'\''.$userdata->timelimitaction.'\'':'null' ?>, 'mod':'r'},
- 'cmi.total_time':{'defaultvalue':'<?php echo !empty($userdata->{'cmi.total_time'})?$userdata->{'cmi.total_time'}:'PT0H0M0S' ?>', 'mod':'r'},
+ 'cmi.success_status':{'defaultvalue':def['cmi.success_status'], 'format':CMISStatus, 'mod':'rw'},
+ 'cmi.suspend_data':{'defaultvalue':def['cmi.suspend_data'], 'format':CMIString64000, 'mod':'rw'},
+ 'cmi.time_limit_action':{'defaultvalue':def['cmi.time_limit_action'], 'mod':'r'},
+ 'cmi.total_time':{'defaultvalue':def['cmi.total_time'], 'mod':'r'},
'adl.nav.request':{'defaultvalue':'_none_', 'format':NAVEvent, 'mod':'rw'}
};
//
}
}
-<?php
- // reconstitute objectives, comments_from_learner and comments_from_lms
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.objectives', array('score'));
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.interactions', array('objectives', 'correct_responses'));
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.comments_from_learner', array());
- scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.comments_from_lms', array());
-?>
+ eval(cmiobj);
+ eval(cmiint);
+ eval(cmicommentsuser);
+ eval(cmicommentslms);
if (cmi.completion_status == '') {
cmi.completion_status = 'not attempted';
if ((!Initialized) && (!Terminated)) {
Initialized = true;
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Initialize", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Initialize", param, "", errorCode);
+ }
return "true";
} else {
if (Initialized) {
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Initialize", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Initialize", param, "", errorCode);
+ }
return "false";
}
if (param == "") {
if ((Initialized) && (!Terminated)) {
var AJAXResult = StoreData(cmi,true);
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Terminate", "AJAXResult", AJAXResult, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Terminate", "AJAXResult", AJAXResult, 0);
+ }
result = ('true' == AJAXResult) ? 'true' : 'false';
errorCode = ('true' == result)? '0' : '101'; // General exception for any AJAX fault
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Terminate", "result", result, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Terminate", "result", result, errorCode);
+ }
if ('true' == result) {
Initialized = false;
Terminated = true;
break;
}
} 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);
});
} else {
diagnostic = "Failure calling the Terminate remote callback: the server replied with HTTP Status " + AJAXResult;
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Terminate", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Terminate", param, "", errorCode);
+ }
return "false";
}
if ((typeof eval(subelement) != "undefined") && (eval(subelement) != null)) {
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetValue", element, eval(element), 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("GetValue", element, eval(element), 0);
+ }
return eval(element);
} else {
errorCode = "403";
errorCode = "122";
}
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetValue", element, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("GetValue", element, "", errorCode);
+ }
return "";
}
}
break;
case 'cmi.interactions.n.correct_responses.n.pattern':
- subel= subelement.split('.');
+ subel= subelement.split('.');
subel1= 'cmi.interactions.'+subel[2];
if (typeof eval(subel1+'.type') == "undefined") {
if ((ranges[1] == '*') || (value <= ranges[1])) {
eval(element+'=value;');
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("SetValue", element, value, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("SetValue", element, value, errorCode);
+ }
return "true";
} else {
errorCode = '407';
} else {
eval(element+'=value;');
errorCode = "0";
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("SetValue", element, value, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("SetValue", element, value, errorCode);
+ }
return "true";
}
}
errorCode = "132";
}
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("SetValue", element, value, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("SetValue", element, value, errorCode);
+ }
return "false";
}
if (param == "") {
if ((Initialized) && (!Terminated)) {
var AJAXResult = StoreData(cmi,false);
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Commit", "AJAXResult", AJAXResult, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Commit", "AJAXResult", AJAXResult, 0);
+ }
var result = ('true' == AJAXResult) ? 'true' : 'false';
errorCode = ('true' == result)? '0' : '101'; // General exception for any AJAX fault
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Commit", "result", result, errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Commit", "result", result, errorCode);
+ }
if ('false' == result) {
diagnostic = "Failure calling the Commit remote callback: the server replied with HTTP Status " + AJAXResult;
}
} else {
errorCode = "201";
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("Commit", param, "", errorCode);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("Commit", param, "", errorCode);
+ }
return "false";
}
function GetLastError () {
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetLastError", "", "", errorCode);';
+ if (scormdebugging) {
+ LogAPICall("GetLastError", "", "", errorCode);
}
- ?>
return errorCode;
}
errorString = "Data Model Dependency Not Established";
break;
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetErrorString", param, errorString, 0);';
+ if (scormdebugging) {
+ LogAPICall("GetErrorString", param, errorString, 0);
}
- ?>
return errorString;
} else {
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetErrorString", param, "No error string found!", 0);';
+ if (scormdebugging) {
+ LogAPICall("GetErrorString", param, "No error string found!", 0);
}
- ?>
return "";
}
}
function GetDiagnostic (param) {
if (diagnostic != "") {
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetDiagnostic", param, diagnostic, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("GetDiagnostic", param, diagnostic, 0);
+ }
return diagnostic;
}
- <?php
- if (scorm_debugging($scorm)) {
- echo 'LogAPICall("GetDiagnostic", param, param, 0);';
- }
- ?>
+ if (scormdebugging) {
+ LogAPICall("GetDiagnostic", param, param, 0);
+ }
return param;
}
}
function AddTime (first, second) {
- <?php
-// if (scorm_debugging($scorm)) {
-// echo 'alert("AddTime: "+first+" + "+second);';
-// }
- ?>
var timestring = 'P';
var matchexpr = /^P((\d+)Y)?((\d+)M)?((\d+)D)?(T((\d+)H)?((\d+)M)?((\d+(\.\d{1,2})?)S)?)?$/;
var firstarray = first.match(matchexpr);
var element = 'adl.nav.request';
var navrequest = eval(element) != datamodel[element].defaultvalue ? '&'+underscore(element)+'='+encodeURIComponent(eval(element)) : '';
datastring += navrequest;
- datastring += '&attempt=<?php echo $attempt ?>';
- datastring += '&scoid=<?php echo $scoid ?>';
+
var myRequest = NewHttpReq();
- var result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&a=<?php p($a) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
+ result = DoRequest(myRequest,datamodelurl,datamodelurlparams+datastring);
+
var results = String(result).split('\n');
if ((results.length > 2) && (navrequest != '')) {
eval(results[2]);
this.version = '1.0';
}
-var API_1484_11 = new SCORMapi1_3();
+M.scorm_api = {};
-<?php
-// pull in the debugging utilities
-if (scorm_debugging($scorm)) {
- include_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
- echo 'AppendToLog("Moodle SCORM 1.3 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);';
+M.scorm_api.init = function(Y, def, cmiobj, cmiint, cmicommentsuser, cmicommentslms, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg) {
+ window.API_1484_11 = new SCORMapi1_3(def, cmiobj, cmiint, cmicommentsuser, cmicommentslms, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg);
}
--- /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 = '';
+}
+
+// reconstitute objectives, comments_from_learner and comments_from_lms
+$cmiobj = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.objectives', array('score'));
+$cmiint = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.interactions', array('objectives', 'correct_responses'));
+$cmicommentsuser = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.comments_from_learner', array());
+$cmicommentslms = scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.comments_from_lms', array());
+
+$PAGE->requires->js_init_call('M.scorm_api.init', array($def, $cmiobj, $cmiint, $cmicommentsuser, $cmicommentslms,
+ scorm_debugging($scorm), $scorm->auto, $scorm->id, $CFG->wwwroot,
+ sesskey(), $scoid, $attempt, $mode, $id, $currentorg));
+
+
+// pull in the debugging utilities
+if (scorm_debugging($scorm)) {
+ require_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
+ echo html_writer::script('AppendToLog("Moodle SCORM 1.3 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);');
+}
return $seq;
}
}
+
+/**
+ * Sets up $userdata array and default values for SCORM 1.3 .
+ *
+ * @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 SCORM 1.3 package
+ */
+function get_scorm_default (&$userdata, $scorm, $scoid, $attempt, $mode) {
+ global $DB, $USER;
+
+ $userdata->student_id = $USER->username;
+ $userdata->student_name = $USER->lastname .', '. $USER->firstname;
+
+ if ($usertrack = scorm_get_tracks($scoid, $USER->id, $attempt)) {
+ // According to SCORM 2004(RTE V1, 4.2.8), only cmi.exit==suspend should allow previous datamodel elements on re-launch.
+ if (isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} == 'suspend')) {
+ foreach ($usertrack as $key => $value) {
+ $userdata->$key = $value;
+ }
+ } else {
+ $userdata->status = '';
+ $userdata->score_raw = '';
+ }
+ } 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');
+ }
+
+ if (isset($userdata->status)) {
+ if (!isset($userdata->{'cmi.exit'}) || $userdata->{'cmi.exit'} == 'time-out' || $userdata->{'cmi.exit'} == 'normal') {
+ $userdata->entry = 'ab-initio';
+ } else {
+ if (isset($userdata->{'cmi.exit'}) && ($userdata->{'cmi.exit'} == 'suspend' || $userdata->{'cmi.exit'} == 'logout')) {
+ $userdata->entry = 'resume';
+ } else {
+ $userdata->entry = '';
+ }
+ }
+ }
+
+ $userdata->mode = 'normal';
+ if (!empty($mode)) {
+ $userdata->mode = $mode;
+ }
+ if ($userdata->mode == 'normal') {
+ $userdata->credit = 'credit';
+ } else {
+ $userdata->credit = 'no-credit';
+ }
+
+ $objectives = $DB->get_records('scorm_seq_objective', array('scoid' => $scoid));
+ $index = 0;
+ foreach ($objectives as $objective) {
+ if (!empty($objective->minnormalizedmeasure)) {
+ $userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure;
+ }
+ if (!empty($objective->objectiveid)) {
+ $userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid;
+ $index++;
+ }
+ }
+
+ $def = array();
+ $def['cmi.learner_id'] = $userdata->student_id;
+ $def['cmi.learner_name'] = $userdata->student_name;
+ $def['cmi.mode'] = $userdata->mode;
+ $def['cmi.entry'] = $userdata->entry;
+ $def['cmi.exit'] = scorm_empty($userdata, 'cmi.exit');
+ $def['cmi.credit'] = scorm_empty($userdata, 'credit');
+ $def['cmi.completion_status'] = scorm_empty($userdata, 'cmi.completion_status', 'unknown');
+ $def['cmi.completion_threshold'] = scorm_empty($userdata, 'threshold', 'null', true);
+ $def['cmi.learner_preference.audio_level'] = scorm_empty($userdata, 'cmi.learner_preference.audio_level', '\'1\'', true);
+ $def['cmi.learner_preference.language'] = scorm_empty($userdata, 'cmi.learner_preference.language', '\'\'', true);
+ $def['cmi.learner_preference.delivery_speed'] = scorm_empty($userdata, 'cmi.learner_preference.delivery_speed', '\'1\'', true);
+ $def['cmi.learner_preference.audio_captioning'] = scorm_empty($userdata, 'cmi.learner_preference.audio_captioning', '\'0\'', true);
+ $def['cmi.location'] = scorm_empty($userdata, 'cmi.location', 'null', true);
+ $def['cmi.max_time_allowed'] = scorm_empty($userdata, 'attemptAbsoluteDurationLimit', 'null', true);
+ $def['cmi.progress_measure'] = scorm_empty($userdata, 'cmi.progress_measure', 'null', true);
+ $def['cmi.scaled_passing_score'] = scorm_empty($userdata, 'cmi.scaled_passing_score', 'null', true);
+ $def['cmi.score.scaled'] = scorm_empty($userdata, 'cmi.score.scaled', 'null', true);
+ $def['cmi.score.raw'] = scorm_empty($userdata, 'cmi.score.raw', 'null', true);
+ $def['cmi.score.min'] = scorm_empty($userdata, 'cmi.score.min', 'null', true);
+ $def['cmi.score.max'] = scorm_empty($userdata, 'cmi.score.max', 'null', true);
+ $def['cmi.success_status'] = scorm_empty($userdata, 'cmi.success_status', 'unknown');
+ $def['cmi.suspend_data'] = scorm_empty($userdata, 'cmi.suspend_data', 'null', true);
+ $def['cmi.time_limit_action'] = scorm_empty($userdata, 'timelimitaction', 'null', true);
+ $def['cmi.total_time'] = scorm_empty($userdata, 'cmi.total_time', 'PT0H0M0S');
+
+ return $def;
+}
+++ /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/>.
-
-/**
- * This page loads the correct JS file based on package type
- *
- * @package mod_scorm
- * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once("../../config.php");
-require_once('locallib.php');
-
-$id = optional_param('id', 0, PARAM_INT); // Course Module ID, or
-$a = optional_param('a', 0, PARAM_INT); // scorm ID.
-$scoid = required_param('scoid', PARAM_INT); // sco ID.
-$mode = optional_param('mode', '', PARAM_ALPHA); // navigation mode.
-$currentorg = optional_param('currentorg', '', PARAM_RAW); // Selected organization.
-$attempt = required_param('attempt', PARAM_INT); // new attempt.
-
-if (!empty($id)) {
- $cm = get_coursemodule_from_id('scorm', $id, 0, false, MUST_EXIST);
- $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
- $scorm = $DB->get_record('scorm', array('id' => $cm->instance), '*', MUST_EXIST);
-} else if (!empty($a)) {
- $scorm = $DB->get_record('scorm', array('id' => $a), '*', MUST_EXIST);
- $course = $DB->get_record('course', array('id' => $scorm->course), '*', MUST_EXIST);
- $cm = get_coursemodule_from_instance('scorm', $scorm->id, $course->id, false, MUST_EXIST);
-} else {
- print_error('missingparameter');
-}
-
-$PAGE->set_url('/mod/scorm/loaddatamodel.php', array('scoid' => $scoid, 'id' => $cm->id));
-
-require_login($course, false, $cm);
-
-$userdata = new stdClass();
-if ($usertrack = scorm_get_tracks($scoid, $USER->id, $attempt)) {
- // According to SCORM 2004 spec(RTE V1, 4.2.8), only cmi.exit==suspend should allow previous datamodel elements on re-launch.
- if (!scorm_version_check($scorm->version, SCORM_13) ||
- (isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} == 'suspend'))) {
- foreach ($usertrack as $key => $value) {
- $userdata->$key = addslashes_js($value);
- }
- } else {
- $userdata->status = '';
- $userdata->score_raw = '';
- }
-} else {
- $userdata->status = '';
- $userdata->score_raw = '';
-}
-$userdata->student_id = addslashes_js($USER->username);
-$userdata->student_name = addslashes_js($USER->lastname .', '. $USER->firstname);
-$userdata->mode = 'normal';
-if (!empty($mode)) {
- $userdata->mode = $mode;
-}
-if ($userdata->mode == 'normal') {
- $userdata->credit = 'credit';
-} else {
- $userdata->credit = 'no-credit';
-}
-if ($scodatas = scorm_get_sco($scoid, SCO_DATA)) {
- foreach ($scodatas as $key => $value) {
- $userdata->$key = addslashes_js($value);
- }
-} else {
- print_error('cannotfindsco', 'scorm');
-}
-if (!$sco = scorm_get_sco($scoid)) {
- print_error('cannotfindsco', 'scorm');
-}
-if (scorm_version_check($scorm->version, SCORM_13)) {
- $objectives = $DB->get_records('scorm_seq_objective', array('scoid' => $scoid));
- $index = 0;
- foreach ($objectives as $objective) {
- if (!empty($objective->minnormalizedmeasure)) {
- $userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure;
- }
- if (!empty($objective->objectiveid)) {
- $userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid;
- $index++;
- }
- }
-}
-
-header('Content-Type: text/javascript; charset=UTF-8');
-
-$scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR)); // Just to be safe.
-if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php')) {
- include_once($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php');
-} else {
- include_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_12.js.php');
-}
-// Set the start time of this SCO.
-scorm_insert_track($USER->id, $scorm->id, $scoid, $attempt, 'x.start.time', time());
-?>
-
-
-var errorCode = "0";
-function underscore(str) {
- str = String(str).replace(/.N/g,".");
- return str.replace(/\./g,"__");
-}
* @param array $userdata User track data
* @param string $elementname Name of array element to get values for
* @param array $children list of sub elements of this array element that also need instantiating
- * @return None
+ * @return Javascript array elements
*/
function scorm_reconstitute_array_element($sversion, $userdata, $elementname, $children) {
// Reconstitute comments_from_learner and comments_from_lms.
$count = 0;
$countsub = 0;
$scormseperator = '_';
+ $return = '';
if (scorm_version_check($sversion, SCORM_13)) { // Scorm 1.3 elements use a . instead of an _ .
$scormseperator = '.';
}
}
if (count($matches) > 0 && $current != $matches[1]) {
if ($countsub > 0) {
- echo ' '.$elementname.$scormseperator.$current.'.'.$currentsubelement.'._count = '.$countsub.";\n";
+ $return .= ' '.$elementname.$scormseperator.$current.'.'.$currentsubelement.'._count = '.$countsub.";\n";
}
$current = $matches[1];
$count++;
$countsub = 0;
$end = strpos($element, $matches[1]) + strlen($matches[1]);
$subelement = substr($element, 0, $end);
- echo ' '.$subelement." = new Object();\n";
+ $return .= ' '.$subelement." = new Object();\n";
// now add the children
foreach ($children as $child) {
- echo ' '.$subelement.".".$child." = new Object();\n";
- echo ' '.$subelement.".".$child."._children = ".$child."_children;\n";
+ $return .= ' '.$subelement.".".$child." = new Object();\n";