$hide = optional_param('hide', 0, PARAM_INT);
$show = optional_param('show', 0, PARAM_INT);
$delete = optional_param('delete', 0, PARAM_INT);
+ $unprotect = optional_param('unprotect', 0, PARAM_INT);
+ $protect = optional_param('protect', 0, PARAM_INT);
/// Print headings
$strcourses = get_string('blockinstances', 'admin');
$strname = get_string('name');
$strshowblockcourse = get_string('showblockcourse');
+ $strprotecthdr = get_string('blockprotect', 'admin'). $OUTPUT->help_icon('blockprotect','admin');
+ $strprotect = get_string('blockprotect', 'admin');
+ $strunprotect = get_string('blockunprotect', 'admin');
/// If data submitted, then process and store.
admin_get_root(true, false); // settings not required - only pages
}
+ if (!isset($CFG->undeletableblocktypes) || (!is_array($CFG->undeletableblocktypes) && !is_string($CFG->undeletableblocktypes))) {
+ $undeletableblocktypes = array('navigation', 'settings');
+ } else if (is_string($CFG->undeletableblocktypes)) {
+ $undeletableblocktypes = explode(',', $CFG->undeletableblocktypes);
+ } else {
+ $undeletableblocktypes = $CFG->undeletableblocktypes;
+ }
+
+ if (!empty($protect) && confirm_sesskey()) {
+ if (!$block = $DB->get_record('block', array('id'=>$protect))) {
+ print_error('blockdoesnotexist', 'error');
+ }
+ if (!in_array($block->name, $undeletableblocktypes)) {
+ $undeletableblocktypes[] = $block->name;
+ set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
+ }
+ admin_get_root(true, false); // settings not required - only pages
+ }
+
+ if (!empty($unprotect) && confirm_sesskey()) {
+ if (!$block = $DB->get_record('block', array('id'=>$unprotect))) {
+ print_error('blockdoesnotexist', 'error');
+ }
+ if (in_array($block->name, $undeletableblocktypes)) {
+ $undeletableblocktypes = array_diff($undeletableblocktypes, array($block->name));
+ set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
+ }
+ admin_get_root(true, false); // settings not required - only pages
+ }
+
if (!empty($delete) && confirm_sesskey()) {
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
$table = new flexible_table('admin-blocks-compatible');
- $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'delete', 'settings'));
- $table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strdelete, $strsettings));
+ $table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'delete', 'settings'));
+ $table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strdelete, $strsettings));
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
$table->set_attribute('class', 'compatibleblockstable blockstable generaltable');
$table->setup();
$version = "$block->version ($plugin->version)";
}
+ if (!$blockobject) {
+ // ignore
+ $undeletable = '';
+ } else if (in_array($blockname, $undeletableblocktypes)) {
+ $undeletable = '<a href="blocks.php?unprotect='.$blockid.'&sesskey='.sesskey().'" title="'.$strunprotect.'">'.
+ '<img src="'.$OUTPUT->pix_url('t/unlock') . '" class="icon" alt="'.$strunprotect.'" /></a>';
+ } else {
+ $undeletable = '<a href="blocks.php?protect='.$blockid.'&sesskey='.sesskey().'" title="'.$strprotect.'">'.
+ '<img src="'.$OUTPUT->pix_url('t/unlock_gray') . '" class="icon" alt="'.$strprotect.'" /></a>';
+ }
$table->add_data(array(
'<span'.$class.'>'.$strblockname.'</span>',
$blocklist,
'<span'.$class.'>'.$version.'</span>',
$visible,
+ $undeletable,
$delete,
$settings
));
--adminuser=USERNAME Username for the moodle admin account. Default is admin.
--adminpass=PASSWORD Password for the moodle admin account.
--agree-license Indicates agreement with software license.
+--fullname Name of the site
+--shortname Name of the site
-h, --help Print out this help
Example:
'lang' => 'en',
'adminuser' => 'admin',
'adminpass' => '',
+ 'fullname' => '',
+ 'shortname' => '',
'agree-license' => false,
'help' => false
),
$temp->add(new admin_setting_configcheckbox('disableuserimages', get_string('disableuserimages', 'admin'), get_string('configdisableuserimages', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('emailchangeconfirmation', get_string('emailchangeconfirmation', 'admin'), get_string('configemailchangeconfirmation', 'admin'), 1));
$temp->add(new admin_setting_configselect('rememberusername', get_string('rememberusername','admin'), get_string('rememberusername_desc','admin'), 2, array(1=>get_string('yes'), 0=>get_string('no'), 2=>get_string('optional'))));
+ $temp->add(new admin_setting_configcheckbox('strictformsrequired', get_string('strictformsrequired', 'admin'), get_string('configstrictformsrequired', 'admin'), 0));
$ADMIN->add('security', $temp);
// attach format plugin structure to $module element, only one allowed
$this->add_plugin_structure('format', $module, false);
- // attach plagiarism plugin structure to $module element, only one allowed
- $this->add_plugin_structure('plagiarism', $module, false);
+ // attach plagiarism plugin structure to $module element, there can be potentially
+ // many plagiarism plugins storing information about this course
+ $this->add_plugin_structure('plagiarism', $module, true);
// Define the tree
$module->add_child($availinfo);
// course reports can save course data if required
$this->add_plugin_structure('coursereport', $course, true);
- // attach plagiarism plugin structure to $course element, only one allowed
- $this->add_plugin_structure('plagiarism', $course, false);
+ // attach plagiarism plugin structure to $course element, there can be potentially
+ // many plagiarism plugins storing information about this course
+ $this->add_plugin_structure('plagiarism', $course, true);
// Build the tree
// These blocks are used when no other default setting is found.
// $CFG->defaultblocks = 'participants,activity_modules,search_forums,admin,course_list:news_items,calendar_upcoming,recent_activity';
//
-// The blocks in this list will be protected from deletion, and this is primarily
-// used to protect the navigation and settings blocks which can be very hard to
-// get back if accidentally delete.
-// $CFG->undeletableblocktypes = 'navigation,settings';
-//
// You can specify a different class to be created for the $PAGE global, and to
// compute which blocks appear on each page. However, I cannot think of any good
// reason why you would need to change that. It just felt wrong to hard-code the
$string['flashanimation'] = 'Flash animation';
$string['flashanimation_help'] = 'Files with extension *.swf. For security reasons this filter is used only in trusted texts.';
$string['flashvideo'] = 'Flash video';
-$string['flashvideo_help'] = 'Files with extension *.flv and *.f4v. Plays video clips using Flowplayer, requires Flash plugin and javascript. Uses HTML 5 video fallback if multiple sources psecified.';
+$string['flashvideo_help'] = 'Files with extension *.flv and *.f4v. Plays video clips using Flowplayer, requires Flash plugin and javascript. Uses HTML 5 video fallback if multiple sources specified.';
$string['html5audio'] = 'HTML 5 audio';
$string['html5audio_help'] = 'Audio files with extension *.ogg, *.aac and others. It is compatible with latest web browsers only, unfortunately there is no format that is supported by all browsers.
Workaround is to specify fallbacks separated with # (ex: http://example.org/audio.aac#http://example.org/audio.aac#http://example.org/audio.mp3#), QuickTime player is used as a fallback for old browsers, fallback can be any audio type.';
* see http://flowplayer.org/documentation/skinning/controlbar.html?skin=default for more color properties,
* any property that ends with '...Color' is supported here.
*/
-.mp3flowplayer_backgroundColor {color: #000000};
+.mp3flowplayer_backgroundColor {color: #000000;}
$string['blockediplist'] = 'Blocked IP List';
$string['blockinstances'] = 'Instances';
$string['blockmultiple'] = 'Multiple';
+$string['blockprotect'] = 'Protect from delete';
+$string['blockprotect_help'] = 'Selected block instances will be protected from deletion from the site-wide context. This is primarily used to protect the navigation and settings blocks which can be very hard to get back if accidentally deleted.';
+$string['blockunprotect'] = 'Unprotect';
$string['blocksettings'] = 'Manage blocks';
$string['bloglevel'] = 'Blog visibility';
$string['bloglevelupgrade'] = 'Blog visibility upgrade';
$string['configstatsruntimedays'] = 'Specify the maximum number of days processed in each stats execution. When stats are up-to-date, only one day will be processed, so adjust this value depending of your server load, reducing it if shorter cron executions are needed.';
$string['configstatsruntimestart'] = 'What time should the cronjob that does the stats processing <b>start</b>? Please specify different times if there are multiple Moodles on one physical server.';
$string['configstatsuserthreshold'] = 'This setting specifies the minimum number of enrolled users for a course to be included in statistics calculations.';
+$string['configstrictformsrequired'] = 'If enabled, users are prevented from entering a space or line break only in required fields in forms.';
$string['configstripalltitletags'] = 'Uncheck this setting to allow HTML tags in activity and resource names.';
$string['configsupportemail'] = 'This email address will be published to users of this site as the one to email when they need general help (for example, when new users create their own accounts). If this email is left blank then no such helpful email address is supplied.';
$string['configsupportname'] = 'This is the name of a person or other entity offering general help via the support email or web address.';
$string['stickyblocksduplicatenotice'] = 'If any block you add here is already present in a particular page, it will result in a duplicate.<br />Only the pinned block will be non-editable, the duplicate will still be editable.';
$string['stickyblocksmymoodle'] = 'My Moodle';
$string['stickyblockspagetype'] = 'Page type to configure';
+$string['strictformsrequired'] = 'Strict validation of required fields';
$string['stripalltitletags'] = 'Remove HTML tags from all activity names';
$string['supportcontact'] = 'Support contact';
$string['supportemail'] = 'Support email';
$string['categorymove'] = 'The category \'{$a->name}\' contains {$a->count} questions (some of them may be old, hidden, questions that are still in use in some existing quizzes). Please choose another category to move them to.';
$string['categorymoveto'] = 'Save in category';
$string['categorynamecantbeblank'] = 'The category name cannot be blank.';
-$string['clicktoflag'] = 'Click to flag this question';
-$string['clicktounflag'] = 'Click to un-flag this question';
+$string['clickflag'] = 'Flag question';
+$string['clicktoflag'] = 'Flag this question for future reference';
+$string['clicktounflag'] = 'Remove flag';
+$string['clickunflag'] = 'Remove flag';
$string['contexterror'] = 'You shouldn\'t have got here if you\'re not moving a category to another context.';
$string['copy'] = 'Copy from {$a} and change links.';
$string['created'] = 'Created';
$string['changeoptions'] = 'Change options';
$string['check'] = 'Check';
$string['clearwrongparts'] = 'Clear incorrect responses';
-$string['clicktoflag'] = 'Click to flag this question';
-$string['clicktounflag'] = 'Click to un-flag this question';
$string['closepreview'] = 'Close preview';
$string['combinedfeedback'] = 'Combined feedback';
$string['commented'] = 'Commented: {$a}';
global $CFG;
if (!isset($CFG->undeletableblocktypes) || (!is_array($CFG->undeletableblocktypes) && !is_string($CFG->undeletableblocktypes))) {
- $CFG->undeletableblocktypes = array('navigation','settings');
+ $undeletableblocktypes = array('navigation','settings');
} else if (is_string($CFG->undeletableblocktypes)) {
- $CFG->undeletableblocktypes = explode(',', $CFG->undeletableblocktypes);
+ $undeletableblocktypes = explode(',', $CFG->undeletableblocktypes);
+ } else {
+ $undeletableblocktypes = $CFG->undeletableblocktypes;
}
$controls = array();
}
if ($this->page->user_can_edit_blocks() && $block->user_can_edit() && $block->user_can_addto($this->page)) {
- if (!in_array($block->instance->blockname, $CFG->undeletableblocktypes)) {
+ if (!in_array($block->instance->blockname, $undeletableblocktypes)
+ || !in_array($block->instance->pagetypepattern, array('*', 'site-index'))
+ || $block->instance->parentcontextid != SITEID) {
// Delete icon.
$controls[] = array('url' => $actionurl . '&bui_deleteid=' . $block->instance->id,
'icon' => 't/delete', 'caption' => get_string('delete'));
require_once 'HTML/QuickForm.php';
require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
require_once 'HTML/QuickForm/Renderer/Tableless.php';
+require_once 'HTML/QuickForm/Rule.php';
require_once $CFG->libdir.'/filelib.php';
}
}
+/**
+ * Required elements validation
+ * This class overrides QuickForm validation since it allowed space or empty tag as a value
+ */
+class MoodleQuickForm_Rule_Required extends HTML_QuickForm_Rule {
+ /**
+ * Checks if an element is not empty.
+ * This is a server-side validation, it works for both text fields and editor fields
+ *
+ * @param string $value Value to check
+ * @param mixed $options Not used yet
+ * @return boolean true if value is not empty
+ */
+ function validate($value, $options = null) {
+ global $CFG;
+ if (is_array($value) && array_key_exists('text', $value)) {
+ $value = $value['text'];
+ }
+ $stripvalues = array(
+ '#</?(?!img|canvas|hr).*?>#im', // all tags except img, canvas and hr
+ '#(\xc2|\xa0|\s| )#', //any whitespaces actually
+ );
+ if (!empty($CFG->strictformsrequired)) {
+ $value = preg_replace($stripvalues, '', (string)$value);
+ }
+ if ((string)$value == '') {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This function returns Javascript code used to build client-side validation.
+ * It checks if an element is not empty.
+ * Note, that QuickForm does not know how to work with editor text field and builds not correct
+ * JS code for validation. If client check is enabled for editor field it will not be validated
+ * on client side no matter what this function returns.
+ *
+ * @param mixed $options Not used yet
+ * @return array
+ */
+ function getValidationScript($options = null) {
+ global $CFG;
+ if (!empty($CFG->strictformsrequired)) {
+ return array('', "{jsVar}.replace(/^\s+$/g, '') == ''");
+ } else {
+ return array('', "{jsVar} == ''");
+ }
+ }
+}
+
/**
* @global object $GLOBALS['_HTML_QuickForm_default_renderer']
* @name $_HTML_QuickForm_default_renderer
MoodleQuickForm::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'MoodleQuickForm_textarea');
MoodleQuickForm::registerElementType('url', "$CFG->libdir/form/url.php", 'MoodleQuickForm_url');
MoodleQuickForm::registerElementType('warning', "$CFG->libdir/form/warning.php", 'MoodleQuickForm_warning');
+
+MoodleQuickForm::registerRule('required', null, 'MoodleQuickForm_Rule_Required', "$CFG->libdir/formslib.php");
)
);
$this->add_yui2_modules(); // adds loading info for all YUI2 modules
- $this->js_module($this->find_module('core_filepicker'));
$this->js_module($this->find_module('core_dock'));
// YUI3 init code
$values[] = $this->getSubmitValue($elName);
}
$result = $registry->validate($rule['type'], $values, $rule['format'], true);
- } else if ($rule['type'] === 'required' and $this->getElement($target)->_type === 'editor') {
- //horrible horrible hack
- if (!isset($submitValue['text']) or $submitValue['text'] === '') {
- $result = false;
- } else {
- $result = true;
- }
} elseif (is_array($submitValue) && !isset($rule['howmany'])) {
$result = $registry->validate($rule['type'], $submitValue, $rule['format'], true);
} else {
4/ MDL-20876 - replaced deprecated split() with explode() or str_split() where appropriate
-5/ hardcoded editor element required rule validation
-
Such modifications should be carefully each time the Excel PEAR package is updated
to a new release within Moodle.
--- /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/>.
+
+
+/**
+ * Unit tests for /lib/formslib.php.
+ *
+ * @package file
+ * @copyright 2011 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+}
+require_once($CFG->libdir . '/formslib.php');
+
+class formslib_test extends UnitTestCase {
+
+ public function test_require_rule() {
+ global $CFG;
+
+ $strictformsrequired = false;
+ if (!empty($CFG->strictformsrequired)) {
+ $strictformsrequired = $CFG->strictformsrequired;
+ }
+
+ $rule = new MoodleQuickForm_Rule_Required();
+
+ // First run the tests with strictformsrequired off
+ $CFG->strictformsrequired = false;
+ // Passes
+ $this->assertTrue($rule->validate('Something'));
+ $this->assertTrue($rule->validate("Something\nmore"));
+ $this->assertTrue($rule->validate("\nmore"));
+ $this->assertTrue($rule->validate(" more "));
+ $this->assertTrue($rule->validate("0"));
+ $this->assertTrue($rule->validate(0));
+ $this->assertTrue($rule->validate(true));
+ $this->assertTrue($rule->validate(' '));
+ $this->assertTrue($rule->validate(' '));
+ $this->assertTrue($rule->validate("\t"));
+ $this->assertTrue($rule->validate("\n"));
+ $this->assertTrue($rule->validate("\r"));
+ $this->assertTrue($rule->validate("\r\n"));
+ $this->assertTrue($rule->validate(" \t \n \r "));
+ $this->assertTrue($rule->validate('<p></p>'));
+ $this->assertTrue($rule->validate('<p> </p>'));
+ $this->assertTrue($rule->validate('<p>x</p>'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile" />'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"/>'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"></img>'));
+ $this->assertTrue($rule->validate('<hr />'));
+ $this->assertTrue($rule->validate('<hr/>'));
+ $this->assertTrue($rule->validate('<hr>'));
+ $this->assertTrue($rule->validate('<hr></hr>'));
+ $this->assertTrue($rule->validate('<br />'));
+ $this->assertTrue($rule->validate('<br/>'));
+ $this->assertTrue($rule->validate('<br>'));
+ $this->assertTrue($rule->validate(' '));
+ // Fails
+ $this->assertFalse($rule->validate(''));
+ $this->assertFalse($rule->validate(false));
+ $this->assertFalse($rule->validate(null));
+
+ // Now run the same tests with it on to make sure things work as expected
+ $CFG->strictformsrequired = true;
+ // Passes
+ $this->assertTrue($rule->validate('Something'));
+ $this->assertTrue($rule->validate("Something\nmore"));
+ $this->assertTrue($rule->validate("\nmore"));
+ $this->assertTrue($rule->validate(" more "));
+ $this->assertTrue($rule->validate("0"));
+ $this->assertTrue($rule->validate(0));
+ $this->assertTrue($rule->validate(true));
+ $this->assertTrue($rule->validate('<p>x</p>'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile" />'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"/>'));
+ $this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"></img>'));
+ $this->assertTrue($rule->validate('<hr />'));
+ $this->assertTrue($rule->validate('<hr/>'));
+ $this->assertTrue($rule->validate('<hr>'));
+ $this->assertTrue($rule->validate('<hr></hr>'));
+ // Fails
+ $this->assertFalse($rule->validate(' '));
+ $this->assertFalse($rule->validate(' '));
+ $this->assertFalse($rule->validate("\t"));
+ $this->assertFalse($rule->validate("\n"));
+ $this->assertFalse($rule->validate("\r"));
+ $this->assertFalse($rule->validate("\r\n"));
+ $this->assertFalse($rule->validate(" \t \n \r "));
+ $this->assertFalse($rule->validate('<p></p>'));
+ $this->assertFalse($rule->validate('<p> </p>'));
+ $this->assertFalse($rule->validate('<br />'));
+ $this->assertFalse($rule->validate('<br/>'));
+ $this->assertFalse($rule->validate('<br>'));
+ $this->assertFalse($rule->validate(' '));
+ $this->assertFalse($rule->validate(''));
+ $this->assertFalse($rule->validate(false));
+ $this->assertFalse($rule->validate(null));
+
+ $CFG->strictformsrequired = $strictformsrequired;
+ }
+
+}
\ No newline at end of file
gc_collect_cycles(); // This was really helpful in PHP 5.2. Perhaps remove.
$a = new stdClass();
$a->done = $done;
- $a->todo = $outof;
+ $a->outof = $outof;
$this->progressbar->update($done, $outof,
get_string('resettingquizattemptsprogress', 'local_qeupgradehelper', $a));
}
*
* @param mixed $frm submitted form data
* @param bool $showicontext show text next to action icons?
- * @param object $user1 the current user
+ * @param object $currentuser the current user
* @return void
*/
-function message_print_search_results($frm, $showicontext=false, $user1=null) {
+function message_print_search_results($frm, $showicontext=false, $currentuser=null) {
global $USER, $DB, $OUTPUT;
- if (empty($user1)) {
- $user1 = $USER;
+ if (empty($currentuser)) {
+ $currentuser = $USER;
}
echo html_writer::start_tag('div', array('class' => 'mdl-left'));
echo message_get_fragment($message->fullmessage, $keywords);
echo html_writer::start_tag('div', array('class' => 'link'));
- //find the user involved that isn't the current user
- $user2id = null;
- if ($user1->id == $message->useridto) {
- $user2id = $message->useridfrom;
+ //If the user clicks the context link display message sender on the left
+ //EXCEPT if the current user is in the conversation. Current user == always on the left
+ $leftsideuserid = $rightsideuserid = null;
+ if ($currentuser->id == $message->useridto) {
+ $leftsideuserid = $message->useridto;
+ $rightsideuserid = $message->useridfrom;
} else {
- $user2id = $message->useridto;
+ $leftsideuserid = $message->useridfrom;
+ $rightsideuserid = $message->useridto;
}
- message_history_link($user1->id, $user2id, false,
+ message_history_link($leftsideuserid, $rightsideuserid, false,
$messagesearchstring, 'm'.$message->id, $strcontext);
echo html_writer::end_tag('div');
echo html_writer::end_tag('td');
* echo or return a link to take the user to the full message history between themselves and another user
*
* @staticvar type $strmessagehistory
- * @param int $userid1 the ID of the current user
+ * @param int $userid1 the ID of the user displayed on the left (usually the current user)
* @param int $userid2 the ID of the other user
* @param bool $return true to return the link as a string. False to echo the link.
* @param string $keywords any keywords to highlight in the message history
*/
function message_history_link($userid1, $userid2, $return=false, $keywords='', $position='', $linktext='') {
global $OUTPUT;
-
static $strmessagehistory;
if (empty($strmessagehistory)) {
'scrollbars' => true,
'resizable' => true);
- $link = new moodle_url('/message/index.php?history='.MESSAGE_HISTORY_ALL."&user=$userid1&id=$userid2$keywords$position");
+ $link = new moodle_url('/message/index.php?history='.MESSAGE_HISTORY_ALL."&user1=$userid1&user2=$userid2$keywords$position");
$action = null;
$str = $OUTPUT->action_link($link, $fulllink, $action, array('title' => $strmessagehistory));
$string['existingfiledeleted'] = 'Existing file has been deleted: {$a}';
$string['failedupdatefeedback'] = 'Failed to update submission feedback for user {$a}';
$string['feedback'] = 'Feedback';
-$string['feedbackfromteacher'] = 'Feedback from the {$a}';
+$string['feedbackfromteacher'] = 'Feedback from {$a}';
$string['feedbackupdated'] = 'Submissions feedback updated for {$a} people';
$string['finalize'] = 'Prevent submission updates';
$string['finalizeerror'] = 'An error occurred and that submission could not be finalised';
$pbar = new progress_bar('q15upgrade');
$pbar->create();
$a = new stdClass();
- $a->todo = count($oldattempts);
+ $a->outof = count($oldattempts);
$a->done = 0;
- $pbar->update($a->done, $a->todo,
+ $pbar->update($a->done, $a->outof,
get_string('upgradingveryoldquizattempts', 'quiz', $a));
foreach ($oldattempts as $oldattempt) {
quiz_upgrade_very_old_question_sessions($oldattempt);
$a->done += 1;
- $pbar->update($a->done, $a->todo,
+ $pbar->update($a->done, $a->outof,
get_string('upgradingveryoldquizattempts', 'quiz', $a));
}
}
$reordercheckboxlabel = '<label for="s' . $question->id . '">';
$reordercheckboxlabelclose = '</label>';
}
- if (!$quiz->shufflequestions) {
- // Print and increment question number
- $questioncountstring = '';
- if ($questioncount>999 || ($reordertool && $questioncount>99)) {
- $questioncountstring =
- "$reordercheckboxlabel<small>$questioncount</small>" .
- $reordercheckboxlabelclose . $reordercheckbox;
+ if ($question->length == 0) {
+ $qnodisplay = get_string('infoshort', 'quiz');
+ } else if ($quiz->shufflequestions) {
+ $qnodisplay = '?';
+ } else {
+ if ($qno > 999 || ($reordertool && $qno > 99)) {
+ $qnodisplay = html_writer::tag('small', $qno);
} else {
- $questioncountstring = $reordercheckboxlabel . $questioncount .
- $reordercheckboxlabelclose . $reordercheckbox;
+ $qnodisplay = $qno;
}
- echo $questioncountstring;
$qno += $question->length;
- } else {
- echo "$reordercheckboxlabel ? $reordercheckboxlabelclose" .
- " $reordercheckbox";
}
+ echo $reordercheckboxlabel . $qnodisplay . $reordercheckboxlabelclose .
+ $reordercheckbox;
?>
</div>
$string['allattempts'] = 'Show all attempts';
$string['allattemptscontributetograde'] = 'All attempts contribute to final grade for user.';
$string['allstudents'] = 'Show all {$a}';
-$string['attemptprogress'] = 'Attempt {$a->done} of {$a->todo}';
$string['attemptsonly'] = 'Show {$a} with attempts only';
$string['attemptsprepage'] = 'Attempts shown per page';
$string['deleteselected'] = 'Delete selected attempts';
$string['preferencespage'] = 'Preferences just for this page';
$string['preferencessave'] = 'Show report';
$string['preferencesuser'] = 'Your preferences for this report';
-$string['qprogress'] = 'Question {$a->done} of {$a->todo}';
$string['regrade'] = 'Regrade';
$string['regradeall'] = 'Regrade all';
$string['regradealldry'] = 'Dry run a full regrade';
// Back to overview link.
echo $OUTPUT->box('<a href="' . $reporturl->out() . '">' .
get_string('backtoquizreport', 'quiz_statistics') . '</a>',
- 'boxaligncenter generalbox boxwidthnormal mdl-align');
+ 'backtomainstats boxaligncenter generalbox boxwidthnormal mdl-align');
} else if ($qid) {
// Report on an individual sub-question indexed questionid.
echo $OUTPUT->box(format_text($question->questiontext, $question->questiontextformat,
array('overflowdiv' => true)) . $actions,
- 'boxaligncenter generalbox boxwidthnormal mdl-align');
+ 'questiontext boxaligncenter generalbox boxwidthnormal mdl-align');
echo $OUTPUT->heading(get_string('questionstatistics', 'quiz_statistics'));
echo html_writer::table($questionstatstable);
.ie6#page-mod-quiz-edit div.question div.content .questionname {width:20%;}
.ie6#page-mod-quiz-edit .editq div.question div.content .randomquestioncategory a{width:40%;}
.ie6#page-mod-quiz-edit .reorder .questioncontentcontainer .randomquestioncategory label{width: 35%;}
+.qnum label {padding-right: 0.25em;}
/** settings.php */
#adminquizreviewoptions {margin-bottom: 0.5em;}
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="mod/scorm/db" VERSION="20090420" COMMENT="XMLDB file for Moodle mod/scorm"
+<XMLDB PATH="mod/scorm/db" VERSION="20110731" COMMENT="XMLDB file for Moodle mod/scorm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="scoid"/>
<FIELD NAME="scoid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="primaryobj"/>
<FIELD NAME="primaryobj" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="scoid" NEXT="objectiveid"/>
- <FIELD NAME="objectiveid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="primaryobj" NEXT="satisfiedbymeasure"/>
+ <FIELD NAME="objectiveid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="primaryobj" NEXT="satisfiedbymeasure"/>
<FIELD NAME="satisfiedbymeasure" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" PREVIOUS="objectiveid" NEXT="minnormalizedmeasure"/>
<FIELD NAME="minnormalizedmeasure" TYPE="float" LENGTH="11" NOTNULL="true" UNSIGNED="true" DEFAULT="0.0000" SEQUENCE="false" DECIMALS="4" PREVIOUS="satisfiedbymeasure"/>
</FIELDS>
</KEYS>
</TABLE>
</TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
unset_config('updatetime', 'scorm');
upgrade_mod_savepoint(true, 2011021402, 'scorm');
}
+
+ if ($oldversion < 2011073100) {
+ // change field type of objectiveid
+ $table = new xmldb_table('scorm_seq_objective');
+ $field = new xmldb_field('objectiveid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'primaryobj');
+ $dbman->change_field_type($table, $field);
+ upgrade_main_savepoint(true, 2011073100, 'scorm');
+ }
return true;
}
$string['whatgradedesc'] = 'This preference sets the default attempts grading';
$string['width'] = 'Width';
$string['window'] = 'Window';
-$string['zlibwarning'] = 'Warning: PHP Zlib compression has been enabled on this site, some users may experience issues loading SCORM objects in certain web browsers.';
if (! $cm = get_coursemodule_from_instance('scorm', $scorm->id, $course->id)) {
print_error('invalidcoursemodule');
}
+ $contextmodule = get_context_instance(CONTEXT_MODULE, $cm->id);
+ if ((has_capability('mod/scorm:skipview', $contextmodule))) {
+ scorm_simple_play($scorm, $user, $contextmodule);
+ }
$colspan = '';
$headertext = '<table width="100%"><tr><td class="title">'.get_string('name').': <b>'.format_string($scorm->name).'</b>';
if (has_capability('moodle/course:manageactivities', $context)) {
}
if ($scorm->skipview >= 1) {
$sco = current($scoes);
- if (scorm_get_tracks($sco->id, $user->id) === false) {
- header('Location: player.php?a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$orgidentifier);
- $result = true;
- } else if ($scorm->skipview == 2) {
- header('Location: player.php?a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$orgidentifier);
- $result = true;
+ $url = new moodle_url('/mod/scorm/player.php', array('a' => $scorm->id,
+ 'currentorg'=>$orgidentifier,
+ 'scoid'=>$sco->id));
+ if ($scorm->skipview == 2 || scorm_get_tracks($sco->id, $user->id) === false) {
+ redirect($url);
}
}
}
if (!$CFG->slasharguments) {
$mform->addElement('static', '', '', $OUTPUT->notification(get_string('slashargs', 'scorm'), 'notifyproblem'));
}
- $zlib = ini_get('zlib.output_compression'); //check for zlib compression - if used, throw error because of IE bug. - SEE MDL-16185
- if (isset($zlib) && $zlib) {
- $mform->addElement('static', '', '', $OUTPUT->notification(get_string('zlibwarning', 'scorm'), 'notifyproblem'));
- }
//-------------------------------------------------------------------------------
$mform->addElement('header', 'general', get_string('general', 'form'));
}
scorm_layout_widget.setStyle('height', '100%');
+ var center = scorm_layout_widget.getUnitByPosition('center');
+ center.setStyle('height', '100%');
+
+ // calculate the rough new height
+ newheight = YAHOO.util.Dom.getViewportHeight() *.82;
+ if (newheight < 600) {
+ newheight = 600;
+ }
+ scorm_layout_widget.set('height', newheight);
+
scorm_layout_widget.render();
scorm_resize_frame();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-$module->version = 2011060500; // The (date) version of this module
+$module->version = 2011073100; // The (date) version of this module
$module->requires = 2010080300; // The version of Moodle that is required
$module->cron = 300; // How often should cron check this module (seconds)?
add_to_log($course->id, 'scorm', 'pre-view', 'view.php?id='.$cm->id, "$scorm->id", $cm->id);
-if ((has_capability('mod/scorm:skipview', $contextmodule)) && scorm_simple_play($scorm, $USER, $contextmodule)) {
- exit;
+if ((has_capability('mod/scorm:skipview', $contextmodule))) {
+ scorm_simple_play($scorm, $USER, $contextmodule);
}
//
'requires' => array('base', 'dom', 'event-delegate', 'io-base'),
);
$actionurl = $CFG->wwwroot . '/question/toggleflag.php';
+ $flagtext = array(
+ 0 => get_string('clickflag', 'question'),
+ 1 => get_string('clickunflag', 'question')
+ );
$flagattributes = array(
0 => array(
'src' => $OUTPUT->pix_url('i/unflagged') . '',
'title' => get_string('clicktoflag', 'question'),
'alt' => get_string('notflagged', 'question'),
+ // 'text' => get_string('clickflag', 'question'),
),
1 => array(
'src' => $OUTPUT->pix_url('i/flagged') . '',
'title' => get_string('clicktounflag', 'question'),
'alt' => get_string('flagged', 'question'),
+ // 'text' => get_string('clickunflag', 'question'),
),
);
$PAGE->requires->js_init_call('M.core_question_flags.init',
- array($actionurl, $flagattributes), false, $module);
+ array($actionurl, $flagattributes, $flagtext), false, $module);
$done = true;
}
}
* @return string the img tag.
*/
protected function get_flag_html($flagged, $id = '') {
+ if ($flagged) {
+ $icon = 'i/flagged';
+ $alt = get_string('flagged', 'question');
+ } else {
+ $icon = 'i/unflagged';
+ $alt = get_string('notflagged', 'question');
+ }
+ $attributes = array(
+ 'src' => $this->pix_url($icon),
+ 'alt' => $alt,
+ );
if ($id) {
- $id = 'id="' . $id . '" ';
+ $attributes['id'] = $id;
}
+ $img = html_writer::empty_tag('img', $attributes);
if ($flagged) {
- $img = 'flagged';
- } else {
- $img = 'unflagged';
+ $img .= ' ' . get_string('flagged', 'question');
}
- return '<img ' . $id . 'src="' . $this->pix_url('/i/' . $img) .
- '" alt="' . get_string('flagthisquestion', 'question') . '" />';
+ return $img;
}
protected function edit_question_link(question_attempt $qa,
M.core_question_flags = {
flagattributes: null,
actionurl: null,
+ flagtext: null,
listeners: [],
- init: function(Y, actionurl, flagattributes) {
+ init: function(Y, actionurl, flagattributes, flagtext) {
M.core_question_flags.flagattributes = flagattributes;
M.core_question_flags.actionurl = actionurl;
+ M.core_question_flags.flagtext = flagtext;
Y.all('div.questionflag').each(function(flagdiv, i) {
var checkbox = flagdiv.one('input[type=checkbox]');
return;
}
- var input = Y.Node.create('<input type="hidden" />');
+ var input = Y.Node.create('<input type="hidden" class="questionflagvalue" />');
input.set('id', checkbox.get('id'));
input.set('name', checkbox.get('name'));
input.set('value', checkbox.get('checked') ? 1 : 0);
// Create an image input to replace the img tag.
var image = Y.Node.create('<input type="image" class="questionflagimage" />');
- M.core_question_flags.update_flag(input, image);
+ var flagtext = Y.Node.create('<span class="questionflagtext">.</span>');
+ M.core_question_flags.update_flag(input, image, flagtext);
checkbox.remove();
flagdiv.one('label').remove();
flagdiv.append(input);
flagdiv.append(image);
+ flagdiv.append(flagtext);
});
Y.delegate('click', function(e) {
- var input = this.previous('input');
+ var input = this.one('input.questionflagvalue');
input.set('value', 1 - input.get('value'));
- M.core_question_flags.update_flag(input, this);
- var postdata = this.previous('input.questionflagpostdata').get('value') +
+ M.core_question_flags.update_flag(input, this.one('input.questionflagimage'),
+ this.one('span.questionflagtext'));
+ var postdata = this.one('input.questionflagpostdata').get('value') +
input.get('value');
e.halt();
Y.io(M.core_question_flags.actionurl , {method: 'POST', 'data': postdata});
M.core_question_flags.fire_listeners(postdata);
- }, document.body, 'input.questionflagimage');
+ }, document.body, 'div.questionflag');
},
- update_flag: function(input, image) {
- image.setAttrs(M.core_question_flags.flagattributes[input.get('value')]);
+ update_flag: function(input, image, flagtext) {
+ var value = input.get('value');
+ image.setAttrs(M.core_question_flags.flagattributes[value]);
+ flagtext.replaceChild(flagtext.create(M.core_question_flags.flagtext[value]),
+ flagtext.get('firstChild'));
+ flagtext.set('title', M.core_question_flags.flagattributes[value].title);
},
add_listener: function(listener) {
} else {
// Must be the first line of a new question, since no recognised prefix.
$question->qtype = MULTICHOICE;
- $question->name = htmlspecialchars(substr($nowline, 0, 50));
- $question->questiontext = htmlspecialchars($nowline);
+ $question->name = shorten_text(s($nowline), 50);
+ $question->questiontext = s($nowline);
$question->single = 1;
$question->feedback[] = '';
}
foreach ($xml->entry as $entry) {
$media = $entry->children('http://search.yahoo.com/mrss/');
$title = $media->group->title;
- $attrs = $media->group->thumbnail->attributes();
+ $attrs = $media->group->thumbnail[2]->attributes();
$thumbnail = $attrs['url'];
$arr = explode('/', $entry->id);
$id = $arr[count($arr)-1];
.que {clear: left;text-align: left;margin: 0 auto 1.8em auto;}
.dir-rtl .que {text-align: right;}
-.que .info {float: left;width: 6em;padding:0.5em;margin-bottom: 1.8em;background: #eee;}
+.que .info {float: left;width: 7em;padding:0.5em;margin-bottom: 1.8em;background: #eee;}
.que h2.no {margin: 0;font-size: 0.8em;line-height: 1;}
.que span.qno {font-size: 1.5em;font-weight:bold;}
-.que .state,
-.que .grade,
-.que .editquestion {font-size: 0.8em; margin-top: 0.7em;}
-.que .info .questionflag {margin-top: 1em;margin-right: 1em;text-align: center;}
+.que .info * {font-size: 0.8em;}
+.que .info .state,
+.que .info .grade,
+.que .info .editquestion,
+.que .info .questionflag {margin-top: 0.7em;}
+.que .info .questionflag {cursor:pointer;}
-.que .content {margin: 0 0 0 7.5em;}
+.que .content {margin: 0 0 0 8.5em;}
.que .formulation,
.que .outcome,