Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of https://github.com/moodle/moodle

  • Loading branch information...
commit b0b6ead6b9648b2c4d59dc548052ecaf7e3ffc3e 2 parents 3e01e06 + 3294034
@pcharsle pcharsle authored
Showing with 1,256 additions and 289 deletions.
  1. +211 −0 admin/cli/mysql_collation.php
  2. +30 −5 admin/roles/check.php
  3. +4 −0 admin/settings/grades.php
  4. +1 −0  auth/shibboleth/login.php
  5. +12 −4 backup/moodle2/backup_stepslib.php
  6. +28 −12 backup/moodle2/restore_stepslib.php
  7. +3 −1 blocks/blog_recent/block_blog_recent.php
  8. +1 −1  blocks/completionstatus/block_completionstatus.php
  9. +1 −1  blog/index.php
  10. +0 −8 calendar/lib.php
  11. +1 −1  course/completion_form.php
  12. +2 −2 course/delete.php
  13. +1 −1  course/dndupload.js
  14. +3 −7 course/editsection.php
  15. +185 −4 course/externallib.php
  16. +17 −15 course/format/renderer.php
  17. +27 −21 course/lib.php
  18. +1 −1  enrol/authorize/index.php
  19. +5 −1 enrol/database/tests/adodb_test.php
  20. +1 −1  filter/tex/latex.php
  21. +1 −1  filter/tex/texdebug.php
  22. +25 −11 grade/export/lib.php
  23. +1 −1  grade/export/ods/export.php
  24. +21 −22 grade/export/ods/grade_export_ods.php
  25. +1 −1  grade/export/ods/index.php
  26. +1 −1  grade/export/txt/export.php
  27. +31 −13 grade/export/txt/grade_export_txt.php
  28. +1 −1  grade/export/txt/index.php
  29. +1 −1  grade/export/xls/export.php
  30. +20 −21 grade/export/xls/grade_export_xls.php
  31. +1 −1  grade/export/xls/index.php
  32. +135 −2 grade/lib.php
  33. +5 −0 install/lang/ca/install.php
  34. +1 −0  install/lang/is/admin.php
  35. +1 −1  install/lang/is/langconfig.php
  36. +3 −3 install/lang/pt/admin.php
  37. +3 −4 lang/en/completion.php
  38. +1 −1  lang/en/error.php
  39. +4 −0 lang/en/grades.php
  40. +0 −1  lang/en/notes.php
  41. +2 −0  lang/en/role.php
  42. +56 −0 lib/accesslib.php
  43. +2 −2 lib/completion/completion_criteria_course.php
  44. +3 −2 lib/completion/cron.php
  45. +4 −4 lib/db/install.xml
  46. +9 −0 lib/db/services.php
  47. +47 −20 lib/ddl/mysql_sql_generator.php
  48. +93 −13 lib/dml/mysqli_native_moodle_database.php
  49. +1 −0  lib/form/yui/dateselector/assets/skins/sam/dateselector.css
  50. +24 −1 lib/form/yui/dateselector/dateselector.js
  51. +22 −14 lib/formslib.php
  52. +19 −6 lib/javascript-static.js
  53. +1 −0  lib/navigationlib.php
  54. +9 −1 lib/yui/formchangechecker/formchangechecker.js
  55. +1 −1  mod/assign/lang/en/assign.php
  56. +2 −5 mod/assign/locallib.php
  57. +2 −2 mod/assign/settings.php
  58. +1 −1  mod/assignment/lib.php
  59. +28 −0 mod/assignment/type/online/assignment.class.php
  60. +2 −2 mod/chat/gui_ajax/module.js
  61. +4 −2 mod/choice/renderer.php
  62. +1 −1  mod/data/export.php
  63. +55 −1 mod/forum/lib.php
  64. +3 −0  mod/forum/mod_form.php
  65. +5 −0 mod/forum/post.php
  66. +1 −1  mod/quiz/module.js
  67. +20 −2 mod/quiz/renderer.php
  68. +8 −13 mod/quiz/report/overview/report.php
  69. +4 −5 mod/quiz/report/statistics/report.php
  70. +1 −1  mod/quiz/version.php
  71. +1 −1  notes/externallib.php
  72. +2 −2 plagiarism/lib.php
  73. +2 −0  portfolio/googledocs/lib.php
  74. +2 −0  portfolio/picasa/lib.php
  75. +2 −2 question/type/shortanswer/backup/moodle2/restore_qtype_shortanswer_plugin.class.php
  76. +1 −1  repository/filepicker.js
  77. +2 −0  repository/googledocs/lib.php
  78. +2 −0  repository/picasa/lib.php
  79. +1 −1  theme/base/style/course.css
  80. +1 −1  theme/base/style/filemanager.css
  81. +17 −7 user/lib.php
  82. +2 −2 version.php
View
211 admin/cli/mysql_collation.php
@@ -0,0 +1,211 @@
+<?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/>.
+
+/**
+ * MySQL collation conversion tool.
+ *
+ * @package core
+ * @copyright 2012 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+
+require(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once($CFG->libdir.'/clilib.php'); // cli only functions
+
+if ($DB->get_dbfamily() !== 'mysql') {
+ cli_error('This function is designed for MySQL databases only!');
+}
+
+// now get cli options
+list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'collation'=>false, 'available'=>false),
+ array('h'=>'help', 'l'=>'list', 'a'=>'available'));
+
+if ($unrecognized) {
+ $unrecognized = implode("\n ", $unrecognized);
+ cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
+}
+
+$help =
+ "MySQL collation conversions script.
+
+It is strongly recommended to stop the web server before the conversion.
+This script may be executed before the main upgrade - 1.9.x data for example.
+
+Options:
+--collation=COLLATION Convert MySQL tables to different collation
+-l, --list Show table and column information
+-a, --available Show list of available collations
+-h, --help Print out this help
+
+Example:
+\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8_general_ci
+";
+
+if (!empty($options['collation'])) {
+ $collations = mysql_get_collations();
+ $collation = clean_param($options['collation'], PARAM_ALPHANUMEXT);
+ $collation = strtolower($collation);
+ if (!isset($collations[$collation])) {
+ cli_error("Error: collation '$collation' is not available on this server!");
+ }
+
+ echo "Converting tables and columns to '$collation' for $CFG->wwwroot:\n";
+ $prefix = $DB->get_prefix();
+ $prefix = str_replace('_', '\\_', $prefix);
+ $sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
+ $rs = $DB->get_recordset_sql($sql);
+ $converted = 0;
+ $skipped = 0;
+ $errors = 0;
+ foreach ($rs as $table) {
+ echo str_pad($table->name, 40). " - ";
+
+ if ($table->collation === $collation) {
+ echo "NO CHANGE\n";
+ $skipped++;
+
+ } else {
+ $DB->change_database_structure("ALTER TABLE $table->name DEFAULT COLLATE = $collation");
+ echo "CONVERTED\n";
+ $converted++;
+ }
+
+ $sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
+ $rs2 = $DB->get_recordset_sql($sql);
+ foreach ($rs2 as $column) {
+ $column = (object)array_change_key_case((array)$column, CASE_LOWER);
+ echo ' '.str_pad($column->field, 36). " - ";
+ if ($column->collation === $collation) {
+ echo "NO CHANGE\n";
+ $skipped++;
+ continue;
+ }
+
+ if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text' or $column->type === 'longtext') {
+ $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
+ $default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
+ // primary, unique and inc are not supported for texts
+ $sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
+ $DB->change_database_structure($sql);
+
+ } else if (strpos($column->type, 'varchar') === 0) {
+ $notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
+ $default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
+ // primary, unique and inc are not supported for texts
+ $sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
+ $DB->change_database_structure($sql);
+ } else {
+ echo "ERROR (unknown column type: $column->type)\n";
+ $error++;
+ continue;
+ }
+ echo "CONVERTED\n";
+ $converted++;
+ }
+ $rs2->close();
+ }
+ $rs->close();
+ echo "Converted: $converted, skipped: $skipped, errors: $errors\n";
+ exit(0); // success
+
+} else if (!empty($options['list'])) {
+ echo "List of tables for $CFG->wwwroot:\n";
+ $prefix = $DB->get_prefix();
+ $prefix = str_replace('_', '\\_', $prefix);
+ $sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
+ $rs = $DB->get_recordset_sql($sql);
+ $counts = array();
+ foreach ($rs as $table) {
+ if (isset($counts[$table->collation])) {
+ $counts[$table->collation]++;
+ } else {
+ $counts[$table->collation] = 1;
+ }
+ echo str_pad($table->name, 40);
+ echo $table->collation. "\n";
+ $collations = mysql_get_column_collations($table->name);
+ foreach ($collations as $columname=>$collation) {
+ if (isset($counts[$collation])) {
+ $counts[$collation]++;
+ } else {
+ $counts[$collation] = 1;
+ }
+ echo ' ';
+ echo str_pad($columname, 36);
+ echo $collation. "\n";
+ }
+ }
+ $rs->close();
+
+ echo "\n";
+ echo "Table collations summary for $CFG->wwwroot:\n";
+ foreach ($counts as $collation => $count) {
+ echo "$collation: $count\n";
+ }
+ exit(0); // success
+
+} else if (!empty($options['available'])) {
+ echo "List of available MySQL collations for $CFG->wwwroot:\n";
+ $collations = mysql_get_collations();
+ foreach ($collations as $collation) {
+ echo " $collation\n";
+ }
+ die;
+
+} else {
+ echo $help;
+ die;
+}
+
+
+
+// ========== Some functions ==============
+
+function mysql_get_collations() {
+ global $DB;
+
+ $collations = array();
+ $sql = "SHOW COLLATION WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'";
+ $rs = $DB->get_recordset_sql($sql);
+ foreach ($rs as $collation) {
+ $collations[$collation->collation] = $collation->collation;
+ }
+ $rs->close();
+
+ $collation = $DB->get_dbcollation();
+ if (isset($collations[$collation])) {
+ $collations[$collation] .= ' (default)';
+ }
+
+ return $collations;
+}
+
+function mysql_get_column_collations($tablename) {
+ global $DB;
+
+ $collations = array();
+ $sql = "SELECT column_name, collation_name
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE table_schema = DATABASE() AND table_name = ? AND collation_name IS NOT NULL";
+ $rs = $DB->get_recordset_sql($sql, array($tablename));
+ foreach($rs as $record) {
+ $collations[$record->column_name] = $record->collation_name;
+ }
+ $rs->close();
+ return $collations;
+}
View
35 admin/roles/check.php
@@ -104,20 +104,45 @@
break;
}
+// Get the list of the reported-on user's role assignments - must be after
+// the page setup code above, or the language might be wrong.
+$reportuser = $userselector->get_selected_user();
+if (!is_null($reportuser)) {
+ $roleassignments = get_user_roles_with_special($context, $reportuser->id);
+ $rolenames = role_get_names($context);
+}
+
echo $OUTPUT->header();
-// These are needed early because of tabs.php
-$assignableroles = get_assignable_roles($context, ROLENAME_BOTH);
-$overridableroles = get_overridable_roles($context, ROLENAME_BOTH);
// Print heading.
echo $OUTPUT->heading($title);
// If a user has been chosen, show all the permissions for this user.
-$reportuser = $userselector->get_selected_user();
if (!is_null($reportuser)) {
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
- echo $OUTPUT->heading(get_string('permissionsforuser', 'role', fullname($reportuser)), 3);
+ if (!empty($roleassignments)) {
+ echo $OUTPUT->heading(get_string('rolesforuser', 'role', fullname($reportuser)), 3);
+ echo html_writer::start_tag('ul');
+
+ $systemcontext = context_system::instance();
+ foreach ($roleassignments as $ra) {
+ $racontext = context::instance_by_id($ra->contextid);
+ $link = html_writer::link($racontext->get_url(), $racontext->get_context_name());
+
+ $rolename = $rolenames[$ra->roleid]->localname;
+ if (has_capability('moodle/role:manage', $systemcontext)) {
+ $rolename = html_writer::link(new moodle_url('/admin/roles/define.php',
+ array('action' => 'view', 'roleid' => $ra->roleid)), $rolename);
+ }
+
+ echo html_writer::tag('li', get_string('roleincontext', 'role',
+ array('role' => $rolename, 'context' => $link)));
+ }
+ echo html_writer::end_tag('ul');
+ }
+
+ echo $OUTPUT->heading(get_string('permissionsforuser', 'role', fullname($reportuser)), 3);
$table = new check_capability_table($context, $reportuser, $contextname);
$table->display();
echo $OUTPUT->box_end();
View
4 admin/settings/grades.php
@@ -58,6 +58,10 @@
GRADE_NAVMETHOD_TABS => new lang_string('tabs', 'grades'),
GRADE_NAVMETHOD_COMBO => new lang_string('combo', 'grades'))));
+ $temp->add(new admin_setting_configtext('grade_export_userprofilefields', new lang_string('gradeexportuserprofilefields', 'grades'), new lang_string('gradeexportuserprofilefields_desc', 'grades'), 'firstname,lastname,idnumber,institution,department,email', PARAM_TEXT));
+
+ $temp->add(new admin_setting_configtext('grade_export_customprofilefields', new lang_string('gradeexportcustomprofilefields', 'grades'), new lang_string('gradeexportcustomprofilefields_desc', 'grades'), null, PARAM_TEXT));
+
$temp->add(new admin_setting_configcheckbox('recovergradesdefault', new lang_string('recovergradesdefault', 'grades'), new lang_string('recovergradesdefault_help', 'grades'), 0));
$temp->add(new admin_setting_special_gradeexport());
View
1  auth/shibboleth/login.php
@@ -63,6 +63,7 @@
$loginsite = get_string("loginsite");
$PAGE->set_url('/auth/shibboleth/login.php');
+ $PAGE->set_context(context_system::instance());
$PAGE->navbar->add($loginsite);
$PAGE->set_title("$site->fullname: $loginsite");
$PAGE->set_heading($site->fullname);
View
16 backup/moodle2/backup_stepslib.php
@@ -323,7 +323,7 @@ protected function define_structure() {
$availability = new backup_nested_element('availability', array('id'), array(
'sourcecmid', 'requiredcompletion', 'gradeitemid', 'grademin', 'grademax'));
$availabilityfield = new backup_nested_element('availability_field', array('id'), array(
- 'userfield', 'customfieldid', 'operator', 'value'));
+ 'userfield', 'customfield', 'customfieldtype', 'operator', 'value'));
// attach format plugin structure to $module element, only one allowed
$this->add_plugin_structure('format', $module, false);
@@ -346,7 +346,11 @@ protected function define_structure() {
WHERE cm.id = ?', array(backup::VAR_MODID));
$availability->set_source_table('course_modules_availability', array('coursemoduleid' => backup::VAR_MODID));
- $availabilityfield->set_source_table('course_modules_avail_fields', array('coursemoduleid' => backup::VAR_MODID));
+ $availabilityfield->set_source_sql('
+ SELECT cmaf.*, uif.shortname AS customfield, uif.datatype AS customfieldtype
+ FROM {course_modules_avail_fields} cmaf
+ LEFT JOIN {user_info_field} uif ON uif.id = cmaf.customfieldid
+ WHERE cmaf.coursemoduleid = ?', array(backup::VAR_MODID));
// Define annotations
$module->annotate_ids('grouping', 'groupingid');
@@ -377,14 +381,18 @@ protected function define_structure() {
$avail = new backup_nested_element('availability', array('id'), array(
'sourcecmid', 'requiredcompletion', 'gradeitemid', 'grademin', 'grademax'));
$availfield = new backup_nested_element('availability_field', array('id'), array(
- 'userfield', 'customfieldid', 'operator', 'value'));
+ 'userfield', 'operator', 'value', 'customfield', 'customfieldtype'));
$section->add_child($avail);
$section->add_child($availfield);
// Define sources
$section->set_source_table('course_sections', array('id' => backup::VAR_SECTIONID));
$avail->set_source_table('course_sections_availability', array('coursesectionid' => backup::VAR_SECTIONID));
- $availfield->set_source_table('course_sections_avail_fields', array('coursesectionid' => backup::VAR_SECTIONID));
+ $availfield->set_source_sql('
+ SELECT csaf.*, uif.shortname AS customfield, uif.datatype AS customfieldtype
+ FROM {course_sections_avail_fields} csaf
+ LEFT JOIN {user_info_field} uif ON uif.id = csaf.customfieldid
+ WHERE csaf.coursesectionid = ?', array(backup::VAR_SECTIONID));
// Aliases
$section->set_source_alias('section', 'number');
View
40 backup/moodle2/restore_stepslib.php
@@ -1139,18 +1139,26 @@ public function process_availability_field($data) {
$data = (object)$data;
// Mark it is as passed by default
$passed = true;
- // Ok, if it is a profile field we need to check it exists
- if (!is_null($data->customfieldid)) {
- if (!$DB->record_exists('user_info_field', array('id' => $data->customfieldid))) {
- $passed = false;
- }
+ $customfieldid = null;
+
+ // If a customfield has been used in order to pass we must be able to match an existing
+ // customfield by name (data->customfield) and type (data->customfieldtype)
+ if (is_null($data->customfield) xor is_null($data->customfieldtype)) {
+ // xor is sort of uncommon. If either customfield is null or customfieldtype is null BUT not both.
+ // If one is null but the other isn't something clearly went wrong and we'll skip this condition.
+ $passed = false;
+ } else if (!is_null($data->customfield)) {
+ $params = array('shortname' => $data->customfield, 'datatype' => $data->customfieldtype);
+ $customfieldid = $DB->get_field('user_info_field', 'id', $params);
+ $passed = ($customfieldid !== false);
}
+
if ($passed) {
// Create the object to insert into the database
$availfield = new stdClass();
$availfield->coursesectionid = $this->task->get_sectionid();
$availfield->userfield = $data->userfield;
- $availfield->customfieldid = $data->customfieldid;
+ $availfield->customfieldid = $customfieldid;
$availfield->operator = $data->operator;
$availfield->value = $data->value;
$DB->insert_record('course_sections_avail_fields', $availfield);
@@ -2637,18 +2645,26 @@ protected function process_availability_field($data) {
$data = (object)$data;
// Mark it is as passed by default
$passed = true;
- // Ok, if it is a profile field we need to check it exists
- if (!is_null($data->customfieldid)) {
- if (!$DB->record_exists('user_info_field', array('id' => $data->customfieldid))) {
- $passed = false;
- }
+ $customfieldid = null;
+
+ // If a customfield has been used in order to pass we must be able to match an existing
+ // customfield by name (data->customfield) and type (data->customfieldtype)
+ if (!empty($data->customfield) xor !empty($data->customfieldtype)) {
+ // xor is sort of uncommon. If either customfield is null or customfieldtype is null BUT not both.
+ // If one is null but the other isn't something clearly went wrong and we'll skip this condition.
+ $passed = false;
+ } else if (!empty($data->customfield)) {
+ $params = array('shortname' => $data->customfield, 'datatype' => $data->customfieldtype);
+ $customfieldid = $DB->get_field('user_info_field', 'id', $params);
+ $passed = ($customfieldid !== false);
}
+
if ($passed) {
// Create the object to insert into the database
$availfield = new stdClass();
$availfield->coursemoduleid = $this->task->get_moduleid(); // Lets add the availability cmid
$availfield->userfield = $data->userfield;
- $availfield->customfieldid = $data->customfieldid;
+ $availfield->customfieldid = $customfieldid;
$availfield->operator = $data->operator;
$availfield->value = $data->value;
// Insert into the database
View
4 blocks/blog_recent/block_blog_recent.php
@@ -86,17 +86,20 @@ function get_content() {
$context = $this->page->context;
+ $url = new moodle_url('/blog/index.php');
$filter = array();
if ($context->contextlevel == CONTEXT_MODULE) {
$filter['module'] = $context->instanceid;
$a = new stdClass;
$a->type = get_string('modulename', $this->page->cm->modname);
$strview = get_string('viewallmodentries', 'blog', $a);
+ $url->param('modid', $context->instanceid);
} else if ($context->contextlevel == CONTEXT_COURSE) {
$filter['course'] = $context->instanceid;
$a = new stdClass;
$a->type = get_string('course');
$strview = get_string('viewblogentries', 'blog', $a);
+ $url->param('courseid', $context->instanceid);
} else {
$strview = get_string('viewsiteentries', 'blog');
}
@@ -104,7 +107,6 @@ function get_content() {
$bloglisting = new blog_listing($filter);
$entries = $bloglisting->get_entries(0, $this->config->numberofrecentblogentries, 4);
- $url = new moodle_url('/blog/index.php', $filter);
if (!empty($entries)) {
$entrieslist = array();
View
2  blocks/completionstatus/block_completionstatus.php
@@ -166,7 +166,7 @@ public function get_content() {
if (!empty($prerequisites)) {
$phtml = '<tr><td>';
- $phtml .= get_string('prerequisitescompleted', 'completion');
+ $phtml .= get_string('dependenciescompleted', 'completion');
$phtml .= '</td><td style="text-align: right">';
$a = new stdClass();
$a->first = $prerequisites_complete;
View
2  blog/index.php
@@ -143,7 +143,7 @@
}
if (!$course = $DB->get_record('course', array('id'=>$group->courseid))) {
- print_error(get_string('invalidcourseid', 'blog'));
+ print_error('invalidcourseid');
}
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
View
8 calendar/lib.php
@@ -85,14 +85,6 @@
*/
define('CALENDAR_EVENT_USER', 8);
-/**
- * CALENDAR_STARTING_WEEKDAY - has since been deprecated please call calendar_get_starting_weekday() instead
- *
- * @deprecated Moodle 2.0 MDL-24284- please do not use this function any more.
- * @todo MDL-31132 This will be deleted in Moodle 2.3.
- * @see calendar_get_starting_weekday()
- */
-define('CALENDAR_STARTING_WEEKDAY', CALENDAR_DEFAULT_STARTING_WEEKDAY);
/**
* Return the days of the week
View
2  course/completion_form.php
@@ -65,7 +65,7 @@ function definition() {
$mform->setDefault('overall_aggregation', $completion->get_aggregation_method());
// Course prerequisite completion criteria
- $mform->addElement('header', 'courseprerequisites', get_string('courseprerequisites', 'completion'));
+ $mform->addElement('header', 'courseprerequisites', get_string('completiondependencies', 'completion'));
// Get applicable courses
$courses = $DB->get_records_sql(
View
4 course/delete.php
@@ -18,11 +18,11 @@
$strcategories = get_string("categories");
if (! $course = $DB->get_record("course", array("id"=>$id))) {
- print_error("invalidcourseid", 'error', '', $id);
+ print_error("invalidcourseid");
}
if ($site->id == $course->id) {
// can not delete frontpage!
- print_error("invalidcourseid", 'error', '', $id);
+ print_error("invalidcourseid");
}
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
View
2  course/dndupload.js
@@ -514,7 +514,7 @@ M.course_dndupload = {
namespan: document.createElement('span')
};
- preview.li.className = 'dndupload-preview activity resource modtype_resource dndupload-hidden';
+ preview.li.className = 'dndupload-preview dndupload-hidden';
preview.div.className = 'mod-indent';
preview.li.appendChild(preview.div);
View
10 course/editsection.php
@@ -33,9 +33,9 @@
require_once('editsection_form.php');
$id = required_param('id',PARAM_INT); // Week/topic ID
-$sectionreturn = optional_param('sectionreturn', 0, PARAM_BOOL);
+$sectionreturn = optional_param('sr', 0, PARAM_INT);
-$PAGE->set_url('/course/editsection.php', array('id'=>$id, 'sectionreturn'=> $sectionreturn));
+$PAGE->set_url('/course/editsection.php', array('id'=>$id, 'sr'=> $sectionreturn));
$section = $DB->get_record('course_sections', array('id' => $id), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $section->course), '*', MUST_EXIST);
@@ -61,11 +61,7 @@
'cs' => $section, 'showavailability' => $section->showavailability));
$mform->set_data($section); // set current value
-if ($sectionreturn) {
- $returnurl = course_get_url($course, $section->section);
-} else {
- $returnurl = course_get_url($course);
-}
+$returnurl = course_get_url($course, $sectionreturn);
/// If data submitted, then process and store.
if ($mform->is_cancelled()){
View
189 course/externallib.php
@@ -668,13 +668,12 @@ public static function duplicate_course_parameters() {
'options' => new external_multiple_structure(
new external_single_structure(
array(
- 'name' => new external_value(PARAM_ALPHA, 'The backup option name:
+ 'name' => new external_value(PARAM_ALPHAEXT, 'The backup option name:
"activities" (int) Include course activites (default to 1 that is equal to yes),
"blocks" (int) Include course blocks (default to 1 that is equal to yes),
"filters" (int) Include course filters (default to 1 that is equal to yes),
"users" (int) Include users (default to 0 that is equal to no),
"role_assignments" (int) Include role assignments (default to 0 that is equal to no),
- "user_files" (int) Include user files (default to 0 that is equal to no),
"comments" (int) Include user comments (default to 0 that is equal to no),
"completion_information" (int) Include user course completion information (default to 0 that is equal to no),
"logs" (int) Include course logs (default to 0 that is equal to no),
@@ -722,7 +721,7 @@ public static function duplicate_course($courseid, $fullname, $shortname, $categ
// Context validation.
if (! ($course = $DB->get_record('course', array('id'=>$params['courseid'])))) {
- throw new moodle_exception('invalidcourseid', 'error', '', $params['courseid']);
+ throw new moodle_exception('invalidcourseid', 'error');
}
// Category where duplicated course is going to be created.
@@ -739,7 +738,6 @@ public static function duplicate_course($courseid, $fullname, $shortname, $categ
'filters' => 1,
'users' => 0,
'role_assignments' => 0,
- 'user_files' => 0,
'comments' => 0,
'completion_information' => 0,
'logs' => 0,
@@ -886,6 +884,189 @@ public static function duplicate_course_returns() {
}
/**
+ * Returns description of method parameters for import_course
+ *
+ * @return external_function_parameters
+ * @since Moodle 2.4
+ */
+ public static function import_course_parameters() {
+ return new external_function_parameters(
+ array(
+ 'importfrom' => new external_value(PARAM_INT, 'the id of the course we are importing from'),
+ 'importto' => new external_value(PARAM_INT, 'the id of the course we are importing to'),
+ 'deletecontent' => new external_value(PARAM_INT, 'whether to delete the course content where we are importing to (default to 0 = No)', VALUE_DEFAULT, 0),
+ 'options' => new external_multiple_structure(
+ new external_single_structure(
+ array(
+ 'name' => new external_value(PARAM_ALPHA, 'The backup option name:
+ "activities" (int) Include course activites (default to 1 that is equal to yes),
+ "blocks" (int) Include course blocks (default to 1 that is equal to yes),
+ "filters" (int) Include course filters (default to 1 that is equal to yes)'
+ ),
+ 'value' => new external_value(PARAM_RAW, 'the value for the option 1 (yes) or 0 (no)'
+ )
+ )
+ ), VALUE_DEFAULT, array()
+ ),
+ )
+ );
+ }
+
+ /**
+ * Imports a course
+ *
+ * @param int $importfrom The id of the course we are importing from
+ * @param int $importto The id of the course we are importing to
+ * @param bool $deletecontent Whether to delete the course we are importing to content
+ * @param array $options List of backup options
+ * @return null
+ * @since Moodle 2.4
+ */
+ public static function import_course($importfrom, $importto, $deletecontent = 0, $options = array()) {
+ global $CFG, $USER, $DB;
+ require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
+ require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
+
+ // Parameter validation.
+ $params = self::validate_parameters(
+ self::import_course_parameters(),
+ array(
+ 'importfrom' => $importfrom,
+ 'importto' => $importto,
+ 'deletecontent' => $deletecontent,
+ 'options' => $options
+ )
+ );
+
+ if ($params['deletecontent'] !== 0 and $params['deletecontent'] !== 1) {
+ throw new moodle_exception('invalidextparam', 'webservice', '', $option['deletecontent']);
+ }
+
+ // Context validation.
+
+ if (! ($importfrom = $DB->get_record('course', array('id'=>$params['importfrom'])))) {
+ throw new moodle_exception('invalidcourseid', 'error');
+ }
+
+ if (! ($importto = $DB->get_record('course', array('id'=>$params['importto'])))) {
+ throw new moodle_exception('invalidcourseid', 'error');
+ }
+
+ $importfromcontext = context_course::instance($importfrom->id);
+ self::validate_context($importfromcontext);
+
+ $importtocontext = context_course::instance($importto->id);
+ self::validate_context($importtocontext);
+
+ $backupdefaults = array(
+ 'activities' => 1,
+ 'blocks' => 1,
+ 'filters' => 1
+ );
+
+ $backupsettings = array();
+
+ // Check for backup and restore options.
+ if (!empty($params['options'])) {
+ foreach ($params['options'] as $option) {
+
+ // Strict check for a correct value (allways 1 or 0, true or false).
+ $value = clean_param($option['value'], PARAM_INT);
+
+ if ($value !== 0 and $value !== 1) {
+ throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
+ }
+
+ if (!isset($backupdefaults[$option['name']])) {
+ throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']);
+ }
+
+ $backupsettings[$option['name']] = $value;
+ }
+ }
+
+ // Capability checking.
+
+ require_capability('moodle/backup:backuptargetimport', $importfromcontext);
+ require_capability('moodle/restore:restoretargetimport', $importtocontext);
+
+ $bc = new backup_controller(backup::TYPE_1COURSE, $importfrom->id, backup::FORMAT_MOODLE,
+ backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id);
+
+ foreach ($backupsettings as $name => $value) {
+ $bc->get_plan()->get_setting($name)->set_value($value);
+ }
+
+ $backupid = $bc->get_backupid();
+ $backupbasepath = $bc->get_plan()->get_basepath();
+
+ $bc->execute_plan();
+ $bc->destroy();
+
+ // Restore the backup immediately.
+
+ // Check if we must delete the contents of the destination course.
+ if ($params['deletecontent']) {
+ $restoretarget = backup::TARGET_EXISTING_DELETING;
+ } else {
+ $restoretarget = backup::TARGET_EXISTING_ADDING;
+ }
+
+ $rc = new restore_controller($backupid, $importto->id,
+ backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, $restoretarget);
+
+ foreach ($backupsettings as $name => $value) {
+ $rc->get_plan()->get_setting($name)->set_value($value);
+ }
+
+ if (!$rc->execute_precheck()) {
+ $precheckresults = $rc->get_precheck_results();
+ if (is_array($precheckresults) && !empty($precheckresults['errors'])) {
+ if (empty($CFG->keeptempdirectoriesonbackup)) {
+ fulldelete($backupbasepath);
+ }
+
+ $errorinfo = '';
+
+ foreach ($precheckresults['errors'] as $error) {
+ $errorinfo .= $error;
+ }
+
+ if (array_key_exists('warnings', $precheckresults)) {
+ foreach ($precheckresults['warnings'] as $warning) {
+ $errorinfo .= $warning;
+ }
+ }
+
+ throw new moodle_exception('backupprecheckerrors', 'webservice', '', $errorinfo);
+ }
+ } else {
+ if ($restoretarget == backup::TARGET_EXISTING_DELETING) {
+ restore_dbops::delete_course_content($importto->id);
+ }
+ }
+
+ $rc->execute_plan();
+ $rc->destroy();
+
+ if (empty($CFG->keeptempdirectoriesonbackup)) {
+ fulldelete($backupbasepath);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns description of method result value
+ *
+ * @return external_description
+ * @since Moodle 2.4
+ */
+ public static function import_course_returns() {
+ return null;
+ }
+
+ /**
* Returns description of method parameters
*
* @return external_function_parameters
View
32 course/format/renderer.php
@@ -122,9 +122,10 @@ protected function section_left_content($section, $course, $onsectionpage) {
* @param stdClass $section The course_section entry from DB
* @param stdClass $course The course entry from DB
* @param bool $onsectionpage true if being printed on a single-section page
+ * @param int $sectionreturn The section to return to after an action
* @return string HTML to output.
*/
- protected function section_header($section, $course, $onsectionpage) {
+ protected function section_header($section, $course, $onsectionpage, $sectionreturn=0) {
global $PAGE;
$o = '';
@@ -150,7 +151,13 @@ protected function section_header($section, $course, $onsectionpage) {
$o.= html_writer::tag('div', $rightcontent, array('class' => 'right side'));
$o.= html_writer::start_tag('div', array('class' => 'content'));
- if (!$onsectionpage) {
+ // When not on a section page, we display the section titles except the general section if null
+ $hasnamenotsecpg = (!$onsectionpage && ($section->section != 0 || !is_null($section->name)));
+
+ // When on a section page, we only display the general section title, if title is not the default one
+ $hasnamesecpg = ($onsectionpage && ($section->section == 0 && !is_null($section->name)));
+
+ if ($hasnamenotsecpg || $hasnamesecpg) {
$o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname');
}
@@ -159,12 +166,7 @@ protected function section_header($section, $course, $onsectionpage) {
$context = context_course::instance($course->id);
if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
- $url = new moodle_url('/course/editsection.php', array('id'=>$section->id));
-
- if ($onsectionpage) {
- $url->param('sectionreturn', 1);
- }
-
+ $url = new moodle_url('/course/editsection.php', array('id'=>$section->id, 'sr'=>$sectionreturn));
$o.= html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/edit'), 'class' => 'iconsmall edit')),
array('title' => get_string('editsummary')));
@@ -560,10 +562,10 @@ public function print_single_section_page($course, $sections, $mods, $modnames,
$thissection = $sections[0];
if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
echo $this->start_section_list();
- echo $this->section_header($thissection, $course, true);
- print_section($course, $thissection, $mods, $modnamesused, true);
+ echo $this->section_header($thissection, $course, true, $displaysection);
+ print_section($course, $thissection, $mods, $modnamesused, true, "100%", false, $displaysection);
if ($PAGE->user_is_editing()) {
- print_section_add_menus($course, 0, $modnames, false, false, true);
+ print_section_add_menus($course, 0, $modnames, false, false, $displaysection);
}
echo $this->section_footer();
echo $this->end_section_list();
@@ -592,14 +594,14 @@ public function print_single_section_page($course, $sections, $mods, $modnames,
// The requested section page.
$thissection = $sections[$displaysection];
- echo $this->section_header($thissection, $course, true);
+ echo $this->section_header($thissection, $course, true, $displaysection);
// Show completion help icon.
$completioninfo = new completion_info($course);
echo $completioninfo->display_help_icon();
- print_section($course, $thissection, $mods, $modnamesused, true, '100%', false, true);
+ print_section($course, $thissection, $mods, $modnamesused, true, '100%', false, $displaysection);
if ($PAGE->user_is_editing()) {
- print_section_add_menus($course, $displaysection, $modnames, false, false, true);
+ print_section_add_menus($course, $displaysection, $modnames, false, false, $displaysection);
}
echo $this->section_footer();
echo $this->end_section_list();
@@ -646,7 +648,7 @@ public function print_multiple_section_page($course, $sections, $mods, $modnames
$thissection = $sections[0];
unset($sections[0]);
if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
- echo $this->section_header($thissection, $course, true);
+ echo $this->section_header($thissection, $course, false);
print_section($course, $thissection, $mods, $modnamesused, true);
if ($PAGE->user_is_editing()) {
print_section_add_menus($course, 0, $modnames);
View
48 course/lib.php
@@ -1377,8 +1377,18 @@ function get_print_section_cm_text(cm_info $cm, $course) {
/**
* Prints a section full of activity modules
+ *
+ * @param stdClass $course The course
+ * @param stdClass $section The section
+ * @param array $mods The modules in the section
+ * @param array $modnamesused An array containing the list of modules and their names
+ * @param bool $absolute All links are absolute
+ * @param string $width Width of the container
+ * @param bool $hidecompletion Hide completion status
+ * @param int $sectionreturn The section to return to
+ * @return void
*/
-function print_section($course, $section, $mods, $modnamesused, $absolute=false, $width="100%", $hidecompletion=false, $sectionreturn = false) {
+function print_section($course, $section, $mods, $modnamesused, $absolute=false, $width="100%", $hidecompletion=false, $sectionreturn=0) {
global $CFG, $USER, $DB, $PAGE, $OUTPUT;
static $initialised;
@@ -1638,12 +1648,7 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
$mod->groupmode = false;
}
echo '&nbsp;&nbsp;';
-
- if ($sectionreturn) {
- echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section);
- } else {
- echo make_editing_buttons($mod, $absolute, true, $mod->indent, 0);
- }
+ echo make_editing_buttons($mod, $absolute, true, $mod->indent, $sectionreturn);
echo $mod->get_after_edit_icons();
}
@@ -1762,8 +1767,16 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false,
/**
* Prints the menus to add activities and resources.
+ *
+ * @param stdClass $course The course
+ * @param stdClass $section The section
+ * @param array $modnames An array containing the list of modules and their names
+ * @param bool $vertical Vertical orientation
+ * @param bool $return Return the menus or send them to output
+ * @param int $sectionreturn The section to link back to
+ * @return void|string depending on $return
*/
-function print_section_add_menus($course, $section, $modnames, $vertical=false, $return=false, $sectionreturn = false) {
+function print_section_add_menus($course, $section, $modnames, $vertical=false, $return=false, $sectionreturn=0) {
global $CFG, $OUTPUT;
// check to see if user can add menus
@@ -1779,14 +1792,7 @@ function print_section_add_menus($course, $section, $modnames, $vertical=false,
$activities = array();
// We need to add the section section to the link for each module
- $sectionlink = '&section=' . $section;
-
- // We need to add the section to return to
- if ($sectionreturn) {
- $sectionreturnlink = '&sr=' . $section;
- } else {
- $sectionreturnlink = '&sr=0';
- }
+ $sectionlink = '&section=' . $section . '&sr=' . $sectionreturn;
foreach ($modules as $module) {
if (isset($module->types)) {
@@ -1794,7 +1800,7 @@ function print_section_add_menus($course, $section, $modnames, $vertical=false,
// NOTE: this is legacy stuff, module subtypes are very strongly discouraged!!
$subtypes = array();
foreach ($module->types as $subtype) {
- $subtypes[$subtype->link . $sectionlink . $sectionreturnlink] = $subtype->title;
+ $subtypes[$subtype->link . $sectionlink] = $subtype->title;
}
// Sort module subtypes into the list
@@ -1816,11 +1822,11 @@ function print_section_add_menus($course, $section, $modnames, $vertical=false,
} else {
// This module has no subtypes
if ($module->archetype == MOD_ARCHETYPE_RESOURCE) {
- $resources[$module->link . $sectionlink . $sectionreturnlink] = $module->title;
+ $resources[$module->link . $sectionlink] = $module->title;
} else if ($module->archetype === MOD_ARCHETYPE_SYSTEM) {
// System modules cannot be added by user, do not add to dropdown
} else {
- $activities[$module->link . $sectionlink . $sectionreturnlink] = $module->title;
+ $activities[$module->link . $sectionlink] = $module->title;
}
}
}
@@ -4032,7 +4038,7 @@ function average_number_of_participants() {
WHERE ue.enrolid = e.id
AND e.courseid <> :siteid
AND c.id = e.courseid
- AND c.visible = 1) as total';
+ AND c.visible = 1)';
$params = array('siteid' => $SITE->id);
$enrolmenttotal = $DB->count_records_sql($sql, $params);
@@ -4065,7 +4071,7 @@ function average_number_of_courses_modules() {
WHERE c.id = cm.course
AND c.id <> :siteid
AND cm.visible = 1
- AND c.visible = 1) as total';
+ AND c.visible = 1)';
$params = array('siteid' => $SITE->id);
$moduletotal = $DB->count_records_sql($sql, $params);
View
2  enrol/authorize/index.php
@@ -53,7 +53,7 @@
/// Get course
if (!($course = $DB->get_record('course', array('id'=>$courseid)))) {
- print_error('invalidcourseid', '', '', $courseid);
+ print_error('invalidcourseid');
}
/// Only SITE users can access to this page
View
6 enrol/database/tests/adodb_test.php
@@ -70,7 +70,11 @@ public function test_read_table() {
set_config('dbsetupsql', 'SET NAMES \'UTF-8\'', 'enrol_database');
set_config('dbsybasequoting', '0', 'enrol_database');
if (!empty($CFG->dboptions['dbsocket']) and ($CFG->dbhost === 'localhost' or $CFG->dbhost === '127.0.0.1')) {
- set_config('dbhost', $CFG->dboptions['dbsocket'], 'enrol_database');
+ if (strpos($CFG->dboptions['dbsocket'], '/') !== false) {
+ set_config('dbhost', $CFG->dboptions['dbsocket'], 'enrol_database');
+ } else {
+ set_config('dbhost', '', 'enrol_database');
+ }
}
break;
View
2  filter/tex/latex.php
@@ -108,7 +108,7 @@ function render( $formula, $filename, $fontsize=12, $density=240, $background=''
fclose( $fh );
// run latex on document
- $command = "{$CFG->filter_tex_pathlatex} --interaction=nonstopmode $tex";
+ $command = "{$CFG->filter_tex_pathlatex} --interaction=nonstopmode --halt-on-error $tex";
chdir( $this->temp_dir );
if ($this->execute($command, $log)) { // It allways False on Windows
// return false;
View
2  filter/tex/texdebug.php
@@ -244,7 +244,7 @@ function TexOutput($expression, $graphic=false) {
chdir($latex->temp_dir);
// step 1: latex command
- $cmd = "$CFG->filter_tex_pathlatex --interaction=nonstopmode $tex";
+ $cmd = "$CFG->filter_tex_pathlatex --interaction=nonstopmode --halt-on-error $tex";
$output .= execute($cmd);
// step 2: dvips command
View
36 grade/export/lib.php
@@ -40,6 +40,8 @@
public $displaytype; // display type (e.g. real, percentages, letter) for exports
public $decimalpoints; // number of decimal points for exports
public $onlyactive; // only include users with an active enrolment
+ public $usercustomfields; // include users custom fields
+
/**
* Constructor should set up all the private variables ready to be pulled
* @access public
@@ -47,10 +49,14 @@
* @param int $groupid id of selected group, 0 means all
* @param string $itemlist comma separated list of item ids, empty means all
* @param boolean $export_feedback
- * @param boolean $export_letters
+ * @param boolean $updatedgradesonly
+ * @param string $displaytype
+ * @param int $decimalpoints
+ * @param boolean $onlyactive
+ * @param boolean $usercustomfields include user custom field in export
* @note Exporting as letters will lead to data loss if that exported set it re-imported.
*/
- public function grade_export($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2, $onlyactive = false) {
+ public function grade_export($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2, $onlyactive = false, $usercustomfields = false) {
$this->course = $course;
$this->groupid = $groupid;
$this->grade_items = grade_item::fetch_all(array('courseid'=>$this->course->id));
@@ -85,6 +91,7 @@ public function grade_export($course, $groupid=0, $itemlist='', $export_feedback
$this->displaytype = $displaytype;
$this->decimalpoints = $decimalpoints;
$this->onlyactive = $onlyactive;
+ $this->usercustomfields = $usercustomfields;
}
/**
@@ -205,16 +212,18 @@ public function format_feedback($feedback) {
*/
public function display_preview($require_user_idnumber=false) {
global $OUTPUT;
+
+ $userprofilefields = grade_helper::get_user_profile_fields($this->course->id, $this->usercustomfields);
+ $formatoptions = new stdClass();
+ $formatoptions->para = false;
+
echo $OUTPUT->heading(get_string('previewrows', 'grades'));
echo '<table>';
echo '<tr>';
- echo '<th>'.get_string("firstname")."</th>".
- '<th>'.get_string("lastname")."</th>".
- '<th>'.get_string("idnumber")."</th>".
- '<th>'.get_string("institution")."</th>".
- '<th>'.get_string("department")."</th>".
- '<th>'.get_string("email")."</th>";
+ foreach ($userprofilefields as $field) {
+ echo '<th>' . $field->fullname . '</th>';
+ }
foreach ($this->columns as $grade_item) {
echo '<th>'.$this->format_column_name($grade_item).'</th>';
@@ -225,10 +234,10 @@ public function display_preview($require_user_idnumber=false) {
}
echo '</tr>';
/// Print all the lines of data.
-
$i = 0;
$gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
$gui->require_active_enrolment($this->onlyactive);
+ $gui->allow_user_custom_fields($this->usercustomfields);
$gui->init();
while ($userdata = $gui->next_user()) {
// number of preview rows
@@ -269,7 +278,11 @@ public function display_preview($require_user_idnumber=false) {
}
echo '<tr>';
- echo "<td>$user->firstname</td><td>$user->lastname</td><td>$user->idnumber</td><td>$user->institution</td><td>$user->department</td><td>$user->email</td>";
+ foreach ($userprofilefields as $field) {
+ $fieldvalue = grade_helper::get_user_field_value($user, $field);
+ // @see profile_field_base::display_data().
+ echo '<td>' . format_text($fieldvalue, FORMAT_MOODLE, $formatoptions) . '</td>';
+ }
echo $rowstr;
echo "</tr>";
@@ -298,7 +311,8 @@ public function get_export_params() {
'updatedgradesonly' =>$this->updatedgradesonly,
'displaytype' =>$this->displaytype,
'decimalpoints' =>$this->decimalpoints,
- 'export_onlyactive' =>$this->onlyactive);
+ 'export_onlyactive' =>$this->onlyactive,
+ 'usercustomfields' =>$this->usercustomfields);
return $params;
}
View
2  grade/export/ods/export.php
@@ -45,7 +45,7 @@
}
// print all the exported data here
-$export = new grade_export_ods($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive);
+$export = new grade_export_ods($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive, true);
$export->print_grades();
View
43 grade/export/ods/grade_export_ods.php
@@ -34,49 +34,48 @@ function print_grades() {
$shortname = format_string($this->course->shortname, true, array('context' => get_context_instance(CONTEXT_COURSE, $this->course->id)));
- /// Calculate file name
+ // Calculate file name
$downloadfilename = clean_filename("$shortname $strgrades.ods");
- /// Creating a workbook
+ // Creating a workbook
$workbook = new MoodleODSWorkbook("-");
- /// Sending HTTP headers
+ // Sending HTTP headers
$workbook->send($downloadfilename);
- /// Adding the worksheet
+ // Adding the worksheet
$myxls =& $workbook->add_worksheet($strgrades);
- /// Print names of all the fields
- $myxls->write_string(0,0,get_string("firstname"));
- $myxls->write_string(0,1,get_string("lastname"));
- $myxls->write_string(0,2,get_string("idnumber"));
- $myxls->write_string(0,3,get_string("institution"));
- $myxls->write_string(0,4,get_string("department"));
- $myxls->write_string(0,5,get_string("email"));
- $pos=6;
+
+ // Print names of all the fields.
+ $profilefields = grade_helper::get_user_profile_fields($this->course->id, $this->usercustomfields);
+ foreach ($profilefields as $id => $field) {
+ $myxls->write_string(0, $id, $field->fullname);
+ }
+ $pos = count($profilefields);
foreach ($this->columns as $grade_item) {
$myxls->write_string(0, $pos++, $this->format_column_name($grade_item));
- /// add a column_feedback column
+ // Add a column_feedback column.
if ($this->export_feedback) {
$myxls->write_string(0, $pos++, $this->format_column_name($grade_item, true));
}
}
- /// Print all the lines of data.
+ // Print all the lines of data.
$i = 0;
$geub = new grade_export_update_buffer();
$gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
$gui->require_active_enrolment($this->onlyactive);
+ $gui->allow_user_custom_fields($this->usercustomfields);
$gui->init();
while ($userdata = $gui->next_user()) {
$i++;
$user = $userdata->user;
- $myxls->write_string($i,0,$user->firstname);
- $myxls->write_string($i,1,$user->lastname);
- $myxls->write_string($i,2,$user->idnumber);
- $myxls->write_string($i,3,$user->institution);
- $myxls->write_string($i,4,$user->department);
- $myxls->write_string($i,5,$user->email);
- $j=6;
+ foreach($profilefields as $id => $field) {
+ $fieldvalue = grade_helper::get_user_field_value($user, $field);
+ $myxls->write_string($i, $id, $fieldvalue);
+ }
+ $j = count($profilefields);
+
foreach ($userdata->grades as $itemid => $grade) {
if ($export_tracking) {
$status = $geub->track($grade);
@@ -99,7 +98,7 @@ function print_grades() {
$gui->close();
$geub->close();
- /// Close the workbook
+ // Close the workbook.
$workbook->close();
exit;
View
2  grade/export/ods/index.php
@@ -51,7 +51,7 @@
// process post information
if ($data = $mform->get_data()) {
- $export = new grade_export_ods($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->export_onlyactive);
+ $export = new grade_export_ods($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->export_onlyactive, true);
// print the grades on screen for feedbacks
$export->process_form($data);
View
2  grade/export/txt/export.php
@@ -46,7 +46,7 @@
}
// print all the exported data here
-$export = new grade_export_txt($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $separator, $onlyactive);
+$export = new grade_export_txt($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $separator, $onlyactive, true);
$export->print_grades();
View
44 grade/export/txt/grade_export_txt.php
@@ -23,8 +23,20 @@ class grade_export_txt extends grade_export {
public $separator; // default separator
- public function __construct($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2, $separator = 'comma', $onlyactive = false) {
- parent::__construct($course, $groupid, $itemlist, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive);
+ /**
+ * Constructor should set up all the private variables ready to be pulled
+ * @param object $course
+ * @param int $groupid id of selected group, 0 means all
+ * @param string $itemlist comma separated list of item ids, empty means all
+ * @param boolean $export_feedback
+ * @param boolean $updatedgradesonly
+ * @param string $displaytype
+ * @param int $decimalpoints
+ * @param boolean $onlyactive
+ * @param boolean $usercustomfields include user custom field in export
+ */
+ public function __construct($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2, $separator = 'comma', $onlyactive = false, $usercustomfields = false) {
+ parent::__construct($course, $groupid, $itemlist, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive, $usercustomfields);
$this->separator = $separator;
}
@@ -40,6 +52,7 @@ public function print_grades() {
$export_tracking = $this->track_exports();
$strgrades = get_string('grades');
+ $profilefields = grade_helper::get_user_profile_fields($this->course->id, $this->usercustomfields);
switch ($this->separator) {
case 'comma':
@@ -50,7 +63,7 @@ public function print_grades() {
$separator = "\t";
}
- /// Print header to force download
+ // Print header to force download
if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431
@header('Cache-Control: max-age=10');
@header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
@@ -65,34 +78,39 @@ public function print_grades() {
$downloadfilename = clean_filename("$shortname $strgrades");
header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\"");
-/// Print names of all the fields
- echo get_string("firstname").$separator.
- get_string("lastname").$separator.
- get_string("idnumber").$separator.
- get_string("institution").$separator.
- get_string("department").$separator.
- get_string("email");
+ // Print names of all the fields
+ $fieldfullnames = array();
+ foreach ($profilefields as $field) {
+ $fieldfullnames[] = $field->fullname;
+ }
+ echo implode($separator, $fieldfullnames);
foreach ($this->columns as $grade_item) {
echo $separator.$this->format_column_name($grade_item);
- /// add a feedback column
+ // Add a feedback column.
if ($this->export_feedback) {
echo $separator.$this->format_column_name($grade_item, true);
}
}
echo "\n";
-/// Print all the lines of data.
+ // Print all the lines of data.
$geub = new grade_export_update_buffer();
$gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
$gui->require_active_enrolment($this->onlyactive);
+ $gui->allow_user_custom_fields($this->usercustomfields);
$gui->init();
while ($userdata = $gui->next_user()) {
$user = $userdata->user;
- echo $user->firstname.$separator.$user->lastname.$separator.$user->idnumber.$separator.$user->institution.$separator.$user->department.$separator.$user->email;
+ $items = array();
+ foreach ($profilefields as $field) {
+ $fieldvalue = grade_helper::get_user_field_value($user, $field);
+ $items[] = $fieldvalue;
+ }
+ echo implode($separator, $items);
foreach ($userdata->grades as $itemid => $grade) {
if ($export_tracking) {
View
2  grade/export/txt/index.php
@@ -51,7 +51,7 @@
// process post information
if ($data = $mform->get_data()) {
- $export = new grade_export_txt($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->separator, $data->export_onlyactive);
+ $export = new grade_export_txt($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->separator, $data->export_onlyactive, true);
// print the grades on screen for feedback
View
2  grade/export/xls/export.php
@@ -45,7 +45,7 @@
}
// print all the exported data here
-$export = new grade_export_xls($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive);
+$export = new grade_export_xls($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $onlyactive, true);
$export->print_grades();
View
41 grade/export/xls/grade_export_xls.php
@@ -32,50 +32,49 @@ public function print_grades() {
$strgrades = get_string('grades');
- /// Calculate file name
+ // Calculate file name
$shortname = format_string($this->course->shortname, true, array('context' => get_context_instance(CONTEXT_COURSE, $this->course->id)));
$downloadfilename = clean_filename("$shortname $strgrades.xls");
- /// Creating a workbook
+ // Creating a workbook
$workbook = new MoodleExcelWorkbook("-");
- /// Sending HTTP headers
+ // Sending HTTP headers
$workbook->send($downloadfilename);
- /// Adding the worksheet
+ // Adding the worksheet
$myxls =& $workbook->add_worksheet($strgrades);
- /// Print names of all the fields
- $myxls->write_string(0,0,get_string("firstname"));
- $myxls->write_string(0,1,get_string("lastname"));
- $myxls->write_string(0,2,get_string("idnumber"));
- $myxls->write_string(0,3,get_string("institution"));
- $myxls->write_string(0,4,get_string("department"));
- $myxls->write_string(0,5,get_string("email"));
- $pos=6;
+ // Print names of all the fields
+ $profilefields = grade_helper::get_user_profile_fields($this->course->id, $this->usercustomfields);
+ foreach ($profilefields as $id => $field) {
+ $myxls->write_string(0, $id, $field->fullname);
+ }
+ $pos = count($profilefields);
+
foreach ($this->columns as $grade_item) {
$myxls->write_string(0, $pos++, $this->format_column_name($grade_item));
- /// add a column_feedback column
+ // Add a column_feedback column
if ($this->export_feedback) {
$myxls->write_string(0, $pos++, $this->format_column_name($grade_item, true));
}
}
- /// Print all the lines of data.
+ // Print all the lines of data.
$i = 0;
$geub = new grade_export_update_buffer();
$gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
$gui->require_active_enrolment($this->onlyactive);
+ $gui->allow_user_custom_fields($this->usercustomfields);
$gui->init();
while ($userdata = $gui->next_user()) {
$i++;
$user = $userdata->user;
- $myxls->write_string($i,0,$user->firstname);
- $myxls->write_string($i,1,$user->lastname);
- $myxls->write_string($i,2,$user->idnumber);
- $myxls->write_string($i,3,$user->institution);
- $myxls->write_string($i,4,$user->department);
- $myxls->write_string($i,5,$user->email);
- $j=6;
+ foreach ($profilefields as $id => $field) {
+ $fieldvalue = grade_helper::get_user_field_value($user, $field);
+ $myxls->write_string($i, $id, $fieldvalue);
+ }
+ $j = count($profilefields);
+
foreach ($userdata->grades as $itemid => $grade) {
if ($export_tracking) {
$status = $geub->track($grade);
View
2  grade/export/xls/index.php
@@ -51,7 +51,7 @@
// process post information
if ($data = $mform->get_data()) {
- $export = new grade_export_xls($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->export_onlyactive);
+ $export = new grade_export_xls($course, $currentgroup, '', false, false, $data->display, $data->decimals, $data->export_onlyactive, true);
// print the grades on screen for feedbacks
$export->process_form($data);
View
137 grade/lib.php
@@ -89,6 +89,11 @@ class graded_users_iterator {
protected $onlyactive = false;
/**
+ * Enable user custom fields
+ */
+ protected $allowusercustomfields = false;
+
+ /**
* Constructor
*
* @param object $course A course object
@@ -169,11 +174,29 @@ public function init() {
}
}
+ $userfields = 'u.*';
+ $customfieldssql = '';
+ if ($this->allowusercustomfields && !empty($CFG->grade_export_customprofilefields)) {
+ $customfieldscount = 0;
+ $customfieldsarray = grade_helper::get_user_profile_fields($this->course->id, $this->allowusercustomfields);
+ foreach ($customfieldsarray as $field) {
+ if (!empty($field->customid)) {
+ $customfieldssql .= "
+ LEFT JOIN (SELECT * FROM {user_info_data}
+ WHERE fieldid = :cf$customfieldscount) cf$customfieldscount
+ ON u.id = cf$customfieldscount.userid";
+ $userfields .= ", cf$customfieldscount.data AS 'customfield_{$field->shortname}'";
+ $params['cf'.$customfieldscount] = $field->customid;
+ $customfieldscount++;
+ }
+ }
+ }
+
// $params contents: gradebookroles and groupid (for $groupwheresql)
- $users_sql = "SELECT u.* $ofields
+ $users_sql = "SELECT $userfields $ofields
FROM {user} u
JOIN ($enrolledsql) je ON je.id = u.id
- $groupsql
+ $groupsql $customfieldssql
JOIN (
SELECT DISTINCT ra.userid
FROM {role_assignments} ra
@@ -311,6 +334,19 @@ public function require_active_enrolment($onlyactive = true) {
$this->onlyactive = $onlyactive;
}
+ /**
+ * Allow custom fields to be included
+ *
+ * @param bool $allow Whether to allow custom fields or not
+ * @return void
+ */
+ public function allow_user_custom_fields($allow = true) {
+ if ($allow) {
+ $this->allowusercustomfields = true;
+ } else {
+ $this->allowusercustomfields = false;
+ }
+ }
/**
* Add a grade_grade instance to the grade stack
@@ -2665,4 +2701,101 @@ public static function get_plugins_export($courseid) {
}
return self::$exportplugins;
}
+
+ /**
+ * Returns the value of a field from a user record
+ *
+ * @param stdClass $user object
+ * @param stdClass $field object
+ * @return string value of the field
+ */
+ public static function get_user_field_value($user, $field) {
+ if (!empty($field->customid)) {
+ $fieldname = 'customfield_' . $field->shortname;
+ if (!empty($user->{$fieldname}) || is_numeric($user->{$fieldname})) {
+ $fieldvalue = $user->{$fieldname};
+ } else {
+ $fieldvalue = $field->default;
+ }
+ } else {
+ $fieldvalue = $user->{$field->shortname};
+ }
+ return $fieldvalue;
+ }
+
+ /**
+ * Returns an array of user profile fields to be included in export
+ *
+ * @param int $courseid
+ * @param bool $includecustomfields
+ * @return array An array of stdClass instances with customid, shortname, datatype, default and fullname fields
+ */
+ public static function get_user_profile_fields($courseid, $includecustomfields = false) {
+ global $CFG, $DB;
+
+ // Gets the fields that have to be hidden
+ $hiddenfields = array_map('trim', explode(',', $CFG->hiddenuserfields));
+ $context = context_course::instance($courseid);
+ $canseehiddenfields = has_capability('moodle/course:viewhiddenuserfields', $context);
+ if ($canseehiddenfields) {
+ $hiddenfields = array();
+ }
+
+ $fields = array();
+ require_once($CFG->dirroot.'/user/lib.php'); // Loads user_get_default_fields()
+ require_once($CFG->dirroot.'/user/profile/lib.php'); // Loads constants, such as PROFILE_VISIBLE_ALL
+ $userdefaultfields = user_get_default_fields();
+
+ // Sets the list of profile fields
+ $userprofilefields = array_map('trim', explode(',', $CFG->grade_export_userprofilefields));
+ if (!empty($userprofilefields)) {
+ foreach ($userprofilefields as $field) {
+ $field = trim($field);
+ if (in_array($field, $hiddenfields) || !in_array($field, $userdefaultfields)) {
+ continue;
+ }
+ $obj = new stdClass();
+ $obj->customid = 0;
+ $obj->shortname = $field;
+ $obj->fullname = get_string($field);
+ $fields[] = $obj;
+ }
+ }
+
+ // Sets the list of custom profile fields
+ $customprofilefields = array_map('trim', explode(',', $CFG->grade_export_customprofilefields));
+ if ($includecustomfields && !empty($customprofilefields)) {
+ list($wherefields, $whereparams) = $DB->get_in_or_equal($customprofilefields);
+ $customfields = $DB->get_records_sql("SELECT f.*
+ FROM {user_info_field} f
+ JOIN {user_info_category} c ON f.categoryid=c.id
+ WHERE f.shortname $wherefields
+ ORDER BY c.sortorder ASC, f.sortorder ASC", $whereparams);
+ if (!is_array($customfields)) {
+ continue;
+ }
+
+ foreach ($customfields as $field) {
+ // Make sure we can display this custom field
+ if (!in_array($field->shortname, $customprofilefields)) {
+ continue;
+ } else if (in_array($field->shortname, $hiddenfields)) {
+ continue;
+ } else if ($field->visible != PROFILE_VISIBLE_ALL && !$canseehiddenfields) {
+ continue;
+ }
+
+ $obj = new stdClass();
+ $obj->customid = $field->id;
+ $obj->shortname = $field->shortname;
+ $obj->fullname = format_string($field->name);
+ $obj->datatype = $field->datatype;
+ $obj->default = $field->defaultdata;
+ $fields[] = $obj;
+ }
+ }
+
+ return $fields;
+ }
}
+
View
5 install/lang/ca/install.php
@@ -70,6 +70,11 @@
$string['pathssubadmindir'] = 'Alguns serveis d\'allotjament web (pocs) utilitzen un URL especial /admin p. ex. per a accedir a un tauler de control o quelcom semblant. Malauradament això entra en conflicte amb la ubicació estàndard de les pàgines d\'administració de Moodle. Podeu arreglar aquest problema canviant el nom del directori d\'administració de Moodle en la vostra instal·lació i posant el nou nom aquí. Per exemple <em>moodleadmin</em>. Això modificarà els enllaços d\'administració de Moodle.';
$string['pathssubdataroot'] = 'Necessiteu un espai on Moodle pugui desar els fitxers penjats. Aquest directori hauria de tenir permisos de lectura I ESCRIPTURA per a l\'usuari del servidor web (normalment \'nobody\' o \'apache\'), però no cal que sigui accessible directament via web. L\'instal·lador provarà de crear-lo si no existeix.';
$string['pathssubdirroot'] = 'Camí complet del directori d\'instal·lació de Moodle.';
+$string['pathssubwwwroot'] = 'L\'adreça web completa on s\'accedirà a Moodle.
+No és possible accedir a Moodle en diferents adreces.
+Si el vostre lloc té múltiples adreces públiques haureu de configurar redireccions permanents per a totes excepte aquesta.
+Si el vostre lloc és accessible tant des d\'Internet com des d\'una intranet, utilitzeu aquí l\'adreça pública i configureu el DNS de manera que els usuaris de la intranet puguin utilitzar també l\'adreça pública.
+Si l\'adreça no és correcta, canvieu l\'URL en el vostre navegador per reiniciar la instal·lació amb un altre valor.';
$string['pathsunsecuredataroot'] = 'La ubicació del dataroot no és segura.';
$string['pathswrongadmindir'] = 'No existeix el directori d\'administració';
$string['phpextension'] = 'Extensió PHP {$a}';
View
1  install/lang/is/admin.php
@@ -32,6 +32,7 @@
$string['clianswerno'] = 'n';
$string['cliansweryes'] = 'j';
+$string['cliincorrectvalueerror'] = 'Villa, ótækt gildi "{$a->value}" fyrir "{$a->option}"';
$string['cliincorrectvalueretry'] = 'Rangt gildi, vinsamlegast reyndu aftur';
$string['clitypevalue'] = 'Sláðu inn gildi';
$string['clitypevaluedefault'] = 'Sláðu inn gildi, sláðu á Enter hnappinn á lyklaborðinu til að nota sjálfgefið gildi ({$a})';
View
2  install/lang/is/langconfig.php
@@ -31,4 +31,4 @@
defined('MOODLE_INTERNAL') || die();
$string['thisdirection'] = 'ltr';
-$string['thislanguage'] = '&Iacute;slenska';
+$string['thislanguage'] = 'Íslenska';
View
6 install/lang/pt/admin.php
@@ -35,10 +35,10 @@
$string['cliincorrectvalueerror'] = 'Erro. Valor "{$a->value}" incorreto para "{$a->option}"';
$string['cliincorrectvalueretry'] = 'Valor incorreto, por favor tente novamente';
$string['clitypevalue'] = 'valor do tipo';
-$string['clitypevaluedefault'] = 'Escreva o valor. Ou Enter para usar o valor por omissão ({$a}).';
+$string['clitypevaluedefault'] = 'valor do tipo, pressione a tecla Enter para usar o valor predefinido ({$a})';
$string['cliunknowoption'] = 'Opções desconhecidas:
{$a}
Por favor use a opção --help';
$string['cliyesnoprompt'] = 'digite s (para sim) ou n (para não)';
-$string['environmentrequireinstall'] = 'é necessário estar instalada/ativa';
-$string['environmentrequireversion'] = 'É requerida a versão {$a->needed} e está a correr a versão {$a->current}';
+$string['environmentrequireinstall'] = 'deve estar instalada e ativa';
+$string['environmentrequireversion'] = 'é requerida a versão {$a->needed} e está a correr a versão {$a->current}';
View
7 lang/en/completion.php
@@ -88,12 +88,12 @@
$string['achievinggrade']='Achieving grade';
$string['activities']='Activities';
$string['activitiescompleted']='Activities completed';
-$string['addcourseprerequisite']='Add course prerequisite';
$string['afterspecifieddate']='After specified date';
$string['aggregationmethod']='Aggregation method';
$string['all']='All';
$string['any']='Any';
$string['approval']='Approval';
+$string['completiondependencies']='Completion dependencies';
$string['completionenabled']='Enabled, control via completion and activity settings';
$string['completionmenuitem']='Completion';
$string['completiononunenrolment']='Completion on unenrolment';
@@ -106,7 +106,6 @@
$string['coursecomplete']='Course complete';
$string['coursecompleted']='Course completed';
$string['coursegrade']='Course grade';
-$string['courseprerequisites']='Course prerequisites';
$string['coursesavailable']='Courses available';
$string['coursesavailableexplaination']='<i>Course completion criteria must be set for a course to appear in this list</i>';
$string['criteria']='Criteria';