Merge branch 'MDL-56486-master-workshopfiletypes' of git://github.com/mudrd8mz/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 11 Jul 2017 09:18:48 +0000 (10:18 +0100)
committerDan Poltawski <dan@moodle.com>
Tue, 11 Jul 2017 09:18:48 +0000 (10:18 +0100)
236 files changed:
.travis.yml
admin/category.php
admin/cli/install.php
admin/cli/install_database.php
admin/environment.xml
admin/index.php
admin/tool/customlang/db/upgrade.php
admin/tool/filetypes/lang/en/tool_filetypes.php
admin/tool/log/db/upgrade.php
admin/tool/log/store/database/classes/log/store.php
admin/tool/log/store/database/db/upgrade.php
admin/tool/log/store/database/lang/en/logstore_database.php
admin/tool/log/store/database/settings.php
admin/tool/log/store/database/test_settings.php
admin/tool/log/store/database/tests/store_test.php
admin/tool/log/store/database/upgrade.txt [new file with mode: 0644]
admin/tool/log/store/database/version.php
admin/tool/log/store/standard/db/upgrade.php
admin/tool/mobile/lang/en/tool_mobile.php
admin/tool/mobile/lib.php
admin/tool/monitor/db/upgrade.php
admin/tool/oauth2/classes/form/issuer.php
admin/tool/oauth2/lang/en/tool_oauth2.php
admin/tool/task/lang/en/tool_task.php
admin/tool/uploadcourse/classes/course.php
admin/tool/uploadcourse/classes/step2_form.php
admin/tool/uploadcourse/cli/uploadcourse.php
admin/tool/uploadcourse/tests/course_test.php
auth/cas/CAS/CAS/Client.php
auth/cas/CAS/moodle_readme.txt
auth/cas/db/upgrade.php
auth/classes/external.php
auth/ldap/db/upgrade.php
auth/manual/db/upgrade.php
auth/mnet/db/upgrade.php
auth/oauth2/classes/api.php
auth/oauth2/classes/auth.php
auth/oauth2/tests/api_test.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
backup/moodle2/tests/moodle2_test.php
blocks/badges/db/upgrade.php
blocks/calendar_month/db/upgrade.php
blocks/calendar_upcoming/db/upgrade.php
blocks/community/db/upgrade.php
blocks/completionstatus/db/upgrade.php
blocks/course_summary/db/upgrade.php
blocks/html/classes/search/content.php [new file with mode: 0644]
blocks/html/db/upgrade.php
blocks/html/lang/en/block_html.php
blocks/html/lib.php
blocks/html/tests/search_content_test.php [new file with mode: 0644]
blocks/login/block_login.php
blocks/moodleblock.class.php
blocks/myoverview/lang/en/block_myoverview.php
blocks/navigation/db/upgrade.php
blocks/participants/tests/behat/block_participants_course.feature
blocks/quiz_results/db/upgrade.php
blocks/recent_activity/db/upgrade.php
blocks/rss_client/db/upgrade.php
blocks/section_links/db/upgrade.php
blocks/selfcompletion/db/upgrade.php
blocks/settings/db/upgrade.php
blocks/upgrade.txt
cache/classes/factory.php
cache/classes/helper.php
cache/tests/cache_test.php
calendar/amd/build/calendar.min.js [new file with mode: 0644]
calendar/amd/build/calendar_repository.min.js [new file with mode: 0644]
calendar/amd/build/summary_modal.min.js [new file with mode: 0644]
calendar/amd/src/calendar.js [new file with mode: 0644]
calendar/amd/src/calendar_repository.js [new file with mode: 0644]
calendar/amd/src/summary_modal.js [new file with mode: 0644]
calendar/classes/local/event/container.php
calendar/externallib.php
calendar/renderer.php
calendar/templates/event_summary_body.mustache [new file with mode: 0644]
calendar/templates/event_summary_modal.mustache [new file with mode: 0644]
calendar/tests/container_test.php
calendar/view.php
course/lib.php
course/renderer.php
enrol/database/db/upgrade.php
enrol/flatfile/db/upgrade.php
enrol/guest/db/upgrade.php
enrol/guest/locallib.php
enrol/imsenterprise/db/upgrade.php
enrol/ldap/lib.php
enrol/manual/db/upgrade.php
enrol/mnet/db/upgrade.php
enrol/paypal/db/upgrade.php
enrol/self/db/upgrade.php
enrol/self/locallib.php
filter/mathjaxloader/db/upgrade.php
filter/mediaplugin/db/upgrade.php
filter/tex/db/upgrade.php
grade/grading/form/rubric/db/upgrade.php
grade/report/user/db/upgrade.php
install.php
install/lang/pt_br/error.php
lang/en/admin.php
lang/en/blog.php
lang/en/calendar.php
lang/en/hub.php
lang/en/repository.php
lib/adminlib.php
lib/blocklib.php
lib/classes/oauth2/issuer.php
lib/classes/output/icon_system_fontawesome.php
lib/classes/output/mustache_javascript_helper.php
lib/db/install.php
lib/db/install.xml [changed mode: 0644->0755]
lib/db/services.php
lib/db/upgrade.php
lib/db/upgradelib.php
lib/editor/atto/db/upgrade.php
lib/editor/atto/plugins/equation/db/upgrade.php
lib/editor/atto/plugins/equation/db/upgradelib.php [deleted file]
lib/editor/atto/plugins/equation/tests/upgradelib_testcase.php [deleted file]
lib/editor/atto/upgrade.txt
lib/editor/tinymce/db/upgrade.php
lib/editor/tinymce/plugins/spellchecker/db/upgrade.php
lib/filelib.php
lib/navigationlib.php
lib/outputlib.php
lib/outputrenderers.php
lib/phpminimumversionlib.php [new file with mode: 0644]
lib/templates/loginform.mustache
lib/testing/generator/block_generator.php
lib/tests/admintree_test.php
lib/tests/behat/alpha_chooser.feature
lib/tests/blocklib_test.php
lib/tests/upgradelib_test.php
lib/upgrade.txt
lib/upgradelib.php
login/forgot_password_form.php
login/lib.php
login/signup_form.php
login/tests/lib_test.php [new file with mode: 0644]
media/player/videojs/settings.php
message/classes/api.php
message/output/email/db/upgrade.php
message/output/jabber/db/upgrade.php
message/output/popup/classes/api.php
message/output/popup/db/upgrade.php
mod/assign/backup/moodle2/restore_assign_stepslib.php
mod/assign/db/upgrade.php
mod/assign/feedback/comments/db/upgrade.php
mod/assign/feedback/editpdf/db/upgrade.php
mod/assign/feedback/file/db/upgrade.php
mod/assign/submission/comments/db/upgrade.php
mod/assign/submission/file/db/upgrade.php
mod/assign/submission/file/lang/en/assignsubmission_file.php
mod/assign/submission/onlinetext/db/upgrade.php
mod/assignment/db/upgrade.php
mod/book/db/upgrade.php
mod/chat/db/upgrade.php
mod/choice/db/upgrade.php
mod/data/db/upgrade.php
mod/data/import.php
mod/feedback/db/upgrade.php
mod/feedback/lang/en/feedback.php
mod/folder/db/upgrade.php
mod/forum/db/upgrade.php
mod/forum/user.php
mod/glossary/db/upgrade.php
mod/glossary/lang/en/glossary.php
mod/imscp/db/upgrade.php
mod/label/db/upgrade.php
mod/lesson/db/upgrade.php
mod/lti/db/access.php
mod/lti/db/upgrade.php
mod/lti/db/upgradelib.php [deleted file]
mod/lti/lang/en/lti.php
mod/lti/locallib.php
mod/lti/tests/upgradelib_test.php [deleted file]
mod/lti/upgrade.txt
mod/lti/version.php
mod/page/db/upgrade.php
mod/quiz/db/upgrade.php
mod/quiz/report/overview/db/upgrade.php
mod/quiz/report/statistics/db/upgrade.php
mod/resource/db/upgrade.php
mod/resource/locallib.php
mod/scorm/db/upgrade.php
mod/survey/db/upgrade.php
mod/url/db/upgrade.php
mod/wiki/db/upgrade.php
mod/workshop/db/upgrade.php
mod/workshop/form/accumulative/db/upgrade.php
mod/workshop/form/comments/db/upgrade.php
mod/workshop/form/numerrors/db/upgrade.php
mod/workshop/form/rubric/db/upgrade.php
mod/workshop/lang/en/workshop.php
my/lib.php
phpunit.xml.dist
pluginfile.php
portfolio/boxnet/db/upgrade.php
portfolio/googledocs/db/upgrade.php
portfolio/picasa/db/upgrade.php
question/behaviour/manualgraded/db/upgrade.php
question/type/calculated/db/upgrade.php
question/type/ddmarker/db/upgrade.php
question/type/essay/db/upgrade.php
question/type/match/db/upgrade.php
question/type/multianswer/db/upgrade.php
question/type/multichoice/db/upgrade.php
question/type/multichoice/lang/en/qtype_multichoice.php
question/type/numerical/db/upgrade.php
question/type/random/db/upgrade.php
question/type/randomsamatch/db/upgrade.php
question/type/shortanswer/db/upgrade.php
report/log/tests/behat/filter_log.feature
report/log/tests/behat/user_log.feature
repository/boxnet/db/upgrade.php
repository/dropbox/db/upgrade.php
repository/googledocs/db/upgrade.php
repository/googledocs/lib.php
repository/onedrive/lib.php
repository/picasa/db/upgrade.php
repository/repository_callback.php
search/classes/base.php
search/classes/base_block.php [new file with mode: 0644]
search/classes/manager.php
search/tests/base_block_test.php [new file with mode: 0644]
search/tests/fixtures/mock_block_area.php [new file with mode: 0644]
search/tests/manager_test.php
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/style/moodle.css
theme/more/db/upgrade.php
user/classes/participants_table.php [new file with mode: 0644]
user/index.php
user/lib.php
user/tests/behat/view_full_profile.feature
user/tests/userlib_test.php
version.php

index d58effa..9c21e74 100644 (file)
@@ -14,7 +14,7 @@ language: php
 php:
     # We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
     - 7.1
-    - 5.6
+    - 7.0
 
 addons:
   postgresql: "9.3"
@@ -65,11 +65,7 @@ matrix:
         # Exclude it on all versions except for 7.1
 
         - env: DB=mysqli   TASK=PHPUNIT
-          php: 5.6
-
-        # Moodle 2.7 is not compatible with PHP 7 for the upgrade test.
-        - env: DB=pgsql    TASK=UPGRADE
-          php: 7.1
+          php: 7.0
 
 cache:
     directories:
@@ -233,9 +229,9 @@ before_script:
         # We need the official upstream.
         git remote add upstream https://github.com/moodle/moodle.git;
 
-        # Checkout 27 STABLE branch.
-        git fetch upstream MOODLE_27_STABLE;
-        git checkout MOODLE_27_STABLE;
+        # Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
+        git fetch upstream MOODLE_30_STABLE;
+        git checkout MOODLE_30_STABLE;
 
         # Perform the upgrade
         php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
index cb83e0d..0a80394 100644 (file)
@@ -89,7 +89,7 @@ if ($PAGE->user_allowed_editing()) {
 $savebutton = false;
 $outputhtml = '';
 foreach ($settingspage->children as $childpage) {
-    if ($childpage->is_hidden()) {
+    if ($childpage->is_hidden() || !$childpage->check_access()) {
         continue;
     }
     if ($childpage instanceof admin_externalpage) {
index 0b6c5ca..28e9cb8 100644 (file)
@@ -146,14 +146,9 @@ define('PHPUNIT_TEST', false);
 
 define('IGNORE_COMPONENT_CACHE', true);
 
-// Check that PHP is of a sufficient version
-if (version_compare(phpversion(), "5.6.5") < 0) {
-    $phpversion = phpversion();
-    // do NOT localise - lang strings would not work here and we CAN NOT move it after installib
-    fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
-    fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
-    exit(1);
-}
+// Check that PHP is of a sufficient version as soon as possible.
+require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
+moodle_require_minimum_php_version();
 
 // set up configuration
 global $CFG;
index f41263e..cede6cb 100644 (file)
@@ -62,14 +62,9 @@ Example:
 \$sudo -u www-data /usr/bin/php admin/cli/install_database.php --lang=cs --adminpass=soMePass123 --agree-license
 ";
 
-// Check that PHP is of a sufficient version
-if (version_compare(phpversion(), "5.6.5") < 0) {
-    $phpversion = phpversion();
-    // do NOT localise - lang strings would not work here and we CAN NOT move it after installib
-    fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
-    fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
-    exit(1);
-}
+// Check that PHP is of a sufficient version as soon as possible.
+require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
+moodle_require_minimum_php_version();
 
 // Nothing to do if config.php does not exist
 $configfile = __DIR__.'/../../config.php';
index 916c8a7..b8c7f16 100644 (file)
       </CUSTOM_CHECK>
     </CUSTOM_CHECKS>
   </MOODLE>
+  <MOODLE version="3.4" requires="3.0">
+    <UNICODE level="required">
+      <FEEDBACK>
+        <ON_ERROR message="unicoderequired" />
+      </FEEDBACK>
+    </UNICODE>
+    <DATABASE level="required">
+      <VENDOR name="mariadb" version="5.5.31" />
+      <VENDOR name="mysql" version="5.5.31" />
+      <VENDOR name="postgres" version="9.3" />
+      <VENDOR name="mssql" version="10.0" />
+      <VENDOR name="oracle" version="10.2" />
+    </DATABASE>
+    <PHP version="7.0.0" level="required">
+    </PHP>
+    <PCREUNICODE level="optional">
+      <FEEDBACK>
+        <ON_CHECK message="pcreunicodewarning" />
+      </FEEDBACK>
+    </PCREUNICODE>
+    <PHP_EXTENSIONS>
+      <PHP_EXTENSION name="iconv" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="iconvrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="mbstring" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="mbstringrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="curl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="curlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="openssl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="opensslrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="tokenizer" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="tokenizerrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlrpc" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="xmlrpcrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="soap" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="soaprecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="ctype" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ctyperequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zip" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ziprequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zlib" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="gd" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="gdrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="simplexml" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="simplexmlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="spl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="splrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="pcre" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="dom" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xml" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlreader" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="intl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="intlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="json" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="hash" level="required"/>
+      <PHP_EXTENSION name="fileinfo" level="required"/>
+    </PHP_EXTENSIONS>
+    <PHP_SETTINGS>
+      <PHP_SETTING name="memory_limit" value="96M" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="settingmemorylimit" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="file_uploads" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingfileuploads" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="opcache.enable" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="opcacherecommended" />
+        </FEEDBACK>
+      </PHP_SETTING>
+    </PHP_SETTINGS>
+    <CUSTOM_CHECKS>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbstorageengine" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="quizattemptsupgradedmessage" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="slashargumentswarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="unsupporteddbtablerowformat" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="unoconvwarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="libcurlwarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbfileformat" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbfilepertable" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddblargeprefix" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="ishttpswarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="incompleteunicodesupport" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+    </CUSTOM_CHECKS>
+  </MOODLE>
 </COMPATIBILITY_MATRIX>
index 6cf7f45..d0da26b 100644 (file)
@@ -29,14 +29,9 @@ if (!file_exists('../config.php')) {
     die();
 }
 
-// Check that PHP is of a sufficient version as soon as possible
-if (version_compare(phpversion(), '5.6.5') < 0) {
-    $phpversion = phpversion();
-    // do NOT localise - lang strings would not work here and we CAN NOT move it to later place
-    echo "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).<br />";
-    echo "Please upgrade your server software or install older Moodle version.";
-    die();
-}
+// Check that PHP is of a sufficient version as soon as possible.
+require_once(__DIR__.'/../lib/phpminimumversionlib.php');
+moodle_require_minimum_php_version();
 
 // make sure iconv is available and actually works
 if (!function_exists('iconv')) {
index d6fa182..afda140 100644 (file)
@@ -29,15 +29,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_tool_customlang_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 2640b44..c2a817c 100644 (file)
@@ -31,7 +31,7 @@ $string['delete_confirmation'] = 'Are you absolutely sure you want to remove <st
 $string['deletea'] = 'Delete {$a}';
 $string['deletefiletypes'] = 'Delete a file type';
 $string['description'] = 'Custom description';
-$string['description_help'] = 'Simple file type description, e.g. &lsquo;Kindle ebook&rsquo;. If your site supports multiple languages and uses the multi-language filter, you can enter multi-language tags in this field to supply a description in different languages.';
+$string['description_help'] = 'Simple file type description, e.g. \'Kindle ebook\'. If your site supports multiple languages and uses the multi-language filter, you can enter multi-language tags in this field to supply a description in different languages.';
 $string['descriptiontype'] = 'Description type';
 $string['descriptiontype_help'] = 'There are three possible ways to specify a description.
 
@@ -49,15 +49,15 @@ $string['error_defaulticon'] = 'Another file extension with the same MIME type i
 $string['error_extension'] = 'The file type extension <strong>{$a}</strong> already exists or is invalid. File extensions must be unique and must not contain special characters.';
 $string['error_notfound'] = 'The file type with extension {$a} cannot be found.';
 $string['extension'] = 'Extension';
-$string['extension_help'] = 'File name extension without the dot, e.g. &lsquo;mobi&rsquo;';
+$string['extension_help'] = 'File name extension without the dot, e.g. \'mobi\'';
 $string['groups'] = 'Type groups';
-$string['groups_help'] = 'Optional list of file type groups that this type belongs to. These are generic categories such as &lsquo;document&rsquo; and &lsquo;image&rsquo;.';
+$string['groups_help'] = 'Optional list of file type groups that this type belongs to. These are generic categories such as \'document\' and \'image\'.';
 $string['icon'] = 'File icon';
 $string['icon_help'] = 'Icon filename.
 
 The list of icons is taken from the /pix/f directory inside your Moodle installation. You can add custom icons to this folder if required.';
 $string['mimetype'] = 'MIME type';
-$string['mimetype_help'] = 'MIME type associated with this file type, e.g. &lsquo;application/x-mobipocket-ebook&rsquo;';
+$string['mimetype_help'] = 'MIME type associated with this file type, e.g. \'application/x-mobipocket-ebook\'';
 $string['pluginname'] = 'File types';
 $string['revert'] = 'Restore {$a} to Moodle defaults';
 $string['revert_confirmation'] = 'Are you sure you want to restore <strong>.{$a}</strong> to Moodle defaults, discarding your changes?';
index 3d7f4f9..13befec 100644 (file)
@@ -33,15 +33,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_tool_log_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index cddf3f9..10398df 100644 (file)
@@ -88,6 +88,7 @@ class store implements \tool_log\log\writer, \core\log\sql_reader {
         $dboptions['dbport'] = $this->get_config('dbport', '');
         $dboptions['dbschema'] = $this->get_config('dbschema', '');
         $dboptions['dbcollation'] = $this->get_config('dbcollation', '');
+        $dboptions['dbhandlesoptions'] = $this->get_config('dbhandlesoptions', false);
         try {
             $db->connect($this->get_config('dbhost'), $this->get_config('dbuser'), $this->get_config('dbpass'),
                 $this->get_config('dbname'), false, $dboptions);
index 789415e..0dbe11a 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_logstore_database_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 4e81a4a..0873229 100644 (file)
@@ -31,6 +31,8 @@ $string['databasesettings_help'] = 'Connection details for the external log data
 $string['databasepersist'] = 'Persistent database connections';
 $string['databaseschema'] = 'Database schema';
 $string['databasecollation'] = 'Database collation';
+$string['databasehandlesoptions'] = 'Database handles options';
+$string['databasehandlesoptions_help'] = 'Does the remote database handle its own options.';
 $string['databasetable'] = 'Database table';
 $string['databasetable_help'] = 'Name of the table where logs will be stored. This table should have a structure identical to the one used by logstore_standard (mdl_logstore_standard_log).';
 $string['includeactions'] = 'Include actions of these types';
index 5b930f4..4e45038 100644 (file)
@@ -54,6 +54,8 @@ if ($hassiteconfig) {
         'logstore_database'), '', ''));
     $settings->add(new admin_setting_configtext('logstore_database/dbcollation', get_string('databasecollation',
         'logstore_database'), '', ''));
+    $settings->add(new admin_setting_configcheckbox('logstore_database/dbhandlesoptions', get_string('databasehandlesoptions',
+        'logstore_database'), get_string('databasehandlesoptions_help', 'logstore_database'), '0'));
     $settings->add(new admin_setting_configtext('logstore_database/buffersize', get_string('buffersize',
         'logstore_database'), get_string('buffersize_help', 'logstore_database'), 50));
 
index ce35bc8..21a470e 100644 (file)
@@ -64,6 +64,7 @@ $dboptions['dbsocket'] = get_config('logstore_database', 'dbsocket');
 $dboptions['dbport'] = get_config('logstore_database', 'dbport');
 $dboptions['dbschema'] = get_config('logstore_database', 'dbschema');
 $dboptions['dbcollation'] = get_config('logstore_database', 'dbcollation');
+$dboptions['dbhandlesoptions'] = get_config('logstore_database', 'dbhandlesoptions');
 
 try {
     $db->connect(get_config('logstore_database', 'dbhost'), get_config('logstore_database', 'dbuser'),
index e40a8a4..a05c33f 100644 (file)
@@ -83,6 +83,11 @@ class logstore_database_store_testcase extends advanced_testcase {
         } else {
             set_config('dbcollation', '', 'logstore_database');
         }
+        if (!empty($CFG->dboptions['dbhandlesoptions'])) {
+            set_config('dbhandlesoptions', $CFG->dboptions['dbhandlesoptions'], 'logstore_database');
+        } else {
+            set_config('dbhandlesoptions', false, 'logstore_database');
+        }
 
         // Enable logging plugin.
         set_config('enabled_stores', 'logstore_database', 'tool_log');
diff --git a/admin/tool/log/store/database/upgrade.txt b/admin/tool/log/store/database/upgrade.txt
new file mode 100644 (file)
index 0000000..a8fa834
--- /dev/null
@@ -0,0 +1,11 @@
+This files describes API changes in the logstore_database code.
+
+=== 3.4 ===
+* PostgreSQL connections now use advanced options to reduce connection overhead.  These options are not compatible
+  with some connection poolers.  The dbhandlesoptions parameter has been added to allow the database to configure the
+  required defaults. The parameters that are required in the database are;
+    ALTER DATABASE moodle SET client_encoding = UTF8;
+    ALTER DATABASE moodle SET standard_conforming_strings = on;
+    ALTER DATABASE moodle SET search_path = 'moodle,public';  -- Optional, if you wish to use a custom schema.
+  You can set these options against the database or the moodle user who connects.
+
index 40d4db1..3105716 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
+$plugin->version = 2017062600; // The current plugin version (Date: YYYYMMDDXX).
 $plugin->requires = 2017050500; // Requires this Moodle version.
 $plugin->component = 'logstore_database'; // Full name of the plugin (used for diagnostics).
index 2614e0a..bcd8d1d 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 function xmldb_logstore_standard_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    $dbman = $DB->get_manager();
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2016041200) {
-        // This could take a long time. Unfortunately, no way to know how long, and no way to do progress, so setting for 1 hour.
-        upgrade_set_timeout(3600);
-
-        // Define key contextid (foreign) to be added to logstore_standard_log.
-        $table = new xmldb_table('logstore_standard_log');
-        $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
-
-        // Launch add key contextid.
-        $dbman->add_key($table, $key);
-
-        // Standard savepoint reached.
-        upgrade_plugin_savepoint(true, 2016041200, 'logstore', 'standard');
-    }
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index e2234bc..9955cb6 100644 (file)
@@ -63,17 +63,18 @@ $string['loginintheembeddedbrowser'] = 'Via an embedded browser (for SSO plugins
 $string['mainmenu'] = 'Main menu';
 $string['mobileapp'] = 'Mobile app';
 $string['mobileappconnected'] = 'Mobile app connected';
-$string['mobileappenabled'] = 'This site has mobile app access enabled. You can use mobile app to access the content of your courses and much more. Click <a href="{$a}">here</a> for more information';
+$string['mobileappenabled'] = 'This site has mobile app access enabled.<br /><a href="{$a}">Download the mobile app</a>.';
 $string['mobileappearance'] = 'Mobile appearance';
 $string['mobileauthentication'] = 'Mobile authentication';
 $string['mobilecssurl'] = 'CSS';
 $string['mobilefeatures'] = 'Mobile features';
 $string['mobilesettings'] = 'Mobile settings';
 $string['pluginname'] = 'Moodle Mobile tools';
-$string['setuplink'] = 'Mobile setup link';
-$string['setuplink_desc'] = 'Link to documentation page to help users setup their mobile app.';
+$string['setuplink'] = 'App download page';
+$string['setuplink_desc'] = 'URL of page with links to download the mobile app from the App Store and Google Play.';
 $string['smartappbanners'] = 'App Banners';
 $string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
 $string['remoteaddons'] = 'Remote add-ons';
 $string['typeoflogin'] = 'Type of login';
 $string['typeoflogin_desc'] = 'If the site uses a SSO authentication method, then select via a browser window or via an embedded browser. An embedded browser provides a better user experience, though it doesn\'t work with all SSO plugins. If using SSO, autologinguests should be disabled.';
+$string['getmoodleonyourmobile'] = 'Get Moodle on your mobile';
index 37f1043..0ecfeff 100644 (file)
@@ -126,3 +126,18 @@ function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree
     $node = new  core_user\output\myprofile\node('mobile', 'mobileappnode', $mobilestr, null);
     $tree->add_node($node);
 }
+
+/**
+ * Callback to add footer elements.
+ *
+ * @return str valid html footer content
+ * @since  Moodle 3.4
+ */
+function tool_mobile_standard_footer_html() {
+    global $CFG;
+    $output = '';
+    if (!empty($CFG->enablemobilewebservice) && $url = tool_mobile_create_app_download_url()) {
+        $output .= html_writer::link($url, get_string('getmoodleonyourmobile', 'tool_mobile'));
+    }
+    return $output;
+}
index 1a47f3a..4d7c475 100644 (file)
@@ -31,34 +31,10 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool always true
  */
 function xmldb_tool_monitor_upgrade($oldversion) {
-    global $DB;
+    global $CFG, $DB;
 
     $dbman = $DB->get_manager();
 
-    if ($oldversion < 2014102000) {
-
-        // Define field lastnotificationsent to be added to tool_monitor_subscriptions.
-        $table = new xmldb_table('tool_monitor_subscriptions');
-        $field = new xmldb_field('lastnotificationsent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timecreated');
-
-        // Conditionally launch add field lastnotificationsent.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Monitor savepoint reached.
-        upgrade_plugin_savepoint(true, 2014102000, 'tool', 'monitor');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 3a0b64d..a57b4c2 100644 (file)
@@ -119,6 +119,10 @@ class issuer extends persistent {
         $mform->addElement('checkbox', 'showonloginpage', get_string('issuershowonloginpage', 'tool_oauth2'));
         $mform->addHelpButton('showonloginpage', 'issuershowonloginpage', 'tool_oauth2');
 
+        // Require confirmation email for new accounts.
+        $mform->addElement('advcheckbox', 'requireconfirmation', get_string('issuerrequireconfirmation', 'tool_oauth2'));
+        $mform->addHelpButton('requireconfirmation', 'issuerrequireconfirmation', 'tool_oauth2');
+
         $mform->addElement('hidden', 'sortorder');
         $mform->setType('sortorder', PARAM_INT);
 
index 3fdb55f..8c20c6a 100644 (file)
@@ -72,15 +72,17 @@ $string['issuerimage'] = 'Logo URL';
 $string['issuerloginparams'] = 'Additional parameters included in a login request.';
 $string['issuerloginparams_help'] = 'Some systems require additional parameters for a login request in order to read the user\'s basic profile.';
 $string['issuerloginparamsoffline'] = 'Additional parameters included in a login request for offline access.';
-$string['issuerloginparamsoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Google requires the additional params: "access_type=offline&prompt=consent" these parameters should be in url query parameter format.';
-$string['issuerloginscopes_help'] = 'Some systems require additional scopes for a login request in order to read the users basic profile. The standard scopes for an OpenID Connect compliant system are "openid profile email".';
-$string['issuerloginscopesoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Microsoft requires an additional scope "offline_access"';
+$string['issuerloginparamsoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Google requires the additional params: "access_type=offline&prompt=consent". These parameters should be in URL query parameter format.';
+$string['issuerloginscopes_help'] = 'Some systems require additional scopes for a login request in order to read the user\'s basic profile. The standard scopes for an OpenID Connect compliant system are "openid profile email".';
+$string['issuerloginscopesoffline_help'] = 'Each OAuth system defines a different way to request offline access. E.g. Microsoft requires an additional scope "offline_access".';
 $string['issuerloginscopesoffline'] = 'Scopes included in a login request for offline access.';
 $string['issuerloginscopes'] = 'Scopes included in a login request.';
 $string['issuername_help'] = 'Name of the identity issuer. May be displayed on login page.';
 $string['issuername'] = 'Name';
-$string['issuershowonloginpage_help'] = 'If the OpenID Connect Authentication plugin is enabled, this login issuer will be listed on the login page to allow users to log in with accounts from this issuer.';
-$string['issuershowonloginpage'] = 'Show on login page.';
+$string['issuershowonloginpage_help'] = 'If the OAuth 2 authentication plugin is enabled, this login issuer will be listed on the login page to allow users to log in with accounts from this issuer.';
+$string['issuershowonloginpage'] = 'Show on login page';
+$string['issuerrequireconfirmation_help'] = 'Require that all users verify their email address before they can log in with OAuth. This applies to newly created accounts as part of the login process, or when an existing Moodle account is connected to an OAuth login via matching email addresses.';
+$string['issuerrequireconfirmation'] = 'Require email verification';
 $string['issuers'] = 'Issuers';
 $string['loginissuer'] = 'Allow login';
 $string['notconfigured'] = 'Not configured';
index 593ea98..8663112 100644 (file)
@@ -31,7 +31,7 @@ $string['default'] = 'Default';
 $string['disabled'] = 'Disabled';
 $string['disabled_help'] = 'Disabled scheduled tasks are not executed from cron, however they can still be executed manually via the CLI tool.';
 $string['edittaskschedule'] = 'Edit task schedule: {$a}';
-$string['enablerunnow'] = 'Allow &lsquo;Run now&rsquo; for scheduled tasks';
+$string['enablerunnow'] = 'Allow \'Run now\' for scheduled tasks';
 $string['enablerunnow_desc'] = 'Allows administrators to run a single scheduled task immediately, rather than waiting for it to run as scheduled. The task runs on the web server, so some sites may wish to disable this feature to avoid potential performance issues.';
 $string['faildelay'] = 'Fail delay';
 $string['lastruntime'] = 'Last run';
@@ -41,7 +41,7 @@ $string['pluginname'] = 'Scheduled task configuration';
 $string['resettasktodefaults'] = 'Reset task schedule to defaults';
 $string['resettasktodefaults_help'] = 'This will discard any local changes and revert the schedule for this task back to its original settings.';
 $string['runnow'] = 'Run now';
-$string['runnow_confirm'] = 'Are you sure you want to run this task &lsquo;{$a}&rsquo; now? The task will run on the web server and may take some time to complete.';
+$string['runnow_confirm'] = 'Are you sure you want to run this task \'{$a}\' now? The task will run on the web server and may take some time to complete.';
 $string['scheduledtasks'] = 'Scheduled tasks';
 $string['scheduledtaskchangesdisabled'] = 'Modifications to the list of scheduled tasks have been prevented in Moodle configuration';
 $string['taskdisabled'] = 'Task disabled';
index 75500b2..da1592e 100644 (file)
@@ -95,7 +95,7 @@ class tool_uploadcourse_course {
     /** @var array fields allowed as course data. */
     static protected $validfields = array('fullname', 'shortname', 'idnumber', 'category', 'visible', 'startdate', 'enddate',
         'summary', 'format', 'theme', 'lang', 'newsitems', 'showgrades', 'showreports', 'legacyfiles', 'maxbytes',
-        'groupmode', 'groupmodeforce', 'groupmodeforce', 'enablecompletion');
+        'groupmode', 'groupmodeforce', 'enablecompletion');
 
     /** @var array fields required on course creation. */
     static protected $mandatoryfields = array('fullname', 'category');
@@ -676,6 +676,17 @@ class tool_uploadcourse_course {
             return false;
         }
 
+        // TODO MDL-59259 allow to set course format options for the current course format.
+
+        // Special case, 'numsections' is not a course format option any more but still should apply from defaults.
+        if (!$exists || !array_key_exists('numsections', $coursedata)) {
+            if (isset($this->rawdata['numsections']) && is_numeric($this->rawdata['numsections'])) {
+                $coursedata['numsections'] = (int)$this->rawdata['numsections'];
+            } else {
+                $coursedata['numsections'] = get_config('moodlecourse', 'numsections');
+            }
+        }
+
         // Saving data.
         $this->data = $coursedata;
         $this->enrolmentdata = tool_uploadcourse_helper::get_enrolment_data($this->rawdata);
index 4601500..d3c5024 100644 (file)
@@ -166,6 +166,13 @@ class tool_uploadcourse_step2_form extends tool_uploadcourse_base_form {
         $mform->addHelpButton('defaults[groupmodeforce]', 'groupmodeforce', 'group');
         $mform->setDefault('defaults[groupmodeforce]', $courseconfig->groupmodeforce);
 
+        // Completion tracking.
+        if (!empty($CFG->enablecompletion)) {
+            $mform->addElement('selectyesno', 'defaults[enablecompletion]', get_string('enablecompletion', 'completion'));
+            $mform->setDefault('defaults[enablecompletion]', $courseconfig->enablecompletion);
+            $mform->addHelpButton('defaults[enablecompletion]', 'enablecompletion', 'completion');
+        }
+
         // Hidden fields.
         $mform->addElement('hidden', 'importid');
         $mform->setType('importid', PARAM_INT);
index 7d9970f..75c39d8 100644 (file)
@@ -166,6 +166,7 @@ $defaults['groupmode'] = $courseconfig->groupmode;
 $defaults['groupmodeforce'] = $courseconfig->groupmodeforce;
 $defaults['visible'] = $courseconfig->visible;
 $defaults['lang'] =  $courseconfig->lang;
+$defaults['enablecompletion'] = $courseconfig->enablecompletion;
 
 // Course template.
 if (isset($options['templatecourse'])) {
index 3ac9fe0..3356163 100644 (file)
@@ -120,6 +120,36 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
         $this->assertTrue($DB->record_exists('course', array('shortname' => 'c2')));
     }
 
+    public function test_create_with_sections() {
+        global $DB;
+        $this->resetAfterTest(true);
+        $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING;
+        $defaultnumsections = get_config('moodlecourse', 'numsections');
+
+        // Add new course, make sure default number of sections is created.
+        $mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
+        $data = array('shortname' => 'newcourse1', 'fullname' => 'New course1', 'format' => 'topics', 'category' => 1);
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data);
+        $this->assertTrue($co->prepare());
+        $co->proceed();
+        $courseid = $DB->get_field('course', 'id', array('shortname' => 'newcourse1'));
+        $this->assertNotEmpty($courseid);
+        $this->assertEquals($defaultnumsections + 1,
+            $DB->count_records('course_sections', ['course' => $courseid]));
+
+        // Add new course specifying number of sections.
+        $mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
+        $data = array('shortname' => 'newcourse2', 'fullname' => 'New course2', 'format' => 'topics', 'category' => 1,
+            'numsections' => 15);
+        $co = new tool_uploadcourse_course($mode, $updatemode, $data);
+        $this->assertTrue($co->prepare());
+        $co->proceed();
+        $courseid = $DB->get_field('course', 'id', array('shortname' => 'newcourse2'));
+        $this->assertNotEmpty($courseid);
+        $this->assertEquals(15 + 1,
+            $DB->count_records('course_sections', ['course' => $courseid]));
+    }
+
     public function test_delete() {
         global $DB;
         $this->resetAfterTest(true);
index 7282e28..522d6c6 100644 (file)
@@ -3187,6 +3187,18 @@ class CAS_Client
                 false/*$no_response*/, true/*$bad_response*/, $text_response
             );
             $result = false;
+       } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) {
+            // authentication failed, extract the error code and message and throw exception
+            $auth_fail_list = $tree_response
+                ->getElementsByTagName("authenticationFailure");
+            throw new CAS_AuthenticationException(
+                $this, 'Ticket not validated', $validate_url,
+                false/*$no_response*/, false/*$bad_response*/,
+                $text_response,
+                $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/,
+                trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/
+            );
+            $result = false;
         } else if ($tree_response->getElementsByTagName("authenticationSuccess")->length != 0) {
             // authentication succeded, extract the user name
             $success_elements = $tree_response
@@ -3227,18 +3239,6 @@ class CAS_Client
                     $result = true;
                 }
             }
-        } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) {
-            // authentication succeded, extract the error code and message
-            $auth_fail_list = $tree_response
-                ->getElementsByTagName("authenticationFailure");
-            throw new CAS_AuthenticationException(
-                $this, 'Ticket not validated', $validate_url,
-                false/*$no_response*/, false/*$bad_response*/,
-                $text_response,
-                $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/,
-                trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/
-            );
-            $result = false;
         } else {
             throw new CAS_AuthenticationException(
                 $this, 'Ticket not validated', $validate_url,
index e0d726d..2ef9d66 100644 (file)
@@ -2,3 +2,4 @@ Description of phpCAS 1.3.4 library import
 
 * downloaded from http://downloads.jasig.org/cas-clients/php/current/
 
+* MDL-59456 phpCAS library has been patched because of an authentication bypass security vulnerability.
\ No newline at end of file
index a17ef91..ce506d6 100644 (file)
@@ -30,28 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool result
  */
 function xmldb_auth_cas_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2014111001) {
-        // From now on the default LDAP objectClass setting for AD has been changed, from 'user' to '(samaccounttype=805306368)'.
-        if (is_enabled_auth('cas')
-                && ($DB->get_field('config_plugins', 'value', array('name' => 'user_type', 'plugin' => 'auth/cas')) === 'ad')
-                && ($DB->get_field('config_plugins', 'value', array('name' => 'objectclass', 'plugin' => 'auth/cas')) === '')) {
-            // Save the backwards-compatible default setting.
-            set_config('objectclass', 'user', 'auth/cas');
-        }
-
-        upgrade_plugin_savepoint(true, 2014111001, 'auth', 'cas');
-    }
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 3bf9979..baa86d9 100644 (file)
@@ -121,4 +121,98 @@ class core_auth_external extends external_api {
             )
         );
     }
+
+    /**
+     * Describes the parameters for request_password_reset.
+     *
+     * @return external_function_parameters
+     * @since Moodle 3.4
+     */
+    public static function request_password_reset_parameters() {
+        return new external_function_parameters(
+            array(
+                'username' => new external_value(core_user::get_property_type('username'), 'User name', VALUE_DEFAULT, ''),
+                'email' => new external_value(core_user::get_property_type('email'), 'User email', VALUE_DEFAULT, ''),
+            )
+        );
+    }
+
+    /**
+     * Requests a password reset.
+     *
+     * @param  string $username user name
+     * @param  string $email    user email
+     * @return array warnings and success status (including notices and errors while processing)
+     * @since Moodle 3.4
+     * @throws moodle_exception
+     */
+    public static function request_password_reset($username = '', $email = '') {
+        global $CFG, $PAGE;
+        require_once($CFG->dirroot . '/login/lib.php');
+
+        $warnings = array();
+        $params = self::validate_parameters(
+            self::request_password_reset_parameters(),
+            array(
+                'username' => $username,
+                'email' => $email,
+            )
+        );
+
+        $context = context_system::instance();
+        $PAGE->set_context($context);   // Needed by format_string calls.
+
+        // Check if an alternate forgotten password method is set.
+        if (!empty($CFG->forgottenpasswordurl)) {
+            throw new moodle_exception('cannotmailconfirm');
+        }
+
+        $errors = core_login_validate_forgot_password_data($params);
+        if (!empty($errors)) {
+            $status = 'dataerror';
+            $notice = '';
+
+            foreach ($errors as $itemname => $message) {
+                $warnings[] = array(
+                    'item' => $itemname,
+                    'itemid' => 0,
+                    'warningcode' => 'fielderror',
+                    'message' => s($message)
+                );
+            }
+        } else {
+            list($status, $notice, $url) = core_login_process_password_reset($params['username'], $params['email']);
+        }
+
+        return array(
+            'status' => $status,
+            'notice' => $notice,
+            'warnings' => $warnings,
+        );
+    }
+
+    /**
+     * Describes the request_password_reset return value.
+     *
+     * @return external_single_structure
+     * @since Moodle 3.4
+     */
+    public static function request_password_reset_returns() {
+
+        return new external_single_structure(
+            array(
+                'status' => new external_value(PARAM_ALPHANUMEXT, 'The returned status of the process:
+                    dataerror: Error in the sent data (username or email). More information in warnings field.
+                    emailpasswordconfirmmaybesent: Email sent or not (depends on user found in database).
+                    emailpasswordconfirmnotsent: Failure, user not found.
+                    emailpasswordconfirmnoemail: Failure, email not found.
+                    emailalreadysent: Email already sent.
+                    emailpasswordconfirmsent: User pending confirmation.
+                    emailresetconfirmsent: Email sent.
+                '),
+                'notice' => new external_value(PARAM_RAW, 'Important information for the user about the process.'),
+                'warnings'  => new external_warnings(),
+            )
+        );
+    }
 }
index a2fe48e..3e1c58f 100644 (file)
@@ -30,28 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool result
  */
 function xmldb_auth_ldap_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2014111001) {
-        // From now on the default LDAP objectClass setting for AD has been changed, from 'user' to '(samaccounttype=805306368)'.
-        if (is_enabled_auth('ldap')
-                && ($DB->get_field('config_plugins', 'value', array('name' => 'user_type', 'plugin' => 'auth/ldap')) === 'ad')
-                && ($DB->get_field('config_plugins', 'value', array('name' => 'objectclass', 'plugin' => 'auth/ldap')) === '')) {
-            // Save the backwards-compatible default setting.
-            set_config('objectclass', 'user', 'auth/ldap');
-        }
-
-        upgrade_plugin_savepoint(true, 2014111001, 'auth', 'ldap');
-    }
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 6a947d8..a73861d 100644 (file)
@@ -30,16 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool result
  */
 function xmldb_auth_manual_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index c66ead0..99e326c 100644 (file)
@@ -30,16 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool result
  */
 function xmldb_auth_mnet_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 9d678a8..1b152b5 100644 (file)
@@ -239,6 +239,50 @@ class api {
         return true;
     }
 
+    /**
+     * Create an account with a linked login that is already confirmed.
+     *
+     * @param array $userinfo as returned from an oauth client.
+     * @param \core\oauth2\issuer $issuer
+     * @return bool
+     */
+    public static function create_new_confirmed_account($userinfo, $issuer) {
+        global $CFG, $DB;
+        require_once($CFG->dirroot.'/user/profile/lib.php');
+        require_once($CFG->dirroot.'/user/lib.php');
+
+        $user = new stdClass();
+        $user->username = $userinfo['username'];
+        $user->email = $userinfo['email'];
+        $user->auth = 'oauth2';
+        $user->mnethostid = $CFG->mnet_localhost_id;
+        $user->lastname = isset($userinfo['lastname']) ? $userinfo['lastname'] : '';
+        $user->firstname = isset($userinfo['firstname']) ? $userinfo['firstname'] : '';
+        $user->url = isset($userinfo['url']) ? $userinfo['url'] : '';
+        $user->alternatename = isset($userinfo['alternatename']) ? $userinfo['alternatename'] : '';
+        $user->secret = random_string(15);
+
+        $user->password = '';
+        // This user is confirmed.
+        $user->confirmed = 1;
+
+        $user->id = user_create_user($user, false, true);
+
+        // The linked account is pre-confirmed.
+        $record = new stdClass();
+        $record->issuerid = $issuer->get('id');
+        $record->username = $userinfo['username'];
+        $record->userid = $user->id;
+        $record->email = $userinfo['email'];
+        $record->confirmtoken = '';
+        $record->confirmtokenexpires = 0;
+
+        $linkedlogin = new linked_login(0, $record);
+        $linkedlogin->create();
+
+        return $user;
+    }
+
     /**
      * Send an email with a link to confirm creating this account.
      *
index aa5f70c..be99012 100644 (file)
@@ -450,15 +450,21 @@ class auth extends \auth_plugin_base {
 
             $moodleuser = \core_user::get_user_by_email($userinfo['email']);
             if (!empty($moodleuser)) {
-                $PAGE->set_url('/auth/oauth2/confirm-link-login.php');
-                $PAGE->set_context(context_system::instance());
-
-                \auth_oauth2\api::send_confirm_link_login_email($userinfo, $issuer, $moodleuser->id);
-                // Request to link to existing account.
-                $emailconfirm = get_string('emailconfirmlink', 'auth_oauth2');
-                $message = get_string('emailconfirmlinksent', 'auth_oauth2', $moodleuser->email);
-                $this->print_confirm_required($emailconfirm, $message);
-                exit();
+                if ($issuer->get('requireconfirmation')) {
+                    $PAGE->set_url('/auth/oauth2/confirm-link-login.php');
+                    $PAGE->set_context(context_system::instance());
+
+                    \auth_oauth2\api::send_confirm_link_login_email($userinfo, $issuer, $moodleuser->id);
+                    // Request to link to existing account.
+                    $emailconfirm = get_string('emailconfirmlink', 'auth_oauth2');
+                    $message = get_string('emailconfirmlinksent', 'auth_oauth2', $moodleuser->email);
+                    $this->print_confirm_required($emailconfirm, $message);
+                    exit();
+                } else {
+                    \auth_oauth2\api::link_login($userinfo, $issuer, $moodleuser->id, true);
+                    $userinfo = get_complete_user_data('id', $moodleuser->id);
+                    // No redirect, we will complete this login.
+                }
 
             } else {
                 // This is a new account.
@@ -506,17 +512,25 @@ class auth extends \auth_plugin_base {
                     redirect(new moodle_url($CFG->httpswwwroot . '/login/index.php'));
                 }
 
-                $PAGE->set_url('/auth/oauth2/confirm-account.php');
-                $PAGE->set_context(context_system::instance());
+                if ($issuer->get('requireconfirmation')) {
+                    $PAGE->set_url('/auth/oauth2/confirm-account.php');
+                    $PAGE->set_context(context_system::instance());
 
-                // Create a new (unconfirmed account) and send an email to confirm it.
-                $user = \auth_oauth2\api::send_confirm_account_email($userinfo, $issuer);
+                    // Create a new (unconfirmed account) and send an email to confirm it.
+                    $user = \auth_oauth2\api::send_confirm_account_email($userinfo, $issuer);
 
-                $this->update_picture($user);
-                $emailconfirm = get_string('emailconfirm');
-                $message = get_string('emailconfirmsent', '', $userinfo['email']);
-                $this->print_confirm_required($emailconfirm, $message);
-                exit();
+                    $this->update_picture($user);
+                    $emailconfirm = get_string('emailconfirm');
+                    $message = get_string('emailconfirmsent', '', $userinfo['email']);
+                    $this->print_confirm_required($emailconfirm, $message);
+                    exit();
+                } else {
+                    // Create a new confirmed account.
+                    $newuser = \auth_oauth2\api::create_new_confirmed_account($userinfo, $issuer);
+                    $userinfo = get_complete_user_data('id', $newuser->id);
+
+                    // No redirect, we will complete this login.
+                }
             }
         }
 
index 817430a..83bf1a6 100644 (file)
@@ -98,4 +98,46 @@ class auth_oauth2_external_testcase extends advanced_testcase {
         $this->assertCount(1, $linkedlogins);
     }
 
+    /**
+     * Test auto-confirming linked logins.
+     */
+    public function test_linked_logins() {
+        $this->resetAfterTest();
+
+        $this->setAdminUser();
+        $issuer = \core\oauth2\api::create_standard_issuer('google');
+
+        $user = $this->getDataGenerator()->create_user();
+
+        $info = [];
+        $info['username'] = 'banana';
+        $info['email'] = 'banana@example.com';
+
+        \auth_oauth2\api::link_login($info, $issuer, $user->id, false);
+
+        // Try and match a user with a linked login.
+        $match = \auth_oauth2\api::match_username_to_user('banana', $issuer);
+
+        $this->assertEquals($user->id, $match->get('userid'));
+        $linkedlogins = \auth_oauth2\api::get_linked_logins($user->id, $issuer);
+        \auth_oauth2\api::delete_linked_login($linkedlogins[0]->get('id'));
+
+        $match = \auth_oauth2\api::match_username_to_user('banana', $issuer);
+        $this->assertFalse($match);
+
+        $info = [];
+        $info['username'] = 'apple';
+        $info['email'] = 'apple@example.com';
+        $info['firstname'] = 'Apple';
+        $info['lastname'] = 'Fruit';
+        $info['url'] = 'http://apple.com/';
+        $info['alternamename'] = 'Beatles';
+
+        $newuser = \auth_oauth2\api::create_new_confirmed_account($info, $issuer);
+
+        $match = \auth_oauth2\api::match_username_to_user('apple', $issuer);
+
+        $this->assertEquals($newuser->id, $match->get('userid'));
+    }
+
 }
index 2ea5248..b0c6e89 100644 (file)
@@ -1410,8 +1410,9 @@ class backup_block_instance_structure_step extends backup_structure_step {
         // Define each element separated
 
         $block = new backup_nested_element('block', array('id', 'contextid', 'version'), array(
-            'blockname', 'parentcontextid', 'showinsubcontexts', 'pagetypepattern',
-            'subpagepattern', 'defaultregion', 'defaultweight', 'configdata'));
+                'blockname', 'parentcontextid', 'showinsubcontexts', 'pagetypepattern',
+                'subpagepattern', 'defaultregion', 'defaultweight', 'configdata',
+                'timecreated', 'timemodified'));
 
         $positions = new backup_nested_element('block_positions');
 
index f886496..00132f6 100644 (file)
@@ -3937,6 +3937,14 @@ class restore_block_instance_structure_step extends restore_structure_step {
             $data->configdata = base64_encode(serialize((object)$configdata));
         }
 
+        // Set timecreated, timemodified if not included (older backup).
+        if (empty($data->timecreated)) {
+            $data->timecreated = time();
+        }
+        if (empty($data->timemodified)) {
+            $data->timemodified = $data->timecreated;
+        }
+
         // Create the block instance
         $newitemid = $DB->insert_record('block_instances', $data);
         // Save the mapping (with restorefiles support)
index a5f531c..21773b9 100644 (file)
@@ -464,9 +464,10 @@ class core_backup_moodle2_testcase extends advanced_testcase {
      *
      * @param stdClass $course Course object to backup
      * @param int $newdate If non-zero, specifies custom date for new course
+     * @param callable|null $inbetween If specified, function that is called before restore
      * @return int ID of newly restored course
      */
-    protected function backup_and_restore($course, $newdate = 0) {
+    protected function backup_and_restore($course, $newdate = 0, $inbetween = null) {
         global $USER, $CFG;
 
         // Turn off file logging, otherwise it can't delete the file (Windows).
@@ -481,6 +482,10 @@ class core_backup_moodle2_testcase extends advanced_testcase {
         $bc->execute_plan();
         $bc->destroy();
 
+        if ($inbetween) {
+            $inbetween($backupid);
+        }
+
         // Do restore to new course with default settings.
         $newcourseid = restore_dbops::create_new_course(
                 $course->fullname, $course->shortname . '_2', $course->category);
@@ -802,4 +807,64 @@ class core_backup_moodle2_testcase extends advanced_testcase {
         $enrolment = reset($enrolments);
         $this->assertEquals('self', $enrolment->enrol);
     }
+
+    /**
+     * Test the block instance time fields (timecreated, timemodified) through a backup and restore.
+     */
+    public function test_block_instance_times_backup() {
+        global $DB;
+        $this->resetAfterTest();
+
+        $this->setAdminUser();
+        $generator = $this->getDataGenerator();
+
+        // Create course and add HTML block.
+        $course = $generator->create_course();
+        $context = context_course::instance($course->id);
+        $page = new moodle_page();
+        $page->set_context($context);
+        $page->set_course($course);
+        $page->set_pagelayout('standard');
+        $page->set_pagetype('course-view');
+        $page->blocks->load_blocks();
+        $page->blocks->add_block_at_end_of_default_region('html');
+
+        // Update (hack in database) timemodified and timecreated to specific values for testing.
+        $blockdata = $DB->get_record('block_instances',
+                ['blockname' => 'html', 'parentcontextid' => $context->id]);
+        $originalblockid = $blockdata->id;
+        $blockdata->timecreated = 12345;
+        $blockdata->timemodified = 67890;
+        $DB->update_record('block_instances', $blockdata);
+
+        // Do backup and restore.
+        $newcourseid = $this->backup_and_restore($course);
+
+        // Confirm that values were transferred correctly into HTML block on new course.
+        $newcontext = context_course::instance($newcourseid);
+        $blockdata = $DB->get_record('block_instances',
+                ['blockname' => 'html', 'parentcontextid' => $newcontext->id]);
+        $this->assertEquals(12345, $blockdata->timecreated);
+        $this->assertEquals(67890, $blockdata->timemodified);
+
+        // Simulate what happens with an older backup that doesn't have those fields, by removing
+        // them from the backup before doing a restore.
+        $before = time();
+        $newcourseid = $this->backup_and_restore($course, 0, function($backupid) use($originalblockid) {
+            global $CFG;
+            $path = $CFG->dataroot . '/temp/backup/' . $backupid . '/course/blocks/html_' .
+                    $originalblockid . '/block.xml';
+            $xml = file_get_contents($path);
+            $xml = preg_replace('~<timecreated>.*?</timemodified>~s', '', $xml);
+            file_put_contents($path, $xml);
+        });
+        $after = time();
+
+        // The fields not specified should default to current time.
+        $newcontext = context_course::instance($newcourseid);
+        $blockdata = $DB->get_record('block_instances',
+                ['blockname' => 'html', 'parentcontextid' => $newcontext->id]);
+        $this->assertTrue($before <= $blockdata->timecreated && $after >= $blockdata->timecreated);
+        $this->assertTrue($before <= $blockdata->timemodified && $after >= $blockdata->timemodified);
+    }
 }
index 7d529ad..7c73f83 100644 (file)
  * @param object $block
  */
 function xmldb_block_badges_upgrade($oldversion, $block) {
-    global $DB;
-
-    if ($oldversion < 2014062600) {
-        // Add this block the default blocks on /my.
-        $blockname = 'badges';
-
-        // Do not try to add the block if we cannot find the default my_pages entry.
-        // Private => 1 refers to MY_PAGE_PRIVATE.
-        if ($systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => 1))) {
-            $page = new moodle_page();
-            $page->set_context(context_system::instance());
-
-            // Check to see if this block is already on the default /my page.
-            $criteria = array(
-                'blockname' => $blockname,
-                'parentcontextid' => $page->context->id,
-                'pagetypepattern' => 'my-index',
-                'subpagepattern' => $systempage->id,
-            );
-
-            if (!$DB->record_exists('block_instances', $criteria)) {
-                // Add the block to the default /my.
-                $page->blocks->add_region(BLOCK_POS_RIGHT);
-                $page->blocks->add_block($blockname, BLOCK_POS_RIGHT, 0, false, 'my-index', $systempage->id);
-            }
-        }
-
-        upgrade_block_savepoint(true, 2014062600, $blockname);
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 09f73a6..1d287b5 100644 (file)
  * @param object $block
  */
 function xmldb_block_calendar_month_upgrade($oldversion, $block) {
-    global $DB;
-
-    if ($oldversion < 2014062600) {
-        // Add this block the default blocks on /my.
-        $blockname = 'calendar_month';
-
-        // Do not try to add the block if we cannot find the default my_pages entry.
-        // Private => 1 refers to MY_PAGE_PRIVATE.
-        if ($systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => 1))) {
-            $page = new moodle_page();
-            $page->set_context(context_system::instance());
-
-            // Check to see if this block is already on the default /my page.
-            $criteria = array(
-                'blockname' => $blockname,
-                'parentcontextid' => $page->context->id,
-                'pagetypepattern' => 'my-index',
-                'subpagepattern' => $systempage->id,
-            );
-
-            if (!$DB->record_exists('block_instances', $criteria)) {
-                // Add the block to the default /my.
-                $page->blocks->add_region(BLOCK_POS_RIGHT);
-                $page->blocks->add_block($blockname, BLOCK_POS_RIGHT, 0, false, 'my-index', $systempage->id);
-            }
-        }
-
-        upgrade_block_savepoint(true, 2014062600, $blockname);
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index d867d08..df77631 100644 (file)
  * @param object $block
  */
 function xmldb_block_calendar_upcoming_upgrade($oldversion, $block) {
-    global $DB;
-
-    if ($oldversion < 2014062600) {
-        // Add this block the default blocks on /my.
-        $blockname = 'calendar_upcoming';
-
-        // Do not try to add the block if we cannot find the default my_pages entry.
-        // Private => 1 refers to MY_PAGE_PRIVATE.
-        if ($systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => 1))) {
-            $page = new moodle_page();
-            $page->set_context(context_system::instance());
-
-            // Check to see if this block is already on the default /my page.
-            $criteria = array(
-                'blockname' => $blockname,
-                'parentcontextid' => $page->context->id,
-                'pagetypepattern' => 'my-index',
-                'subpagepattern' => $systempage->id,
-            );
-
-            if (!$DB->record_exists('block_instances', $criteria)) {
-                // Add the block to the default /my.
-                $page->blocks->add_region(BLOCK_POS_RIGHT);
-                $page->blocks->add_block($blockname, BLOCK_POS_RIGHT, 0, false, 'my-index', $systempage->id);
-            }
-        }
-
-        upgrade_block_savepoint(true, 2014062600, $blockname);
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 12ae568..efb36bd 100644 (file)
@@ -46,15 +46,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_community_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index a04db38..e345754 100644 (file)
@@ -48,15 +48,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_completionstatus_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 3d972ce..bf3ccdd 100644 (file)
@@ -48,15 +48,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_course_summary_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
diff --git a/blocks/html/classes/search/content.php b/blocks/html/classes/search/content.php
new file mode 100644 (file)
index 0000000..32b20b9
--- /dev/null
@@ -0,0 +1,91 @@
+<?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/>.
+
+/**
+ * Search area for block_html blocks
+ *
+ * @package block_html
+ * @copyright 2017 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_html\search;
+
+use core_search\moodle_recordset;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Search area for block_html blocks
+ *
+ * @package block_html
+ * @copyright 2017 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class content extends \core_search\base_block {
+
+    public function get_document($record, $options = array()) {
+        // Create empty document.
+        $doc = \core_search\document_factory::instance($record->id,
+                $this->componentname, $this->areaname);
+
+        // Get stdclass object with data from DB.
+        $data = unserialize(base64_decode($record->configdata));
+
+        // Get content.
+        $content = content_to_text($data->text, $data->format);
+        $doc->set('content', $content);
+
+        if (isset($data->title)) {
+            // If there is a title, use it as title.
+            $doc->set('title', content_to_text($data->title, false));
+        } else {
+            // If there is no title, use the content text again.
+            $doc->set('title', shorten_text($content));
+        }
+
+        // Set standard fields.
+        $doc->set('contextid', $record->contextid);
+        $doc->set('type', \core_search\manager::TYPE_TEXT);
+        $doc->set('courseid', $record->courseid);
+        $doc->set('modified', $record->timemodified);
+        $doc->set('owneruserid', \core_search\manager::NO_OWNER_ID);
+
+        // Mark document new if appropriate.
+        if (isset($options['lastindexedtime']) &&
+                ($options['lastindexedtime'] < $record->timecreated)) {
+            // If the document was created after the last index time, it must be new.
+            $doc->set_is_new(true);
+        }
+
+        return $doc;
+    }
+
+    public function uses_file_indexing() {
+        return true;
+    }
+
+    public function attach_files($document) {
+        $fs = get_file_storage();
+
+        $context = \context::instance_by_id($document->get('contextid'));
+
+        $files = $fs->get_area_files($context->id, 'block_html', 'content');
+        foreach ($files as $file) {
+            $document->add_stored_file($file);
+        }
+    }
+}
index 2899efe..36ee50b 100644 (file)
@@ -33,15 +33,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_html_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index bf6df6f..7eb2ad4 100644 (file)
@@ -33,3 +33,4 @@ $string['html:myaddinstance'] = 'Add a new HTML block to Dashboard';
 $string['leaveblanktohide'] = 'leave blank to hide the title';
 $string['newhtmlblock'] = '(new HTML block)';
 $string['pluginname'] = 'HTML';
+$string['search:content'] = 'HTML block content';
index 531a32a..a86b827 100644 (file)
@@ -104,7 +104,8 @@ function block_html_global_db_replace($search, $replace) {
         $config = unserialize(base64_decode($instance->configdata));
         if (isset($config->text) and is_string($config->text)) {
             $config->text = str_replace($search, $replace, $config->text);
-            $DB->set_field('block_instances', 'configdata', base64_encode(serialize($config)), array('id' => $instance->id));
+            $DB->update_record('block_instances', ['id' => $instance->id,
+                    'configdata' => base64_encode(serialize($config)), 'timemodified' => time()]);
         }
     }
     $instances->close();
diff --git a/blocks/html/tests/search_content_test.php b/blocks/html/tests/search_content_test.php
new file mode 100644 (file)
index 0000000..5afb8cd
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Unit test for search indexing.
+ *
+ * @package block_html
+ * @copyright 2017 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_html;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Unit test for search indexing.
+ *
+ * @package block_html
+ * @copyright 2017 The Open University
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class search_content_testcase extends \advanced_testcase {
+
+    /**
+     * Creates an HTML block on a course.
+     *
+     * @param \stdClass $course Course object
+     * @return \block_html Block instance object
+     */
+    protected function create_block($course) {
+        $page = self::construct_page($course);
+        $page->blocks->add_block_at_end_of_default_region('html');
+
+        // Load the block.
+        $page = self::construct_page($course);
+        $page->blocks->load_blocks();
+        $blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region());
+        $block = end($blocks);
+        return $block;
+    }
+
+    /**
+     * Constructs a page object for the test course.
+     *
+     * @param \stdClass $course Moodle course object
+     * @return \moodle_page Page object representing course view
+     */
+    protected static function construct_page($course) {
+        $context = \context_course::instance($course->id);
+        $page = new \moodle_page();
+        $page->set_context($context);
+        $page->set_course($course);
+        $page->set_pagelayout('standard');
+        $page->set_pagetype('course-view');
+        $page->blocks->load_blocks();
+        return $page;
+    }
+
+    /**
+     * Tests all functionality in the search area.
+     */
+    public function test_search_area() {
+        global $CFG, $USER, $DB;
+        require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
+
+        $this->resetAfterTest();
+        $this->setAdminUser();
+
+        // Create course and add HTML block.
+        $generator = $this->getDataGenerator();
+        $course = $generator->create_course();
+        $before = time();
+        $block = $this->create_block($course);
+
+        // Change block settings to add some text and a file.
+        $itemid = file_get_unused_draft_itemid();
+        $fs = get_file_storage();
+        $usercontext = \context_user::instance($USER->id);
+        $fs->create_file_from_string(['component' => 'user', 'filearea' => 'draft',
+                'contextid' => $usercontext->id, 'itemid' => $itemid, 'filepath' => '/',
+                'filename' => 'file.txt'], 'File content');
+        $data = (object)['title' => 'Block title', 'text' => ['text' => 'Block text',
+                'itemid' => $itemid, 'format' => FORMAT_HTML]];
+        $block->instance_config_save($data);
+        $after = time();
+
+        // Set up fake search engine so we can create documents.
+        \testable_core_search::instance();
+
+        // Do indexing query.
+        $area = new \block_html\search\content();
+        $this->assertEquals('html', $area->get_block_name());
+        $rs = $area->get_recordset_by_timestamp();
+        $count = 0;
+        foreach ($rs as $record) {
+            $count++;
+
+            $this->assertEquals($course->id, $record->courseid);
+
+            // Check context is correct.
+            $blockcontext = \context::instance_by_id($record->contextid);
+            $this->assertInstanceOf('\context_block', $blockcontext);
+            $coursecontext = $blockcontext->get_parent_context();
+            $this->assertEquals($course->id, $coursecontext->instanceid);
+
+            // Check created and modified times are correct.
+            $this->assertTrue($record->timecreated >= $before && $record->timecreated <= $after);
+            $this->assertTrue($record->timemodified >= $before && $record->timemodified <= $after);
+
+            // Get config data.
+            $data = unserialize(base64_decode($record->configdata));
+            $this->assertEquals('Block title', $data->title);
+            $this->assertEquals('Block text', $data->text);
+            $this->assertEquals(FORMAT_HTML, $data->format);
+
+            // Check the get_document function 'new' flag.
+            $doc = $area->get_document($record, ['lastindexedtime' => 1]);
+            $this->assertTrue($doc->get_is_new());
+            $doc = $area->get_document($record, ['lastindexedtime' => time() + 1]);
+            $this->assertFalse($doc->get_is_new());
+
+            // Check the attach_files function results in correct list of associated files.
+            $this->assertCount(0, $doc->get_files());
+            $area->attach_files($doc);
+            $files = $doc->get_files();
+            $this->assertCount(2, $files);
+            foreach ($files as $file) {
+                if ($file->is_directory()) {
+                    continue;
+                }
+                $this->assertEquals('file.txt', $file->get_filename());
+                $this->assertEquals('File content', $file->get_content());
+            }
+
+            // Check the document fields are all as expected.
+            $this->assertEquals('Block title', $doc->get('title'));
+            $this->assertEquals('Block text', $doc->get('content'));
+            $this->assertEquals($blockcontext->id, $doc->get('contextid'));
+            $this->assertEquals(\core_search\manager::TYPE_TEXT, $doc->get('type'));
+            $this->assertEquals($course->id, $doc->get('courseid'));
+            $this->assertEquals($record->timemodified, $doc->get('modified'));
+            $this->assertEquals(\core_search\manager::NO_OWNER_ID, $doc->get('owneruserid'));
+
+            // Also check getting the doc url and context url.
+            $url = new \moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $record->id);
+            $this->assertTrue($url->compare($area->get_doc_url($doc)));
+            $this->assertTrue($url->compare($area->get_context_url($doc)));
+        }
+        $rs->close();
+
+        // Should only be one HTML block systemwide.
+        $this->assertEquals(1, $count);
+
+        // If we run the query starting from 1 second after now, there should be no results.
+        $rs = $area->get_recordset_by_timestamp($after + 1);
+        $count = 0;
+        foreach ($rs as $record) {
+            $count++;
+        }
+        $rs->close();
+        $this->assertEquals(0, $count);
+
+        // Create another block, but this time leave it empty (no data set). Hack the time though.
+        $block = $this->create_block($course);
+        $DB->set_field('block_instances', 'timemodified',
+                $after + 10, ['id' => $block->instance->id]);
+        $rs = $area->get_recordset_by_timestamp($after + 10);
+        $count = 0;
+        foreach ($rs as $record) {
+            // Because there is no configdata we don't index it.
+            $count++;
+        }
+        $rs->close();
+        $this->assertEquals(0, $count);
+    }
+}
+
index 636b1ba..e8f2491 100644 (file)
@@ -115,7 +115,7 @@ class block_login extends block_base {
                 $this->content->text .= '<div class="potentialidplist">';
                 foreach ($potentialidps as $idp) {
                     $this->content->text .= '<div class="potentialidp">';
-                    $this->content->text .= '<a class="btn btn-secondary btn-block" ';
+                    $this->content->text .= '<a class="btn btn-default btn-block" ';
                     $this->content->text .= 'href="' . $idp['url']->out() . '" title="' . s($idp['name']) . '">';
                     if (!empty($idp['iconurl'])) {
                         $this->content->text .= '<img src="' . s($idp['iconurl']) . '" width="24" height="24" class="m-r-1"/>';
index 57ae2b3..a81f7ac 100644 (file)
@@ -474,8 +474,8 @@ class block_base {
      */
     function instance_config_save($data, $nolongerused = false) {
         global $DB;
-        $DB->set_field('block_instances', 'configdata', base64_encode(serialize($data)),
-                array('id' => $this->instance->id));
+        $DB->update_record('block_instances', ['id' => $this->instance->id,
+                'configdata' => base64_encode(serialize($data)), 'timemodified' => time()]);
     }
 
     /**
index 99fb83f..2176ec5 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 $string['defaulttab'] = 'Default tab';
-$string['defaulttab_desc'] = 'This is the default tab that will be shown to a user.';
+$string['defaulttab_desc'] = 'The tab that will be displayed when a user first views their course overview. When returning to their course overview, the user\'s active tab is remembered.';
 $string['future'] = 'Future';
 $string['inprogress'] = 'In progress';
 $string['morecourses'] = 'More courses';
index 538c829..1f9ff6d 100644 (file)
@@ -55,15 +55,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_navigation_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index aeb75be..a850602 100644 (file)
@@ -30,7 +30,6 @@ Feature: People Block used in a course
     And I am on "Course 1" course homepage
     And I click on "Participants" "link" in the "People" "block"
     Then I should see "All participants" in the "#page-content" "css_element"
-    And the "My courses" select box should contain "C101"
 
   Scenario: Student without permission can not view participants link
     Given the following "permission overrides" exist:
index 68dfa30..20f93f7 100644 (file)
  * @param object $block
  */
 function xmldb_block_quiz_results_upgrade($oldversion, $block) {
-    global $DB, $CFG;
-
-    if ($oldversion < 2015022200) {
-        // Only migrate if the block_activity_results is installed.
-        if (is_dir($CFG->dirroot . '/blocks/activity_results')) {
-
-            // Migrate all instances of block_quiz_results to block_activity_results.
-            $records = $DB->get_records('block_instances', array('blockname' => 'quiz_results'));
-            foreach ($records as $record) {
-                $configdata = '';
-
-                // The block was configured.
-                if (!empty($record->configdata)) {
-
-                    $config = unserialize(base64_decode($record->configdata));
-                    $config->activityparent = 'quiz';
-                    $config->activityparentid = isset($config->quizid) ? $config->quizid : 0;
-                    $config->gradeformat = isset($config->gradeformat) ? $config->gradeformat : 1;
-
-                    // Set the decimal valuue as appropriate.
-                    if ($config->gradeformat == 1) {
-                        // This block is using percentages, do not display any decimal places.
-                        $config->decimalpoints = 0;
-                    } else {
-                        // Get the decimal value from the corresponding quiz.
-                        $config->decimalpoints = $DB->get_field('quiz', 'decimalpoints', array('id' => $config->activityparentid));
-                    }
-
-                    // Get the grade_items record to set the activitygradeitemid.
-                    $info = $DB->get_record('grade_items',
-                            array('iteminstance' => $config->activityparentid, 'itemmodule' => $config->activityparent));
-                    $config->activitygradeitemid = 0;
-                    if ($info) {
-                        $config->activitygradeitemid = $info->id;
-                    }
-
-                    unset($config->quizid);
-                    $configdata = base64_encode(serialize($config));
-                }
-
-                // Save the new configuration and update the record.
-                $record->configdata = $configdata;
-                $record->blockname = 'activity_results';
-                $DB->update_record('block_instances', $record);
-            }
-
-            // Disable the Quiz_results block.
-            if ($block = $DB->get_record("block", array("name" => "quiz_results"))) {
-                $DB->set_field("block", "visible", "0", array("id" => $block->id));
-            }
-
-        }
-        upgrade_block_savepoint(true, 2015022200, 'quiz_results');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
@@ -117,4 +55,4 @@ function xmldb_block_quiz_results_upgrade($oldversion, $block) {
     // Put any upgrade step following this.
 
     return true;
-}
\ No newline at end of file
+}
index 186c752..dfc2c41 100644 (file)
@@ -47,15 +47,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_recent_activity_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 78e0c0a..f0b8caf 100644 (file)
@@ -31,27 +31,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return boolean
  */
 function xmldb_block_rss_client_upgrade($oldversion) {
-    global $DB;
-    $dbman = $DB->get_manager();
-
-    if ($oldversion < 2015071700) {
-        // Support for skipping RSS feeds for a while when they fail.
-        $table = new xmldb_table('block_rss_client');
-        // How many seconds we are currently ignoring this RSS feed for (due to an error).
-        $field = new xmldb_field('skiptime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'url');
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-        // When to next update this RSS feed.
-        $field = new xmldb_field('skipuntil', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'skiptime');
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-        upgrade_block_savepoint(true, 2015071700, 'rss_client');
-    }
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 397768a..6eca3b6 100644 (file)
@@ -49,15 +49,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_section_links_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index cc7971d..0d50fed 100644 (file)
@@ -48,15 +48,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_selfcompletion_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index b48a648..0bb3bfb 100644 (file)
@@ -55,15 +55,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_block_settings_upgrade($oldversion, $block) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 0fa83c7..6b8fc56 100644 (file)
@@ -1,6 +1,15 @@
 This files describes API changes in /blocks/* - activity modules,
 information provided here is intended especially for developers.
 
+=== 3.4 ===
+
+* The block_instances table now contains fields timecreated and timemodified. If third-party code
+  creates or updates these rows (without using the standard API), it should be modified to set
+  these fields as appropriate.
+* Blocks can now be included in Moodle global search, with some limitations (at present, the search
+  works only for blocks located directly on course pages or site home page). See the HTML block for
+  an example.
+
 === 3.3 ===
 
 * block_manager::get_required_by_theme_block_types() is no longer static.
index 6ae461d..9abfe0e 100644 (file)
@@ -335,6 +335,15 @@ class cache_factory {
         return $this->cachesfromdefinitions;
     }
 
+    /**
+     * Gets all adhoc caches that have been used within this request.
+     *
+     * @return cache_store[] Caches currently in use
+     */
+    public function get_adhoc_caches_in_use() {
+        return $this->cachesfromparams;
+    }
+
     /**
      * Creates a cache config instance with the ability to write if required.
      *
index f15e2ee..c2aa399 100644 (file)
@@ -484,6 +484,9 @@ class cache_helper {
         foreach ($config->get_all_stores() as $store) {
             self::purge_store($store['name'], $config);
         }
+        foreach ($factory->get_adhoc_caches_in_use() as $cache) {
+            $cache->purge();
+        }
     }
 
     /**
index 0a47e4f..8d04cd1 100644 (file)
@@ -1730,6 +1730,16 @@ class core_cache_testcase extends advanced_testcase {
         }
     }
 
+    /**
+     * Tests that ad-hoc caches are correctly purged with a purge_all call.
+     */
+    public function test_purge_all_with_adhoc_caches() {
+        $cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'core_cache', 'test');
+        $cache->set('test', 123);
+        cache_helper::purge_all();
+        $this->assertFalse($cache->get('test'));
+    }
+
     /**
      * Test that the default stores all support searching.
      */
diff --git a/calendar/amd/build/calendar.min.js b/calendar/amd/build/calendar.min.js
new file mode 100644 (file)
index 0000000..67a1cb2
Binary files /dev/null and b/calendar/amd/build/calendar.min.js differ
diff --git a/calendar/amd/build/calendar_repository.min.js b/calendar/amd/build/calendar_repository.min.js
new file mode 100644 (file)
index 0000000..156cad8
Binary files /dev/null and b/calendar/amd/build/calendar_repository.min.js differ
diff --git a/calendar/amd/build/summary_modal.min.js b/calendar/amd/build/summary_modal.min.js
new file mode 100644 (file)
index 0000000..bb8b25a
Binary files /dev/null and b/calendar/amd/build/summary_modal.min.js differ
diff --git a/calendar/amd/src/calendar.js b/calendar/amd/src/calendar.js
new file mode 100644 (file)
index 0000000..ace3364
--- /dev/null
@@ -0,0 +1,117 @@
+// 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/>.
+
+/**
+ * A javascript module to calendar events.
+ *
+ * @module     core_calendar/calendar
+ * @package    core_calendar
+ * @copyright  2017 Simey Lameze <simey@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax', 'core/str', 'core/templates', 'core/notification', 'core/custom_interaction_events',
+        'core/modal_factory', 'core_calendar/summary_modal', 'core_calendar/calendar_repository'],
+    function($, Ajax, Str, Templates, Notification, CustomEvents, ModalFactory, SummaryModal, CalendarRepository) {
+
+        var SELECTORS = {
+            ROOT: "[data-region='calendar']",
+            EVENT_LINK: "[data-action='view-event']",
+        };
+
+        var modalPromise = null;
+
+        /**
+         * Get the event type lang string.
+         *
+         * @param {String} eventType The event type.
+         * @return {String} The lang string of the event type.
+         */
+        var getEventType = function(eventType) {
+            var lang = 'type' + eventType;
+            return Str.get_string(lang, 'core_calendar').then(function(langStr) {
+                return langStr;
+            }).fail(Notification.exception);
+        };
+
+        /**
+         * Render the event summary modal.
+         *
+         * @param {Number} eventId The calendar event id.
+         * @return {promise} The summary modal promise.
+         */
+        var renderEventSummaryModal = function(eventId) {
+
+            var promise = CalendarRepository.getEventById(eventId);
+
+            return promise.then(function(result) {
+                if (!result.event) {
+                    promise.fail(Notification.exception);
+                } else {
+                    return result.event;
+                }
+            }).then(function(eventdata) {
+                return getEventType(eventdata.eventtype).then(function(langStr) {
+                    eventdata.eventtype = langStr;
+                    return eventdata;
+                });
+            }).then(function(eventdata) {
+                return modalPromise.done(function(modal) {
+                    modal.setTitle(eventdata.name);
+                    modal.setBody(Templates.render('core_calendar/event_summary_body', eventdata));
+
+                    // Hide edit and delete buttons if I don't have permission.
+                    if (eventdata.caneditevent == false) {
+                        modal.setFooter('');
+                    }
+
+                    modal.show();
+                });
+            });
+        };
+
+        /**
+         * Register event listeners for the module.
+         *
+         * @param {object} root The root element.
+         */
+        var registerEventListeners = function(root) {
+            root = $(root);
+
+            var loading = false;
+            root.on('click', SELECTORS.EVENT_LINK, function(e) {
+                if (!loading) {
+                    loading = true;
+                    e.preventDefault();
+
+                    var eventElement = $(e.target).closest(SELECTORS.EVENT_LINK);
+                    var eventId = eventElement.attr('data-event-id');
+
+                    renderEventSummaryModal(eventId).done(function() {
+                        loading = false;
+                    });
+                }
+            });
+        };
+
+        return {
+            init: function() {
+                modalPromise = ModalFactory.create({
+                    type: SummaryModal.TYPE
+                });
+
+                registerEventListeners(SELECTORS.ROOT);
+            }
+        };
+    });
diff --git a/calendar/amd/src/calendar_repository.js b/calendar/amd/src/calendar_repository.js
new file mode 100644 (file)
index 0000000..3e7a68c
--- /dev/null
@@ -0,0 +1,50 @@
+// 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/>.
+
+/**
+ * A javascript module to handle calendar ajax actions.
+ *
+ * @module     core_calendar/calendar_repository
+ * @class      repository
+ * @package    core_calendar
+ * @copyright  2017 Simey Lameze <lameze@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax'], function($, Ajax) {
+
+
+    /**
+     * Get a calendar event by id.
+     *
+     * @method getEventById
+     * @param {int} eventId The event id.
+     * @return {promise} Resolved with requested calendar event
+     */
+    var getEventById = function(eventId) {
+
+        var request = {
+            methodname: 'core_calendar_get_calendar_event_by_id',
+            args: {
+                eventid: eventId
+            }
+        };
+
+        return Ajax.call([request])[0];
+    };
+
+    return {
+        getEventById: getEventById
+    };
+});
diff --git a/calendar/amd/src/summary_modal.js b/calendar/amd/src/summary_modal.js
new file mode 100644 (file)
index 0000000..a1801f5
--- /dev/null
@@ -0,0 +1,64 @@
+// 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/>.
+
+/**
+ * A javascript module to handle summary modal.
+ *
+ * @module     core_calendar/summary_modal
+ * @package    core_calendar
+ * @copyright  2017 Simey Lameze <simey@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_registry'],
+    function($, Notification, CustomEvents, Modal, ModalRegistry) {
+
+    var registered = false;
+    var SELECTORS = {
+        EDIT_BUTTON: '[data-action="edit"]',
+        DELETE_BUTTON: '[data-action="delete"]',
+        EVENT_LINK: '[data-action="event-link"]'
+    };
+
+    /**
+     * Constructor for the Modal.
+     *
+     * @param {object} root The root jQuery element for the modal
+     */
+    var ModalEventSummary = function(root) {
+        Modal.call(this, root);
+
+        if (!this.getFooter().find(SELECTORS.EDIT_BUTTON).length) {
+            Notification.exception({message: 'No edit button found'});
+        }
+
+        if (!this.getFooter().find(SELECTORS.DELETE_BUTTON).length) {
+            Notification.exception({message: 'No delete button found'});
+        }
+    };
+
+    ModalEventSummary.TYPE = 'core_calendar-event_summary';
+    ModalEventSummary.prototype = Object.create(Modal.prototype);
+    ModalEventSummary.prototype.constructor = ModalEventSummary;
+
+    // Automatically register with the modal registry the first time this module is imported so that you can create modals
+    // of this type using the modal factory.
+    if (!registered) {
+        ModalRegistry.register(ModalEventSummary.TYPE, ModalEventSummary, 'core_calendar/event_summary_modal');
+        registered = true;
+    }
+
+    return ModalEventSummary;
+
+});
\ No newline at end of file
index 9ac8cbf..70c2cb7 100644 (file)
@@ -137,10 +137,15 @@ class container {
                     // have that capability set on the "Authenticated User" role rather than
                     // on "Student" role, which means uservisible returns true even when the user
                     // is no longer enrolled in the course.
-                    $modulecontext = \context_module::instance($cm->id);
-                    // A user with the 'moodle/course:view' capability is able to see courses
-                    // that they are not a participant in.
-                    $canseecourse = (has_capability('moodle/course:view', $modulecontext) || is_enrolled($modulecontext));
+                    // So, with the following we are checking -
+                    // 1) Only process modules if $cm->uservisible is true.
+                    // 2) Only process modules for courses a user has the capability to view OR they are enrolled in.
+                    // 3) Only process modules for courses that are visible OR if the course is not visible, the user
+                    //    has the capability to view hidden courses.
+                    $coursecontext = \context_course::instance($dbrow->courseid);
+                    $canseecourse = has_capability('moodle/course:view', $coursecontext) || is_enrolled($coursecontext);
+                    $canseecourse = $canseecourse &&
+                        ($cm->get_course()->visible || has_capability('moodle/course:viewhiddencourses', $coursecontext));
                     if (!$cm->uservisible || !$canseecourse) {
                         return true;
                     }
index bf0855b..fbc7737 100644 (file)
@@ -687,4 +687,77 @@ class core_calendar_external extends external_api {
                     )
             );
     }
+
+    /**
+     * Returns description of method parameters.
+     *
+     * @return external_function_parameters
+     */
+    public static function get_calendar_event_by_id_parameters() {
+        return new external_function_parameters(
+            array(
+                'eventid' => new external_value(PARAM_INT, 'The event id to be retrieved'),
+            )
+        );
+    }
+    /**
+     * Get calendar event by id.
+     *
+     * @param int $eventid The calendar event id to be retrieved.
+     * @return array Array of event details
+     */
+    public static function get_calendar_event_by_id($eventid) {
+        global $CFG;
+        require_once($CFG->dirroot."/calendar/lib.php");
+
+        // Parameter validation.
+        $params = ['eventid' => $eventid];
+        $params = self::validate_parameters(self::get_calendar_event_by_id_parameters(), $params);
+
+        $warnings = array();
+
+        // We need to get events asked for eventids.
+        $event = calendar_get_events_by_id([$eventid]);
+        $eventobj = calendar_event::load($eventid);
+        $event[$eventid]->caneditevent = calendar_edit_event_allowed($eventobj);
+
+        return array('event' => $event[$eventid], 'warnings' => $warnings);
+    }
+
+    /**
+     * Returns description of method result value
+     *
+     * @return external_description
+     */
+    public static function  get_calendar_event_by_id_returns() {
+
+        return new external_single_structure(array(
+            'event' => new external_single_structure(
+                array(
+                    'id' => new external_value(PARAM_INT, 'event id'),
+                    'name' => new external_value(PARAM_TEXT, 'event name'),
+                    'description' => new external_value(PARAM_RAW, 'Description', VALUE_OPTIONAL, null, NULL_ALLOWED),
+                    'format' => new external_format_value('description'),
+                    'courseid' => new external_value(PARAM_INT, 'course id'),
+                    'groupid' => new external_value(PARAM_INT, 'group id'),
+                    'userid' => new external_value(PARAM_INT, 'user id'),
+                    'repeatid' => new external_value(PARAM_INT, 'repeat id'),
+                    'modulename' => new external_value(PARAM_TEXT, 'module name', VALUE_OPTIONAL, null, NULL_ALLOWED),
+                    'instance' => new external_value(PARAM_INT, 'instance id'),
+                    'eventtype' => new external_value(PARAM_TEXT, 'Event type'),
+                    'timestart' => new external_value(PARAM_INT, 'timestart'),
+                    'timeduration' => new external_value(PARAM_INT, 'time duration'),
+                    'visible' => new external_value(PARAM_INT, 'visible'),
+                    'uuid' => new external_value(PARAM_TEXT, 'unique id of ical events', VALUE_OPTIONAL, null, NULL_NOT_ALLOWED),
+                    'sequence' => new external_value(PARAM_INT, 'sequence'),
+                    'timemodified' => new external_value(PARAM_INT, 'time modified'),
+                    'subscriptionid' => new external_value(PARAM_INT, 'Subscription id', VALUE_OPTIONAL, null, NULL_ALLOWED),
+                    'caneditevent' => new external_value(PARAM_BOOL, 'Whether the user can edit the event'),
+                ),
+                'event'
+            ),
+            'warnings' => new external_warnings()
+            )
+        );
+    }
 }
index 6711693..ee450e1 100644 (file)
@@ -38,7 +38,7 @@ class core_calendar_renderer extends plugin_renderer_base {
      * @return string
      */
     public function start_layout() {
-        return html_writer::start_tag('div', array('class'=>'maincalendar'));
+        return html_writer::start_tag('div', ['data-region' => 'calendar', 'class' => 'maincalendar']);
     }
 
     /**
@@ -517,7 +517,8 @@ class core_calendar_renderer extends plugin_renderer_base {
                         ];
                         $eventname = get_string('eventnameandcourse', 'calendar', $eventnameparams);
                     }
-                    $link = html_writer::link($dayhref, $eventname);
+                    $link = html_writer::link($dayhref, $eventname, ['data-action' => 'view-event',
+                            'data-event-id' => $events[$eventindex]->id]);
                     $cell->text .= html_writer::tag('li', $link, $attributes);
                 }
                 $cell->text .= html_writer::end_tag('ul');
diff --git a/calendar/templates/event_summary_body.mustache b/calendar/templates/event_summary_body.mustache
new file mode 100644 (file)
index 0000000..23946c9
--- /dev/null
@@ -0,0 +1,37 @@
+{{!
+    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/>.
+}}
+{{!
+    @template core_calendar/event_summary_body
+
+    This template renders the body of calendar events summary modal.
+
+    Example context (json):
+    {
+        "timestart": 1490320388,
+        "description": "An random event description",
+        "eventtype": "open",
+    }
+}}
+<div class="container">
+    <h4>{{#str}} when, core_calendar {{/str}}</h4>
+    {{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}
+    <br>
+    <h4>{{#str}} description {{/str}}</h4>
+    {{{description}}}
+    <h4>{{#str}} eventtype, core_calendar {{/str}}</h4>
+    {{eventtype}}
+</div>
diff --git a/calendar/templates/event_summary_modal.mustache b/calendar/templates/event_summary_modal.mustache
new file mode 100644 (file)
index 0000000..18498d7
--- /dev/null
@@ -0,0 +1,32 @@
+{{!
+    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/>.
+}}
+{{!
+    @template core_calendar/event_summary_modal
+
+    This template renders the calendar events summary modal.
+
+    Example context (json):
+    {
+        "title": "Assignment due 1",
+    }
+}}
+{{< core/modal }}
+{{$footer}}
+<button type="button" class="btn btn-secondary pull-xs-left" data-action="delete">{{#str}} delete {{/str}}</button>
+<button type="button" class="btn btn-primary" data-action="edit">{{#str}} edit {{/str}}</button>
+{{/footer}}
+{{/ core/modal }}
index 3f08efb..ba1eb6c 100644 (file)
@@ -183,6 +183,63 @@ class core_calendar_container_testcase extends advanced_testcase {
         $this->assertNull($event);
     }
 
+    /**
+     * Test that the event factory deals with invisible courses as an admin.
+     *
+     * @dataProvider get_event_factory_testcases()
+     * @param \stdClass $dbrow Row from the "database".
+     */
+    public function test_event_factory_when_course_visibility_is_toggled_as_admin($dbrow) {
+        $legacyevent = $this->create_event($dbrow);
+        $factory = \core_calendar\local\event\container::get_event_factory();
+
+        // Create a hidden course with an assignment.
+        $course = $this->getDataGenerator()->create_course(['visible' => 0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $moduleinstance = $generator->create_instance(['course' => $course->id]);
+
+        $dbrow->id = $legacyevent->id;
+        $dbrow->courseid = $course->id;
+        $dbrow->instance = $moduleinstance->id;
+        $dbrow->modulename = 'assign';
+        $event = $factory->create_instance($dbrow);
+
+        // Module is still visible to admins even if the course is invisible.
+        $this->assertInstanceOf(event_interface::class, $event);
+    }
+
+    /**
+     * Test that the event factory deals with invisible courses as a student.
+     *
+     * @dataProvider get_event_factory_testcases()
+     * @param \stdClass $dbrow Row from the "database".
+     */
+    public function test_event_factory_when_course_visibility_is_toggled_as_student($dbrow) {
+        $legacyevent = $this->create_event($dbrow);
+        $factory = \core_calendar\local\event\container::get_event_factory();
+
+        // Create a hidden course with an assignment.
+        $course = $this->getDataGenerator()->create_course(['visible' => 0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $moduleinstance = $generator->create_instance(['course' => $course->id]);
+
+        // Enrol a student into this course.
+        $student = $this->getDataGenerator()->create_user();
+        $this->getDataGenerator()->enrol_user($student->id, $course->id);
+
+        // Set the user to the student.
+        $this->setUser($student);
+
+        $dbrow->id = $legacyevent->id;
+        $dbrow->courseid = $course->id;
+        $dbrow->instance = $moduleinstance->id;
+        $dbrow->modulename = 'assign';
+        $event = $factory->create_instance($dbrow);
+
+        // Module is invisible to students if the course is invisible.
+        $this->assertNull($event);
+    }
+
     /**
      * Test that the event factory deals with completion related events properly.
      */
index 18245a5..f974ba5 100644 (file)
@@ -176,4 +176,5 @@ if (!empty($CFG->enablecalendarexport)) {
 echo $OUTPUT->container_end();
 echo html_writer::end_tag('div');
 echo $renderer->complete_layout();
+$PAGE->requires->js_call_amd('core_calendar/calendar', 'init');
 echo $OUTPUT->footer();
index bc444f8..dbd8b18 100644 (file)
@@ -2942,6 +2942,7 @@ class course_request {
         $data->visibleold         = $data->visible;
         $data->lang               = $courseconfig->lang;
         $data->enablecompletion   = $courseconfig->enablecompletion;
+        $data->numsections        = $courseconfig->numsections;
 
         $course = create_course($data);
         $context = context_course::instance($course->id, MUST_EXIST);
index 565f90c..609ae6a 100644 (file)
@@ -450,7 +450,7 @@ class core_course_renderer extends plugin_renderer_base {
     public function course_section_cm_completion($course, &$completioninfo, cm_info $mod, $displayoptions = array()) {
         global $CFG;
         $output = '';
-        if (!$mod->is_visible_on_course_page()) {
+        if (!empty($displayoptions['hidecompletion']) || !isloggedin() || isguestuser() || !$mod->uservisible) {
             return $output;
         }
         if ($completioninfo === null) {
index 78f3a3d..eaf2e1e 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_database_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 4626f79..32f4164 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_flatfile_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 75a721e..8f66610 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_guest_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index b1757a7..934d47a 100644 (file)
@@ -38,7 +38,7 @@ class enrol_guest_enrol_form extends moodleform {
         $heading = $plugin->get_instance_name($instance);
         $mform->addElement('header', 'guestheader', $heading);
 
-        $mform->addElement('passwordunmask', 'guestpassword', get_string('password', 'enrol_guest'));
+        $mform->addElement('password', 'guestpassword', get_string('password', 'enrol_guest'));
 
         $this->add_action_buttons(false, get_string('submit'));
 
index a2f1f59..e3383d5 100644 (file)
@@ -33,15 +33,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_imsenterprise_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index aafc0e7..e6f4140 100644 (file)
@@ -328,7 +328,7 @@ class enrol_ldap_plugin extends enrol_plugin {
             return;
         }
 
-        $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'));
+        $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'), $this->ldapconnection);
 
         // we may need a lot of memory here
         core_php_time_limit::raise();
@@ -761,7 +761,7 @@ class enrol_ldap_plugin extends enrol_plugin {
 
         // Get all contexts and look for first matching user
         $ldap_contexts = explode(';', $ldap_contexts);
-        $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'));
+        $ldap_pagedresults = ldap_paged_results_supported($this->get_config('ldap_version'), $this->ldapconnection);
         foreach ($ldap_contexts as $context) {
             $context = trim($context);
             if (empty($context)) {
index 9c9fad4..2a0608c 100644 (file)
@@ -27,21 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_manual_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2015091500) {
-        // We keep today as default enrolment start time on upgrades.
-        set_config('enrolstart', 3, 'enrol_manual');
-        upgrade_plugin_savepoint(true, 2015091500, 'enrol', 'manual');
-    }
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 1fe1afc..058867f 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_mnet_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 91e3653..559308d 100644 (file)
@@ -45,15 +45,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_enrol_paypal_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index e1d6ae2..b653ac3 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 function xmldb_enrol_self_upgrade($oldversion) {
-    global $CFG;
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG, $DB;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
     if ($oldversion < 2016052301) {
-        global $DB;
         // Get roles with manager archetype.
         $managerroles = get_archetype_roles('manager');
         if (!empty($managerroles)) {
index a60224e..dc17af1 100644 (file)
@@ -78,7 +78,7 @@ class enrol_self_enrol_form extends moodleform {
 
         if ($instance->password) {
             // Change the id of self enrolment key input as there can be multiple self enrolment methods.
-            $mform->addElement('passwordunmask', 'enrolpassword', get_string('password', 'enrol_self'),
+            $mform->addElement('password', 'enrolpassword', get_string('password', 'enrol_self'),
                     array('id' => 'enrolpassword_'.$instance->id));
             $context = context_course::instance($this->instance->courseid);
             $keyholders = get_users_by_capability($context, 'enrol/self:holdkey', user_picture::fields('u'));
index 8e74a8a..a2a9070 100644 (file)
@@ -29,90 +29,10 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool result
  */
 function xmldb_filter_mathjaxloader_upgrade($oldversion) {
-    global $CFG, $DB;
+    global $CFG;
 
     require_once($CFG->dirroot . '/filter/mathjaxloader/db/upgradelib.php');
 
-    $dbman = $DB->get_manager();
-
-    if ($oldversion < 2014081100) {
-
-        $sslcdnurl = get_config('filter_mathjaxloader', 'httpsurl');
-        if ($sslcdnurl === "https://c328740.ssl.cf1.rackcdn.com/mathjax/2.3-latest/MathJax.js") {
-            set_config('httpsurl', 'https://cdn.mathjax.org/mathjax/2.3-latest/MathJax.js', 'filter_mathjaxloader');
-        }
-
-        upgrade_plugin_savepoint(true, 2014081100, 'filter', 'mathjaxloader');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2015021200) {
-
-        $httpurl = get_config('filter_mathjaxloader', 'httpurl');
-        // Don't change the config if it has been manually changed to something besides the default setting value.
-        if ($httpurl === "http://cdn.mathjax.org/mathjax/2.3-latest/MathJax.js") {
-            set_config('httpurl', 'http://cdn.mathjax.org/mathjax/2.5-latest/MathJax.js', 'filter_mathjaxloader');
-        }
-
-        $httpsurl = get_config('filter_mathjaxloader', 'httpsurl');
-        // Don't change the config if it has been manually changed to something besides the default setting value.
-        if ($httpsurl === "https://cdn.mathjax.org/mathjax/2.3-latest/MathJax.js") {
-            set_config('httpsurl', 'https://cdn.mathjax.org/mathjax/2.5-latest/MathJax.js', 'filter_mathjaxloader');
-        }
-
-        upgrade_plugin_savepoint(true, 2015021200, 'filter', 'mathjaxloader');
-    }
-
-    if ($oldversion < 2015021700) {
-
-        $oldconfig = get_config('filter_mathjaxloader', 'mathjaxconfig');
-        $olddefault = 'MathJax.Hub.Config({
-    config: ["MMLorHTML.js", "Safe.js"],
-    jax: ["input/TeX","input/MathML","output/HTML-CSS","output/NativeMML"],
-    extensions: ["tex2jax.js","mml2jax.js","MathMenu.js","MathZoom.js"],
-    TeX: {
-        extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]
-    },
-    menuSettings: {
-        zoom: "Double-Click",
-        mpContext: true,
-        mpMouse: true
-    },
-    errorSettings: { message: ["!"] },
-    skipStartupTypeset: true,
-    messageStyle: "none"
-});
-';
-        $newdefault = '
-MathJax.Hub.Config({
-    config: ["Accessible.js", "Safe.js"],
-    errorSettings: { message: ["!"] },
-    skipStartupTypeset: true,
-    messageStyle: "none"
-});
-';
-
-        // Ignore white space changes.
-        $oldconfig = trim(preg_replace('/\s+/', ' ', $oldconfig));
-        $olddefault = trim(preg_replace('/\s+/', ' ', $olddefault));
-
-        // Update the default config for mathjax only if it has not been customised.
-
-        if ($oldconfig == $olddefault) {
-            set_config('mathjaxconfig', $newdefault, 'filter_mathjaxloader');
-        }
-
-        upgrade_plugin_savepoint(true, 2015021700, 'filter', 'mathjaxloader');
-    }
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     if ($oldversion < 2016032200) {
 
         $httpurl = get_config('filter_mathjaxloader', 'httpurl');
index db97dd8..872c617 100644 (file)
@@ -32,15 +32,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_filter_mediaplugin_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 7aa3149..d64cc9a 100644 (file)
@@ -32,15 +32,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_filter_tex_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index ef4c0d9..94bf54f 100644 (file)
@@ -33,15 +33,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_gradingform_rubric_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 0f20a91..ce89d60 100644 (file)
  * @return bool result
  */
 function xmldb_gradereport_user_upgrade($oldversion) {
-
-    if ($oldversion < 2014101500) {
-        // Need to always show weight and contribution to course total.
-        set_config('grade_report_user_showweight', 1);
-
-        // User savepoint reached.
-        upgrade_plugin_savepoint(true, 2014101500, 'gradereport', 'user');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 5d1e8fc..9793d99 100644 (file)
@@ -61,14 +61,9 @@ date_default_timezone_set(@date_default_timezone_get());
 @error_reporting(E_ALL);
 @ini_set('display_errors', '1');
 
-// Check that PHP is of a sufficient version.
-if (version_compare(phpversion(), '5.6.5') < 0) {
-    $phpversion = phpversion();
-    // do NOT localise - lang strings would not work here and we CAN not move it after installib
-    echo "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).<br />";
-    echo "Please upgrade your server software or install older Moodle version.";
-    die;
-}
+// Check that PHP is of a sufficient version as soon as possible.
+require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
+moodle_require_minimum_php_version();
 
 // make sure iconv is available and actually works
 if (!function_exists('iconv')) {
index 65e5af6..9ac1174 100644 (file)
@@ -46,7 +46,8 @@ $string['dmlexceptiononinstall'] = '<p> Ocorreu um erro no banco de dados [{$a->
 $string['downloadedfilecheckfailed'] = 'A verificação do arquivo baixado falhou';
 $string['invalidmd5'] = 'A variável de verificação estava errada - tente novamente';
 $string['missingrequiredfield'] = 'Faltam informações obrigatórias';
-$string['remotedownloaderror'] = '<p>O download do componente falhou, por favor verifique as configurações do proxy. A extensão cURL do PHP Ã© altamente recomendada.<p/><p>Você precisar baixar o <a href="{$a->url}">arquivo</a> manualmente, copiar para "{$a->dest}" e descompactar lá.<p/>';
+$string['remotedownloaderror'] = '<p>O download do componente falhou, por favor verifique as configurações do proxy. A extensão cURL do PHP Ã© altamente recomendada.</p>
+<p>Você precisar baixar o <a href="{$a->url}">{$a->url}</a> manualmente, copiar para "{$a->dest}" e descompactar lá.</p>';
 $string['wrongdestpath'] = 'Caminho do destino errado';
 $string['wrongsourcebase'] = 'URL do recurso errada';
 $string['wrongzipfilename'] = 'Nome do arquivo ZIP errado';
index dca2305..64b4132 100644 (file)
@@ -616,6 +616,7 @@ $string['indexinginfo'] = 'The recommended way to index your site\'s contents is
 $string['installhijacked'] = 'Installation must be finished from the original IP address, sorry.';
 $string['installsessionerror'] = 'Can not initialise PHP session, please verify that your browser accepts cookies.';
 $string['intlrecommended'] = 'Intl extension is used to improve internationalization support, such as locale aware sorting.';
+$string['intlrequired'] = 'Intl extension is required to improve internationalization support, such as locale aware sorting and international domain names.';
 $string['invalidsection'] = 'Invalid section.';
 $string['invaliduserchangeme'] = 'Username "changeme" is reserved -- you cannot create an account with it.';
 $string['ipblocked'] = 'This site is not available currently.';
index 9eb4b7a..50c59d1 100644 (file)
@@ -185,7 +185,7 @@ $string['viewmyentriesaboutcourse'] = 'View my entries about this course';
 $string['viewsiteentries'] = 'View all entries';
 $string['viewuserentries'] = 'View all entries by {$a}';
 $string['worldblogs'] = 'The world can read entries set to be world-accessible';
-$string['wrongexternalid'] = 'Wrong external blog id';
+$string['wrongexternalid'] = 'Wrong external blog ID';
 $string['wrongpostid'] = 'Wrong blog post id';
 $string['page-blog-edit'] = 'Blog editing pages';
 $string['page-blog-index'] = 'Blog listing pages';
index 364368c..5fca2dc 100644 (file)
@@ -64,7 +64,7 @@ $string['errorbeforecoursestart'] = 'Cannot set event before course start date';
 $string['errorcannotimport'] = 'You cannot set up a calendar subscription at this time.';
 $string['errorhasuntilandcount'] = 'Either UNTIL or COUNT may appear in a recurrence rule, but UNTIL and COUNT MUST NOT occur in the same recurrence rule.';
 $string['errorinvalidbydaysuffix'] = 'Valid values for the day of the week parts of the BYDAY rule are MO, TU, WE, TH, FR, SA and SU';
-$string['errorinvalidbydayprefix'] = 'Integer values preceding BYDAY rules can only be present for MONTHLY or YEARLY RRULE.';
+$string['errorinvalidbydayprefix'] = 'Integer values preceding BYDAY rules can only be present for a MONTHLY or YEARLY recurrence rule.';
 $string['errorinvalidbyhour'] = 'Valid values for the BYHOUR rule are 0 to 23.';
 $string['errorinvalidinterval'] = 'The value for the INTERVAL rule must be a positive integer.';
 $string['errorinvalidbyminute'] = 'Valid values for the BYMINUTE rule are 0 to 59.';
@@ -83,9 +83,9 @@ $string['errornodescription'] = 'Description is required';
 $string['errornoeventname'] = 'Name is required';
 $string['errornonyearlyfreqwithbyweekno'] = 'The BYWEEKNO rule is only valid for YEARLY rules.';
 $string['errorrequiredurlorfile'] = 'Either a URL or a file is required to import a calendar.';
-$string['errorrrule'] = 'The passed rrule seems incorrect';
-$string['errorrrulefreq'] = 'The rrule has an invalid frequency parameter';
-$string['errorrruleday'] = 'The rrule has an invalid day parameter';
+$string['errorrrule'] = 'The passed recurrence rule seems incorrect.';
+$string['errorrrulefreq'] = 'The recurrence rule has an invalid frequency parameter.';
+$string['errorrruleday'] = 'The recurrence rule has an invalid day parameter.';
 $string['eventdate'] = 'Date';
 $string['eventdescription'] = 'Description';
 $string['eventduration'] = 'Duration';
@@ -108,6 +108,7 @@ $string['eventsrelatedtogroups'] = 'Events related to groups';
 $string['eventstarttime'] = 'Start time';
 $string['eventstoexport'] = 'Events to export';
 $string['eventtime'] = 'Time';
+$string['eventtype'] = 'Event type';
 $string['eventview'] = 'Event details';
 $string['eventcalendareventcreated'] = 'Calendar event created';
 $string['eventcalendareventupdated'] = 'Calendar event updated';
@@ -222,8 +223,11 @@ $string['tt_showgroups'] = 'Group events are hidden (click to show)';
 $string['tt_showuser'] = 'User events are hidden (click to show)';
 $string['tue'] = 'Tue';
 $string['tuesday'] = 'Tuesday';
+$string['typeclose'] = 'Close event';
 $string['typecourse'] = 'Course event';
+$string['typedue'] = 'Due event';
 $string['typegroup'] = 'Group event';
+$string['typeopen'] = 'Open event';
 $string['typesite'] = 'Site event';
 $string['typeuser'] = 'User event';
 $string['upcomingevents'] = 'Upcoming events';
@@ -237,6 +241,7 @@ $string['wednesday'] = 'Wednesday';
 $string['weekly'] = 'Weekly';
 $string['weeknext'] = 'Next week';
 $string['weekthis'] = 'This week';
+$string['when'] = 'When';
 $string['yesterday'] = 'Yesterday';
 $string['youcandeleteallrepeats'] = 'This event is part of a repeating event series. You can delete this event only, or all {$a} events in the series at once.';
 
index d5e1d5f..3bf13d5 100644 (file)
@@ -162,8 +162,8 @@ $string['registeredsites'] = 'Registered sites';
 $string['registrationinfo'] = 'Registration information';
 $string['registeredmoodleorg'] = 'Moodle ({$a})';
 $string['registeredon'] = 'Where your site is registered';
-$string['registereduserdevices'] = 'Number of user\'s registered mobile devices ({$a})';
-$string['registeredactiveuserdevices'] = 'Number of active user\'s registered mobile devices ({$a})';
+$string['registereduserdevices'] = 'Number of users with registered mobile devices ({$a})';
+$string['registeredactiveuserdevices'] = 'Number of active users with registered mobile devices which are receiving notifications ({$a})';
 $string['registermoochtips'] = 'Register your site with Moodle to get security alerts and access to Moodle.net, our course sharing platform.';
 $string['registersite'] = 'Register with {$a}';
 $string['registerwith'] = 'Register with a hub';
index 1a89457..53825f5 100644 (file)
@@ -155,6 +155,7 @@ $string['linkexternal'] = 'Link external';
 $string['listview'] = 'View as list';
 $string['loading'] = 'Loading...';
 $string['login'] = 'Login to your account';
+$string['logintoaccount'] = 'Login to your {$a} account';
 $string['logout'] = 'Logout';
 $string['lostsource'] = 'Error. Source is missing. {$a}';
 $string['makefileinternal'] = 'Make a copy of the file';
index 7fc7d30..5386669 100644 (file)
@@ -8122,21 +8122,25 @@ function admin_find_write_settings($node, $data) {
     }
 
     if ($node instanceof admin_category) {
-        $entries = array_keys($node->children);
-        foreach ($entries as $entry) {
-            $return = array_merge($return, admin_find_write_settings($node->children[$entry], $data));
+        if ($node->check_access()) {
+            $entries = array_keys($node->children);
+            foreach ($entries as $entry) {
+                $return = array_merge($return, admin_find_write_settings($node->children[$entry], $data));
+            }
         }
 
     } else if ($node instanceof admin_settingpage) {
+        if ($node->check_access()) {
             foreach ($node->settings as $setting) {
                 $fullname = $setting->get_full_name();
                 if (array_key_exists($fullname, $data)) {
                     $return[$fullname] = $setting;
                 }
             }
-
         }
 
+    }
+
     return $return;
 }
 
index 09bc947..acdaab3 100644 (file)
@@ -833,6 +833,8 @@ class block_manager {
         $blockinstance->defaultregion = $region;
         $blockinstance->defaultweight = $weight;
         $blockinstance->configdata = '';
+        $blockinstance->timecreated = time();
+        $blockinstance->timemodified = $blockinstance->timecreated;
         $blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
 
         // Ensure the block context is created.
@@ -940,6 +942,7 @@ class block_manager {
             $newbi->id = $bi->id;
             $newbi->defaultregion = $newregion;
             $newbi->defaultweight = $newweight;
+            $newbi->timemodified = time();
             $DB->update_record('block_instances', $newbi);
 
             if ($bi->blockpositionid) {
@@ -1162,6 +1165,8 @@ class block_manager {
         $blockinstance->defaultregion = $defaultregion;
         $blockinstance->defaultweight = 0;
         $blockinstance->configdata = '';
+        $blockinstance->timecreated = time();
+        $blockinstance->timemodified = $blockinstance->timecreated;
         $blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
 
         // Ensure the block context is created.
@@ -1723,6 +1728,7 @@ class block_manager {
 
             $bi->defaultregion = $data->bui_defaultregion;
             $bi->defaultweight = $data->bui_defaultweight;
+            $bi->timemodified = time();
             $DB->update_record('block_instances', $bi);
 
             if (!empty($block->config)) {
index 7960ea6..c6cb756 100644 (file)
@@ -100,6 +100,10 @@ class issuer extends persistent {
             'sortorder' => array(
                 'type' => PARAM_INT,
                 'default' => 0,
+            ),
+            'requireconfirmation' => array(
+                'type' => PARAM_BOOL,
+                'default' => true
             )
         );
     }
index 89edd59..2a25897 100644 (file)
@@ -249,7 +249,7 @@ class icon_system_fontawesome extends icon_system_font {
             'core:i/move_2d' => 'fa-arrows',
             'core:i/navigationitem' => 'fa-fw',
             'core:i/ne_red_mark' => 'fa-remove',
-            'core:i/new' => 'fa-plus',
+            'core:i/new' => 'fa-bolt',
             'core:i/news' => 'fa-newspaper-o',
             'core:i/nosubcat' => 'fa-plus-square-o',
             'core:i/notifications' => 'fa-bell',
index 7ba9b2a..5644b4b 100644 (file)
@@ -34,16 +34,16 @@ namespace core\output;
  */
 class mustache_javascript_helper {
 
-    /** @var page_requirements_manager $requires - Page requirements manager for collecting JS calls. */
-    private $requires = null;
+    /** @var moodle_page $page - Page used to get requirement manager */
+    private $page = null;
 
     /**
      * Create new instance of mustache javascript helper.
      *
-     * @param page_requirements_manager $requires Page requirements manager.
+     * @param moodle_page $page Page.
      */
-    public function __construct($requires) {
-        $this->requires = $requires;
+    public function __construct($page) {
+        $this->page = $page;
     }
 
     /**
@@ -54,6 +54,6 @@ class mustache_javascript_helper {
      * @param \Mustache_LambdaHelper $helper Used to render the content of this block.
      */
     public function help($text, \Mustache_LambdaHelper $helper) {
-        $this->requires->js_amd_inline($helper->render($text));
+        $this->page->requires->js_amd_inline($helper->render($text));
     }
 }
index f291828..92c7252 100644 (file)
@@ -132,7 +132,6 @@ function xmldb_main_install() {
         'texteditors'           => 'atto,tinymce,textarea',
         'antiviruses'           => '',
         'media_plugins_sortorder' => 'videojs,youtube,swf',
-        'upgrade_minmaxgradestepignored' => 1, // New installs should not run this upgrade step.
         'upgrade_extracreditweightsstepignored' => 1, // New installs should not run this upgrade step.
         'upgrade_calculatedgradeitemsignored' => 1, // New installs should not run this upgrade step.
         'upgrade_letterboundarycourses' => 1, // New installs should not run this upgrade step.
old mode 100644 (file)
new mode 100755 (executable)
index ce5dda2..48cb3c9
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20170316" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20170502" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
         <FIELD NAME="defaultregion" TYPE="char" LENGTH="16" NOTNULL="true" SEQUENCE="false" COMMENT="Which block region this block should appear in on each page, in the absence of a specific position in the block_positions table."/>
         <FIELD NAME="defaultweight" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Used to order the blocks within a block region. Again, may be overridden by the block_positions table for a specific page where this block appears."/>
         <FIELD NAME="configdata" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="A serialized blob of configuration data for this block instance."/>
+        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time at which this block instance was originally created"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Time at which block instance was last modified."/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
       </KEYS>
       <INDEXES>
         <INDEX NAME="parentcontextid-showinsubcontexts-pagetypepattern-subpagepattern" UNIQUE="false" FIELDS="parentcontextid, showinsubcontexts, pagetypepattern, subpagepattern"/>
+        <INDEX NAME="timemodified" UNIQUE="false" FIELDS="timemodified"/>
       </INDEXES>
     </TABLE>
     <TABLE NAME="block_positions" COMMENT="Stores the position of a sticky block_instance on a another page than the one where it was added.">
         <FIELD NAME="enabled" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
         <FIELD NAME="showonloginpage" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
         <FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The defined sort order."/>
+        <FIELD NAME="requireconfirmation" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
       </FIELDS>
       <KEYS>
         <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
index d608f24..373cd06 100644 (file)
@@ -42,6 +42,14 @@ $functions = array(
         'ajax'          => true,
         'loginrequired' => false,
     ),
+    'core_auth_request_password_reset' => array(
+        'classname'   => 'core_auth_external',
+        'methodname'  => 'request_password_reset',
+        'description' => 'Requests a password reset.',
+        'type'        => 'write',
+        'ajax'          => true,
+        'loginrequired' => false,
+    ),
     'core_badges_get_user_badges' => array(
         'classname'     => 'core_badges_external',
         'methodname'    => 'get_user_badges',
@@ -107,6 +115,16 @@ $functions = array(
         'ajax' => true,
         'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
     ),
+    'core_calendar_get_calendar_event_by_id' => array(
+        'classname' => 'core_calendar_external',
+        'methodname' => 'get_calendar_event_by_id',
+        'description' => 'Get calendar event by id',
+        'classpath' => 'calendar/externallib.php',
+        'type' => 'read',
+        'capabilities' => 'moodle/calendar:manageentries, moodle/calendar:manageownentries, moodle/calendar:managegroupentries',
+        'ajax' => true,
+        'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+    ),
     'core_cohort_add_cohort_members' => array(
         'classname' => 'core_cohort_external',
         'methodname' => 'add_cohort_members',
index 7798fec..554af22 100644 (file)
@@ -92,988 +92,15 @@ function xmldb_main_upgrade($oldversion) {
     $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
 
     // Always keep this upgrade step with version being the minimum
-    // allowed version to upgrade from (v2.7.0 right now).
-    if ($oldversion < 2014051200) {
+    // allowed version to upgrade from (v3.0.0 right now).
+    if ($oldversion < 2015111600) {
         // Just in case somebody hacks upgrade scripts or env, we really can not continue.
-        echo("You need to upgrade to 2.7.x or higher first!\n");
+        echo("You need to upgrade to 3.0.x or higher first!\n");
         exit(1);
         // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks.
-        upgrade_main_savepoint(true, 2014051200);
+        upgrade_main_savepoint(true, 2015111600);
     }
 
-    // MDL-32543 Make sure that the log table has correct length for action and url fields.
-    if ($oldversion < 2014051200.02) {
-
-        $table = new xmldb_table('log');
-
-        $columns = $DB->get_columns('log');
-        if ($columns['action']->max_length < 40) {
-            $index1 = new xmldb_index('course-module-action', XMLDB_INDEX_NOTUNIQUE, array('course', 'module', 'action'));
-            if ($dbman->index_exists($table, $index1)) {
-                $dbman->drop_index($table, $index1);
-            }
-            $index2 = new xmldb_index('action', XMLDB_INDEX_NOTUNIQUE, array('action'));
-            if ($dbman->index_exists($table, $index2)) {
-                $dbman->drop_index($table, $index2);
-            }
-            $field = new xmldb_field('action', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'cmid');
-            $dbman->change_field_precision($table, $field);
-            $dbman->add_index($table, $index1);
-            $dbman->add_index($table, $index2);
-        }
-
-        if ($columns['url']->max_length < 100) {
-            $field = new xmldb_field('url', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'action');
-            $dbman->change_field_precision($table, $field);
-        }
-
-        upgrade_main_savepoint(true, 2014051200.02);
-    }
-
-    if ($oldversion < 2014060300.00) {
-        $gspath = get_config('assignfeedback_editpdf', 'gspath');
-        if ($gspath !== false) {
-            set_config('pathtogs', $gspath);
-            unset_config('gspath', 'assignfeedback_editpdf');
-        }
-        upgrade_main_savepoint(true, 2014060300.00);
-    }
-
-    if ($oldversion < 2014061000.00) {
-        // Fixing possible wrong MIME type for Publisher files.
-        $filetypes = array('%.pub'=>'application/x-mspublisher');
-        upgrade_mimetypes($filetypes);
-        upgrade_main_savepoint(true, 2014061000.00);
-    }
-
-    if ($oldversion < 2014062600.01) {
-        // We only want to delete DragMath if the directory no longer exists. If the directory
-        // is present then it means it has been restored, so do not perform the uninstall.
-        if (!check_dir_exists($CFG->libdir . '/editor/tinymce/plugins/dragmath', false)) {
-            // Purge DragMath plugin which is incompatible with GNU GPL license.
-            unset_all_config_for_plugin('tinymce_dragmath');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014062600.01);
-    }
-
-    // Switch the order of the fields in the files_reference index, to improve the performance of search_references.
-    if ($oldversion < 2014070100.00) {
-        $table = new xmldb_table('files_reference');
-        $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('repositoryid', 'referencehash'));
-        if ($dbman->index_exists($table, $index)) {
-            $dbman->drop_index($table, $index);
-        }
-        upgrade_main_savepoint(true, 2014070100.00);
-    }
-
-    if ($oldversion < 2014070101.00) {
-        $table = new xmldb_table('files_reference');
-        $index = new xmldb_index('uq_external_file', XMLDB_INDEX_UNIQUE, array('referencehash', 'repositoryid'));
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-        upgrade_main_savepoint(true, 2014070101.00);
-    }
-
-    if ($oldversion < 2014072400.01) {
-        $table = new xmldb_table('user_devices');
-        $oldindex = new xmldb_index('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
-        if ($dbman->index_exists($table, $oldindex)) {
-            $key = new xmldb_key('pushid-platform', XMLDB_KEY_UNIQUE, array('pushid', 'platform'));
-            $dbman->drop_key($table, $key);
-        }
-        upgrade_main_savepoint(true, 2014072400.01);
-    }
-
-    if ($oldversion < 2014080801.00) {
-
-        // Define index behaviour (not unique) to be added to question_attempts.
-        $table = new xmldb_table('question_attempts');
-        $index = new xmldb_index('behaviour', XMLDB_INDEX_NOTUNIQUE, array('behaviour'));
-
-        // Conditionally launch add index behaviour.
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014080801.00);
-    }
-
-    if ($oldversion < 2014082900.01) {
-        // Fixing possible wrong MIME type for 7-zip and Rar files.
-        $filetypes = array(
-                '%.7z' => 'application/x-7z-compressed',
-                '%.rar' => 'application/x-rar-compressed');
-        upgrade_mimetypes($filetypes);
-        upgrade_main_savepoint(true, 2014082900.01);
-    }
-
-    if ($oldversion < 2014082900.02) {
-        // Replace groupmembersonly usage with new availability system.
-        $transaction = $DB->start_delegated_transaction();
-        if ($CFG->enablegroupmembersonly) {
-            // If it isn't already enabled, we need to enable availability.
-            if (!$CFG->enableavailability) {
-                set_config('enableavailability', 1);
-            }
-
-            // Count all course-modules with groupmembersonly set (for progress
-            // bar).
-            $total = $DB->count_records('course_modules', array('groupmembersonly' => 1));
-            $pbar = new progress_bar('upgradegroupmembersonly', 500, true);
-
-            // Get all these course-modules, one at a time.
-            $rs = $DB->get_recordset('course_modules', array('groupmembersonly' => 1),
-                    'course, id');
-            $i = 0;
-            foreach ($rs as $cm) {
-                // Calculate and set new availability value.
-                $availability = upgrade_group_members_only($cm->groupingid, $cm->availability);
-                $DB->set_field('course_modules', 'availability', $availability,
-                        array('id' => $cm->id));
-
-                // Update progress.
-                $i++;
-                $pbar->update($i, $total, "Upgrading groupmembersonly settings - $i/$total.");
-            }
-            $rs->close();
-        }
-
-        // Define field groupmembersonly to be dropped from course_modules.
-        $table = new xmldb_table('course_modules');
-        $field = new xmldb_field('groupmembersonly');
-
-        // Conditionally launch drop field groupmembersonly.
-        if ($dbman->field_exists($table, $field)) {
-            $dbman->drop_field($table, $field);
-        }
-
-        // Unset old config variable.
-        unset_config('enablegroupmembersonly');
-        $transaction->allow_commit();
-
-        upgrade_main_savepoint(true, 2014082900.02);
-    }
-
-    if ($oldversion < 2014100100.00) {
-
-        // Define table messageinbound_handlers to be created.
-        $table = new xmldb_table('messageinbound_handlers');
-
-        // Adding fields to table messageinbound_handlers.
-        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('defaultexpiration', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '86400');
-        $table->add_field('validateaddress', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
-        $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
-
-        // Adding keys to table messageinbound_handlers.
-        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->add_key('classname', XMLDB_KEY_UNIQUE, array('classname'));
-
-        // Conditionally launch create table for messageinbound_handlers.
-        if (!$dbman->table_exists($table)) {
-            $dbman->create_table($table);
-        }
-
-        // Define table messageinbound_datakeys to be created.
-        $table = new xmldb_table('messageinbound_datakeys');
-
-        // Adding fields to table messageinbound_datakeys.
-        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('handler', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('datavalue', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('datakey', XMLDB_TYPE_CHAR, '64', null, null, null, null);
-        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
-
-        // Adding keys to table messageinbound_datakeys.
-        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->add_key('handler_datavalue', XMLDB_KEY_UNIQUE, array('handler', 'datavalue'));
-        $table->add_key('handler', XMLDB_KEY_FOREIGN, array('handler'), 'messageinbound_handlers', array('id'));
-
-        // Conditionally launch create table for messageinbound_datakeys.
-        if (!$dbman->table_exists($table)) {
-            $dbman->create_table($table);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100100.00);
-    }
-
-    if ($oldversion < 2014100600.01) {
-        // Define field aggregationstatus to be added to grade_grades.
-        $table = new xmldb_table('grade_grades');
-        $field = new xmldb_field('aggregationstatus', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'unknown', 'timemodified');
-
-        // Conditionally launch add field aggregationstatus.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        $field = new xmldb_field('aggregationweight', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null, 'aggregationstatus');
-
-        // Conditionally launch add field aggregationweight.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Define field aggregationcoef2 to be added to grade_items.
-        $table = new xmldb_table('grade_items');
-        $field = new xmldb_field('aggregationcoef2', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0', 'aggregationcoef');
-
-        // Conditionally launch add field aggregationcoef2.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        $field = new xmldb_field('weightoverride', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'needsupdate');
-
-        // Conditionally launch add field weightoverride.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100600.01);
-    }
-
-    if ($oldversion < 2014100600.02) {
-
-        // Define field aggregationcoef2 to be added to grade_items_history.
-        $table = new xmldb_table('grade_items_history');
-        $field = new xmldb_field('aggregationcoef2', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0', 'aggregationcoef');
-
-        // Conditionally launch add field aggregationcoef2.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100600.02);
-    }
-
-    if ($oldversion < 2014100600.03) {
-
-        // Define field weightoverride to be added to grade_items_history.
-        $table = new xmldb_table('grade_items_history');
-        $field = new xmldb_field('weightoverride', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'decimals');
-
-        // Conditionally launch add field weightoverride.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100600.03);
-    }
-    if ($oldversion < 2014100600.04) {
-        // Set flags so we can display a notice on all courses that might
-        // be affected by the uprade to natural aggregation.
-        if (!get_config('grades_sumofgrades_upgrade_flagged', 'core')) {
-            // 13 == SUM_OF_GRADES.
-            $sql = 'SELECT DISTINCT courseid
-                      FROM {grade_categories}
-                     WHERE aggregation = ?';
-            $courses = $DB->get_records_sql($sql, array(13));
-
-            foreach ($courses as $course) {
-                set_config('show_sumofgrades_upgrade_' . $course->courseid, 1);
-                // Set each of the grade items to needing an update so that when the user visits the grade reports the
-                // figures will be updated.
-                $DB->set_field('grade_items', 'needsupdate', 1, array('courseid' => $course->courseid));
-            }
-
-            set_config('grades_sumofgrades_upgrade_flagged', 1);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100600.04);
-    }
-
-    if ($oldversion < 2014100700.00) {
-
-        // Define table messageinbound_messagelist to be created.
-        $table = new xmldb_table('messageinbound_messagelist');
-
-        // Adding fields to table messageinbound_messagelist.
-        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('messageid', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
-        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('address', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
-        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-
-        // Adding keys to table messageinbound_messagelist.
-        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
-
-        // Conditionally launch create table for messageinbound_messagelist.
-        if (!$dbman->table_exists($table)) {
-            $dbman->create_table($table);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100700.00);
-    }
-
-    if ($oldversion < 2014100700.01) {
-
-        // Define field visible to be added to cohort.
-        $table = new xmldb_table('cohort');
-        $field = new xmldb_field('visible', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'descriptionformat');
-
-        // Conditionally launch add field visible.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100700.01);
-    }
-
-    if ($oldversion < 2014100800.00) {
-        // Remove qformat_learnwise (unless it has manually been added back).
-        if (!file_exists($CFG->dirroot . '/question/format/learnwise/format.php')) {
-            unset_all_config_for_plugin('qformat_learnwise');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014100800.00);
-    }
-
-    if ($oldversion < 2014101001.00) {
-        // Some blocks added themselves to the my/ home page, but they did not declare the
-        // subpage of the default my home page. While the upgrade script has been fixed, this
-        // upgrade script will fix the data that was wrongly added.
-
-        // We only proceed if we can find the right entry from my_pages. Private => 1 refers to
-        // the constant value MY_PAGE_PRIVATE.
-        if ($systempage = $DB->get_record('my_pages', array('userid' => null, 'private' => 1))) {
-
-            // Select the blocks there could have been automatically added. showinsubcontexts is hardcoded to 0
-            // because it is possible for administrators to have forced it on the my/ page by adding it to the
-            // system directly rather than updating the default my/ page.
-            $blocks = array('course_overview', 'private_files', 'online_users', 'badges', 'calendar_month', 'calendar_upcoming');
-            list($blocksql, $blockparams) = $DB->get_in_or_equal($blocks, SQL_PARAMS_NAMED);
-            $select = "parentcontextid = :contextid
-                    AND pagetypepattern = :page
-                    AND showinsubcontexts = 0
-                    AND subpagepattern IS NULL
-                    AND blockname $blocksql";
-            $params = array(
-                'contextid' => context_system::instance()->id,
-                'page' => 'my-index'
-            );
-            $params = array_merge($params, $blockparams);
-
-            $DB->set_field_select(
-                'block_instances',
-                'subpagepattern',
-                $systempage->id,
-                $select,
-                $params
-            );
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014101001.00);
-    }
-
-    if ($oldversion < 2014102000.00) {
-
-        // Define field aggregatesubcats to be dropped from grade_categories.
-        $table = new xmldb_table('grade_categories');
-        $field = new xmldb_field('aggregatesubcats');
-
-        // Conditionally launch drop field aggregatesubcats.
-        if ($dbman->field_exists($table, $field)) {
-
-            $sql = 'SELECT DISTINCT courseid
-                      FROM {grade_categories}
-                     WHERE aggregatesubcats = ?';
-            $courses = $DB->get_records_sql($sql, array(1));
-
-            foreach ($courses as $course) {
-                set_config('show_aggregatesubcats_upgrade_' . $course->courseid, 1);
-                // Set each of the grade items to needing an update so that when the user visits the grade reports the
-                // figures will be updated.
-                $DB->set_field('grade_items', 'needsupdate', 1, array('courseid' => $course->courseid));
-            }
-
-
-            $dbman->drop_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014102000.00);
-    }
-
-    if ($oldversion < 2014110300.00) {
-        // Run script restoring missing folder records for draft file areas.
-        upgrade_fix_missing_root_folders_draft();
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014110300.00);
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2014111000.00) {
-        // Coming from 2.7 or older, we need to flag the step minmaxgrade to be ignored.
-        set_config('upgrade_minmaxgradestepignored', 1);
-        // Coming from 2.7 or older, we need to flag the step for changing calculated grades to be regraded.
-        set_config('upgrade_calculatedgradeitemsonlyregrade', 1);
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014111000.00);
-    }
-
-    if ($oldversion < 2014120100.00) {
-
-        // Define field sslverification to be added to mnet_host.
-        $table = new xmldb_table('mnet_host');
-        $field = new xmldb_field('sslverification', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'applicationid');
-
-        // Conditionally launch add field sslverification.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014120100.00);
-    }
-
-    if ($oldversion < 2014120101.00) {
-
-        // Define field component to be added to comments.
-        $table = new xmldb_table('comments');
-        $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'contextid');
-
-        // Conditionally launch add field component.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014120101.00);
-    }
-
-    if ($oldversion < 2014120102.00) {
-
-        // Define table user_password_history to be created.
-        $table = new xmldb_table('user_password_history');
-
-        // Adding fields to table user_password_history.
-        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('hash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-
-        // Adding keys to table user_password_history.
-        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
-
-        // Conditionally launch create table for user_password_history.
-        if (!$dbman->table_exists($table)) {
-            $dbman->create_table($table);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2014120102.00);
-    }
-
-    if ($oldversion < 2015010800.01) {
-
-        // Make sure the private files handler is not set to expire.
-        $DB->set_field('messageinbound_handlers', 'defaultexpiration', 0,
-                array('classname' => '\core\message\inbound\private_files_handler'));
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015010800.01);
-
-    }
-
-    if ($oldversion < 2015012600.00) {
-
-        // If the site is using internal and external storage, or just external
-        // storage, and the external path specified is empty we change the setting
-        // to internal only. That is how the backup code is handling this
-        // misconfiguration.
-        $storage = (int) get_config('backup', 'backup_auto_storage');
-        $folder = get_config('backup', 'backup_auto_destination');
-        if ($storage !== 0 && empty($folder)) {
-            set_config('backup_auto_storage', 0, 'backup');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015012600.00);
-    }
-
-    if ($oldversion < 2015012600.01) {
-
-        // Convert calendar_lookahead to nearest new value.
-        $value = $DB->get_field('config', 'value', array('name' => 'calendar_lookahead'));
-        if ($value > 90) {
-            set_config('calendar_lookahead', '120');
-        } else if ($value > 60 and $value < 90) {
-            set_config('calendar_lookahead', '90');
-        } else if ($value > 30 and $value < 60) {
-            set_config('calendar_lookahead', '60');
-        } else if ($value > 21 and $value < 30) {
-            set_config('calendar_lookahead', '30');
-        } else if ($value > 14 and $value < 21) {
-            set_config('calendar_lookahead', '21');
-        } else if ($value > 7 and $value < 14) {
-            set_config('calendar_lookahead', '14');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015012600.01);
-    }
-
-    if ($oldversion < 2015021100.00) {
-
-        // Define field timemodified to be added to registration_hubs.
-        $table = new xmldb_table('registration_hubs');
-        $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'secret');
-
-        // Conditionally launch add field timemodified.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015021100.00);
-    }
-
-    if ($oldversion < 2015022401.00) {
-
-        // Define index useridfromto (not unique) to be added to message.
-        $table = new xmldb_table('message');
-        $index = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'useridto'));
-
-        // Conditionally launch add index useridfromto.
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-
-        // Define index useridfromto (not unique) to be added to message_read.
-        $table = new xmldb_table('message_read');
-        $index = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'useridto'));
-
-        // Conditionally launch add index useridfromto.
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015022401.00);
-    }
-
-    if ($oldversion < 2015022500.00) {
-        $table = new xmldb_table('user_devices');
-        $index = new xmldb_index('uuid-userid', XMLDB_INDEX_NOTUNIQUE, array('uuid', 'userid'));
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-        upgrade_main_savepoint(true, 2015022500.00);
-    }
-
-    if ($oldversion < 2015030400.00) {
-        // We have long since switched to storing timemodified per hub rather than a single 'registered' timestamp.
-        unset_config('registered');
-        upgrade_main_savepoint(true, 2015030400.00);
-    }
-
-    if ($oldversion < 2015031100.00) {
-        // Unset old config variable.
-        unset_config('enabletgzbackups');
-
-        upgrade_main_savepoint(true, 2015031100.00);
-    }
-
-    if ($oldversion < 2015031400.00) {
-
-        // Define index useridfrom (not unique) to be dropped form message.
-        $table = new xmldb_table('message');
-        $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
-
-        // Conditionally launch drop index useridfrom.
-        if ($dbman->index_exists($table, $index)) {
-            $dbman->drop_index($table, $index);
-        }
-
-        // Define index useridfrom (not unique) to be dropped form message_read.
-        $table = new xmldb_table('message_read');
-        $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, array('useridfrom'));
-
-        // Conditionally launch drop index useridfrom.
-        if ($dbman->index_exists($table, $index)) {
-            $dbman->drop_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015031400.00);
-    }
-
-    if ($oldversion < 2015031900.01) {
-        unset_config('crontime', 'registration');
-        upgrade_main_savepoint(true, 2015031900.01);
-    }
-
-    if ($oldversion < 2015032000.00) {
-        $table = new xmldb_table('badge_criteria');
-
-        $field = new xmldb_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
-        // Conditionally add description field to the badge_criteria table.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        $field = new xmldb_field('descriptionformat', XMLDB_TYPE_INTEGER, 2, null, XMLDB_NOTNULL, null, 0);
-        // Conditionally add description format field to the badge_criteria table.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        upgrade_main_savepoint(true, 2015032000.00);
-    }
-
-    if ($oldversion < 2015040200.01) {
-        // Force uninstall of deleted tool.
-        if (!file_exists("$CFG->dirroot/$CFG->admin/tool/timezoneimport")) {
-            // Remove capabilities.
-            capabilities_cleanup('tool_timezoneimport');
-            // Remove all other associated config.
-            unset_all_config_for_plugin('tool_timezoneimport');
-        }
-        upgrade_main_savepoint(true, 2015040200.01);
-    }
-
-    if ($oldversion < 2015040200.02) {
-        // Define table timezone to be dropped.
-        $table = new xmldb_table('timezone');
-        // Conditionally launch drop table for timezone.
-        if ($dbman->table_exists($table)) {
-            $dbman->drop_table($table);
-        }
-        upgrade_main_savepoint(true, 2015040200.02);
-    }
-
-    if ($oldversion < 2015040200.03) {
-        if (isset($CFG->timezone) and $CFG->timezone == 99) {
-            // Migrate to real server timezone.
-            unset_config('timezone');
-        }
-        upgrade_main_savepoint(true, 2015040200.03);
-    }
-
-    if ($oldversion < 2015040700.01) {
-        $DB->delete_records('config_plugins', array('name' => 'requiremodintro'));
-        upgrade_main_savepoint(true, 2015040700.01);
-    }
-
-    if ($oldversion < 2015040900.01) {
-        // Add "My grades" to the user menu.
-        $oldconfig = get_config('core', 'customusermenuitems');
-        if (strpos("mygrades,grades|/grade/report/mygrades.php|grades", $oldconfig) === false) {
-            $newconfig = "mygrades,grades|/grade/report/mygrades.php|grades\n" . $oldconfig;
-            set_config('customusermenuitems', $newconfig);
-        }
-
-        upgrade_main_savepoint(true, 2015040900.01);
-    }
-
-    if ($oldversion < 2015040900.02) {
-        // Update the default user menu (add preferences, remove my files and my badges).
-        $oldconfig = get_config('core', 'customusermenuitems');
-
-        // Add "My preferences" at the end.
-        if (strpos($oldconfig, "mypreferences,moodle|/user/preference.php|preferences") === false) {
-            $newconfig = $oldconfig . "\nmypreferences,moodle|/user/preferences.php|preferences";
-        } else {
-            $newconfig = $oldconfig;
-        }
-        // Remove my files.
-        $newconfig = str_replace("myfiles,moodle|/user/files.php|download", "", $newconfig);
-        // Remove my badges.
-        $newconfig = str_replace("mybadges,badges|/badges/mybadges.php|award", "", $newconfig);
-        // Remove holes.
-        $newconfig = preg_replace('/\n+/', "\n", $newconfig);
-        $newconfig = preg_replace('/(\r\n)+/', "\n", $newconfig);
-        set_config('customusermenuitems', $newconfig);
-
-        upgrade_main_savepoint(true, 2015040900.02);
-    }
-
-    if ($oldversion < 2015050400.00) {
-        $config = get_config('core', 'customusermenuitems');
-
-        // Change "My preferences" in the user menu to "Preferences".
-        $config = str_replace("mypreferences,moodle|/user/preferences.php|preferences",
-            "preferences,moodle|/user/preferences.php|preferences", $config);
-
-        // Change "My grades" in the user menu to "Grades".
-        $config = str_replace("mygrades,grades|/grade/report/mygrades.php|grades",
-            "grades,grades|/grade/report/mygrades.php|grades", $config);
-
-        set_config('customusermenuitems', $config);
-
-        upgrade_main_savepoint(true, 2015050400.00);
-    }
-
-    if ($oldversion < 2015050401.00) {
-        // Make sure we have messages in the user menu because it's no longer in the nav tree.
-        $oldconfig = get_config('core', 'customusermenuitems');
-        $messagesconfig = "messages,message|/message/index.php|message";
-        $preferencesconfig = "preferences,moodle|/user/preferences.php|preferences";
-
-        // See if it exists.
-        if (strpos($oldconfig, $messagesconfig) === false) {
-            // See if preferences exists.
-            if (strpos($oldconfig, "preferences,moodle|/user/preferences.php|preferences") !== false) {
-                // Insert it before preferences.
-                $newconfig = str_replace($preferencesconfig, $messagesconfig . "\n" . $preferencesconfig, $oldconfig);
-            } else {
-                // Custom config - we can only insert it at the end.
-                $newconfig = $oldconfig . "\n" . $messagesconfig;
-            }
-            set_config('customusermenuitems', $newconfig);
-        }
-
-        upgrade_main_savepoint(true, 2015050401.00);
-    }
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    if ($oldversion < 2015060400.02) {
-
-        // Sites that were upgrading from 2.7 and older will ignore this step.
-        if (empty($CFG->upgrade_minmaxgradestepignored)) {
-
-            upgrade_minmaxgrade();
-
-            // Flags this upgrade step as already run to prevent it from running multiple times.
-            set_config('upgrade_minmaxgradestepignored', 1);
-        }
-
-        upgrade_main_savepoint(true, 2015060400.02);
-    }
-
-    if ($oldversion < 2015061900.00) {
-        // MDL-49257. Changed the algorithm of calculating automatic weights of extra credit items.
-
-        // Before the change, in case when grade category (in "Natural" agg. method) had items with
-        // overridden weights, the automatic weight of extra credit items was illogical.
-        // In order to prevent grades changes after the upgrade we need to freeze gradebook calculation
-        // for the affected courses.
-
-        // This script in included in each major version upgrade process so make sure we don't run it twice.
-        if (empty($CFG->upgrade_extracreditweightsstepignored)) {
-            upgrade_extra_credit_weightoverride();
-
-            // To skip running the same script on the upgrade to the next major release.
-            set_config('upgrade_extracreditweightsstepignored', 1);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015061900.00);
-    }
-
-    if ($oldversion < 2015062500.01) {
-        // MDL-48239. Changed calculated grade items so that the maximum and minimum grade can be set.
-
-        // If the changes are accepted and a regrade is done on the gradebook then some grades may change significantly.
-        // This is here to freeze the gradebook in affected courses.
-
-        // This script is included in each major version upgrade process so make sure we don't run it twice.
-        if (empty($CFG->upgrade_calculatedgradeitemsignored)) {
-            upgrade_calculated_grade_items();
-
-            // To skip running the same script on the upgrade to the next major release.
-            set_config('upgrade_calculatedgradeitemsignored', 1);
-            // This config value is never used again.
-            unset_config('upgrade_calculatedgradeitemsonlyregrade');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015062500.01);
-    }
-
-    if ($oldversion < 2015081300.01) {
-
-        // Define field importtype to be added to grade_import_values.
-        $table = new xmldb_table('grade_import_values');
-        $field = new xmldb_field('importonlyfeedback', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'importer');
-
-        // Conditionally launch add field importtype.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015081300.01);
-    }
-
-    if ($oldversion < 2015082400.00) {
-
-        // Define table webdav_locks to be dropped.
-        $table = new xmldb_table('webdav_locks');
-
-        // Conditionally launch drop table for webdav_locks.
-        if ($dbman->table_exists($table)) {
-            $dbman->drop_table($table);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015082400.00);
-    }
-
-    if ($oldversion < 2015090200.00) {
-        $table = new xmldb_table('message');
-
-        // Define the deleted fields to be added to the message tables.
-        $field1 = new xmldb_field('timeuserfromdeleted', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0',
-            'timecreated');
-        $field2 = new xmldb_field('timeusertodeleted', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0',
-            'timecreated');
-        $oldindex = new xmldb_index('useridfromto', XMLDB_INDEX_NOTUNIQUE,
-            array('useridfrom', 'useridto'));
-        $newindex = new xmldb_index('useridfromtodeleted', XMLDB_INDEX_NOTUNIQUE,
-            array('useridfrom', 'useridto', 'timeuserfromdeleted', 'timeusertodeleted'));
-
-        // Conditionally launch add field timeuserfromdeleted.
-        if (!$dbman->field_exists($table, $field1)) {
-            $dbman->add_field($table, $field1);
-        }
-
-        // Conditionally launch add field timeusertodeleted.
-        if (!$dbman->field_exists($table, $field2)) {
-            $dbman->add_field($table, $field2);
-        }
-
-        // Conditionally launch drop index useridfromto.
-        if ($dbman->index_exists($table, $oldindex)) {
-            $dbman->drop_index($table, $oldindex);
-        }
-
-        // Conditionally launch add index useridfromtodeleted.
-        if (!$dbman->index_exists($table, $newindex)) {
-            $dbman->add_index($table, $newindex);
-        }
-
-        // Now add them to the message_read table.
-        $table = new xmldb_table('message_read');
-
-        // Conditionally launch add field timeuserfromdeleted.
-        if (!$dbman->field_exists($table, $field1)) {
-            $dbman->add_field($table, $field1);
-        }
-
-        // Conditionally launch add field timeusertodeleted.
-        if (!$dbman->field_exists($table, $field2)) {
-            $dbman->add_field($table, $field2);
-        }
-
-        // Conditionally launch drop index useridfromto.
-        if ($dbman->index_exists($table, $oldindex)) {
-            $dbman->drop_index($table, $oldindex);
-        }
-
-        // Conditionally launch add index useridfromtodeleted.
-        if (!$dbman->index_exists($table, $newindex)) {
-            $dbman->add_index($table, $newindex);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015090200.00);
-    }
-
-    if ($oldversion < 2015090801.00) {
-        // This upgrade script merges all tag instances pointing to the same course tag.
-        // User id is no longer used for those tag instances.
-        upgrade_course_tags();
-
-        // If configuration variable "Show course tags" is set, disable the block
-        // 'tags' because it can not be used for tagging courses any more.
-        if (!empty($CFG->block_tags_showcoursetags)) {
-            if ($record = $DB->get_record('block', array('name' => 'tags'), 'id, visible')) {
-                if ($record->visible) {
-                    $DB->update_record('block', array('id' => $record->id, 'visible' => 0));
-                }
-            }
-        }
-
-        // Define index idname (unique) to be dropped form tag (it's really weird).
-        $table = new xmldb_table('tag');
-        $index = new xmldb_index('idname', XMLDB_INDEX_UNIQUE, array('id', 'name'));
-
-        // Conditionally launch drop index idname.
-        if ($dbman->index_exists($table, $index)) {
-            $dbman->drop_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015090801.00);
-    }
-
-    if ($oldversion < 2015092200.00) {
-        // Define index qtype (not unique) to be added to question.
-        $table = new xmldb_table('question');
-        $index = new xmldb_index('qtype', XMLDB_INDEX_NOTUNIQUE, array('qtype'));
-
-        // Conditionally launch add index qtype.
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015092200.00);
-    }
-
-    if ($oldversion < 2015092900.00) {
-        // Rename backup_auto_keep setting to backup_auto_max_kept.
-        $keep = get_config('backup', 'backup_auto_keep');
-        if ($keep !== false) {
-            set_config('backup_auto_max_kept', $keep, 'backup');
-            unset_config('backup_auto_keep', 'backup');
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015092900.00);
-    }
-
-    if ($oldversion < 2015100600.00) {
-
-        // Define index notification (not unique) to be added to message_read.
-        $table = new xmldb_table('message_read');
-        $index = new xmldb_index('notificationtimeread', XMLDB_INDEX_NOTUNIQUE, array('notification', 'timeread'));
-
-        // Conditionally launch add index notification.
-        if (!$dbman->index_exists($table, $index)) {
-            $dbman->add_index($table, $index);
-        }
-
-        // Main savepoint reached.
-        upgrade_main_savepoint(true, 2015100600.00);
-    }
-
-    if ($oldversion < 2015100800.01) {
-        // The only flag for preventing all plugins installation features is
-        // now $CFG->disableupdateautodeploy in config.php.
-        unset_config('updateautodeploy');
-        upgrade_main_savepoint(true, 2015100800.01);
-    }
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     if ($oldversion < 2016011300.01) {
 
         // This is a big upgrade script. We create new table tag_coll and the field
@@ -2887,5 +1914,79 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2017061301.00);
     }
 
+    if ($oldversion < 2017071000.00) {
+
+        // Define field requireconfirmation to be added to oauth2_issuer.
+        $table = new xmldb_table('oauth2_issuer');
+        $field = new xmldb_field('requireconfirmation', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1', 'sortorder');
+
+        // Conditionally launch add field requireconfirmation.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2017071000.00);
+    }
+
+    if ($oldversion < 2017071001.00) {
+
+        // Define field timemodified to be added to block_instances.
+        $table = new xmldb_table('block_instances');
+        $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null,
+                null, null, 'configdata');
+
+        // Conditionally launch add field timemodified.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+
+            // Set field to current time.
+            $DB->set_field('block_instances', 'timemodified', time());
+
+            // Changing nullability of field timemodified on table block_instances to not null.
+            $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL,
+                    null, null, 'configdata');
+
+            // Launch change of nullability for field timemodified.
+            $dbman->change_field_notnull($table, $field);
+
+            // Define index timemodified (not unique) to be added to block_instances.
+            $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
+
+            // Conditionally launch add index timemodified.
+            if (!$dbman->index_exists($table, $index)) {
+                $dbman->add_index($table, $index);
+            }
+        }
+
+        // Define field timecreated to be added to block_instances.
+        $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null,
+                null, null, 'configdata');
+
+        // Conditionally launch add field timecreated.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+
+            // Set field to current time.
+            $DB->set_field('block_instances', 'timecreated', time());
+
+            // Changing nullability of field timecreated on table block_instances to not null.
+            $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL,
+                    null, null, 'configdata');
+
+            // Launch change of nullability for field timecreated.
+            $dbman->change_field_notnull($table, $field);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2017071001.00);
+    }
+
+    if ($oldversion < 2017071100.00 ) {
+        // Clean old upgrade setting not used anymore.
+        unset_config('upgrade_minmaxgradestepignored');
+        upgrade_main_savepoint(true, 2017071100.00);
+    }
+
     return true;
 }
index bfb630d..134d4c0 100644 (file)
@@ -130,26 +130,6 @@ function upgrade_group_members_only($groupingid, $availability) {
     return json_encode($tree);
 }
 
-/**
- * Updates the mime-types for files that exist in the database, based on their
- * file extension.
- *
- * @param array $filetypes Array with file extension as the key, and mimetype as the value
- */
-function upgrade_mimetypes($filetypes) {
-    global $DB;
-    $select = $DB->sql_like('filename', '?', false);
-    foreach ($filetypes as $extension=>$mimetype) {
-        $DB->set_field_select(
-            'files',
-            'mimetype',
-            $mimetype,
-            $select,
-            array($extension)
-        );
-    }
-}
-
 /**
  * Marks all courses with changes in extra credit weight calculation
  *
@@ -288,26 +268,6 @@ function upgrade_calculated_grade_items($courseid = null) {
     }
 }
 
-/**
- * This upgrade script merges all tag instances pointing to the same course tag
- *
- * User id is no longer used for those tag instances
- */
-function upgrade_course_tags() {
-    global $DB;
-    $sql = "SELECT min(ti.id)
-        FROM {tag_instance} ti
-        LEFT JOIN {tag_instance} tii on tii.itemtype = ? and tii.itemid = ti.itemid and tii.tiuserid = 0 and tii.tagid = ti.tagid
-        where ti.itemtype = ? and ti.tiuserid <> 0 AND tii.id is null
-        group by ti.tagid, ti.itemid";
-    $ids = $DB->get_fieldset_sql($sql, array('course', 'course'));
-    if ($ids) {
-        list($idsql, $idparams) = $DB->get_in_or_equal($ids);
-        $DB->execute('UPDATE {tag_instance} SET tiuserid = 0 WHERE id ' . $idsql, $idparams);
-    }
-    $DB->execute("DELETE FROM {tag_instance} WHERE itemtype = ? AND tiuserid <> 0", array('course'));
-}
-
 /**
  * This function creates a default separated/connected scale
  * so there's something in the database.  The locations of
index db73f07..be2acfd 100644 (file)
@@ -30,61 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool
  */
 function xmldb_editor_atto_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    $dbman = $DB->get_manager();
-
-    if ($oldversion < 2014081400) {
-
-        // Define table editor_atto_autosave to be created.
-        $table = new xmldb_table('editor_atto_autosave');
-
-        // Adding fields to table editor_atto_autosave.
-        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
-        $table->add_field('elementid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('pagehash', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
-        $table->add_field('drafttext', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
-        $table->add_field('draftid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
-        $table->add_field('pageinstance', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
-
-        // Adding keys to table editor_atto_autosave.
-        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->add_key('autosave_uniq_key', XMLDB_KEY_UNIQUE, array('elementid', 'contextid', 'userid', 'pagehash'));
-
-        // Conditionally launch create table for editor_atto_autosave.
-        if (!$dbman->table_exists($table)) {
-            $dbman->create_table($table);
-        }
-
-        // Atto savepoint reached.
-        upgrade_plugin_savepoint(true, 2014081400, 'editor', 'atto');
-    }
-
-    if ($oldversion < 2014081900) {
-
-        // Define field timemodified to be added to editor_atto_autosave.
-        $table = new xmldb_table('editor_atto_autosave');
-        $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'pageinstance');
-
-        // Conditionally launch add field timemodified.
-        if (!$dbman->field_exists($table, $field)) {
-            $dbman->add_field($table, $field);
-        }
-
-        // Atto savepoint reached.
-        upgrade_plugin_savepoint(true, 2014081900, 'editor', 'atto');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 1682d19..c17c2ce 100644 (file)
@@ -30,17 +30,7 @@ defined('MOODLE_INTERNAL') || die();
  * @return bool
  */
 function xmldb_atto_equation_upgrade($oldversion) {
-    require_once(__DIR__ . '/upgradelib.php');
-
-    if ($oldversion < 2015083100) {
-        atto_equation_update_librarygroup4_setting();
-
-        // Atto equation savepoint reached.
-        upgrade_plugin_savepoint(true, 2015083100, 'atto', 'equation');
-    }
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
@@ -52,4 +42,4 @@ function xmldb_atto_equation_upgrade($oldversion) {
     // Put any upgrade step following this.
 
     return true;
-}
\ No newline at end of file
+}
diff --git a/lib/editor/atto/plugins/equation/db/upgradelib.php b/lib/editor/atto/plugins/equation/db/upgradelib.php
deleted file mode 100644 (file)
index f60c0f9..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?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/>.
-
-/**
- * Atto equation upgrade helper functions.
- *
- * @package    atto_equation
- * @copyright  2015 Sam Chaffee <sam@moodlerooms.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * Updates the librarygroup4 setting if has not been changed from the default.
- */
-function atto_equation_update_librarygroup4_setting() {
-    // Original default setting for librarygroup4.
-    $settingdefault = '
-\sum{a,b}
-\int_{a}^{b}{c}
-\iint_{a}^{b}{c}
-\iiint_{a}^{b}{c}
-\oint{a}
-(a)
-[a]
-\lbrace{a}\rbrace
-\left| \begin{matrix} a_1 & a_2 \\ a_3 & a_4 \end{matrix} \right|
-';
-    // Make a comparison string.
-    $settingdefaultcmpr = trim(str_replace(array("\r", "\n"), '', $settingdefault));
-
-    // Make the current librarygroup4 setting into a comparison string.
-    $currentsetting = get_config('atto_equation', 'librarygroup4');
-    $currentsettingcmpr = trim(str_replace(array("\r", "\n"), '', $currentsetting));
-
-    if ($settingdefaultcmpr === $currentsettingcmpr) {
-        // Only if the original defaults match the current setting do we set the new config.
-        $newconfig = '
-\sum{a,b}
-\sqrt[a]{b+c}
-\int_{a}^{b}{c}
-\iint_{a}^{b}{c}
-\iiint_{a}^{b}{c}
-\oint{a}
-(a)
-[a]
-\lbrace{a}\rbrace
-\left| \begin{matrix} a_1 & a_2 \\ a_3 & a_4 \end{matrix} \right|
-\frac{a}{b+c}
-\vec{a}
-\binom {a} {b}
-{a \brack b}
-{a \brace b}
-';
-        set_config('librarygroup4', $newconfig, 'atto_equation');
-    }
-}
\ No newline at end of file
diff --git a/lib/editor/atto/plugins/equation/tests/upgradelib_testcase.php b/lib/editor/atto/plugins/equation/tests/upgradelib_testcase.php
deleted file mode 100644 (file)
index bd872e5..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?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/>.
-
-/**
- * PHPUnit testcase class for atto equation upgrade lib.
- *
- * @package    atto_equation
- * @copyright  2015 Sam Chaffee <sam@moodlerooms.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * PHPUnit testcase class for atto equation upgrade lib.
- *
- * @package    atto_equation
- * @copyright  2015 Sam Chaffee <sam@moodlerooms.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class atto_equation_upgradelib_testcase extends advanced_testcase {
-    /**
-     * The name of the plugin in config_plugins.
-     */
-    const SETTING_PLUGIN = 'atto_equation';
-
-    /**
-     * The name of the setting in config_plugins.
-     */
-    const SETTING_NAME = 'librarygroup4';
-
-    /**
-     * Does testsuite set up.
-     */
-    public function setUp() {
-        $this->resetAfterTest();
-    }
-
-    /**
-     * Tests the upgradelib atto_equation_update_librarygroup4_setting function.
-     */
-    public function test_update_librarygroup4_update() {
-        global $CFG;
-        require_once($CFG->libdir . '/editor/atto/plugins/equation/db/upgradelib.php');
-
-        $originaldefaults = [
-            '\sum{a,b}',
-            '\int_{a}^{b}{c}',
-            '\iint_{a}^{b}{c}',
-            '\iiint_{a}^{b}{c}',
-            '\oint{a}',
-            '(a)',
-            '[a]',
-            '\lbrace{a}\rbrace',
-            '\left| \begin{matrix} a_1 & a_2 \\ a_3 & a_4 \end{matrix} \right|',
-        ];
-
-        $newconfig = '
-\sum{a,b}
-\sqrt[a]{b+c}
-\int_{a}^{b}{c}
-\iint_{a}^{b}{c}
-\iiint_{a}^{b}{c}
-\oint{a}
-(a)
-[a]
-\lbrace{a}\rbrace
-\left| \begin{matrix} a_1 & a_2 \\ a_3 & a_4 \end{matrix} \right|
-\frac{a}{b+c}
-\vec{a}
-\binom {a} {b}
-{a \brack b}
-{a \brace b}
-';
-
-        // Test successful update using windows line endings.
-        $originaldefaultswindows = "\r\n" . implode("\r\n", $originaldefaults) . "\r\n";
-        set_config(self::SETTING_NAME, $originaldefaultswindows, self::SETTING_PLUGIN);
-        atto_equation_update_librarygroup4_setting();
-
-        $this->assertEquals($newconfig, get_config(self::SETTING_PLUGIN, self::SETTING_NAME));
-
-        // Test successful update using linux line .
-        $originaldefaultslinux = "\n" . implode("\n", $originaldefaults) . "\n";
-        set_config(self::SETTING_NAME, $originaldefaultslinux, self::SETTING_PLUGIN);
-        atto_equation_update_librarygroup4_setting();
-
-        $this->assertEquals($newconfig, get_config(self::SETTING_PLUGIN, self::SETTING_NAME));
-
-        // Alter the original configuration by removing one of the equations.
-        $alteredconfig = array_slice($originaldefaults, 0, -1);
-
-        // Test no update using windows line endings.
-        $alteredconfigwindows = "\r\n" . implode("\r\n", $alteredconfig) . "\r\n";
-        set_config(self::SETTING_NAME, $alteredconfigwindows, self::SETTING_PLUGIN);
-        atto_equation_update_librarygroup4_setting();
-
-        $this->assertEquals($alteredconfigwindows, get_config(self::SETTING_PLUGIN, self::SETTING_NAME));
-
-        // Test no update using linux line endings.
-        $alteredconfiglinux = "\n" . implode("\n", $alteredconfig) . "\n";
-        set_config(self::SETTING_NAME, $alteredconfiglinux, self::SETTING_PLUGIN);
-        atto_equation_update_librarygroup4_setting();
-
-        $this->assertEquals($alteredconfiglinux, get_config(self::SETTING_PLUGIN, self::SETTING_NAME));
-
-        // Test no configuration.
-        unset_config(self::SETTING_NAME, self::SETTING_PLUGIN);
-        atto_equation_update_librarygroup4_setting();
-
-        $this->assertFalse(get_config(self::SETTING_PLUGIN, self::SETTING_NAME));
-    }
-}
\ No newline at end of file
index f52c1f5..f892f5b 100644 (file)
@@ -1,5 +1,13 @@
 This files describes API changes in the editor_atto code.
+
+=== 3.4 ===
+
+* The following functions, previously used (exclusively) by upgrade steps are not available
+  anymore because of the upgrade cleanup performed for this version. See MDL-57432 for more info:
+    - atto_equation_update_librarygroup4_setting()
+
 === 3.0 ===
+
 * Rangy updated to 1.3.0.
   Rangy has deprecated the createCssClassApplier function in this version (it is now createClassApplier).
 
index e3950dc..b90b6ef 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 function xmldb_editor_tinymce_upgrade($oldversion) {
-    global $CFG, $DB;
-
-    if ($oldversion < 2014062900) {
-        // We only want to delete DragMath from the customtoolbar setting if the directory no longer exists. If
-        // the directory is present then it means it has been restored, so do not remove any settings.
-        if (!check_dir_exists($CFG->libdir . '/editor/tinymce/plugins/dragmath', false)) {
-            // Remove the DragMath plugin from the 'customtoolbar' setting (if it exists) as it has been removed.
-            $currentorder = get_config('editor_tinymce', 'customtoolbar');
-            $newtoolbarrows = array();
-            $currenttoolbarrows = explode("\n", $currentorder);
-            foreach ($currenttoolbarrows as $currenttoolbarrow) {
-                $currenttoolbarrow = implode(',', array_diff(str_getcsv($currenttoolbarrow), array('dragmath')));
-                $newtoolbarrows[] = $currenttoolbarrow;
-            }
-            $neworder = implode("\n", $newtoolbarrows);
-            unset_config('customtoolbar', 'editor_tinymce');
-            set_config('customtoolbar', $neworder, 'editor_tinymce');
-        }
-
-        upgrade_plugin_savepoint(true, 2014062900, 'editor', 'tinymce');
-    }
-
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
+    global $CFG;
 
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
index 90c1108..0d74bc9 100644 (file)
@@ -27,15 +27,6 @@ defined('MOODLE_INTERNAL') || die();
 function xmldb_tinymce_spellchecker_upgrade($oldversion) {
     global $CFG;
 
-    // Moodle v2.8.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v2.9.0 release upgrade line.
-    // Put any upgrade step following this.
-
-    // Moodle v3.0.0 release upgrade line.
-    // Put any upgrade step following this.
-
     // Moodle v3.1.0 release upgrade line.
     // Put any upgrade step following this.
 
index 28faa7e..20112a0 100644 (file)
@@ -972,7 +972,9 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea
                 if (!empty($repoid)) {
                     $context = context::instance_by_id($contextid, MUST_EXIST);
                     $repo = repository::get_repository_by_id($repoid, $context);
-
+                    if (!empty($options)) {
+                        $repo->options = $options;
+                    }
                     $file_record['repositoryid'] = $repoid;
                     // This hook gives the repo a place to do some house cleaning, and update the $reference before it's saved
                     // to the file store. E.g. transfer ownership of the file to a system account etc.
@@ -3886,9 +3888,10 @@ class curl_cache {
  * @param null|string $preview the preview mode, defaults to serving the original file
  * @param boolean $offline If offline is requested - don't serve a redirect to an external file, return a file suitable for viewing
  *                         offline (e.g. mobile app).
+ * @param bool $embed Whether this file will be served embed into an iframe.
  * @todo MDL-31088 file serving improments
  */
-function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false) {
+function file_pluginfile($relativepath, $forcedownload, $preview = null, $offline = false, $embed = false) {
     global $DB, $CFG, $USER;
     // relative path must start with '/'
     if (!$relativepath) {
@@ -3912,7 +3915,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null, $offlin
 
     $fs = get_file_storage();
 
-    $sendfileoptions = ['preview' => $preview, 'offline' => $offline];
+    $sendfileoptions = ['preview' => $preview, 'offline' => $offline, 'embed' => $embed];
 
     // ========================================================================================================================
     if ($component === 'blog') {
index 935c538..79981cc 100644 (file)
@@ -2272,8 +2272,28 @@ class global_navigation extends navigation_node {
             return false;
         }
         // Add a branch for the current user.
-        $canseefullname = has_capability('moodle/site:viewfullnames', $coursecontext);
-        $usernode = $usersnode->add(fullname($user, $canseefullname), $userviewurl, self::TYPE_USER, null, 'user' . $user->id);
+        // Only reveal user details if $user is the current user, or a user to which the current user has access.
+        $viewprofile = true;
+        if (!$iscurrentuser) {
+            require_once($CFG->dirroot . '/user/lib.php');
+            if ($this->page->context->contextlevel == CONTEXT_USER && !has_capability('moodle/user:viewdetails', $usercontext) ) {
+                $viewprofile = false;
+            } else if ($this->page->context->contextlevel != CONTEXT_USER && !user_can_view_profile($user, $course, $usercontext)) {
+                $viewprofile = false;
+            }
+            if (!$viewprofile) {
+                $viewprofile = user_can_view_profile($user, null, $usercontext);
+            }
+        }
+
+        // Now, conditionally add the user node.
+        if ($viewprofile) {
+            $canseefullname = has_capability('moodle/site:viewfullnames', $coursecontext);
+            $usernode = $usersnode->add(fullname($user, $canseefullname), $userviewurl, self::TYPE_USER, null, 'user' . $user->id);
+        } else {
+            $usernode = $usersnode->add(get_string('user'));
+        }
+
         if ($this->page->context->contextlevel == CONTEXT_USER && $user->id == $this->page->context->instanceid) {
             $usernode->make_active();
         }
index ca3b355..e99177d 100644 (file)
@@ -67,7 +67,7 @@ function theme_get_sub_revision_for_theme($themename) {
 
     if (empty($CFG->themedesignermode)) {
         $pluginname = "theme_{$themename}";
-        $revision = get_config($pluginname, 'themerev');
+        $revision = during_initial_install() ? null : get_config($pluginname, 'themerev');
 
         if (empty($revision)) {
             // This only happens during install. It doesn't matter what themerev we use as long as it's positive.
index 15705a8..139e6f9 100644 (file)
@@ -89,7 +89,7 @@ class renderer_base {
             $loader = new \core\output\mustache_filesystem_loader();
             $stringhelper = new \core\output\mustache_string_helper();
             $quotehelper = new \core\output\mustache_quote_helper();
-            $jshelper = new \core\output\mustache_javascript_helper($this->page->requires);
+            $jshelper = new \core\output\mustache_javascript_helper($this->page);
             $pixhelper = new \core\output\mustache_pix_helper($this);
             $shortentexthelper = new \core\output\mustache_shorten_text_helper();
             $userdatehelper = new \core\output\mustache_user_date_helper();
@@ -741,16 +741,26 @@ class core_renderer extends renderer_base {
     public function standard_footer_html() {
         global $CFG, $SCRIPT;
 
+        $output = '';
         if (during_initial_install()) {
             // Debugging info can not work before install is finished,
             // in any case we do not want any links during installation!
-            return '';
+            return $output;
+        }
+
+        // Give plugins an opportunity to add any footer elements.
+        // The callback must always return a string containing valid html footer content.
+        $pluginswithfunction = get_plugins_with_function('standard_footer_html', 'lib.php');
+        foreach ($pluginswithfunction as $plugins) {
+            foreach ($plugins as $function) {
+                $output .= $function();
+            }
         }
 
         // This function is normally called from a layout.php file in {@link core_renderer::header()}
         // but some of the content won't be known until later, so we return a placeholder
         // for now. This will be replaced with the real content in {@link core_renderer::footer()}.
-        $output = $this->unique_performance_info_token;
+        $output .= $this->unique_performance_info_token;
         if ($this->page->devicetypeinuse == 'legacy') {
             // The legacy theme is in use print the notification
             $output .= html_writer::tag('div', get_string('legacythemeinuse'), array('class'=>'legacythemeinuse'));
@@ -4065,16 +4075,16 @@ EOD;
 
     public function context_header($headerinfo = null, $headinglevel = 1) {
         global $DB, $USER, $CFG;
+        require_once($CFG->dirroot . '/user/lib.php');
         $context = $this->page->context;
+        $heading = null;
+        $imagedata = null;
+        $subheader = null;
+        $userbuttons = null;
         // Make sure to use the heading if it has been set.
         if (isset($headerinfo['heading'])) {
             $heading = $headerinfo['heading'];
-        } else {
-            $heading = null;
         }
-        $imagedata = null;
-        $subheader = null;
-        $userbuttons = null;
         // The user context currently has images and buttons. Other contexts may follow.
         if (isset($headerinfo['user']) || $context->contextlevel == CONTEXT_USER) {
             if (isset($headerinfo['user'])) {
@@ -4083,47 +4093,60 @@ EOD;
                 // Look up the user information if it is not supplied.
                 $user = $DB->get_record('user', array('id' => $context->instanceid));
             }
+
             // If the user context is set, then use that for capability checks.
             if (isset($headerinfo['usercontext'])) {
                 $context = $headerinfo['usercontext'];
             }
-            // Use the user's full name if the heading isn't set.
-            if (!isset($heading)) {
-                $heading = fullname($user);
+
+            // Only provide user information if the user is the current user, or a user which the current user can view.
+            $canviewdetails = false;
+            if ($user->id == $USER->id || user_can_view_profile($user)) {
+                $canviewdetails = true;
             }
 
-            $imagedata = $this->user_picture($user, array('size' => 100));
-            // Check to see if we should be displaying a message button.
-            if (!empty($CFG->messaging) && $USER->id != $user->id && has_capability('moodle/site:sendmessage', $context)) {
-                $iscontact = !empty(message_get_contact($user->id));
-                $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
-                $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
-                $contactimage = $iscontact ? 'removecontact' : 'addcontact';
-                $userbuttons = array(
-                    'messages' => array(
-                        'buttontype' => 'message',
-                        'title' => get_string('message', 'message'),
-                        'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
-                        'image' => 'message',
-                        'linkattributes' => array('role' => 'button'),
-                        'page' => $this->page
-                    ),
-                    'togglecontact' => array(
-                        'buttontype' => 'togglecontact',
-                        'title' => get_string($contacttitle, 'message'),
-                        'url' => new moodle_url('/message/index.php', array(
-                                'user1' => $USER->id,
-                                'user2' => $user->id,
-                                $contacturlaction => $user->id,
-                                'sesskey' => sesskey())
+            if ($canviewdetails) {
+                // Use the user's full name if the heading isn't set.
+                if (!isset($heading)) {
+                    $heading = fullname($user);
+                }
+
+                $imagedata = $this->user_picture($user, array('size' => 100));
+
+                // Check to see if we should be displaying a message button.
+                if (!empty($CFG->messaging) && $USER->id != $user->id && has_capability('moodle/site:sendmessage', $context)) {
+                    $iscontact = !empty(message_get_contact($user->id));
+                    $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
+                    $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
+                    $contactimage = $iscontact ? 'removecontact' : 'addcontact';
+                    $userbuttons = array(
+                        'messages' => array(
+                            'buttontype' => 'message',
+                            'title' => get_string('message', 'message'),
+                            'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
+                            'image' => 'message',
+                            'linkattributes' => array('role' => 'button'),
+                            'page' => $this->page
                         ),
-                        'image' => $contactimage,
-                        'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
-                        'page' => $this->page
-                    ),
-                );
+                        'togglecontact' => array(
+                            'buttontype' => 'togglecontact',
+                            'title' => get_string($contacttitle, 'message'),
+                            'url' => new moodle_url('/message/index.php', array(
+                                    'user1' => $USER->id,
+                                    'user2' => $user->id,
+                                    $contacturlaction => $user->id,
+                                    'sesskey' => sesskey())
+                            ),
+                            'image' => $contactimage,
+                            'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
+                            'page' => $this->page
+                        ),
+                    );
 
-                $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
+                    $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
+                }
+            } else {
+                $heading = null;
             }
         }
 
diff --git a/lib/phpminimumversionlib.php b/lib/phpminimumversionlib.php
new file mode 100644 (file)
index 0000000..7beeac0
--- /dev/null
@@ -0,0 +1,76 @@
+<?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/>.
+
+// MOODLE_INTERNAL check intentionally missing to allow this to be used more widely!
+
+/**
+ * A set of PHP-compatible convenience functions to check Moodle minimum PHP version in
+ * a unified place.
+ *
+ * PLEASE NOTE: This file is made to be both php-version compatible and without requirement on
+ * any moodle functions or installation so it can be used in installer or incompatible PHP versions.
+ *
+ * @package    core
+ * @copyright  2017 Dan Poltawski <dan@moodle.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Require our minimum php version or halt execution if requirement not met.
+ * @return void Execution is halted if version is not met.
+ */
+function moodle_require_minimum_php_version() {
+    // PLEASE NOTE THIS FUNCTION MUST BE COMPATIBLE WITH OLD UNSUPPORTED VERSIONS OF PHP!
+    moodle_minimum_php_version_is_met(true);
+}
+
+/**
+ * Tests the current PHP version against Moodle's minimum requirement. When requirement
+ * is not met returns false or halts execution depending $haltexecution param.
+ *
+ * @param bool $haltexecution Should execution be halted when requirement not met? Defaults to false.
+ * @return bool returns true if requirement is met (false if not)
+ */
+function moodle_minimum_php_version_is_met($haltexecution = false) {
+    // PLEASE NOTE THIS FUNCTION MUST BE COMPATIBLE WITH OLD UNSUPPORTED VERSIONS OF PHP.
+    // Do not use modern php features or Moodle convenience functions (e.g. localised strings).
+
+    $minimumversion = '7.0.0';
+    $moodlerequirementchanged = '3.4';
+
+    if (version_compare(PHP_VERSION, $minimumversion) < 0) {
+        if ($haltexecution) {
+            $error = "Moodle ${moodlerequirementchanged} or later requires at least PHP ${minimumversion} "
+                . "(currently using version " . PHP_VERSION .").\n"
+                . "Some servers may have multiple PHP versions installed, are you using the correct executable?\n";
+
+            // Our CLI scripts define CLI_SCRIPT before running this test, so make use of
+            // to send error on STDERR.
+            if (defined('CLI_SCRIPT') && defined('STDERR')) {
+                fwrite(STDERR, $error);
+            } else {
+                echo $error;
+            }
+            exit(1);
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+// DO NOT ADD EXTRA FUNCTIONS TO THIS FILE!!
+// This file must be functioning on all versions of PHP, extra functions belong elsewhere.
index 1d65ea1..a6c2cf3 100644 (file)
 
     </div>
 
+    <div class="signuppanel">
     {{#hasinstructions}}
-        <div class="signuppanel">
-            <h2>{{#str}} firsttime {{/str}}</h2>
-            <div class="subcontent">
-                {{{instructions}}}
-                {{#cansignup}}
-                    <div class="signupform">
-                        <form action="{{signupurl}}" method="get" id="signup">
-                            <div>
-                                <input type="submit" value={{#quote}}{{#str}} startsignup {{/str}}{{/quote}} />
-                            </div>
-                        </form>
-                    </div>
-                {{/cansignup}}
-            </div>
+        <h2>{{#str}} firsttime {{/str}}</h2>
+        <div class="subcontent">
+            {{{instructions}}}
+            {{#cansignup}}
+                <div class="signupform">
+                    <form action="{{signupurl}}" method="get" id="signup">
+                        <div>
+                            <input type="submit" value={{#quote}}{{#str}} startsignup {{/str}}{{/quote}} />
+                        </div>
+                    </form>
+                </div>
+            {{/cansignup}}
         </div>
     {{/hasinstructions}}
 
             <div class="potentialidplist">
                 {{#identityproviders}}
                     <div class="potentialidp">
-                        <a href="{{url}}" title={{#quote}}{{name}}{{/quote}}>
-                            {{#iconurl}}
-                                <img src="{{iconurl}}" alt="" width=