.path-admin-tool-health dl.notice dd {
background-color: #e5db36;
}
-.path-admin-tool-health dt.solution,
-.path-admin-tool-health dd.solution,
+.path-admin-tool-health dl dt.solution,
+.path-admin-tool-health dl dd.solution,
.path-admin-tool-health div#healthnoproblemsfound {
- background-color: #5BB83E !important;
+ background-color: #5BB83E;
}
.path-admin-tool-health dl.healthissues dt,
.path-admin-tool-health dl.healthissues dd {
.tool-lp-menu li {
float: left;
- display: inline;
position: relative;
list-style-type: none;
white-space: nowrap;
};
// Add the event listeners.
- $('[data-region="list-templates"]').on('click', '[data-templatename]', function() {
+ $('[data-region="list-templates"]').on('click', '[data-templatename]', function(e) {
var templatename = $(this).data('templatename');
+ e.preventDefault();
loadTemplate(templatename);
});
#page-blocks-community-communitycourse .hubtext {display: block; width: 68%; padding-left: 165px;}
#page-blocks-community-communitycourse .hubimgandtext {display:table;}
#page-blocks-community-communitycourse .hubimage {float: left; display: block; width: 100px;}
-#page-blocks-community-communitycourse .hubdescriptiontext {}
#page-blocks-community-communitycourse .hubstats {padding-top: 10px}
#page-blocks-community-communitycourse .hubstats .iconhelp {float: left; padding-right: 3px;}
#page-blocks-community-communitycourse .hubadditionaldesc {color: #666666; font-size: 90%; display:block;}
#page-blocks-community-communitycourse .hubscreenshot {margin-right: 10px;}
-#page-blocks-community-communitycourse .hubnottrusted {}
#page-blocks-community-communitycourse .hubtrusted {display:inline;}
-#page-blocks-community-communitycourse .hubnottrusted {}
#page-blocks-community-communitycourse .trustedtr {background-color: #ffe1c3;}
#page-blocks-community-communitycourse .prioritisetr {background-color: #ffd4ff;}
#page-blocks-community-communitycourse .blockdescription {font-size: 80%; color: #555555;}
#page-blocks-community-communitycourse .comment-link {font-size: 80%; color: #555555;}
#page-blocks-community-communitycourse .coursescreenshot {text-align:center;cursor: pointer;}
#page-blocks-community-communitycourse .hubcourseinfo {margin-left: 15px;}
-#page-blocks-community-communitycourse .coursesitelink {}
#page-blocks-community-communitycourse .pagingbar {text-align: center;}
#page-blocks-community-communitycourse .coursecomment {float: right;}
#page-blocks-community-communitycourse .courseoperations {margin-top:9px; text-align:center}
font-size: 95%;
margin-bottom: 9px;
}
-#page-blocks-community-communitycourse .comment-list li {
- background-color:#FFFAFA !important;
- -moz-border-radius: 6px;
- -webkit-border-radius: 6px;
- padding-right: 4px;
- padding-bottom: 2px;
-}
/* STAR RATING */
#page-blocks-community-communitycourse .ratingcount {color: #8B8989;font-size: 80%;vertical-align: top;}
margin-top:15px;
}
#page-blocks-community-communitycourse .hubrateandcomment { font-size: 80%;}
-#page-blocks-community-communitycourse .hubcourseoutcomes {}
#page-blocks-community-communitycourse .nextlink {text-align: center;margin-top: 6px;}
#page-blocks-community-communitycourse .textinfo { text-align: center;}
} else if (!empty($options->courseid)) {
$this->courseid = $options->courseid;
} else {
- $this->courseid = SITEID;
+ if ($coursecontext = $this->context->get_course_context(false)) {
+ $this->courseid = $coursecontext->instanceid;
+ } else {
+ $this->courseid = SITEID;
+ }
}
// setup coursemodule
*/
public function config_form_display(&$mform, $data = null) {
$modnames = get_module_types_names();
- $mform->addElement('checkbox', 'criteria_activity['.$data->id.']',
- $modnames[self::get_mod_name($data->module)].
- ' - '.
- format_string($data->name));
+ $mform->addElement('advcheckbox',
+ 'criteria_activity['.$data->id.']',
+ $modnames[self::get_mod_name($data->module)] . ' - ' . format_string($data->name),
+ null,
+ array('group' => 1));
if ($this->id) {
$mform->setDefault('criteria_activity['.$data->id.']', 1);
$activities = $completion->get_activities();
if (!empty($activities)) {
+ if (!$completion->is_course_locked()) {
+ $this->add_checkbox_controller(1, null, null, 0);
+ }
foreach ($activities as $activity) {
$params_a = array('moduleinstance' => $activity->id);
$criteria = new completion_criteria_activity(array_merge($params, $params_a));
If this file exists it will be included in the CSS Moodle generates.
-
-Optional delete course hook
----------------------------
-
-* in your yourformat/lib.php add function format_yourformat_delete_course($courseid)
\ No newline at end of file
Then I should see "Use default section name [Topic 2]"
Scenario: Edit section summary in topics format
- When I edit the section "2"
- And I set the following fields to these values:
+ When I edit the section "2" and I fill the form with:
| Summary | Welcome to section 2 |
And I press "Save changes"
Then I should see "Welcome to section 2" in the "li#section-2" "css_element"
Scenario: Edit section default name in topics format
- When I edit the section "2"
- And I set the following fields to these values:
+ When I edit the section "2" and I fill the form with:
| Use default section name | 0 |
| name | This is the second topic |
And I press "Save changes"
Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
+=== 3.2 ===
+* Callback delete_course is deprecated and should be replaced with observer for event \core\event\course_content_deleted
+
=== 3.1 ===
* Course format may use the inplace_editable template to allow quick editing of section names, see
https://docs.moodle.org/dev/Inplace_editable and MDL-51802 for example implementation.
public function __construct(moodle_page $page, $target) {
$this->strings = new stdClass;
parent::__construct($page, $target);
- $this->add_modchoosertoggle();
}
/**
*
* Theme can overwrite as an empty function to exclude it (for example if theme does not
* use modchooser at all)
+ *
+ * @deprecated since 3.2
*/
protected function add_modchoosertoggle() {
+ debugging('core_course_renderer::add_modchoosertoggle() is deprecated.', DEBUG_DEVELOPER);
+
global $CFG;
// Only needs to be done once per page.
array(array('courseid' => $course->id, 'closeButtonTitle' => get_string('close', 'editor')))
);
$this->page->requires->strings_for_js(array(
- 'addresourceoractivity',
- 'modchooserenable',
- 'modchooserdisable',
+ 'addresourceoractivity'
), 'moodle');
// Add the header
/**
* Renders HTML for the menus to add activities and resources to the current course
*
- * Note, if theme overwrites this function and it does not use modchooser,
- * see also {@link core_course_renderer::add_modchoosertoggle()}
- *
* @param stdClass $course
* @param int $section relative section number (field course_sections.section)
* @param int $sectionreturn The section to link back to
public function i_edit_the_section_and_i_fill_the_form_with($sectionnumber, TableNode $data) {
// Edit given section.
- $this->execute("behat_course::i_edit_the_section");
+ $this->execute("behat_course::i_edit_the_section", $sectionnumber);
// Set form fields.
$this->execute("behat_forms::i_set_the_following_fields_to_these_values", $data);
$move = optional_param('move', 0, PARAM_INT);
$marker = optional_param('marker',-1 , PARAM_INT);
$switchrole = optional_param('switchrole',-1, PARAM_INT); // Deprecated, use course/switchrole.php instead.
- $modchooser = optional_param('modchooser', -1, PARAM_BOOL);
$return = optional_param('return', 0, PARAM_LOCALURL);
$params = array();
redirect($PAGE->url);
}
}
- if (($modchooser == 1) && confirm_sesskey()) {
- set_user_preference('usemodchooser', $modchooser);
- } else if (($modchooser == 0) && confirm_sesskey()) {
- set_user_preference('usemodchooser', $modchooser);
- }
if (has_capability('moodle/course:sectionvisibility', $context)) {
if ($hide && confirm_sesskey()) {
// Initialize existing sections and register for dynamically created sections
this.setup_for_section();
M.course.coursebase.register_module(this);
-
- // Catch the page toggle
- Y.all('.block_settings #settingsnav .type_course .modchoosertoggle a').on('click', this.toggle_mod_chooser, this);
},
/**
this.display_chooser(e);
},
- /**
- * Toggle availability of the activity chooser.
- *
- * @method toggle_mod_chooser
- * @param {EventFacade} e
- */
- toggle_mod_chooser : function(e) {
- // Get the add section link
- var modchooserlinks = Y.all('div.addresourcemodchooser');
-
- // Get the dropdowns
- var dropdowns = Y.all('div.addresourcedropdown');
-
- if (modchooserlinks.size() === 0) {
- // Continue with non-js action if there are no modchoosers to add
- return;
- }
-
- // We need to update the text and link
- var togglelink = Y.one('.block_settings #settingsnav .type_course .modchoosertoggle a');
-
- // The actual text is in the last child
- var toggletext = togglelink.get('lastChild');
-
- var usemodchooser;
- // Determine whether they're currently hidden
- if (modchooserlinks.item(0).hasClass('visibleifjs')) {
- // The modchooser is currently visible, hide it
- usemodchooser = 0;
- modchooserlinks
- .removeClass('visibleifjs')
- .addClass('hiddenifjs');
- dropdowns
- .addClass('visibleifjs')
- .removeClass('hiddenifjs');
- toggletext.set('data', M.util.get_string('modchooserenable', 'moodle'));
- togglelink.set('href', togglelink.get('href').replace('off', 'on'));
- } else {
- // The modchooser is currently not visible, show it
- usemodchooser = 1;
- modchooserlinks
- .addClass('visibleifjs')
- .removeClass('hiddenifjs');
- dropdowns
- .removeClass('visibleifjs')
- .addClass('hiddenifjs');
- toggletext.set('data', M.util.get_string('modchooserdisable', 'moodle'));
- togglelink.set('href', togglelink.get('href').replace('on', 'off'));
- }
-
- M.util.set_user_preference('usemodchooser', usemodchooser);
-
- // Prevent the page from reloading
- e.preventDefault();
- },
-
/**
* Helper function to set the value of a hidden radio button when a
* selection is made.
/**
* Filters
*/
-.mediaplugin_html5audio, .mediaplugin_html5video, .mediaplugin_swf, .mediaplugin_flv, .mediaplugin_real, .mediaplugin_youtube, .mediaplugin_vimeo, .mediaplugin_wmp, .mediaplugin_qt
- {display:block;margin-top:5px;margin-bottom:5px;text-align: center;}
-.mediaplugin.mediaplugin_mp3 object {display:inline;height:15px;width:180px;margin-left:0.5em;}
-
+.mediaplugin_html5audio,
+.mediaplugin_html5video,
+.mediaplugin_swf,
+.mediaplugin_flv,
+.mediaplugin_real,
+.mediaplugin_youtube,
+.mediaplugin_vimeo,
+.mediaplugin_wmp,
+.mediaplugin_qt {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ text-align: center;
+}
/*
* mp3 player colours -this read using JS and applied to swf audio flow player
* 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;
+}
.dir-rtl.path-grade-report-grader .gradeparent table {
border-left-width: 0;
border-right-width: 1px;
- max-width: initial;
}
/**
.path-grade-report-grader .yui3-overlay {
border: 0;
background: none;
- background-color: initial;
+ background-color: inherit;
min-width: 200px;
}
.path-grade-report-singleview .itemnav {
font-size: small;
display: inline;
- margin-bottom: 0.5em;
+ padding-bottom: 0.5em;
}
.path-grade-report-singleview itemnav.previtem {
float:left;
$string['computedfromlogs'] = 'Computed from logs since {$a}.';
$string['condifmodeditdefaults'] = 'Default values are used in the settings form when creating a new activity or resource.';
$string['confeditorhidebuttons'] = 'Select the buttons that should be hidden in the HTML editor.';
+$string['configenableactivitychooser'] = 'The activity chooser is a dialog box with a short description of each activity and resource. If disabled, separate resource and activity dropdown menus are provided instead.';
$string['configallcountrycodes'] = 'This is the list of countries that may be selected in various places, for example in a user\'s profile. If blank (the default) the list in countries.php in the standard English language pack is used. That is the list from ISO 3166-1. Otherwise, you can specify a comma-separated list of codes, for example \'GB,FR,ES\'. If you add new, non-standard codes here, you will need to add them to countries.php in \'en\' and your language pack.';
$string['configallowassign'] = 'You can allow people who have the roles on the left side to assign some of the column roles to other people';
$string['configallowblockstodock'] = 'If enabled and supported by the selected theme users can choose to move blocks to a special dock.';
* Alternative text (optional) - String identifier and component of the alternative text of the emoticon.';
$string['emoticonsreset'] = 'Reset emoticons setting to default values';
$string['emptysettingvalue'] = 'Empty';
+$string['enableactivitychooser'] = 'Enable activity chooser';
$string['enableblogs'] = 'Enable blogs';
$string['enablecalendarexport'] = 'Enable calendar export';
$string['enablecomments'] = 'Enable comments';
$string['update_onupdate'] = 'On update';
$string['user_activatenotsupportusertype'] = 'auth: ldap user_activate() does not support selected usertype: {$a}';
$string['user_disablenotsupportusertype'] = 'auth: ldap user_disable() does not support selected usertype (..yet)';
+$string['username'] = 'Username';
+$string['username_help'] = 'Please be aware that some authentication plugins will not allow you to change the username.';
settypeofficial,core_tag
filetoolarge,core
maxbytesforfile,core
+modchooserenable,core
+modchooserdisable,core
maxbytes,core_error
downloadcsv,core_table
downloadexcel,core_table
downloadods,core_table
downloadoptions,core_table
downloadtsv,core_table
-downloadxhtml,core_table
+downloadxhtml,core_table
\ No newline at end of file
$string['nativemariadb'] = 'MariaDB (native/mariadb)';
$string['nativemariadbhelp'] = '<p>The database is where most of the Moodle settings and data are stored and must be configured here.</p>
<p>The database name, username, and password are required fields; table prefix is optional.</p>
+<p>The database name may contain only alphanumeric characters, dollar ($) and underscore (_).</p>
<p>If the database currently does not exist, and the user you specify has permission, Moodle will attempt to create a new database with the correct permissions and settings.</p>
<p>This driver is not compatible with legacy MyISAM engine.</p>';
$string['nativemysqli'] = 'Improved MySQL (native/mysqli)';
$string['nativemysqlihelp'] = '<p>The database is where most of the Moodle settings and data are stored and must be configured here.</p>
<p>The database name, username, and password are required fields; table prefix is optional.</p>
+<p>The database name may contain only alphanumeric characters, dollar ($) and underscore (_).</p>
<p>If the database currently does not exist, and the user you specify has permission, Moodle will attempt to create a new database with the correct permissions and settings.</p>';
$string['nativemssql'] = 'SQL*Server FreeTDS (native/mssql)';
$string['nativemssqlhelp'] = 'Now you need to configure the database where most Moodle data will be stored.
$string['courseformatoptions'] = 'Formatting options for {$a}';
$string['courseformatudpate'] = 'Update format';
$string['courseprofiles'] = 'Course profiles';
+$string['coursepreferences'] = 'Course preferences';
$string['coursegrades'] = 'Course grades';
$string['coursehelpcategory'] = 'Position the course on the course listing and may make it easier for students to find it.';
$string['coursehelpforce'] = 'Force the course group mode to every activity in the course.';
$string['month'] = 'Month';
$string['months'] = 'Months';
$string['modified'] = 'Modified';
-$string['modchooserenable'] = 'Activity chooser on';
-$string['modchooserdisable'] = 'Activity chooser off';
$string['moduleintro'] = 'Description';
$string['modulesetup'] = 'Setting up module tables';
$string['modulesuccess'] = '{$a} tables have been set up correctly';
// Deprecated since Moodle 3.1.
$string['filetoolarge'] = 'is too large to upload';
$string['maxbytesforfile'] = 'The file {$a} is larger than the maximum size allowed.';
+
+// Deprecated since Moodle 3.2.
+$string['modchooserenable'] = 'Activity chooser on';
+$string['modchooserdisable'] = 'Activity chooser off';
\ No newline at end of file
* - large: 2560x1600
*
* @param string $windowsize size of window.
+ * @param bool $viewport If true, changes viewport rather than window size
* @throws ExpectationException
*/
- protected function resize_window($windowsize) {
+ protected function resize_window($windowsize, $viewport = false) {
// Non JS don't support resize window.
if (!$this->running_javascript()) {
return;
$width = (int) $size[0];
$height = (int) $size[1];
}
+ if ($viewport) {
+ // When setting viewport size, we set it so that the document width will be exactly
+ // as specified, assuming that there is a vertical scrollbar. (In cases where there is
+ // no scrollbar it will be slightly wider. We presume this is rare and predictable.)
+ // The window inner height will be as specified, which means the available viewport will
+ // actually be smaller if there is a horizontal scrollbar. We assume that horizontal
+ // scrollbars are rare so this doesn't matter.
+ $offset = $this->getSession()->getDriver()->evaluateScript(
+ 'return (function() { var before = document.body.style.overflowY;' .
+ 'document.body.style.overflowY = "scroll";' .
+ 'var result = {};' .
+ 'result.x = window.outerWidth - document.body.offsetWidth;' .
+ 'result.y = window.outerHeight - window.innerHeight;' .
+ 'document.body.style.overflowY = before;' .
+ 'return result; })();');
+ $width += $offset['x'];
+ $height += $offset['y'];
+ }
+
$this->getSession()->getDriver()->resizeWindow($width, $height);
}
}
}
+ /**
+ * Updates the provided users profile picture based upon the expected fields returned from the edit or edit_advanced forms.
+ *
+ * @param stdClass $usernew An object that contains some information about the user being updated
+ * @param array $filemanageroptions
+ * @return bool True if the user was updated, false if it stayed the same.
+ */
+ public static function update_picture(stdClass $usernew, $filemanageroptions = array()) {
+ global $CFG, $DB;
+ require_once("$CFG->libdir/gdlib.php");
+
+ $context = context_user::instance($usernew->id, MUST_EXIST);
+ $user = core_user::get_user($usernew->id, 'id, picture', MUST_EXIST);
+
+ $newpicture = $user->picture;
+ // Get file_storage to process files.
+ $fs = get_file_storage();
+ if (!empty($usernew->deletepicture)) {
+ // The user has chosen to delete the selected users picture.
+ $fs->delete_area_files($context->id, 'user', 'icon'); // Drop all images in area.
+ $newpicture = 0;
+
+ } else {
+ // Save newly uploaded file, this will avoid context mismatch for newly created users.
+ file_save_draft_area_files($usernew->imagefile, $context->id, 'user', 'newicon', 0, $filemanageroptions);
+ if (($iconfiles = $fs->get_area_files($context->id, 'user', 'newicon')) && count($iconfiles) == 2) {
+ // Get file which was uploaded in draft area.
+ foreach ($iconfiles as $file) {
+ if (!$file->is_directory()) {
+ break;
+ }
+ }
+ // Copy file to temporary location and the send it for processing icon.
+ if ($iconfile = $file->copy_content_to_temp()) {
+ // There is a new image that has been uploaded.
+ // Process the new image and set the user to make use of it.
+ // NOTE: Uploaded images always take over Gravatar.
+ $newpicture = (int)process_new_icon($context, 'user', 'icon', 0, $iconfile);
+ // Delete temporary file.
+ @unlink($iconfile);
+ // Remove uploaded file.
+ $fs->delete_area_files($context->id, 'user', 'newicon');
+ } else {
+ // Something went wrong while creating temp file.
+ // Remove uploaded file.
+ $fs->delete_area_files($context->id, 'user', 'newicon');
+ return false;
+ }
+ }
+ }
+
+ if ($newpicture != $user->picture) {
+ $DB->set_field('user', 'picture', $newpicture, array('id' => $user->id));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+
/**
* Definition of user profile fields and the expected parameter type for data validation.
*
echo $OUTPUT->notification($strdeleted.get_string('type_block_plural', 'plugin'), 'notifysuccess');
}
+ // Get the list of all modules that are properly installed.
+ $allmodules = $DB->get_records_menu('modules', array(), '', 'name, id');
+
// Delete every instance of every module,
// this has to be done before deleting of course level stuff.
$locations = core_component::get_plugin_list('mod');
if ($modname === 'NEWMODULE') {
continue;
}
- if ($module = $DB->get_record('modules', array('name' => $modname))) {
+ if (array_key_exists($modname, $allmodules)) {
+ $sql = "SELECT cm.*, m.id AS modinstance, m.name, '$modname' AS modname
+ FROM {".$modname."} m
+ LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid
+ WHERE m.course = :courseid";
+ $instances = $DB->get_records_sql($sql, array('courseid' => $course->id,
+ 'modulename' => $modname, 'moduleid' => $allmodules[$modname]));
+
include_once("$moddir/lib.php"); // Shows php warning only if plugin defective.
$moddelete = $modname .'_delete_instance'; // Delete everything connected to an instance.
$moddeletecourse = $modname .'_delete_course'; // Delete other stray stuff (uncommon).
- if ($instances = $DB->get_records($modname, array('course' => $course->id))) {
- foreach ($instances as $instance) {
- if ($cm = get_coursemodule_from_instance($modname, $instance->id, $course->id)) {
+ if ($instances) {
+ foreach ($instances as $cm) {
+ if ($cm->id) {
// Delete activity context questions and question categories.
question_delete_activity($cm, $showfeedback);
-
// Notify the competency subsystem.
\core_competency\api::hook_course_module_deleted($cm);
}
if (function_exists($moddelete)) {
// This purges all module data in related tables, extra user prefs, settings, etc.
- $moddelete($instance->id);
+ $moddelete($cm->modinstance);
} else {
// NOTE: we should not allow installation of modules with missing delete support!
debugging("Defective module '$modname' detected when deleting course contents: missing function $moddelete()!");
- $DB->delete_records($modname, array('id' => $instance->id));
+ $DB->delete_records($modname, array('id' => $cm->modinstance));
}
- if ($cm) {
+ if ($cm->id) {
// Delete cm and its context - orphaned contexts are purged in cron in case of any race condition.
context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
$DB->delete_records('course_modules', array('id' => $cm->id));
}
}
if (function_exists($moddeletecourse)) {
- // Execute ptional course cleanup callback.
+ // Execute optional course cleanup callback. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
+ debugging("Callback delete_course is deprecated. Function $moddeletecourse should be converted " .
+ 'to observer of event \core\event\course_content_deleted', DEBUG_DEVELOPER);
$moddeletecourse($course, $showfeedback);
}
if ($instances and $showfeedback) {
'coursemoduleid IN (SELECT id from {course_modules} WHERE course=?)',
array($courseid));
- // Remove course-module data.
+ // Remove course-module data that has not been removed in modules' _delete_instance callbacks.
$cms = $DB->get_records('course_modules', array('course' => $course->id));
+ $allmodulesbyid = array_flip($allmodules);
foreach ($cms as $cm) {
- if ($module = $DB->get_record('modules', array('id' => $cm->module))) {
+ if (array_key_exists($cm->module, $allmodulesbyid)) {
try {
- $DB->delete_records($module->name, array('id' => $cm->instance));
+ $DB->delete_records($allmodulesbyid[$cm->module], array('id' => $cm->instance));
} catch (Exception $e) {
// Ignore weird or missing table problems.
}
echo $OUTPUT->notification($strdeleted.get_string('type_mod_plural', 'plugin'), 'notifysuccess');
}
- // Cleanup the rest of plugins.
+ // Cleanup the rest of plugins. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6.
$cleanuplugintypes = array('report', 'coursereport', 'format');
$callbacks = get_plugins_with_function('delete_course', 'lib.php');
foreach ($cleanuplugintypes as $type) {
if (!empty($callbacks[$type])) {
foreach ($callbacks[$type] as $pluginfunction) {
+ debugging("Callback delete_course is deprecated. Function $pluginfunction should be converted " .
+ 'to observer of event \core\event\course_content_deleted', DEBUG_DEVELOPER);
$pluginfunction($course->id, $showfeedback);
}
- }
- if ($showfeedback) {
- echo $OUTPUT->notification($strdeleted.get_string('type_'.$type.'_plural', 'plugin'), 'notifysuccess');
+ if ($showfeedback) {
+ echo $OUTPUT->notification($strdeleted.get_string('type_'.$type.'_plural', 'plugin'), 'notifysuccess');
+ }
}
}
}
}
+ // Add "Course preferences" link.
+ if (isloggedin() && !isguestuser($user)) {
+ if ($currentuser && has_capability('moodle/user:editownprofile', $systemcontext) ||
+ has_capability('moodle/user:editprofile', $usercontext)) {
+ $url = new moodle_url('/user/course.php', array('id' => $user->id, 'course' => $course->id));
+ $useraccount->add(get_string('coursepreferences'), $url, self::TYPE_SETTING, null, 'coursepreferences');
+ }
+ }
+
// View the roles settings.
if (has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override',
'moodle/role:manage'), $usercontext)) {
* Change browser window size small: 640x480, medium: 1024x768, large: 2560x1600, custom: widthxheight
*
* Example: I change window size to "small" or I change window size to "1024x768"
+ * or I change viewport size to "800x600". The viewport option is useful to guarantee that the
+ * browser window has same viewport size even when you run Behat on multiple operating systems.
*
* @throws ExpectationException
- * @Then /^I change window size to "(small|medium|large|\d+x\d+)"$/
+ * @Then /^I change (window|viewport) size to "(small|medium|large|\d+x\d+)"$/
* @param string $windowsize size of the window (small|medium|large|wxh).
*/
- public function i_change_window_size_to($windowsize) {
- $this->resize_window($windowsize);
+ public function i_change_window_size_to($windowviewport, $windowsize) {
+ $this->resize_window($windowsize, $windowviewport === 'viewport');
}
/**
.dir-rtl .assignfeedback_editpdf_widget .commentdrawable a {
float: left;
- left: none;
right: -17px;
border-left: 0px;
border-right: 1px solid #ccc;
-
+/*csslint important:false */
#page-mod-book-print {
color: #000;
background-color: #fff;
-.path-mod-choice .results {border-collapse: separate;}
-.path-mod-choice .results .data {vertical-align:top;white-space: nowrap;}
-.path-mod-choice .button {text-align:center;}
-.path-mod-choice .attemptcell {width:5px;white-space: nowrap;}
+.path-mod-choice .results {
+ border-collapse: separate;
+}
+
+.path-mod-choice .results .data {
+ vertical-align: top;
+ white-space: nowrap;
+}
+
+.path-mod-choice .button {
+ text-align: center;
+}
+
+.path-mod-choice .attemptcell {
+ width: 5px;
+ white-space: nowrap;
+}
+
.path-mod-choice .anonymous,
-.path-mod-choice .names {margin-left:auto;margin-right:auto; width:80%;}
-.path-mod-choice .downloadreport {border-width:0;margin-left:10%;}
-.path-mod-choice .choiceresponse {width:100%;}
-.path-mod-choice .choiceresponse .picture {width:10px;white-space: nowrap;}
-.path-mod-choice .choiceresponse .fullname {width:100%;white-space: nowrap;}
+.path-mod-choice .names {
+ margin-left: auto;
+ margin-right: auto;
+ width: 80%;
+}
+
+.path-mod-choice .downloadreport {
+ border-width: 0;
+ margin-left: 10%;
+}
+
+.path-mod-choice .choiceresponse {
+ width: 100%;
+}
+
+.path-mod-choice .choiceresponse .picture {
+ width: 10px;
+ white-space: nowrap;
+}
+
+.path-mod-choice .choiceresponse .fullname {
+ width: 100%;
+ white-space: nowrap;
+}
-.path-mod-choice .responseheader {width: 100%; text-align: center; margin-top: 10px;}
-.path-mod-choice .choices .option label {vertical-align: top;}
-.path-mod-choice .choices .option input {vertical-align: middle;}
+.path-mod-choice .responseheader {
+ width: 100%;
+ text-align: center;
+ margin-top: 10px;
+}
+
+.path-mod-choice .choices .option label {
+ vertical-align: top;
+}
+
+.path-mod-choice .choices .option input {
+ vertical-align: middle;
+}
.path-mod-choice .horizontal,
-.path-mod-choice .vertical {margin-left: 10%;margin-right: 10%;}
-.path-mod-choice .horizontal .choices .option {padding-right: 20px; display: inline-block; white-space: normal;}
-.path-mod-choice .horizontal .choices .button {margin-top: 10px;}
-.path-mod-choice ul.choices li {list-style:none;}
-.path-mod-choice .results { text-align: center;}
-.path-mod-choice .results.anonymous .graph.horizontal {vertical-align: middle;text-align: left;width:70%;}
+.path-mod-choice .vertical {
+ margin-left: 10%;
+ margin-right: 10%;
+}
+
+.path-mod-choice .horizontal .choices .option {
+ padding-right: 20px;
+ display: inline-block;
+ white-space: normal;
+}
+
+.path-mod-choice .horizontal .choices .button {
+ margin-top: 10px;
+}
+
+.path-mod-choice ul.choices li {
+ list-style: none;
+}
+
+.path-mod-choice .results {
+ text-align: center;
+}
+
+.path-mod-choice .results.anonymous .graph.horizontal {
+ vertical-align: middle;
+ text-align: left;
+ width: 70%;
+}
.path-mod-choice .results.anonymous .graph.vertical,
-.path-mod-choice .cell {vertical-align: bottom; text-align: center; }
-.path-mod-choice .results.anonymous th.header {border: 1px solid inherit;}
+.path-mod-choice .cell {
+ vertical-align: bottom;
+ text-align: center;
+}
+
+.path-mod-choice .results.names .header {
+ width: 10%;
+ white-space: normal;
+}
+
+.path-mod-choice .results.names .cell {
+ vertical-align: top;
+ text-align: left;
+}
-.path-mod-choice .results.names .header{width:10%; white-space: normal;}
-.path-mod-choice .results.names .cell{vertical-align: top; text-align: left;}
.path-mod-choice .results.names .user,
-.path-mod-choice #yourselection {padding: 5px;}
+.path-mod-choice #yourselection {
+ padding: 5px;
+}
+
.path-mod-choice .results.names .user .attemptaction,
.path-mod-choice .results.names .user .image,
-.path-mod-choice .results.names .user .fullname{float:left;}
-.path-mod-choice .results.names .user .fullname{padding-left: 5px;}
-.path-mod-choice .results .data.header {width: 10%;}
-.path-mod-choice .responseaction {text-align: center;}
-.path-mod-choice .results .option {white-space: normal;}
-.path-mod-choice .response {overflow: auto;}
+.path-mod-choice .results.names .user .fullname {
+ float: left;
+}
+
+.path-mod-choice .results.names .user .fullname {
+ padding-left: 5px;
+}
+
+.path-mod-choice .results .data.header {
+ width: 10%;
+}
+
+.path-mod-choice .responseaction {
+ text-align: center;
+}
+
+.path-mod-choice .results .option {
+ white-space: normal;
+}
+
+.path-mod-choice .response {
+ overflow: auto;
+}
+
.path-mod-choice .results .option,
.path-mod-choice .results .numberofuser,
-.path-mod-choice .results .percentage {font-weight: bold; font-size: 108%;}
+.path-mod-choice .results .percentage {
+ font-weight: bold;
+ font-size: 108%;
+}
-#page-mod-choice-report .downloadreport ul li {list-style:none;padding: 0 20px; display: inline;float: left; }
-.path-mod-choice .clearfloat {float:none; clear:both;}
+#page-mod-choice-report .downloadreport ul li {
+ list-style: none;
+ padding: 0 20px;
+ float: left;
+}
+
+.path-mod-choice .clearfloat {
+ float: none;
+ clear: both;
+}
/**
* Override for RTL layout
*/
-.path-mod-choice.dir-rtl .horizontal .choices .option {padding-right:0px; padding-left: 20px; float:right;}
-.path-mod-choice.dir-rtl .results.anonymous .graph.horizontal {text-align: right;}
-.path-mod-choice.dir-rtl .results.anonymous { text-align: center; }
-.path-mod-choice.dir-rtl .results.names .cell{text-align: right;}
+.path-mod-choice.dir-rtl .horizontal .choices .option {
+ padding-right: 0px;
+ padding-left: 20px;
+ float: right;
+}
+
+.path-mod-choice.dir-rtl .results.anonymous .graph.horizontal {
+ text-align: right;
+}
+
+.path-mod-choice.dir-rtl .results.anonymous {
+ text-align: center;
+}
+
+.path-mod-choice.dir-rtl .results.names .cell {
+ text-align: right;
+}
+
.path-mod-choice.dir-rtl .results.names .user .attemptaction,
.path-mod-choice.dir-rtl .results.names .user .image,
.path-mod-choice.dir-rtl .results.names .user .fullname,
-.path-mod-choice.dir-rtl .results.names .user .fullname{padding-left: 0px; padding-right: 5px;}
-.path-mod-choice.dir-rtl .downloadreport {margin-left:0;margin-right: 25%;}
+.path-mod-choice.dir-rtl .results.names .user .fullname {
+ padding-left: 0px;
+ padding-right: 5px;
+}
+
+.path-mod-choice.dir-rtl .downloadreport {
+ margin-left: 0;
+ margin-right: 25%;
+}
+
+#page-mod-choice-report.dir-rtl .downloadreport ul li {
+ float: right;
+}
-#page-mod-choice-report.dir-rtl .downloadreport ul li{float:right;}
-#page-mod-choice-view.dir-rtl .reportlink {text-align: left;}
+#page-mod-choice-view.dir-rtl .reportlink {
+ text-align: left;
+}
.picturediv {
display: inline;
- width: 150px;
- height: 200px;
+ max-width: 150px;
+ max-height: 200px;
}
.inline {
#singleimage img {
width: 700px;
height: auto;
-}
\ 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/>.
+
+/**
+ * Event observers supported by this module
+ *
+ * @package mod_feedback
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Event observers supported by this module
+ *
+ * @package mod_feedback
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_feedback_observer {
+
+ /**
+ * Observer for the even course_content_deleted - delete all course templates.
+ *
+ * @param \core\event\course_content_deleted $event
+ */
+ public static function course_content_deleted(\core\event\course_content_deleted $event) {
+ global $DB;
+ // Delete all templates of given course.
+ $DB->delete_records('feedback_template', array('course' => $event->objectid));
+ }
+}
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * Displays the top level category or all courses
+ * Feedback event handler definition.
*
- * @package core_coure
- * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package mod_feedback
+ * @category event
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-require_once("../config.php");
+// List of observers.
+$observers = array(
-$categoryid = required_param('id', PARAM_INT); // Category id.
+ array(
+ 'eventname' => '\core\event\course_content_deleted',
+ 'callback' => 'mod_feedback_observer::course_content_deleted',
+ ),
-debugging('Please use URL /course/index.php?categoryid=XXX instead of /course/category.php?id=XXX', DEBUG_DEVELOPER);
-
-redirect(new moodle_url('/course/index.php', array('categoryid' => $categoryid)));
\ No newline at end of file
+);
return $DB->delete_records("feedback", array("id"=>$id));
}
-/**
- * this is called after deleting all instances if the course will be deleted.
- * only templates have to be deleted
- *
- * @global object
- * @param object $course
- * @return boolean
- */
-function feedback_delete_course($course) {
- global $DB;
-
- //delete all templates of given course
- return $DB->delete_records('feedback_template', array('course'=>$course->id));
-}
-
/**
* Return a small object with summary information about what a
* user has done with a given particular instance of this module
$this->assertContains("The 'anonymous' value must be set in other.", $e->getMessage());
}
}
+
+ /**
+ * Test that event observer is executed on course deletion and the templates are removed.
+ */
+ public function test_delete_course() {
+ global $DB;
+ $this->resetAfterTest();
+ feedback_save_as_template($this->eventfeedback, 'my template', 0);
+ $courseid = $this->eventcourse->id;
+ $this->assertNotEmpty($DB->get_records('feedback_template', array('course' => $courseid)));
+ delete_course($this->eventcourse, false);
+ $this->assertEmpty($DB->get_records('feedback_template', array('course' => $courseid)));
+ }
}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2016052300; // The current module version (Date: YYYYMMDDXX)
+$plugin->version = 2016061300; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2016051900; // Requires this Moodle version
$plugin->component = 'mod_feedback'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;
#page-mod-forum-discuss .discussioncontrol.exporttoportfolio {text-align:left;}
#page-mod-forum-discuss .discussioncontrol.displaymode {padding-right:10px;}
#page-mod-forum-discuss .discussioncontrol.movediscussion {padding-right:10px;}
-#page-mod-forum-discuss .discussioncontrol.movediscussion .movediscussionoption {}
/** Styles for view.php **/
#page-mod-forum-view .forumaddnew {margin-bottom: 20px;}
return $lesson->delete();
}
-/**
- * Given a course object, this function will clean up anything that
- * would be leftover after all the instances were deleted
- *
- * @global object
- * @param object $course an object representing the course that is being deleted
- * @param boolean $feedback to specify if the process must output a summary of its work
- * @return boolean
- */
-function lesson_delete_course($course, $feedback=true) {
- return true;
-}
-
/**
* Return a small object with summary information about what a
* user has done with a given particular instance of this module
return $DB->get_records_select('quiz_attempts',
"quiz $insql AND userid = :userid" . $previewclause . $statuscondition,
- $params, 'attempt ASC');
+ $params, 'quiz, attempt ASC');
}
/**
}
#page-mod-scorm-player #scormpage .scoframe {
- frameborder: 0;
+ border: 0;
}
#page-mod-scorm-player #scormpage #scorm_object {
This files describes API changes in /mod/* - activity modules,
information provided here is intended especially for developers.
+=== 3.2 ===
+
+* Callback delete_course is deprecated and should be replaced with observer for event \core\event\course_content_deleted
+
=== 3.1 ===
* Old /mod/MODULENAME/pix/icon.gif and enrol/paypal/pix/icon.gif GIF icons have been removed. Please use pix_icon
This files describes API changes in /report/* - plugins,
information provided here is intended especially for developers.
+=== 3.2 ===
+* Callback delete_course is deprecated and should be replaced with observer for event \core\event\course_content_deleted
+
=== 2.7 ===
* How to migrate reports accessing table 'log':
http://docs.moodle.org/dev/Migrating_log_access_in_reports
--- /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/>.
+
+/**
+ * Form to edit a users course preferences.
+ *
+ * These are stored as columns in the user table, which
+ * is why they are in /user and not /course or /admin.
+ *
+ * @copyright 2016 Joey Andres <jandres@ualberta.ca>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package core_user
+ */
+
+namespace core_user;
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
+}
+
+require_once($CFG->dirroot.'/lib/formslib.php');
+
+/**
+ * Class user_course_form.
+ *
+ * @copyright 2016 Joey Andres <jandres@ualberta.ca>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_form extends \moodleform {
+
+ /**
+ * Define the form.
+ */
+ public function definition () {
+ global $COURSE;
+
+ $mform = $this->_form;
+
+ $mform->addElement('advcheckbox',
+ 'enableactivitychooser',
+ get_string('enableactivitychooser', 'admin'),
+ get_string('configenableactivitychooser', 'admin'));
+ $mform->setDefault('enableactivitychooser',
+ get_user_preferences('usemodchooser', true, $this->_customdata['userid']));
+
+ // Add some extra hidden fields.
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+ $mform->addElement('hidden', 'course', $COURSE->id);
+ $mform->setType('course', PARAM_INT);
+
+ $this->add_action_buttons(true, get_string('savechanges'));
+ }
+}
\ 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/>.
+
+/**
+ * Allows you to edit course preference.
+ *
+ * @copyright 2016 Joey Andres <jandres@ualberta.ca>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package core_user
+ */
+
+require_once(__DIR__ . "/../config.php");
+require_once($CFG->dirroot.'/user/editlib.php');
+
+$userid = optional_param('id', $USER->id, PARAM_INT); // User id.
+$courseid = optional_param('course', SITEID, PARAM_INT); // Course id (defaults to Site).
+
+$PAGE->set_url('/user/course.php', array('id' => $userid, 'course' => $courseid));
+
+list($user, $course) = useredit_setup_preference_page($userid, $courseid);
+
+// Create form.
+$courseform = new core_user\course_form(null, array('userid' => $user->id));
+
+$courseform->set_data($user);
+
+$redirect = new moodle_url("/user/preferences.php", array('userid' => $user->id));
+if ($courseform->is_cancelled()) {
+ redirect($redirect);
+} else if ($data = $courseform->get_data()) {
+ set_user_preference('usemodchooser', $data->enableactivitychooser, $user);
+
+ redirect($redirect);
+}
+
+// Display page header.
+$streditmycourse = get_string('coursepreferences');
+$userfullname = fullname($user, true);
+
+$PAGE->navbar->includesettingsbase = true;
+
+$PAGE->set_title("$course->shortname: $streditmycourse");
+$PAGE->set_heading($userfullname);
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading($streditmycourse);
+
+// Finally display THE form.
+$courseform->display();
+
+// And proper footer.
+echo $OUTPUT->footer();
// Update user picture.
if (empty($CFG->disableuserimages)) {
- useredit_update_picture($usernew, $userform, $filemanageroptions);
+ core_user::update_picture($usernew, $filemanageroptions);
}
// Update mail bounces.
// Update user picture.
if (empty($USER->newadminuser)) {
- useredit_update_picture($usernew, $userform, $filemanageroptions);
+ core_user::update_picture($usernew, $filemanageroptions);
}
// Update mail bounces.
// Print the required moodle fields first.
$mform->addElement('header', 'moodle', $strgeneral);
- $mform->addElement('text', 'username', get_string('username'), 'size="20"');
- $mform->addRule('username', $strrequired, 'required', null, 'client');
- $mform->setType('username', core_user::get_property_type('username'));
-
$auths = core_component::get_plugin_list('auth');
$enabled = get_string('pluginenabled', 'core_plugin');
$disabled = get_string('plugindisabled', 'core_plugin');
$authoptions = array($enabled => array(), $disabled => array());
$cannotchangepass = array();
+ $cannotchangeusername = array();
foreach ($auths as $auth => $unused) {
$authinst = get_auth_plugin($auth);
+
+ if (!$authinst->is_internal()) {
+ $cannotchangeusername[] = $auth;
+ }
+
$passwordurl = $authinst->change_password_url();
if (!($authinst->can_change_password() && empty($passwordurl))) {
if ($userid < 1 and $authinst->is_internal()) {
$authoptions[$disabled][$auth] = get_string('pluginname', "auth_{$auth}");
}
}
+
+ $mform->addElement('text', 'username', get_string('username'), 'size="20"');
+ $mform->addHelpButton('username', 'username', 'auth');
+ $mform->setType('username', core_user::get_property_type('username'));
+ $mform->disabledIf('username', 'auth', 'in', $cannotchangeusername);
+
$mform->addElement('selectgroups', 'auth', get_string('chooseauthmethod', 'auth'), $authoptions);
$mform->addHelpButton('auth', 'chooseauthmethod', 'auth');
/**
* Updates the provided users profile picture based upon the expected fields returned from the edit or edit_advanced forms.
*
+ * @deprecated since Moodle 3.2 MDL-51789 - please use core_user::update_picture() instead.
+ * @todo MDL-54858 This will be deleted in Moodle 3.6.
+ * @see core_user::update_picture()
+ *
* @global moodle_database $DB
* @param stdClass $usernew An object that contains some information about the user being updated
- * @param moodleform $userform The form that was submitted to edit the form
+ * @param moodleform $userform The form that was submitted to edit the form (unused)
* @param array $filemanageroptions
* @return bool True if the user was updated, false if it stayed the same.
*/
function useredit_update_picture(stdClass $usernew, moodleform $userform, $filemanageroptions = array()) {
- global $CFG, $DB;
- require_once("$CFG->libdir/gdlib.php");
-
- $context = context_user::instance($usernew->id, MUST_EXIST);
- $user = $DB->get_record('user', array('id' => $usernew->id), 'id, picture', MUST_EXIST);
-
- $newpicture = $user->picture;
- // Get file_storage to process files.
- $fs = get_file_storage();
- if (!empty($usernew->deletepicture)) {
- // The user has chosen to delete the selected users picture.
- $fs->delete_area_files($context->id, 'user', 'icon'); // Drop all images in area.
- $newpicture = 0;
-
- } else {
- // Save newly uploaded file, this will avoid context mismatch for newly created users.
- file_save_draft_area_files($usernew->imagefile, $context->id, 'user', 'newicon', 0, $filemanageroptions);
- if (($iconfiles = $fs->get_area_files($context->id, 'user', 'newicon')) && count($iconfiles) == 2) {
- // Get file which was uploaded in draft area.
- foreach ($iconfiles as $file) {
- if (!$file->is_directory()) {
- break;
- }
- }
- // Copy file to temporary location and the send it for processing icon.
- if ($iconfile = $file->copy_content_to_temp()) {
- // There is a new image that has been uploaded.
- // Process the new image and set the user to make use of it.
- // NOTE: Uploaded images always take over Gravatar.
- $newpicture = (int)process_new_icon($context, 'user', 'icon', 0, $iconfile);
- // Delete temporary file.
- @unlink($iconfile);
- // Remove uploaded file.
- $fs->delete_area_files($context->id, 'user', 'newicon');
- } else {
- // Something went wrong while creating temp file.
- // Remove uploaded file.
- $fs->delete_area_files($context->id, 'user', 'newicon');
- return false;
- }
- }
- }
-
- if ($newpicture != $user->picture) {
- $DB->set_field('user', 'picture', $newpicture, array('id' => $user->id));
- return true;
- } else {
- return false;
- }
+ debugging('useredit_update_picture() is deprecated. Please use core_user::update_picture() instead.', DEBUG_DEVELOPER);
+ return core_user::update_picture($usernew, $filemanageroptions);
}
/**
new external_value(core_user::get_property_type('middlename'), 'The middle name of the user', VALUE_OPTIONAL),
'alternatename' =>
new external_value(core_user::get_property_type('alternatename'), 'The alternate name of the user', VALUE_OPTIONAL),
+ 'userpicture' =>
+ new external_value(PARAM_INT, 'The itemid where the new user picture '.
+ 'has been uploaded to, 0 to delete', VALUE_OPTIONAL),
'customfields' => new external_multiple_structure(
new external_single_structure(
array(
$params = self::validate_parameters(self::update_users_parameters(), array('users' => $users));
+ $filemanageroptions = array('maxbytes' => $CFG->maxbytes,
+ 'subdirs' => 0,
+ 'maxfiles' => 1,
+ 'accepted_types' => 'web_image');
+
$transaction = $DB->start_delegated_transaction();
foreach ($params['users'] as $user) {
user_update_user($user, true, false);
+
+ // Update user picture if it was specified for this user.
+ if (empty($CFG->disableuserimages) && isset($user['userpicture'])) {
+ $userobject = (object)$user;
+
+ $userobject->deletepicture = null;
+
+ if ($user['userpicture'] == 0) {
+ $userobject->deletepicture = true;
+ } else {
+ $userobject->imagefile = $user['userpicture'];
+ }
+
+ core_user::update_picture($userobject, $filemanageroptions);
+ }
+
// Update user custom fields.
if (!empty($user['customfields'])) {
--- /dev/null
+@core @core_user
+Feature: As a user, "Course preferences" allows me to set my course preference(s).
+ Background:
+ Given I log in as "admin"
+ And the following "courses" exist:
+ | fullname | shortname | format |
+ | Course 1 | C1 | topics |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | admin | C1 | editingteacher |
+ And I am on site homepage
+ And I follow "Preferences" in the user menu
+ And I follow "Course preferences"
+
+ @javascript
+ Scenario: As a user, "activity chooser" should be the default.
+ # See that the "activity chooser" is enabled by default.
+ Given the field "enableactivitychooser" matches value "1"
+ # See that the "activity chooser" is actually shown by default in course page.
+ When I am on homepage
+ And I follow "Course 1"
+ And I should not see "Add an activity or resource" in the "Topic 1" "section"
+ And I turn editing mode on
+ Then I should see "Add an activity or resource" in the "Topic 1" "section"
+ And I should not see "Add a resource..." in the "Topic 1" "section"
+
+ @javascript
+ Scenario: As a user, "activity chooser" should be disabled when I uncheck it in "Course preferences"
+ Given I set the field "enableactivitychooser" to "0"
+ And I press "Save changes"
+ When I am on homepage
+ And I follow "Course 1"
+ And I should not see "Add a resource..." in the "Topic 1" "section"
+ And I turn editing mode on
+ Then I should see "Add a resource..." in the "Topic 1" "section"
+ And I should not see "Add an activity or resource" in the "Topic 1" "section"
\ No newline at end of file
$this->resetAfterTest(true);
+ $wsuser = self::getDataGenerator()->create_user();
+ self::setUser($wsuser);
+
+ $context = context_user::instance($USER->id);
+ $contextid = $context->id;
+ $filename = "reddot.png";
+ $filecontent = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38"
+ . "GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
+
+ // Call the files api to create a file.
+ $draftfile = core_files_external::upload($contextid, 'user', 'draft', 0, '/',
+ $filename, $filecontent, null, null);
+ $draftfile = external_api::clean_returnvalue(core_files_external::upload_returns(), $draftfile);
+
+ $draftid = $draftfile['itemid'];
+
$user1 = self::getDataGenerator()->create_user();
$user1 = array(
'email' => 'usertest1@example.com',
'description' => 'This is a description for user 1',
'city' => 'Perth',
+ 'userpicture' => $draftid,
'country' => 'AU'
);
$this->assertEquals($dbuser->description, $user1['description']);
$this->assertEquals($dbuser->city, $user1['city']);
$this->assertEquals($dbuser->country, $user1['country']);
+ $this->assertNotEquals(0, $dbuser->picture, 'Picture must be set to the new icon itemid for this user');
+
+ // Confirm no picture change when parameter is not supplied.
+ unset($user1['userpicture']);
+ core_user_external::update_users(array($user1));
+ $dbusernopic = $DB->get_record('user', array('id' => $user1['id']));
+ $this->assertEquals($dbuser->picture, $dbusernopic->picture, 'Picture not change without the parameter.');
+
+ // Confirm delete of picture deletes the picture from the user record.
+ $user1['userpicture'] = 0;
+ core_user_external::update_users(array($user1));
+ $dbuserdelpic = $DB->get_record('user', array('id' => $user1['id']));
+ $this->assertEquals(0, $dbuserdelpic->picture, 'Picture must be deleted when sent as 0.');
+
// Call without required capability.
$this->unassignUserCapability('moodle/user:update', $context->id, $roleid);