Merge branch 'MDL-52608-master' of https://github.com/xow/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Mon, 18 Jan 2016 06:47:52 +0000 (14:47 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Mon, 18 Jan 2016 06:47:52 +0000 (14:47 +0800)
302 files changed:
Gruntfile.js
admin/settings/courses.php
admin/tool/langimport/index.php
admin/tool/uploadcourse/classes/course.php
admin/tool/uploadcourse/tests/course_test.php
admin/tool/uploaduser/index.php
admin/webservice/testclient.php
backup/moodle2/restore_stepslib.php
backup/util/dbops/restore_dbops.class.php
badges/tests/badgeslib_test.php
blocks/activity_results/tests/behat/highscoreswithscales.feature [new file with mode: 0644]
blocks/activity_results/tests/behat/highscoreswithscalesandgroups.feature [new file with mode: 0644]
blocks/activity_results/tests/behat/highscoreswithseperategroups.feature
blocks/activity_results/tests/behat/highscoreswithvisiblegroups.feature
blocks/activity_results/tests/behat/lowscoreswithscales.feature [new file with mode: 0644]
blocks/activity_results/tests/behat/lowscoreswithscalesandgroups.feature [new file with mode: 0644]
blocks/activity_results/tests/behat/lowscoreswithseperategroups.feature
blocks/activity_results/tests/behat/lowscoreswithvisiblegroups.feature
blocks/blog_menu/tests/behat/block_blog_menu.feature [new file with mode: 0644]
blocks/blog_menu/tests/behat/block_blog_menu_course.feature [new file with mode: 0644]
blocks/blog_menu/tests/behat/block_blog_menu_frontpage.feature [new file with mode: 0644]
blocks/blog_tags/block_blog_tags.php
blocks/moodleblock.class.php
blocks/news_items/block_news_items.php
blocks/rss_client/block_rss_client.php
blocks/rss_client/classes/output/block.php [new file with mode: 0644]
blocks/rss_client/classes/output/channel_image.php [new file with mode: 0644]
blocks/rss_client/classes/output/feed.php [new file with mode: 0644]
blocks/rss_client/classes/output/footer.php [new file with mode: 0644]
blocks/rss_client/classes/output/item.php [new file with mode: 0644]
blocks/rss_client/classes/output/renderer.php [new file with mode: 0644]
blocks/rss_client/templates/block.mustache [new file with mode: 0644]
blocks/rss_client/templates/channel_image.mustache [new file with mode: 0644]
blocks/rss_client/templates/feed.mustache [new file with mode: 0644]
blocks/rss_client/templates/footer.mustache [new file with mode: 0644]
blocks/rss_client/templates/item.mustache [new file with mode: 0644]
blocks/tag_flickr/block_tag_flickr.php
blocks/tag_flickr/edit_form.php
blocks/tag_youtube/block_tag_youtube.php
blocks/tags/backup/moodle2/restore_tags_block_task.class.php [new file with mode: 0644]
blocks/tags/block_tags.php
blocks/tags/edit_form.php
blocks/tags/lang/en/block_tags.php
blocks/tags/tests/behat/tagcloud.feature
blog/edit.php
blog/edit_form.php
blog/external_blog_edit.php
blog/external_blog_edit_form.php
blog/index.php
blog/lib.php
blog/locallib.php
blog/renderer.php
blog/rsslib.php
blog/tests/lib_test.php [moved from blog/tests/bloglib_test.php with 78% similarity]
calendar/lib.php
composer.json
composer.lock
course/classes/management_renderer.php
course/edit.php
course/edit_form.php
course/lib.php
course/renderer.php
course/tags.php
course/tags_form.php
course/tests/courselib_test.php
course/tests/externallib_test.php
enrol/externallib.php
enrol/manual/yui/quickenrolment/quickenrolment.js
enrol/paypal/ipn.php
enrol/self/externallib.php
enrol/self/tests/externallib_test.php
enrol/tests/behat/manage_enrolments_from_participants.feature [new file with mode: 0644]
enrol/tests/externallib_test.php
grade/grading/form/guide/amd/build/comment_chooser.min.js [new file with mode: 0644]
grade/grading/form/guide/amd/src/comment_chooser.js [new file with mode: 0644]
grade/grading/form/guide/edit_form.php
grade/grading/form/guide/guideeditor.php
grade/grading/form/guide/js/guideeditor.js
grade/grading/form/guide/lang/en/gradingform_guide.php
grade/grading/form/guide/lib.php
grade/grading/form/guide/renderer.php
grade/grading/form/guide/templates/comment_chooser.mustache [new file with mode: 0644]
grade/grading/form/guide/tests/behat/behat_gradingform_guide.php [new file with mode: 0644]
grade/grading/form/guide/tests/behat/edit_guide.feature [new file with mode: 0644]
grade/report/grader/lib.php
grade/report/history/index.php
grade/report/history/tests/behat/basic_functionality.feature
grade/report/user/tests/lib_test.php [new file with mode: 0644]
grade/tests/behat/grade_hidden_items.feature [new file with mode: 0644]
install/lang/hi/admin.php
install/lang/hr/admin.php
install/lang/hr/error.php
install/lang/hr/install.php
install/lang/lt/moodle.php
install/lang/pt/admin.php
install/lang/pt/moodle.php
lang/en/backup.php
lang/en/cache.php
lang/en/deprecated.txt
lang/en/moodle.php
lang/en/question.php
lang/en/tag.php
lang/en/webservice.php
lib/adminlib.php
lib/amd/build/tag.min.js
lib/amd/src/tag.js
lib/behat/lib.php
lib/bennu/readme_moodle.txt
lib/blocklib.php
lib/classes/event/tag_added.php
lib/classes/event/tag_collection_created.php [new file with mode: 0644]
lib/classes/event/tag_collection_deleted.php [new file with mode: 0644]
lib/classes/event/tag_collection_updated.php [new file with mode: 0644]
lib/classes/event/tag_created.php
lib/classes/event/tag_removed.php
lib/classes/plugin_manager.php
lib/classes/plugininfo/cachestore.php
lib/classes/string_manager_standard.php
lib/classes/task/tag_cron_task.php
lib/coursecatlib.php
lib/db/caches.php
lib/db/install.xml
lib/db/services.php
lib/db/tag.php [new file with mode: 0644]
lib/db/tasks.php
lib/db/upgrade.php
lib/ddl/mysql_sql_generator.php
lib/deprecatedlib.php
lib/dml/moodle_database.php
lib/form/tags.php
lib/grade/grade_grade.php
lib/modinfolib.php
lib/moodlelib.php
lib/myprofilelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/pagelib.php
lib/phpunit/classes/advanced_testcase.php
lib/phpunit/tests/advanced_test.php
lib/questionlib.php
lib/testing/generator/data_generator.php
lib/testing/tests/generator_test.php
lib/tests/myprofilelib_test.php [new file with mode: 0644]
lib/tests/questionlib_test.php
lib/upgrade.txt
lib/upgradelib.php
local/upgrade.txt
login/token.php
message/externallib.php
message/lib.php
message/tests/externallib_test.php
message/upgrade.txt
mod/assign/feedback/editpdf/tests/behat/annotate_pdf.feature
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/editor.js
mod/assign/lang/en/assign.php
mod/assign/locallib.php
mod/assign/tests/locallib_test.php
mod/chat/lib.php
mod/chat/locallib.php
mod/chat/tests/behat/chat_course_reset.feature [new file with mode: 0644]
mod/forum/backup/moodle2/backup_forum_stepslib.php
mod/forum/classes/event/discussion_pinned.php [new file with mode: 0644]
mod/forum/classes/event/discussion_unpinned.php [new file with mode: 0644]
mod/forum/classes/output/forum_post.php
mod/forum/classes/post_form.php
mod/forum/db/access.php
mod/forum/db/install.xml
mod/forum/db/log.php
mod/forum/db/upgrade.php
mod/forum/discuss.php
mod/forum/externallib.php
mod/forum/lang/en/deprecated.txt
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/pix/i/pinned.png [new file with mode: 0644]
mod/forum/pix/i/pinned.svg [new file with mode: 0644]
mod/forum/post.php
mod/forum/styles.css
mod/forum/templates/forum_post_emaildigestbasic_htmlemail.mustache
mod/forum/tests/behat/discussion_navigation.feature
mod/forum/tests/behat/move_discussion.feature
mod/forum/tests/behat/posts_ordering_blog.feature
mod/forum/tests/behat/posts_ordering_general.feature
mod/forum/tests/externallib_test.php
mod/forum/tests/generator/lib.php
mod/forum/tests/generator_test.php
mod/forum/tests/lib_test.php
mod/forum/version.php
mod/forum/view.php
mod/glossary/classes/entry_query_builder.php [new file with mode: 0644]
mod/glossary/classes/external.php
mod/glossary/db/services.php
mod/glossary/lib.php
mod/glossary/print.php
mod/glossary/showentry.php
mod/glossary/showentry_ajax.php
mod/glossary/sql.php
mod/glossary/tests/external_test.php
mod/glossary/tests/lib_test.php [new file with mode: 0644]
mod/glossary/version.php
mod/glossary/view.php
mod/lesson/lang/en/lesson.php
mod/lesson/lib.php
mod/lesson/tests/behat/lesson_complete_report.feature [new file with mode: 0644]
mod/lesson/tests/behat/lesson_outline_report.feature [new file with mode: 0644]
mod/wiki/backup/moodle2/backup_wiki_stepslib.php
mod/wiki/backup/moodle2/restore_wiki_stepslib.php
mod/wiki/db/tag.php [moved from webservice/amf/lang/en/webservice_amf.php with 68% similarity]
mod/wiki/edit_form.php
mod/wiki/lang/en/wiki.php
mod/wiki/lib.php
mod/wiki/locallib.php
mod/wiki/pagelib.php
mod/wiki/styles.css
mod/wiki/tests/behat/edit_tags.feature
mod/wiki/version.php
mod/workshop/styles.css
notes/lib.php
notes/tests/lib_test.php [new file with mode: 0644]
question/format.php
question/format/xml/format.php
question/format/xml/tests/xmlformat_test.php
question/question.php
question/type/edit_question_form.php
report/log/tests/lib_test.php
report/outline/tests/lib_test.php
report/stats/tests/lib_test.php
report/usersessions/tests/lib_test.php [new file with mode: 0644]
repository/s3/lib.php
tag/classes/area.php [new file with mode: 0644]
tag/classes/areas_table.php [new file with mode: 0644]
tag/classes/collection.php [new file with mode: 0644]
tag/classes/collection_form.php [new file with mode: 0644]
tag/classes/collections_table.php [new file with mode: 0644]
tag/classes/external.php
tag/classes/manage_table.php
tag/classes/output/tag.php
tag/classes/output/tagcloud.php [new file with mode: 0644]
tag/classes/output/tagfeed.php [new file with mode: 0644]
tag/classes/output/tagindex.php [new file with mode: 0644]
tag/classes/output/taglist.php [new file with mode: 0644]
tag/classes/renderer.php [new file with mode: 0644]
tag/classes/tag.php [new file with mode: 0644]
tag/edit.php
tag/edit_form.php
tag/index.php
tag/lib.php
tag/locallib.php
tag/manage.php
tag/search.php
tag/templates/index.mustache [new file with mode: 0644]
tag/templates/tagcloud.mustache [new file with mode: 0644]
tag/templates/tagfeed.mustache [new file with mode: 0644]
tag/templates/taglist.mustache [new file with mode: 0644]
tag/tests/behat/collections.feature [new file with mode: 0644]
tag/tests/behat/delete_tag.feature
tag/tests/behat/edit_tag.feature
tag/tests/behat/flag_tags.feature
tag/tests/behat/official_tags.feature
tag/tests/behat/tagindex.feature [new file with mode: 0644]
tag/tests/events_test.php
tag/tests/external_test.php
tag/tests/taglib_test.php
tag/upgrade.txt
tag/user.php
theme/base/style/core.css
theme/bootstrapbase/less/moodle/calendar.less
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/debug.less
theme/bootstrapbase/style/moodle.css
theme/canvas/style/core.css
theme/clean/lang/en/theme_clean.php
theme/more/lang/en/theme_more.php
user/edit.php
user/editadvanced.php
user/editlib.php
user/externallib.php
user/index.php
user/lib.php
user/profile.php
user/renderer.php
user/tests/externallib_test.php
user/view.php
version.php
webservice/amf/db/access.php [deleted file]
webservice/amf/introspector.php [deleted file]
webservice/amf/locallib.php [deleted file]
webservice/amf/server.php [deleted file]
webservice/amf/simpleserver.php [deleted file]
webservice/amf/testclient/AMFTester.mxml [deleted file]
webservice/amf/testclient/AMFTester.swf [deleted file]
webservice/amf/testclient/customValidators/JSONValidator.as [deleted file]
webservice/amf/testclient/flashcompilationinstructions.txt [deleted file]
webservice/amf/testclient/index.php [deleted file]
webservice/amf/version.php [deleted file]
webservice/externallib.php
webservice/lib.php
webservice/tests/externallib_test.php
webservice/upgrade.txt

index 665bb44..3dd3ef0 100644 (file)
@@ -26,13 +26,14 @@ module.exports = function(grunt) {
     var path = require('path'),
         fs = require('fs'),
         tasks = {},
-        cwd = process.env.PWD || process.cwd();
+        cwd = process.env.PWD || process.cwd(),
+        inAMD = path.basename(cwd) == 'amd';
 
     // Project configuration.
     grunt.initConfig({
         jshint: {
             options: {jshintrc: '.jshintrc'},
-            files: ['**/amd/src/*.js']
+            files: [inAMD ? cwd + '/src/*.js' : '**/amd/src/*.js']
         },
         uglify: {
             dynamic_mappings: {
@@ -222,7 +223,7 @@ module.exports = function(grunt) {
         if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
             grunt.task.run('shifter');
         // Are we in an AMD directory?
-        } else if (path.basename(cwd) == 'amd') {
+        } else if (inAMD) {
             grunt.task.run('amd');
         } else {
             // Run them all!.
index bd88630..21ecab7 100644 (file)
@@ -205,6 +205,9 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
     // Create a page for general import configuration and defaults.
     $temp = new admin_settingpage('importgeneralsettings', new lang_string('importgeneralsettings', 'backup'), 'moodle/backup:backupcourse');
     $temp->add(new admin_setting_configtext('backup/import_general_maxresults', new lang_string('importgeneralmaxresults', 'backup'), new lang_string('importgeneralmaxresults_desc', 'backup'), 10));
+    $temp->add(new admin_setting_configcheckbox('backup/import_general_duplicate_admin_allowed',
+            new lang_string('importgeneralduplicateadminallowed', 'backup'),
+            new lang_string('importgeneralduplicateadminallowed_desc', 'backup'), 0));
     $ADMIN->add('backups', $temp);
 
     // Create a page for automated backups configuration and defaults.
index c1ee2fb..6017717 100644 (file)
@@ -188,7 +188,7 @@ echo html_writer::end_tag('td');
 $options = array();
 foreach ($availablelangs as $alang) {
     if (!empty($alang[0]) and trim($alang[0]) !== 'en' and !$controller->is_installed_lang($alang[0], $alang[1])) {
-        $options[$alang[0]] = $alang[2].' ('.$alang[0].')';
+        $options[$alang[0]] = $alang[2].' &lrm;('.$alang[0].')&lrm;';
     }
 }
 if (!empty($options)) {
index ff22833..4486cde 100644 (file)
@@ -659,6 +659,10 @@ class tool_uploadcourse_course {
         $this->data = $coursedata;
         $this->enrolmentdata = tool_uploadcourse_helper::get_enrolment_data($this->rawdata);
 
+        if (isset($this->rawdata['tags']) && strval($this->rawdata['tags']) !== '') {
+            $this->data['tags'] = preg_split('/\s*,\s*/', trim($this->rawdata['tags']), -1, PREG_SPLIT_NO_EMPTY);
+        }
+
         // Restore data.
         // TODO Speed up things by not really extracting the backup just yet, but checking that
         // the backup file or shortname passed are valid. Extraction should happen in proceed().
index a173e72..20bbaa3 100644 (file)
@@ -261,6 +261,7 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
             'groupmode' => '2',
             'groupmodeforce' => '1',
             'enablecompletion' => '1',
+            'tags' => 'Cat, Dog',
 
             'role_teacher' => 'Knight',
             'role_manager' => 'Jedi',
@@ -297,6 +298,7 @@ class tool_uploadcourse_course_testcase extends advanced_testcase {
         $this->assertEquals($data['groupmode'], $course->groupmode);
         $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce);
         $this->assertEquals($data['enablecompletion'], $course->enablecompletion);
+        $this->assertEquals($data['tags'], join(', ', core_tag_tag::get_item_tags_array('core', 'course', $course->id)));
 
         // Roles.
         $roleids = array();
index e687fe3..2b3f43e 100644 (file)
@@ -96,6 +96,7 @@ $STD_FIELDS = array('id', 'username', 'email',
         'suspended',   // 1 means suspend user account, 0 means activate user account, nothing means keep as is for existing users
         'deleted',     // 1 means delete user
         'mnethostid',  // Can not be used for adding, updating or deleting of users - only for enrolments, groups, cohorts and suspending.
+        'interests',
     );
 // Include all name fields.
 $STD_FIELDS = array_merge($STD_FIELDS, get_all_user_name_fields());
@@ -836,6 +837,10 @@ if ($formdata = $mform2->is_cancelled()) {
             }
         }
 
+        // Update user interests.
+        if (isset($user->interests) && strval($user->interests) !== '') {
+            useredit_update_interests($user, preg_split('/\s*,\s*/', $user->interests, -1, PREG_SPLIT_NO_EMPTY));
+        }
 
         // add to cohort first, it might trigger enrolments indirectly - do NOT create cohorts here!
         foreach ($filecolumns as $column) {
index 25e4070..d14dbb9 100644 (file)
@@ -95,10 +95,6 @@ if (!$function or !$protocol) {
     $descparams = new stdClass();
     $descparams->atag = $atag;
     $descparams->mode = get_string('debugnormal', 'admin');
-    $amfclienturl = new moodle_url('/webservice/amf/testclient/index.php');
-    $amfclientatag =html_writer::tag('a', get_string('amftestclient', 'webservice'),
-            array('href' => $amfclienturl));
-    $descparams->amfatag = $amfclientatag;
     echo get_string('testclientdescription', 'webservice', $descparams);
     echo $OUTPUT->box_end();
 
index a41292d..caf5f07 100644 (file)
@@ -1778,22 +1778,8 @@ class restore_course_structure_step extends restore_structure_step {
 
         $data = (object)$data;
 
-        if (!empty($CFG->usetags)) { // if enabled in server
-            // TODO: This is highly inneficient. Each time we add one tag
-            // we fetch all the existing because tag_set() deletes them
-            // so everything must be reinserted on each call
-            $tags = array();
-            $existingtags = tag_get_tags('course', $this->get_courseid());
-            // Re-add all the existitng tags
-            foreach ($existingtags as $existingtag) {
-                $tags[] = $existingtag->rawname;
-            }
-            // Add the one being restored
-            $tags[] = $data->rawname;
-            // Send all the tags back to the course
-            tag_set('course', $this->get_courseid(), $tags, 'core',
-                context_course::instance($this->get_courseid())->id);
-        }
+        core_tag_tag::add_item_tag('core', 'course', $this->get_courseid(),
+                context_course::instance($this->get_courseid()), $data->rawname);
     }
 
     public function process_allowed_module($data) {
@@ -4078,25 +4064,17 @@ class restore_create_categories_and_questions extends restore_structure_step {
             return;
         }
 
-        if (!empty($CFG->usetags)) { // if enabled in server
-            // TODO: This is highly inefficient. Each time we add one tag
-            // we fetch all the existing because tag_set() deletes them
-            // so everything must be reinserted on each call
-            $tags = array();
-            $existingtags = tag_get_tags('question', $newquestion);
-            // Re-add all the existitng tags
-            foreach ($existingtags as $existingtag) {
-                $tags[] = $existingtag->rawname;
-            }
-            // Add the one being restored
-            $tags[] = $data->rawname;
+        if (core_tag_tag::is_enabled('core_question', 'question')) {
+            $tagname = $data->rawname;
             // Get the category, so we can then later get the context.
             $categoryid = $this->get_new_parentid('question_category');
             if (empty($this->cachedcategory) || $this->cachedcategory->id != $categoryid) {
                 $this->cachedcategory = $DB->get_record('question_categories', array('id' => $categoryid));
             }
-            // Send all the tags back to the question
-            tag_set('question', $newquestion, $tags, 'core_question', $this->cachedcategory->contextid);
+            // Add the tag to the question.
+            core_tag_tag::add_item_tag('core_question', 'question', $newquestion,
+                    context::instance_by_id($this->cachedcategory->contextid),
+                    $tagname);
         }
     }
 
index 880e75d..120ea6c 100644 (file)
@@ -1209,16 +1209,14 @@ abstract class restore_dbops {
                 }
 
                 // Process tags
-                if (!empty($CFG->usetags) && isset($user->tags)) { // if enabled in server and present in backup
+                if (core_tag_tag::is_enabled('core', 'user') && isset($user->tags)) { // If enabled in server and present in backup.
                     $tags = array();
                     foreach($user->tags['tag'] as $usertag) {
                         $usertag = (object)$usertag;
                         $tags[] = $usertag->rawname;
                     }
-                    if (empty($newuserctxid)) {
-                        $newuserctxid = null; // Tag apis expect a null contextid not 0.
-                    }
-                    tag_set('user', $newuserid, $tags, 'core', $newuserctxid);
+                    core_tag_tag::set_item_tags('core', 'user', $newuserid,
+                            context_user::instance($newuserid), $tags);
                 }
 
                 // Process preferences
@@ -1287,7 +1285,11 @@ abstract class restore_dbops {
     *      1F - None of the above, return true => User needs to be created
     *
     *  if restoring from another site backup (cannot match by id here, replace it by email/firstaccess combination):
-    *      2A - Normal check: If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user
+    *      2A - Normal check:
+    *           2A1 - If match by username and mnethost and (email or non-zero firstaccess) => ok, return target user
+    *           2A2 - Exceptional handling (MDL-21912): Match "admin" username. Then, if import_general_duplicate_admin_allowed is
+    *                 enabled, attempt to map the admin user to the user 'admin_[oldsiteid]' if it exists. If not,
+    *                 the user 'admin_[oldsiteid]' will be created in precheck_included users
     *      2B - Handle users deleted in DB and "alive" in backup file:
     *           2B1 - If match by mnethost and user is deleted in DB and not empty email = md5(username) and
     *                 (username LIKE 'backup_email.%' or non-zero firstaccess) => ok, return target user
@@ -1305,7 +1307,7 @@ abstract class restore_dbops {
     * Note: for DB deleted users md5(username) is stored *sometimes* in the email field,
     *       hence we are looking there for usernames if not empty. See delete_user()
     */
-    protected static function precheck_user($user, $samesite) {
+    protected static function precheck_user($user, $samesite, $siteid = null) {
         global $CFG, $DB;
 
         // Handle checks from same site backups
@@ -1376,7 +1378,7 @@ abstract class restore_dbops {
         // Handle checks from different site backups
         } else {
 
-            // 2A - If match by username and mnethost and
+            // 2A1 - If match by username and mnethost and
             //     (email or non-zero firstaccess) => ok, return target user
             if ($rec = $DB->get_record_sql("SELECT *
                                               FROM {user} u
@@ -1393,6 +1395,14 @@ abstract class restore_dbops {
                 return $rec; // Matching user found, return it
             }
 
+            // 2A2 - If we're allowing conflicting admins, attempt to map user to admin_[oldsiteid].
+            if (get_config('backup', 'import_general_duplicate_admin_allowed') && $user->username === 'admin' && $siteid
+                    && $user->mnethostid == $CFG->mnet_localhost_id) {
+                if ($rec = $DB->get_record('user', array('username' => 'admin_' . $siteid))) {
+                    return $rec;
+                }
+            }
+
             // 2B - Handle users deleted in DB and "alive" in backup file
             // Note: for DB deleted users email is stored in username field, hence we
             //       are looking there for emails. See delete_user()
@@ -1500,6 +1510,9 @@ abstract class restore_dbops {
         // Calculate the context we are going to use for capability checking
         $context = context_course::instance($courseid);
 
+        // When conflicting users are detected we may need original site info.
+        $restoreinfo = restore_controller_dbops::load_controller($restoreid)->get_info();
+
         // Calculate if we have perms to create users, by checking:
         // to 'moodle/restore:createuser' and 'moodle/restore:userinfo'
         // and also observe $CFG->disableusercreationonrestore
@@ -1535,14 +1548,28 @@ abstract class restore_dbops {
             }
 
             // Now, precheck that user and, based on returned results, annotate action/problem
-            $usercheck = self::precheck_user($user, $samesite);
+            $usercheck = self::precheck_user($user, $samesite, $restoreinfo->original_site_identifier_hash);
 
             if (is_object($usercheck)) { // No problem, we have found one user in DB to be mapped to
                 // Annotate it, for later process. Set newitemid to mapping user->id
                 self::set_backup_ids_record($restoreid, 'user', $recuser->itemid, $usercheck->id);
 
             } else if ($usercheck === false) { // Found conflict, report it as problem
-                 $problems[] = get_string('restoreuserconflict', '', $user->username);
+                if (!get_config('backup', 'import_general_duplicate_admin_allowed')) {
+                    $problems[] = get_string('restoreuserconflict', '', $user->username);
+                } else if ($user->username == 'admin') {
+                    if (!$cancreateuser) {
+                        $problems[] = get_string('restorecannotcreateuser', '', $user->username);
+                    }
+                    if ($user->mnethostid != $CFG->mnet_localhost_id) {
+                        $problems[] = get_string('restoremnethostidmismatch', '', $user->username);
+                    }
+                    if (!$problems) {
+                        // Duplicate admin allowed, append original site idenfitier to username.
+                        $user->username .= '_' . $restoreinfo->original_site_identifier_hash;
+                        self::set_backup_ids_record($restoreid, 'user', $recuser->itemid, 0, null, (array)$user);
+                    }
+                }
 
             } else if ($usercheck === true) { // User needs to be created, check if we are able
                 if ($cancreateuser) { // Can create user, set newitemid to 0 so will be created later
index 2de1122..a8d4382 100644 (file)
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
 
 global $CFG;
 require_once($CFG->libdir . '/badgeslib.php');
+require_once($CFG->dirroot . '/badges/lib.php');
 
 class core_badges_badgeslib_testcase extends advanced_testcase {
     protected $badgeid;
@@ -472,4 +473,69 @@ class core_badges_badgeslib_testcase extends advanced_testcase {
         $this->assertStringMatchesFormat($testassertion->class, json_encode($assertion->get_badge_class()));
         $this->assertStringMatchesFormat($testassertion->issuer, json_encode($assertion->get_issuer()));
     }
+
+    /**
+     * Tests the core_badges_myprofile_navigation() function.
+     */
+    public function test_core_badges_myprofile_navigation() {
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $this->setAdminUser();
+        $badge = new badge($this->badgeid);
+        $badge->issue($this->user->id, true);
+        $iscurrentuser = true;
+        $course = null;
+
+        // Enable badges.
+        set_config('enablebadges', true);
+
+        // Check the node tree is correct.
+        core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayHasKey('localbadges', $nodes->getValue($tree));
+    }
+
+    /**
+     * Tests the core_badges_myprofile_navigation() function with badges disabled..
+     */
+    public function test_core_badges_myprofile_navigation_badges_disabled() {
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $this->setAdminUser();
+        $badge = new badge($this->badgeid);
+        $badge->issue($this->user->id, true);
+        $iscurrentuser = false;
+        $course = null;
+
+        // Disable badges.
+        set_config('enablebadges', false);
+
+        // Check the node tree is correct.
+        core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayNotHasKey('localbadges', $nodes->getValue($tree));
+    }
+
+    /**
+     * Tests the core_badges_myprofile_navigation() function with a course badge.
+     */
+    public function test_core_badges_myprofile_navigation_with_course_badge() {
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $this->setAdminUser();
+        $badge = new badge($this->coursebadge);
+        $badge->issue($this->user->id, true);
+        $iscurrentuser = false;
+
+        // Check the node tree is correct.
+        core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $this->course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayHasKey('localbadges', $nodes->getValue($tree));
+    }
 }
diff --git a/blocks/activity_results/tests/behat/highscoreswithscales.feature b/blocks/activity_results/tests/behat/highscoreswithscales.feature
new file mode 100644 (file)
index 0000000..1263382
--- /dev/null
@@ -0,0 +1,111 @@
+@block @block_activity_results
+Feature: The activity results block displays student scores as scales
+  In order to be display student scores as scales
+  As a user
+  I need to see the activity results block
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+      | student1 | Student | 1 | student1@example.com | S1 |
+      | student2 | Student | 2 | student2@example.com | S2 |
+      | student3 | Student | 3 | student3@example.com | S3 |
+      | student4 | Student | 4 | student4@example.com | S4 |
+      | student5 | Student | 5 | student5@example.com | S5 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+      | student3 | C1 | student |
+      | student4 | C1 | student |
+      | student5 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I navigate to "Scales" node in "Grade administration"
+    And I press "Add a new scale"
+    And I set the following fields to these values:
+      | Name | My Scale |
+      | Scale | Disappointing, Not good enough, Average, Good, Very good, Excellent! |
+    And I press "Save changes"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment |
+      | Description | Offline text |
+      | assignsubmission_file_enabled | 0 |
+      | id_modgrade_type | Scale |
+      | id_modgrade_scale | My Scale |
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I turn editing mode on
+    And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 3" for the grade item "Test assignment"
+    And I give the grade "Average" to the user "Student 4" for the grade item "Test assignment"
+    And I give the grade "Not good enough" to the user "Student 5" for the grade item "Test assignment"
+    And I press "Save changes"
+    And I follow "Course 1"
+
+  Scenario: Configure the block on the course page to show 1 high score
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 1 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display full names |
+      | id_config_decimalpoints | 0 |
+    And I press "Save changes"
+    Then I should see "Student 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using full names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display full names |
+    And I press "Save changes"
+    Then I should see "Student 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "Student 2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Student 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display only ID numbers |
+    And I press "Save changes"
+    Then I should see "User S1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "User S2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "User S3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Anonymous results |
+    And I press "Save changes"
+    Then I should see "User" in the "Activity results" "block"
+    And I should not see "Student 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should not see "Student 2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should not see "Student 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
diff --git a/blocks/activity_results/tests/behat/highscoreswithscalesandgroups.feature b/blocks/activity_results/tests/behat/highscoreswithscalesandgroups.feature
new file mode 100644 (file)
index 0000000..7856da5
--- /dev/null
@@ -0,0 +1,153 @@
+@block @block_activity_results
+Feature: The activity results block displays student scores as scales
+  In order to be display student scores as scales
+  As a user
+  I need to see the activity results block
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+      | student1 | Student | 1 | student1@example.com | S1 |
+      | student2 | Student | 2 | student2@example.com | S2 |
+      | student3 | Student | 3 | student3@example.com | S3 |
+      | student4 | Student | 4 | student4@example.com | S4 |
+      | student5 | Student | 5 | student5@example.com | S5 |
+      | student6 | Student | 6 | student6@example.com | S6 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "groups" exist:
+      | name | course | idnumber |
+      | Group 1 | C1 | G1 |
+      | Group 2 | C1 | G2 |
+      | Group 3 | C1 | G3 |
+      | Group 4 | C1 | G4 |
+      | Group 5 | C1 | G5 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+      | student3 | C1 | student |
+      | student4 | C1 | student |
+      | student5 | C1 | student |
+      | student6 | C1 | student |
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I navigate to "Scales" node in "Grade administration"
+    And I press "Add a new scale"
+    And I set the following fields to these values:
+      | Name | My Scale |
+      | Scale | Disappointing, Not good enough, Average, Good, Very good, Excellent! |
+    And I press "Save changes"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment |
+      | Description | Offline text |
+      | assignsubmission_file_enabled | 0 |
+      | id_modgrade_type | Scale |
+      | id_modgrade_scale | My Scale |
+      | Group mode | Separate groups |
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I turn editing mode on
+    And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 3" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 4" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 5" for the grade item "Test assignment"
+    And I give the grade "Average" to the user "Student 6" for the grade item "Test assignment"
+    And I press "Save changes"
+    And I follow "Course 1"
+
+  Scenario: Try to configure the block on the course page to show 1 high score
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 1 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display full names |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I should see "Student 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using full names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display full names |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group 1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "Group 2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Group 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student3"
+    And I follow "Course 1"
+    And I should see "Student 3" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Student 4" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Display only ID numbers |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I should see "User S1" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "User S2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 3 |
+      | id_config_showworst | 0 |
+      | id_config_nameformat | Anonymous results |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And I should see "User" in the "Activity results" "block"
+    And I should see "Excellent!" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
index 3939bd6..27807f8 100644 (file)
@@ -33,19 +33,15 @@ Feature: The activity results block displays student scores
       | student4 | C1 | student |
       | student5 | C1 | student |
       | student6 | C1 | student |
-
-  @javascript
-  Scenario: Configure the block on the course page to show 1 high score
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
     And I add a "Assignment" to section "1" and I fill the form with:
@@ -64,7 +60,9 @@ Feature: The activity results block displays student scores
     And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
     And I press "Save changes"
     And I follow "Course 1"
-    And I add the "Activity results" block
+
+  Scenario: Configure the block on the course page to show 1 high score
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -77,37 +75,8 @@ Feature: The activity results block displays student scores
     Then I should see "Group 1" in the "Activity results" "block"
     And I should see "95%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 high score as a fraction
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -124,37 +93,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 1" in the "Activity results" "block"
     And I should see "100.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 high score as a absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -171,37 +111,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 1" in the "Activity results" "block"
     And I should see "100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as percentages
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -225,37 +136,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 2" in the "Activity results" "block"
     And I should see "90%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as fractions
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -278,37 +160,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 4" in the "Activity results" "block"
     And I should see "80.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -331,37 +184,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 2" in the "Activity results" "block"
     And I should see "90.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -382,37 +206,8 @@ Feature: The activity results block displays student scores
     And I should see "User S2" in the "Activity results" "block"
     And I should see "90.00%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
index 845e8ab..f5fd1bd 100644 (file)
@@ -33,19 +33,15 @@ Feature: The activity results block displays student scores
       | student4 | C1 | student |
       | student5 | C1 | student |
       | student6 | C1 | student |
-
-  @javascript
-  Scenario: Configure the block on the course page to show 1 high score
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
     And I add a "Assignment" to section "1" and I fill the form with:
@@ -64,7 +60,9 @@ Feature: The activity results block displays student scores
     And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
     And I press "Save changes"
     And I follow "Course 1"
-    And I add the "Activity results" block
+
+  Scenario: Configure the block on the course page to show 1 high score
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -77,37 +75,8 @@ Feature: The activity results block displays student scores
     Then I should see "Group 1" in the "Activity results" "block"
     And I should see "95%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 high score as a fraction
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -122,37 +91,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 1" in the "Activity results" "block"
     And I should see "95.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 high score as a absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 1 |
@@ -167,37 +107,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 1" in the "Activity results" "block"
     And I should see "95.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as percentages
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -217,37 +128,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as fractions
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -266,37 +148,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores as absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -315,37 +168,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
@@ -362,37 +186,8 @@ Feature: The activity results block displays student scores
     And I should see "85.00%" in the "Activity results" "block"
     And I should see "75.00%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 3 |
diff --git a/blocks/activity_results/tests/behat/lowscoreswithscales.feature b/blocks/activity_results/tests/behat/lowscoreswithscales.feature
new file mode 100644 (file)
index 0000000..149e0f6
--- /dev/null
@@ -0,0 +1,112 @@
+@block @block_activity_results
+Feature: The activity results block displays student scores as scales
+  In order to be display student scores as scales
+  As a user
+  I need to see the activity results block
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+      | student1 | Student | 1 | student1@example.com | S1 |
+      | student2 | Student | 2 | student2@example.com | S2 |
+      | student3 | Student | 3 | student3@example.com | S3 |
+      | student4 | Student | 4 | student4@example.com | S4 |
+      | student5 | Student | 5 | student5@example.com | S5 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+      | student3 | C1 | student |
+      | student4 | C1 | student |
+      | student5 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I navigate to "Scales" node in "Grade administration"
+    And I press "Add a new scale"
+    And I set the following fields to these values:
+      | Name | My Scale |
+      | Scale | Disappointing, Not good enough, Average, Good, Very good, Excellent! |
+    And I press "Save changes"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment |
+      | Description | Offline text |
+      | assignsubmission_file_enabled | 0 |
+      | id_modgrade_type | Scale |
+      | id_modgrade_scale | My Scale |
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I turn editing mode on
+    And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 3" for the grade item "Test assignment"
+    And I give the grade "Average" to the user "Student 4" for the grade item "Test assignment"
+    And I give the grade "Not good enough" to the user "Student 5" for the grade item "Test assignment"
+    And I press "Save changes"
+    And I follow "Course 1"
+
+  Scenario: Configure the block on the course page to show 1 low score
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 1 |
+      | id_config_gradeformat | Percentages |
+      | id_config_nameformat | Display full names |
+      | id_config_decimalpoints | 0 |
+    And I press "Save changes"
+    Then I should see "Student 5" in the "Activity results" "block"
+    And I should see "Not good enough" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple low scores using full names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 3 |
+      | id_config_nameformat | Display full names |
+    And I press "Save changes"
+    Then I should see "Student 5" in the "Activity results" "block"
+    And I should see "Not good enough" in the "Activity results" "block"
+    And I should see "Student 4" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+    And I should see "Student 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 3 |
+      | id_config_nameformat | Display only ID numbers |
+    And I press "Save changes"
+    Then I should see "User S5" in the "Activity results" "block"
+    And I should see "Not good enough" in the "Activity results" "block"
+    And I should see "User S4" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+    And I should see "User S3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 3 |
+      | id_config_nameformat | Anonymous results |
+    And I press "Save changes"
+    Then I should see "User" in the "Activity results" "block"
+    And I should not see "Student 5" in the "Activity results" "block"
+    And I should see "Not good enough" in the "Activity results" "block"
+    And I should not see "Student 4" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+    And I should not see "Student 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
diff --git a/blocks/activity_results/tests/behat/lowscoreswithscalesandgroups.feature b/blocks/activity_results/tests/behat/lowscoreswithscalesandgroups.feature
new file mode 100644 (file)
index 0000000..9134339
--- /dev/null
@@ -0,0 +1,150 @@
+@block @block_activity_results
+Feature: The activity results block displays student scores as scales
+  In order to be display student scores as scales
+  As a user
+  I need to see the activity results block
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+      | student1 | Student | 1 | student1@example.com | S1 |
+      | student2 | Student | 2 | student2@example.com | S2 |
+      | student3 | Student | 3 | student3@example.com | S3 |
+      | student4 | Student | 4 | student4@example.com | S4 |
+      | student5 | Student | 5 | student5@example.com | S5 |
+      | student6 | Student | 6 | student6@example.com | S6 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "groups" exist:
+      | name | course | idnumber |
+      | Group 1 | C1 | G1 |
+      | Group 2 | C1 | G2 |
+      | Group 3 | C1 | G3 |
+      | Group 4 | C1 | G4 |
+      | Group 5 | C1 | G5 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+      | student3 | C1 | student |
+      | student4 | C1 | student |
+      | student5 | C1 | student |
+      | student6 | C1 | student |
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I navigate to "Scales" node in "Grade administration"
+    And I press "Add a new scale"
+    And I set the following fields to these values:
+      | Name | My Scale |
+      | Scale | Disappointing, Not good enough, Average, Good, Very good, Excellent! |
+    And I press "Save changes"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Test assignment |
+      | Description | Offline text |
+      | assignsubmission_file_enabled | 0 |
+      | id_modgrade_type | Scale |
+      | id_modgrade_scale | My Scale |
+      | Group mode | Separate groups |
+    And I follow "Course 1"
+    And I navigate to "Grades" node in "Course administration"
+    And I turn editing mode on
+    And I give the grade "Excellent!" to the user "Student 1" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 2" for the grade item "Test assignment"
+    And I give the grade "Very good" to the user "Student 3" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 4" for the grade item "Test assignment"
+    And I give the grade "Good" to the user "Student 5" for the grade item "Test assignment"
+    And I give the grade "Average" to the user "Student 6" for the grade item "Test assignment"
+    And I press "Save changes"
+    And I follow "Course 1"
+
+  Scenario: Try to configure the block on the course page to show 1 low score
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 1 |
+      | id_config_nameformat | Display full names |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student5"
+    And I follow "Course 1"
+    And I should see "Student 6" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using full names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 2 |
+      | id_config_nameformat | Display full names |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group 2" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Group 3" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student3"
+    And I follow "Course 1"
+    And I should see "Student 3" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Student 4" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using ID numbers
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 2 |
+      | id_config_nameformat | Display only ID numbers |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student5"
+    And I follow "Course 1"
+    And I should see "User S5" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I should see "User S6" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+
+  Scenario: Try to configure the block on the course page to show multiple high scores using anonymous names
+    Given I add the "Activity results" block
+    When I configure the "Activity results" block
+    And I set the following fields to these values:
+      | id_config_showbest | 0 |
+      | id_config_showworst | 2 |
+      | id_config_nameformat | Anonymous results |
+      | id_config_usegroups | Yes |
+    And I press "Save changes"
+    Then I should see "Group" in the "Activity results" "block"
+    And I should see "Very good" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I log out
+    And I log in as "student5"
+    And I follow "Course 1"
+    And I should see "User" in the "Activity results" "block"
+    And I should see "Good" in the "Activity results" "block"
+    And I should see "Average" in the "Activity results" "block"
+
index f18ccf8..b5e0546 100644 (file)
@@ -33,19 +33,15 @@ Feature: The activity results block displays student scores
       | student4 | C1 | student |
       | student5 | C1 | student |
       | student6 | C1 | student |
-
-  @javascript
-  Scenario: Configure the block on the course page to show 1 low score
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
     And I add a "Assignment" to section "1" and I fill the form with:
@@ -64,7 +60,9 @@ Feature: The activity results block displays student scores
     And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
     And I press "Save changes"
     And I follow "Course 1"
-    And I add the "Activity results" block
+
+  Scenario: Configure the block on the course page to show 1 low score
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -77,37 +75,8 @@ Feature: The activity results block displays student scores
     Then I should see "Group 3" in the "Activity results" "block"
     And I should see "75%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 low score as a fraction
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -124,37 +93,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 6" in the "Activity results" "block"
     And I should see "70.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 low score as a absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -171,37 +111,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 6" in the "Activity results" "block"
     And I should see "70.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as percentages
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -223,37 +134,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 5" in the "Activity results" "block"
     And I should see "80%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as fractions
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -274,37 +156,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 4" in the "Activity results" "block"
     And I should see "80.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -325,37 +178,8 @@ Feature: The activity results block displays student scores
     And I should see "Student 6" in the "Activity results" "block"
     And I should see "70.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -375,37 +199,8 @@ Feature: The activity results block displays student scores
     And I should see "User S2" in the "Activity results" "block"
     And I should see "90.00%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Separate groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
index e02d58d..7049958 100644 (file)
@@ -33,19 +33,15 @@ Feature: The activity results block displays student scores
       | student4 | C1 | student |
       | student5 | C1 | student |
       | student6 | C1 | student |
-
-  @javascript
-  Scenario: Configure the block on the course page to show 1 low score
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
+    And the following "group members" exist:
+      | user     | group   |
+      | student1 | G1 |
+      | student2 | G1 |
+      | student3 | G2 |
+      | student4 | G2 |
+      | student5 | G3 |
+      | student6 | G3 |
+    And I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
     And I add a "Assignment" to section "1" and I fill the form with:
@@ -64,7 +60,9 @@ Feature: The activity results block displays student scores
     And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
     And I press "Save changes"
     And I follow "Course 1"
-    And I add the "Activity results" block
+
+  Scenario: Configure the block on the course page to show 1 low score
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -77,37 +75,8 @@ Feature: The activity results block displays student scores
     Then I should see "Group 3" in the "Activity results" "block"
     And I should see "75%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 low score as a fraction
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -122,37 +91,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show 1 low score as a absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -167,37 +107,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as percentages
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -219,37 +130,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as fractions
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -266,37 +148,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00/100.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores as absolute numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -313,37 +166,8 @@ Feature: The activity results block displays student scores
     And I should see "Group 3" in the "Activity results" "block"
     And I should see "75.00" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores using ID numbers
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
@@ -359,37 +183,8 @@ Feature: The activity results block displays student scores
     And I should see "85.00%" in the "Activity results" "block"
     And I should see "75.00%" in the "Activity results" "block"
 
-  @javascript
   Scenario: Try to configure the block on the course page to show multiple low scores using anonymous names
-    Given I log in as "teacher1"
-    And I follow "Course 1"
-    And I expand "Users" node
-    And I follow "Groups"
-    And I add "Student 1 (student1@example.com)" user to "Group 1" group members
-    And I add "Student 2 (student2@example.com)" user to "Group 1" group members
-    And I add "Student 3 (student3@example.com)" user to "Group 2" group members
-    And I add "Student 4 (student4@example.com)" user to "Group 2" group members
-    And I add "Student 5 (student5@example.com)" user to "Group 3" group members
-    And I add "Student 6 (student6@example.com)" user to "Group 3" group members
-    And I follow "Course 1"
-    And I turn editing mode on
-    And I add a "Assignment" to section "1" and I fill the form with:
-      | Assignment name | Test assignment |
-      | Description | Offline text |
-      | assignsubmission_file_enabled | 0 |
-      | Group mode | Visible groups |
-    And I follow "Course 1"
-    And I navigate to "Grades" node in "Course administration"
-    And I turn editing mode on
-    And I give the grade "100.00" to the user "Student 1" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 2" for the grade item "Test assignment"
-    And I give the grade "90.00" to the user "Student 3" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 4" for the grade item "Test assignment"
-    And I give the grade "80.00" to the user "Student 5" for the grade item "Test assignment"
-    And I give the grade "70.00" to the user "Student 6" for the grade item "Test assignment"
-    And I press "Save changes"
-    And I follow "Course 1"
-    And I add the "Activity results" block
+    Given I add the "Activity results" block
     When I configure the "Activity results" block
     And I set the following fields to these values:
       | id_config_showbest | 0 |
diff --git a/blocks/blog_menu/tests/behat/block_blog_menu.feature b/blocks/blog_menu/tests/behat/block_blog_menu.feature
new file mode 100644 (file)
index 0000000..b93728f
--- /dev/null
@@ -0,0 +1,81 @@
+@block @block_blog_menu
+Feature: Enable Block blog menu in a course
+  In order to enable the blog menu in a course
+  As a teacher
+  I can add blog menu block to a course
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+
+  Scenario: Add the block to a the course when blogs are disabled
+    Given I log in as "admin"
+    And the following config values are set as admin:
+      | enableblogs | 0 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    When I add the "Blog menu" block
+    Then I should see "Blogging is disabled!" in the "Blog menu" "block"
+
+  Scenario: Add the block to a the course when blog associations are disabled
+    Given I log in as "admin"
+    And the following config values are set as admin:
+      | useblogassociations | 0 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    When I add the "Blog menu" block
+    Then I should see "Blog entries" in the "Blog menu" "block"
+    And I should see "Add a new entry" in the "Blog menu" "block"
+    And I should not see "View all entries for this course" in the "Blog menu" "block"
+    And I should not see "View my entries about this course" in the "Blog menu" "block"
+    And I should not see "Add an entry about this course" in the "Blog menu" "block"
+
+  Scenario: Add the block to a the course when blog associations are enabled
+    Given I log in as "admin"
+    And the following config values are set as admin:
+      | useblogassociations | 1 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    When I add the "Blog menu" block
+    Then I should see "Blog entries" in the "Blog menu" "block"
+    And I should see "Add a new entry" in the "Blog menu" "block"
+    And I should see "View all entries for this course" in the "Blog menu" "block"
+    And I should see "View my entries about this course" in the "Blog menu" "block"
+    And I should see "Add an entry about this course" in the "Blog menu" "block"
+
+  Scenario: Add the block to a the course when RSS is disabled
+    Given I log in as "admin"
+    And the following config values are set as admin:
+      | enablerssfeeds | 0 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    When I add the "Blog menu" block
+    Then I should not see "Blog RSS feed" in the "Blog menu" "block"
+    And I should see "Add a new entry" in the "Blog menu" "block"
+
+  Scenario: Add the block to a the course when RSS is enabled
+    Given I log in as "admin"
+    And the following config values are set as admin:
+      | enablerssfeeds | 1 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    When I add the "Blog menu" block
+    Then I should see "Blog RSS feed" in the "Blog menu" "block"
+    And I should see "Add a new entry" in the "Blog menu" "block"
diff --git a/blocks/blog_menu/tests/behat/block_blog_menu_course.feature b/blocks/blog_menu/tests/behat/block_blog_menu_course.feature
new file mode 100644 (file)
index 0000000..f45f62f
--- /dev/null
@@ -0,0 +1,199 @@
+@block @block_blog_menu
+Feature: Enable Block blog menu in a course
+  In order to enable the blog menu in a course
+  As a teacher
+  I can add blog menu block to a course
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | teacher1 | Teacher | 1 | teacher1@example.com | T1 |
+      | student1 | Student | 1 | student1@example.com | S1 |
+      | student2 | Student | 2 | student2@example.com | S2 |
+    And the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "course enrolments" exist:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+      | student2 | C1 | student |
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add the "Blog menu" block
+    And I log out
+
+  Scenario: Students use the blog menu block to post blogs
+    Given I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Add a new entry"
+    When I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog! |
+    And I press "Save changes"
+    Then I should see "S1 First Blog"
+    And I should see "This is my awesome blog!"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    And I follow "Blog entries"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog!"
+
+  Scenario: Students use the blog menu block to view their blogs about the course
+    Given I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog about this course! |
+    And I press "Save changes"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog about this course!"
+    And I should see "Associated Course: C1"
+    And I log out
+    And I log in as "student2"
+    And I follow "Course 1"
+    And I follow "Add a new entry"
+    And I set the following fields to these values:
+      | Entry title | S2 Second Blog |
+      | Blog entry body | My unrelated blog! |
+    And I press "Save changes"
+    And I should see "S2 Second Blog"
+    And I should see "My unrelated blog!"
+    And I should not see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S2 First Blog |
+      | Blog entry body | My course blog is better! |
+    And I press "Save changes"
+    And I should see "S2 First Blog"
+    And I should see "My course blog is better!"
+    And I should see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    When I follow "View my entries about this course"
+    Then I should see "S2 First Blog"
+    And I should not see "S2 Second Blog"
+    And I should not see "S1 First Blog"
+
+  Scenario: Students use the blog menu block to view all blogs about the course
+    Given I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog about this course! |
+    And I press "Save changes"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog about this course!"
+    And I should see "Associated Course: C1"
+    And I log out
+    And I log in as "student2"
+    And I follow "Course 1"
+    And I follow "Add a new entry"
+    And I set the following fields to these values:
+      | Entry title | S2 Second Blog |
+      | Blog entry body | My unrelated blog! |
+    And I press "Save changes"
+    And I should see "S2 Second Blog"
+    And I should see "My unrelated blog!"
+    And I should not see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S2 First Blog |
+      | Blog entry body | My course blog is better! |
+    And I press "Save changes"
+    And I should see "S2 First Blog"
+    And I should see "My course blog is better!"
+    And I should see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    When I follow "View all entries for this course"
+    Then I should see "S1 First Blog"
+    And I should see "S2 First Blog"
+    And I should not see "S2 Second Blog"
+
+  Scenario: Students use the blog menu block to view all their blog entries
+    Given I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog about this course! |
+    And I press "Save changes"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog about this course!"
+    And I should see "Associated Course: C1"
+    And I log out
+    And I log in as "student2"
+    And I follow "Course 1"
+    And I follow "Add a new entry"
+    And I set the following fields to these values:
+      | Entry title | S2 Second Blog |
+      | Blog entry body | My unrelated blog! |
+    And I press "Save changes"
+    And I should see "S2 Second Blog"
+    And I should see "My unrelated blog!"
+    And I should not see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S2 First Blog |
+      | Blog entry body | My course blog is better! |
+    And I press "Save changes"
+    And I should see "S2 First Blog"
+    And I should see "My course blog is better!"
+    And I should see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    When I follow "Blog entries"
+    Then I should see "S2 First Blog"
+    And I should see "S2 Second Blog"
+    And I should not see "S1 First Blog"
+
+  Scenario: Teacher searches for student blogs
+    Given I log in as "student1"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog about this course! |
+    And I press "Save changes"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog about this course!"
+    And I should see "Associated Course: C1"
+    And I log out
+    And I log in as "student2"
+    And I follow "Course 1"
+    And I follow "Add a new entry"
+    And I set the following fields to these values:
+      | Entry title | S2 Second Blog |
+      | Blog entry body | My unrelated blog! |
+    And I press "Save changes"
+    And I should see "S2 Second Blog"
+    And I should see "My unrelated blog!"
+    And I should not see "Associated Course: C1"
+    And I follow "Dashboard"
+    And I follow "Course 1"
+    And I follow "Add an entry about this course"
+    And I set the following fields to these values:
+      | Entry title | S2 First Blog |
+      | Blog entry body | My course blog is better! |
+    And I press "Save changes"
+    And I should see "S2 First Blog"
+    And I should see "My course blog is better!"
+    And I should see "Associated Course: C1"
+    And I log out
+    When I log in as "teacher1"
+    And I follow "Course 1"
+    And I set the field "blogsearchquery" to "First"
+    And I press "Search"
+    Then I should see "S1 First Blog"
+    And I should see "S2 First Blog"
+    And I should not see "S2 Second Blog"
diff --git a/blocks/blog_menu/tests/behat/block_blog_menu_frontpage.feature b/blocks/blog_menu/tests/behat/block_blog_menu_frontpage.feature
new file mode 100644 (file)
index 0000000..3c2936a
--- /dev/null
@@ -0,0 +1,30 @@
+@block @block_blog_menu
+Feature: Enable Block blog menu on the frontpage
+  In order to enable the blog menu on the frontpage
+  As an admin
+  I can add blog menu block to the frontpage
+
+  Background:
+    Given the following "users" exist:
+      | username | firstname | lastname | email | idnumber |
+      | student1 | Student | 1 | student1@example.com | S1 |
+    And I log in as "admin"
+    And I am on site homepage
+    And I navigate to "Turn editing on" node in "Front page settings"
+    And I add the "Blog menu" block
+    And I log out
+
+  Scenario: Students use the blog menu block to post blogs
+    Given I log in as "student1"
+    And I am on site homepage
+    And I follow "Add a new entry"
+    When I set the following fields to these values:
+      | Entry title | S1 First Blog |
+      | Blog entry body | This is my awesome blog! |
+    And I press "Save changes"
+    Then I should see "S1 First Blog"
+    And I should see "This is my awesome blog!"
+    And I am on site homepage
+    And I follow "Blog entries"
+    And I should see "S1 First Blog"
+    And I should see "This is my awesome blog!"
index de32984..6edc7b5 100644 (file)
@@ -75,7 +75,7 @@ class block_blog_tags extends block_base {
             }
             return $this->content;
 
-        } else if (empty($CFG->usetags)) {
+        } else if (!core_tag_tag::is_enabled('core', 'post')) {
             $this->content = new stdClass();
             $this->content->text = '';
             if ($this->page->user_is_editing()) {
@@ -126,6 +126,7 @@ class block_blog_tags extends block_base {
                   WHERE t.id = ti.tagid AND p.id = ti.itemid
                         $type
                         AND ti.itemtype = 'post'
+                        AND ti.component = 'core'
                         AND ti.timemodified > $timewithin";
 
         if ($context->contextlevel == CONTEXT_MODULE) {
@@ -195,7 +196,9 @@ class block_blog_tags extends block_base {
                 }
 
                 $blogurl->param('tagid', $tag->id);
-                $link = html_writer::link($blogurl, tag_display_name($tag), array('class'=>$tag->class, 'title'=>get_string('numberofentries','blog',$tag->ct)));
+                $link = html_writer::link($blogurl, core_tag_tag::make_display_name($tag),
+                        array('class' => $tag->class,
+                            'title' => get_string('numberofentries', 'blog', $tag->ct)));
                 $this->content->text .= '<li>' . $link . '</li> ';
             }
             $this->content->text .= "\n</ul>\n";
index f16b0bc..57ae2b3 100644 (file)
@@ -344,16 +344,9 @@ class block_base {
      * You don't need to override this if you 're satisfied with the above
      *
      * @deprecated since Moodle 2.9 MDL-49385 - Please use Admin Settings functionality to save block configuration.
-     * @todo MDL-49553 This will be deleted in Moodle 3.1
-     * @param array $data
-     * @return boolean
      */
     function config_save($data) {
-        debugging('config_save($data) is deprecated, use Admin Settings functionality to save block configuration.', DEBUG_DEVELOPER);
-        foreach ($data as $name => $value) {
-            set_config($name, $value);
-        }
-        return true;
+        throw new coding_exception('config_save() can not be used any more, use Admin Settings functionality to save block configuration.');
     }
 
     /**
index de57a2d..c8b7f2c 100644 (file)
@@ -93,7 +93,8 @@ class block_news_items extends block_base {
             // descending order. The call to default sort order here will use
             // that unless the discussion that post is in has a timestart set
             // in the future.
-            $sort = forum_get_default_sort_order(true, 'p.modified');
+            // This sort will ignore pinned posts as we want the most recent.
+            $sort = forum_get_default_sort_order(true, 'p.modified', 'd', false);
             if (! $discussions = forum_get_discussions($cm, $sort, false,
                                                        $currentgroup, $this->page->course->newsitems) ) {
                 $text .= '('.get_string('nonews', 'forum').')';
index 68a13ac..e41e68c 100644 (file)
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
+/**
+ * Contains block_rss_client
+ * @package    block_rss_client
+ * @copyright  Daryl Hawes
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
+ */
+
 /**
  * A block which displays Remote feeds
  *
         }
     }
 
+    /**
+     * Gets the footer, which is the channel link of the last feed in our list of feeds
+     *
+     * @param array $feedrecords The feed records from the database.
+     * @return block_rss_client\output\footer|null The renderable footer or null if none should be displayed.
+     */
+    protected function get_footer($feedrecords) {
+        $footer = null;
+
+        if ($this->config->block_rss_client_show_channel_link) {
+            global $CFG;
+            require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
+
+            $feedrecord     = array_pop($feedrecords);
+            $feed           = new moodle_simplepie($feedrecord->url);
+            $channellink    = new moodle_url($feed->get_link());
+
+            if (!empty($channellink)) {
+                $footer = new block_rss_client\output\footer($channellink);
+            }
+        }
+
+        return $footer;
+    }
+
     function get_content() {
         global $CFG, $DB;
 
             $maxentries = intval($CFG->block_rss_client_num_entries);
         }
 
-
         /* ---------------------------------
          * Begin Normal Display of Block Content
          * --------------------------------- */
 
-        $output = '';
-
+        $renderer = $this->page->get_renderer('block_rss_client');
+        $block = new \block_rss_client\output\block();
 
         if (!empty($this->config->rssid)) {
-            list($rss_ids_sql, $params) = $DB->get_in_or_equal($this->config->rssid);
-
-            $rss_feeds = $DB->get_records_select('block_rss_client', "id $rss_ids_sql", $params);
+            list($rssidssql, $params) = $DB->get_in_or_equal($this->config->rssid);
+            $rssfeeds = $DB->get_records_select('block_rss_client', "id $rssidssql", $params);
+
+            if (!empty($rssfeeds)) {
+                $showtitle = false;
+                if (count($rssfeeds) > 1) {
+                    // When many feeds show the title for each feed.
+                    $showtitle = true;
+                }
 
-            $showtitle = false;
-            if (count($rss_feeds) > 1) {
-                // when many feeds show the title for each feed
-                $showtitle = true;
-            }
+                foreach ($rssfeeds as $feed) {
+                    if ($renderablefeed = $this->get_feed($feed, $maxentries, $showtitle)) {
+                        $block->add_feed($renderablefeed);
+                    }
+                }
 
-            foreach($rss_feeds as $feed){
-                $output.= $this->get_feed_html($feed, $maxentries, $showtitle);
+                $footer = $this->get_footer($rssfeeds);
             }
         }
 
-        $this->content->text = $output;
+        $this->content->text = $renderer->render_block($block);
+        if (isset($footer)) {
+            $this->content->footer = $renderer->render_footer($footer);
+        }
 
         return $this->content;
     }
      * @param mixed feedrecord The feed record from the database
      * @param int maxentries The maximum number of entries to be displayed
      * @param boolean showtitle Should the feed title be displayed in html
-     * @return string html representing the rss feed content
+     * @return block_rss_client\output\feed|null The renderable feed or null of there is an error
      */
-    function get_feed_html($feedrecord, $maxentries, $showtitle){
+    public function get_feed($feedrecord, $maxentries, $showtitle) {
         global $CFG;
         require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
 
-        $feed = new moodle_simplepie($feedrecord->url);
+        $simplepiefeed = new moodle_simplepie($feedrecord->url);
 
         if(isset($CFG->block_rss_client_timeout)){
-            $feed->set_cache_duration($CFG->block_rss_client_timeout*60);
-        }
-
-        if ($CFG->debugdeveloper && $feed->error()) {
-            return '<p>'. $feedrecord->url .' Failed with code: '.$feed->error().'</p>';
+            $simplepiefeed->set_cache_duration($CFG->block_rss_client_timeout * 60);
         }
 
-        $r = ''; // return string
-
-        if($this->config->block_rss_client_show_channel_image){
-            if($image = $feed->get_image_url()){
-                $imagetitle = s($feed->get_image_title());
-                $imagelink  = $feed->get_image_link();
-
-                $r.='<div class="image" title="'.$imagetitle.'">'."\n";
-                if($imagelink){
-                    $r.='<a href="'.$imagelink.'">';
-                }
-                $r.='<img src="'.$image.'" alt="'.$imagetitle.'" />'."\n";
-                if($imagelink){
-                    $r.='</a>';
-                }
-                $r.= '</div>';
-            }
+        if ($simplepiefeed->error()) {
+            debugging($feedrecord->url .' Failed with code: '.$simplepiefeed->error());
+            return null;
         }
 
         if(empty($feedrecord->preferredtitle)){
-            $feedtitle = $this->format_title($feed->get_title());
+            $feedtitle = $this->format_title($simplepiefeed->get_title());
         }else{
             $feedtitle = $this->format_title($feedrecord->preferredtitle);
         }
 
-        if($showtitle){
-            $r.='<div class="title">'.$feedtitle.'</div>';
-        }
-
-
-        $r.='<ul class="list no-overflow">'."\n";
-
-        $feeditems = $feed->get_items(0, $maxentries);
-        foreach($feeditems as $item){
-            $r.= $this->get_item_html($item);
-        }
-
-        $r.='</ul>';
-
-
-        if ($this->config->block_rss_client_show_channel_link) {
-
-            $channellink = $feed->get_link();
-
-            if (!empty($channellink)){
-                //NOTE: this means the 'last feed' display wins the block title - but
-                //this is exiting behaviour..
-                $this->content->footer = '<a href="'.htmlspecialchars(clean_param($channellink,PARAM_URL)).'">'. get_string('clientchannellink', 'block_rss_client') .'</a>';
-            }
-        }
-
         if (empty($this->config->title)){
             //NOTE: this means the 'last feed' displayed wins the block title - but
             //this is exiting behaviour..
             $this->title = strip_tags($feedtitle);
         }
 
-        return $r;
-    }
-
-
-    /**
-     * Returns the html list item of a feed item
-     *
-     * @param mixed item simplepie_item representing the feed item
-     * @return string html li representing the rss feed item
-     */
-    function get_item_html($item){
-
-        $link        = $item->get_link();
-        $title       = $item->get_title();
-        $description = $item->get_description();
-
-
-        if(empty($title)){
-            // no title present, use portion of description
-            $title = core_text::substr(strip_tags($description), 0, 20) . '...';
-        }else{
-            $title = break_up_long_words($title, 30);
+        $feed = new \block_rss_client\output\feed($feedtitle, $showtitle, $this->config->block_rss_client_show_channel_image);
+
+        if ($simplepieitems = $simplepiefeed->get_items(0, $maxentries)) {
+            foreach ($simplepieitems as $simplepieitem) {
+                try {
+                    $item = new \block_rss_client\output\item(
+                        $simplepieitem->get_id(),
+                        new moodle_url($simplepieitem->get_link()),
+                        $simplepieitem->get_title(),
+                        $simplepieitem->get_description(),
+                        new moodle_url($simplepieitem->get_permalink()),
+                        $simplepieitem->get_date('U'),
+                        $this->config->display_description
+                    );
+
+                    $feed->add_item($item);
+                } catch (moodle_exception $e) {
+                    // If there is an error with the RSS item, we don't
+                    // want to crash the page. Specifically, moodle_url can
+                    // throw an exception of the param is an extremely
+                    // malformed url.
+                    debugging($e->getMessage());
+                }
+            }
         }
 
-        if(empty($link)){
-            $link = $item->get_id();
-        } else {
+        // Feed image.
+        if ($imageurl = $simplepiefeed->get_image_url()) {
             try {
-                // URLs in our RSS cache will be escaped (correctly as theyre store in XML)
-                // html_writer::link() will re-escape them. To prevent double escaping unescape here.
-                // This can by done using htmlspecialchars_decode() but moodle_url also has that effect.
-                $link = new moodle_url($link);
+                $image = new \block_rss_client\output\channel_image(
+                    new moodle_url($imageurl),
+                    $simplepiefeed->get_image_title(),
+                    new moodle_url($simplepiefeed->get_image_link())
+                );
+
+                $feed->set_image($image);
             } catch (moodle_exception $e) {
-                // Catching the exception to prevent the whole site to crash in case of malformed RSS feed
-                $link = '';
+                // If there is an error with the RSS image, we don'twant to
+                // crash the page. Specifically, moodle_url can throw an
+                // exception if the param is an extremely malformed url.
+                debugging($e->getMessage());
             }
         }
 
-        $r = html_writer::start_tag('li');
-            $r.= html_writer::start_tag('div',array('class'=>'link'));
-                $r.= html_writer::link($link, s($title), array('onclick'=>'this.target="_blank"'));
-            $r.= html_writer::end_tag('div');
-
-            if($this->config->display_description && !empty($description)){
-
-                $formatoptions = new stdClass();
-                $formatoptions->para = false;
-
-                $r.= html_writer::start_tag('div',array('class'=>'description'));
-                    $description = format_text($description, FORMAT_HTML, $formatoptions, $this->page->course->id);
-                    $description = break_up_long_words($description, 30);
-                    $r.= $description;
-                $r.= html_writer::end_tag('div');
-            }
-        $r.= html_writer::end_tag('li');
-
-        return $r;
+        return $feed;
     }
 
     /**
         return $newskiptime;
     }
 }
-
-
diff --git a/blocks/rss_client/classes/output/block.php b/blocks/rss_client/classes/output/block.php
new file mode 100644 (file)
index 0000000..7789f0c
--- /dev/null
@@ -0,0 +1,104 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\block
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class to help display an RSS Feeds block
+ *
+ * @package   block_rss_client
+ * @copyright 2016 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class block implements \renderable, \templatable {
+
+    /**
+     * An array of renderable feeds
+     *
+     * @var array
+     */
+    protected $feeds;
+
+    /**
+     * Contruct
+     *
+     * @param array $feeds An array of renderable feeds
+     */
+    public function __construct(array $feeds = array()) {
+        $this->feeds = $feeds;
+    }
+
+    /**
+     * Prepare data for use in a template
+     *
+     * @param \renderer_base $output
+     * @return array
+     */
+    public function export_for_template(\renderer_base $output) {
+        $data = array('feeds' => array());
+
+        foreach ($this->feeds as $feed) {
+            $data['feeds'][] = $feed->export_for_template($output);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Add a feed
+     *
+     * @param \block_rss_client\output\feed $feed
+     * @return \block_rss_client\output\block
+     */
+    public function add_feed(feed $feed) {
+        $this->feeds[] = $feed;
+
+        return $this;
+    }
+
+    /**
+     * Set the feeds
+     *
+     * @param array $feeds
+     * @return \block_rss_client\output\block
+     */
+    public function set_feeds(array $feeds) {
+        $this->feeds = $feeds;
+
+        return $this;
+    }
+
+    /**
+     * Get feeds
+     *
+     * @return array
+     */
+    public function get_feeds() {
+        return $this->feeds;
+    }
+}
diff --git a/blocks/rss_client/classes/output/channel_image.php b/blocks/rss_client/classes/output/channel_image.php
new file mode 100644 (file)
index 0000000..af9e22f
--- /dev/null
@@ -0,0 +1,151 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\channel_image
+ *
+ * @package   block_rss_client
+ * @copyright 2016 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class to display RSS channel images
+ *
+ * @package   block_rss_client
+ * @copyright 2016 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class channel_image implements \renderable, \templatable {
+
+    /**
+     * The URL location of the image
+     *
+     * @var string
+     */
+    protected $url;
+
+    /**
+     * The title of the image
+     *
+     * @var string
+     */
+    protected $title;
+
+    /**
+     * The URL of the image link
+     *
+     * @var string
+     */
+    protected $link;
+
+    /**
+     * Contructor
+     *
+     * @param \moodle_url $url The URL location of the image
+     * @param string $title The title of the image
+     * @param \moodle_url $link The URL of the image link
+     */
+    public function __construct(\moodle_url $url, $title, \moodle_url $link = null) {
+        $this->url      = $url;
+        $this->title    = $title;
+        $this->link     = $link;
+    }
+
+    /**
+     * Export this for use in a mustache template context.
+     *
+     * @see templatable::export_for_template()
+     * @param renderer_base $output
+     * @return array The data for the template
+     */
+    public function export_for_template(\renderer_base $output) {
+        return array(
+            'url'   => clean_param($this->url, PARAM_URL),
+            'title' => $this->title,
+            'link'  => clean_param($this->link, PARAM_URL),
+        );
+    }
+
+    /**
+     * Set the URL
+     *
+     * @param \moodle_url $url
+     * @return \block_rss_client\output\channel_image
+     */
+    public function set_url(\moodle_url $url) {
+        $this->url = $url;
+
+        return $this;
+    }
+
+    /**
+     * Get the URL
+     *
+     * @return \moodle_url
+     */
+    public function get_url() {
+        return $this->url;
+    }
+
+    /**
+     * Set the title
+     *
+     * @param string $title
+     * @return \block_rss_client\output\channel_image
+     */
+    public function set_title($title) {
+        $this->title = $title;
+
+        return $this;
+    }
+
+    /**
+     * Get the title
+     *
+     * @return string
+     */
+    public function get_title() {
+        return $this->title;
+    }
+
+    /**
+     * Set the link
+     *
+     * @param \moodle_url $link
+     * @return \block_rss_client\output\channel_image
+     */
+    public function set_link($link) {
+        $this->link = $link;
+
+        return $this;
+    }
+
+    /**
+     * Get the link
+     *
+     * @return \moodle_url
+     */
+    public function get_link() {
+        return $this->link;
+    }
+}
diff --git a/blocks/rss_client/classes/output/feed.php b/blocks/rss_client/classes/output/feed.php
new file mode 100644 (file)
index 0000000..02f7e2d
--- /dev/null
@@ -0,0 +1,224 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\feed
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class to help display an RSS Feed
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class feed implements \renderable, \templatable {
+
+    /**
+     * The feed's title
+     *
+     * @var string
+     */
+    protected $title = null;
+
+    /**
+     * An array of renderable feed items
+     *
+     * @var array
+     */
+    protected $items = array();
+
+    /**
+     * The channel image
+     *
+     * @var channel_image
+     */
+    protected $image = null;
+
+    /**
+     * Whether or not to show the title
+     *
+     * @var boolean
+     */
+    protected $showtitle;
+
+    /**
+     * Whether or not to show the channel image
+     *
+     * @var boolean
+     */
+    protected $showimage;
+
+    /**
+     * Contructor
+     *
+     * @param string $title The title of the RSS feed
+     * @param boolean $showtitle Whether to show the title
+     * @param boolean $showimage Whether to show the channel image
+     */
+    public function __construct($title, $showtitle = true, $showimage = true) {
+        $this->title = $title;
+        $this->showtitle = $showtitle;
+        $this->showimage = $showimage;
+    }
+
+    /**
+     * Export this for use in a mustache template context.
+     *
+     * @see templatable::export_for_template()
+     * @param renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(\renderer_base $output) {
+        $data = array(
+            'title' => $this->showtitle ? $this->title : null,
+            'image' => null,
+            'items' => array(),
+        );
+
+        if ($this->showimage && $this->image) {
+            $data['image'] = $this->image->export_for_template($output);
+        }
+
+        foreach ($this->items as $item) {
+            $data['items'][] = $item->export_for_template($output);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Set the feed title
+     *
+     * @param string $title
+     * @return \block_rss_client\output\feed
+     */
+    public function set_title($title) {
+        $this->title = $title;
+
+        return $this;
+    }
+
+    /**
+     * Get the feed title
+     *
+     * @return string
+     */
+    public function get_title() {
+        return $this->title;
+    }
+
+    /**
+     * Add an RSS item
+     *
+     * @param \block_rss_client\output\item $item
+     */
+    public function add_item(item $item) {
+        $this->items[] = $item;
+
+        return $this;
+    }
+
+    /**
+     * Set the RSS items
+     *
+     * @param array $items An array of renderable RSS items
+     */
+    public function set_items(array $items) {
+        $this->items = $items;
+
+        return $this;
+    }
+
+    /**
+     * Get the RSS items
+     *
+     * @return array An array of renderable RSS items
+     */
+    public function get_items() {
+        return $this->items;
+    }
+
+    /**
+     * Set the channel image
+     *
+     * @param \block_rss_client\output\channel_image $image
+     */
+    public function set_image(channel_image $image) {
+        $this->image = $image;
+    }
+
+    /**
+     * Get the channel image
+     *
+     * @return channel_image
+     */
+    public function get_image() {
+        return $this->image;
+    }
+
+    /**
+     * Set showtitle
+     *
+     * @param boolean $showtitle
+     * @return \block_rss_client\output\feed
+     */
+    public function set_showtitle($showtitle) {
+        $this->showtitle = boolval($showtitle);
+
+        return $this;
+    }
+
+    /**
+     * Get showtitle
+     *
+     * @return boolean
+     */
+    public function get_showtitle() {
+        return $this->showtitle;
+    }
+
+    /**
+     * Set showimage
+     *
+     * @param boolean $showimage
+     * @return \block_rss_client\output\feed
+     */
+    public function set_showimage($showimage) {
+        $this->showimage = boolval($showimage);
+
+        return $this;
+    }
+
+    /**
+     * Get showimage
+     *
+     * @return boolean
+     */
+    public function get_showimage() {
+        return $this->showimage;
+    }
+}
diff --git a/blocks/rss_client/classes/output/footer.php b/blocks/rss_client/classes/output/footer.php
new file mode 100644 (file)
index 0000000..3da2039
--- /dev/null
@@ -0,0 +1,90 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\footer
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class to help display an RSS Block footer
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class footer implements \renderable, \templatable {
+
+    /**
+     * The link provided in the RSS channel
+     *
+     * @var \moodle_url
+     */
+    protected $channelurl;
+
+    /**
+     * Constructor
+     *
+     * @param \moodle_url $channelurl The link provided in the RSS channel
+     */
+    public function __construct(\moodle_url $channelurl) {
+        $this->channelurl = $channelurl;
+    }
+
+    /**
+     * Set the channel url
+     *
+     * @param \moodle_url $channelurl
+     * @return \block_rss_client\output\footer
+     */
+    public function set_channelurl(\moodle_url $channelurl) {
+        $this->channelurl = $channelurl;
+
+        return $this;
+    }
+
+    /**
+     * Get the channel url
+     *
+     * @return \moodle_url
+     */
+    public function get_channelurl() {
+        return $this->channelurl;
+    }
+
+    /**
+     * Export context for use in mustache templates
+     *
+     * @see templatable::export_for_template()
+     * @param renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(\renderer_base $output) {
+        $data = new \stdClass();
+        $data->channellink = clean_param($this->channelurl, PARAM_URL);
+
+        return $data;
+    }
+}
diff --git a/blocks/rss_client/classes/output/item.php b/blocks/rss_client/classes/output/item.php
new file mode 100644 (file)
index 0000000..71a71dc
--- /dev/null
@@ -0,0 +1,286 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\feed
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Class to help display an RSS Item
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class item implements \renderable, \templatable {
+
+    /**
+     * The unique id of the item
+     *
+     * @var string
+     */
+    protected $id;
+
+    /**
+     * The link to the item
+     *
+     * @var \moodle_url
+     */
+    protected $link;
+
+    /**
+     * The title of the item
+     *
+     * @var string
+     */
+    protected $title;
+
+    /**
+     * The description of the item
+     *
+     * @var string
+     */
+    protected $description;
+
+    /**
+     * The item's permalink
+     *
+     * @var \moodle_url
+     */
+    protected $permalink;
+
+    /**
+     * The publish date of the item in Unix timestamp format
+     *
+     * @var int
+     */
+    protected $timestamp;
+
+    /**
+     * Whether or not to show the item's description
+     *
+     * @var string
+     */
+    protected $showdescription;
+
+    /**
+     * Contructor
+     *
+     * @param string $id The id of the RSS item
+     * @param \moodle_url $link The URL of the RSS item
+     * @param string $title The title pf the RSS item
+     * @param string $description The description of the RSS item
+     * @param \moodle_url $permalink The permalink of the RSS item
+     * @param int $timestamp The Unix timestamp that represents the published date
+     * @param boolean $showdescription Whether or not to show the description
+     */
+    public function __construct($id, \moodle_url $link, $title, $description, \moodle_url $permalink, $timestamp,
+            $showdescription = true) {
+        $this->id               = $id;
+        $this->link             = $link;
+        $this->title            = $title;
+        $this->description      = $description;
+        $this->permalink        = $permalink;
+        $this->timestamp        = $timestamp;
+        $this->showdescription  = $showdescription;
+    }
+
+    /**
+     * Export context for use in mustache templates
+     *
+     * @see templatable::export_for_template()
+     * @param renderer_base $output
+     * @return array
+     */
+    public function export_for_template(\renderer_base $output) {
+        $data = array(
+            'id'            => $this->id,
+            'permalink'     => clean_param($this->permalink, PARAM_URL),
+            'datepublished' => $output->format_published_date($this->timestamp),
+            'link'          => clean_param($this->link, PARAM_URL),
+        );
+
+        // If the item does not have a title, create one from the description.
+        $title = $this->title;
+        if (!$title) {
+            $title = strip_tags($this->description);
+            $title = core_text::substr($title, 0, 20) . '...';
+        }
+
+        // Allow the renderer to format the title and description.
+        $data['title']          = $output->format_title($title);
+        $data['description']    = $this->showdescription ? $output->format_description($this->description) : null;
+
+        return $data;
+    }
+
+    /**
+     * Set id
+     *
+     * @param string $id
+     * @return \block_rss_client\output\item
+     */
+    public function set_id($id) {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    /**
+     * Get id
+     *
+     * @return string
+     */
+    public function get_id() {
+        return $this->id;
+    }
+
+    /**
+     * Set link
+     *
+     * @param \moodle_url $link
+     * @return \block_rss_client\output\item
+     */
+    public function set_link(\moodle_url $link) {
+        $this->link = $link;
+
+        return $this;
+    }
+
+    /**
+     * Get link
+     *
+     * @return \moodle_url
+     */
+    public function get_link() {
+        return $this->link;
+    }
+
+    /**
+     * Set title
+     *
+     * @param string $title
+     * @return \block_rss_client\output\item
+     */
+    public function set_title($title) {
+        $this->title = $title;
+
+        return $this;
+    }
+
+    /**
+     * Get title
+     *
+     * @return string
+     */
+    public function get_title() {
+        return $this->title;
+    }
+
+    /**
+     * Set description
+     *
+     * @param string $description
+     * @return \block_rss_client\output\item
+     */
+    public function set_description($description) {
+        $this->description = $description;
+
+        return $this;
+    }
+
+    /**
+     * Get description
+     *
+     * @return string
+     */
+    public function get_description() {
+        return $this->description;
+    }
+
+    /**
+     * Set permalink
+     *
+     * @param string $permalink
+     * @return \block_rss_client\output\item
+     */
+    public function set_permalink($permalink) {
+        $this->permalink = $permalink;
+
+        return $this;
+    }
+
+    /**
+     * Get permalink
+     *
+     * @return string
+     */
+    public function get_permalink() {
+        return $this->permalink;
+    }
+
+    /**
+     * Set timestamp
+     *
+     * @param int $timestamp
+     * @return \block_rss_client\output\item
+     */
+    public function set_timestamp($timestamp) {
+        $this->timestamp = $timestamp;
+
+        return $this;
+    }
+
+    /**
+     * Get timestamp
+     *
+     * @return string
+     */
+    public function get_timestamp() {
+        return $this->timestamp;
+    }
+
+    /**
+     * Set showdescription
+     *
+     * @param boolean $showdescription
+     * @return \block_rss_client\output\item
+     */
+    public function set_showdescription($showdescription) {
+        $this->showdescription = boolval($showdescription);
+
+        return $this;
+    }
+
+    /**
+     * Get showdescription
+     *
+     * @return boolean
+     */
+    public function get_showdescription() {
+        return $this->showdescription;
+    }
+}
diff --git a/blocks/rss_client/classes/output/renderer.php b/blocks/rss_client/classes/output/renderer.php
new file mode 100644 (file)
index 0000000..7a03280
--- /dev/null
@@ -0,0 +1,121 @@
+<?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/>.
+
+/**
+ * Contains class block_rss_client\output\block_renderer_html
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace block_rss_client\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Renderer for RSS Client block
+ *
+ * @package   block_rss_client
+ * @copyright 2015 Howard County Public School System
+ * @author    Brendan Anderson <brendan_anderson@hcpss.org>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class renderer extends \plugin_renderer_base {
+
+    /**
+     * Render an RSS Item
+     *
+     * @param templatable $item
+     * @return string|boolean
+     */
+    public function render_item(\templatable $item) {
+        $data = $item->export_for_template($this);
+
+        return $this->render_from_template('block_rss_client/item', $data);
+    }
+
+    /**
+     * Render an RSS Feed
+     *
+     * @param templatable $feed
+     * @return string|boolean
+     */
+    public function render_feed(\templatable $feed) {
+        $data = $feed->export_for_template($this);
+
+        return $this->render_from_template('block_rss_client/feed', $data);
+    }
+
+    /**
+     * Render an RSS feeds block
+     *
+     * @param \templatable $block
+     * @return string|boolean
+     */
+    public function render_block(\templatable $block) {
+        $data = $block->export_for_template($this);
+
+        return $this->render_from_template('block_rss_client/block', $data);
+    }
+
+    /**
+     * Render the block footer
+     *
+     * @param templatable $footer
+     * @return string|boolean
+     */
+    public function render_footer(\templatable $footer) {
+        $data = $footer->export_for_template($this);
+
+        return $this->render_from_template('block_rss_client/footer', $data);
+    }
+
+    /**
+     * Format a timestamp to use as a published date
+     *
+     * @param int $timestamp Unix timestamp
+     * @return string
+     */
+    public function format_published_date($timestamp) {
+        return strftime(get_string('strftimerecentfull', 'langconfig'), $timestamp);
+        return date('j F Y, g:i a', $timestamp);
+    }
+
+    /**
+     * Format an RSS item title
+     *
+     * @param string $title
+     * @return string
+     */
+    public function format_title($title) {
+        return break_up_long_words($title, 30);
+    }
+
+    /**
+     * Format an RSS item description
+     *
+     * @param string $description
+     * @return string
+     */
+    public function format_description($description) {
+        $description = format_text($description, FORMAT_HTML, array('para' => false));
+        $description = break_up_long_words($description, 30);
+
+        return $description;
+    }
+}
diff --git a/blocks/rss_client/templates/block.mustache b/blocks/rss_client/templates/block.mustache
new file mode 100644 (file)
index 0000000..6cc2c71
--- /dev/null
@@ -0,0 +1,91 @@
+{{!
+    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 block_rss_client/block
+
+    Template which defines an RSS Feeds block
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * feeds - array: An array of RSS feeds.
+
+    Example context (json):
+    {
+        "feeds": [
+            {
+                "title": "News from around my living room",
+                "image": {
+                    "url": "https://www.example.com/feeds/news/poster.jpg",
+                    "title": "Example News Logo",
+                    "link": "https://www.example.com/feeds/news/"
+                },
+                "items": [
+                    {
+                        "id": "https://www.example.com/node/12",
+                        "link": "https://www.example.com/my-turtle-story.html",
+                        "title": "My Turtle Story",
+                        "description": "This is a story about my turtle.",
+                        "permalink": "https://www.example.com/my-turtle-story.html",
+                        "datepublished": "11 January 2016, 7:11 pm"
+                    },
+                    {
+                        "id": "https://www.example.com/node/12",
+                        "link": "https://www.example.com/my-cat-story.html",
+                        "title": "My Story",
+                        "description": "This is a story about my cats.",
+                        "permalink": "https://www.example.com/my-cat-story.html",
+                        "datepublished": "12 January 2016, 9:12 pm"
+                    }
+                ]
+            },
+            {
+                "title": "News from around my kitchen",
+                "image": {
+                    "url": "https://www.example.com/feeds/news/kitchen.jpg",
+                    "title": "Picture of My Kitchen",
+                    "link": "https://www.example.com/feeds/news/kitchen/"
+                },
+                "items": [
+                    {
+                        "id": "https://www.example.com/node/10",
+                        "link": "https://www.example.com/oven-smoke.html",
+                        "title": "Why is the Oven Smoking?",
+                        "description": "There is something smoking in the oven.",
+                        "permalink": "https://www.example.com/oven-smoke.html",
+                        "datepublished": "10 January 2016, 1:13 pm"
+                    },
+                    {
+                        "id": "https://www.example.com/node/13",
+                        "link": "https://www.example.com/coffee-is-good.html",
+                        "title": "Why My Coffee Machine is So Great!",
+                        "description": "Don't be fancy; drips are best.",
+                        "permalink": "https://www.example.com/oven-smoke.html",
+                        "datepublished": "13 January 2016, 8:25 pm"
+                    }
+                ]
+            }
+        ]
+    }
+}}
+{{#feeds}}
+    {{> block_rss_client/feed}}
+{{/feeds}}
diff --git a/blocks/rss_client/templates/channel_image.mustache b/blocks/rss_client/templates/channel_image.mustache
new file mode 100644 (file)
index 0000000..f20166e
--- /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/>.
+}}
+{{!
+    @template block_rss_client/channel_image
+
+    Template which defines an item in an RSS Feed
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * url - string: The escaped URL of the image.
+    * title - string: The title of the image.
+    * link - string: Optionally, a URL to link the image to. Must be escaped.
+
+    Example context (json):
+    {
+        "url": "http://www.example.com/images/catpic.jpg",
+        "title": "A picture of my cat",
+        "link": "http://www.example.com/cat-news/"
+    }
+}}
+<div class="image" title="{{title}}">
+    {{#link}}
+        <a href="{{{link}}}">
+    {{/link}}
+
+    <img src="{{{url}}}" alt="{{title}}" />
+
+    {{#link}}
+        </a>
+    {{/link}}
+</div>
diff --git a/blocks/rss_client/templates/feed.mustache b/blocks/rss_client/templates/feed.mustache
new file mode 100644 (file)
index 0000000..ad9ae3e
--- /dev/null
@@ -0,0 +1,79 @@
+{{!
+    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 block_rss_client/feed
+
+    Template which defines an item in an RSS Feed
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * channel_image - object: URL, title and link for the channel image.
+    * title - string: The title of the feed.
+    * items - array: An array of feed items.
+
+    Example context (json):
+    {
+        "title": "News from around my living room",
+        "image": {
+            "url": "https://www.example.com/feeds/news/poster.jpg",
+            "title": "Example News Logo",
+            "link": "https://www.example.com/feeds/news/"
+        },
+        "feeditems": [
+            {
+                "id": "https://www.example.com/node/12",
+                "link": "https://www.example.com/my-turtle-story.html",
+                "title": "My Turtle Story",
+                "description": "This is a story about my turtle.",
+                "permalink": "https://www.example.com/my-turtle-story.html",
+                "datepublished": "11 January 2016, 7:11 pm"
+            },
+            {
+                "id": "https://www.example.com/node/12",
+                "link": "https://www.example.com/my-cat-story.html",
+                "title": "My Story",
+                "description": "This is a story about my cats.",
+                "permalink": "https://www.example.com/my-cat-story.html",
+                "datepublished": "12 January 2016, 9:12 pm"
+            }
+        ]
+    }
+}}
+{{$image}}
+    {{#image}}
+        {{> block_rss_client/channel_image}}
+    {{/image}}
+{{/image}}
+
+{{$title}}
+    {{#title}}
+        <div class="title">{{feedtitle}}</div>
+    {{/title}}
+{{/title}}
+
+{{$items}}
+    <ul class="list no-overflow">
+        {{#items}}
+            {{> block_rss_client/item}}
+        {{/items}}
+    </ul>
+{{/items}}
diff --git a/blocks/rss_client/templates/footer.mustache b/blocks/rss_client/templates/footer.mustache
new file mode 100644 (file)
index 0000000..b1aa373
--- /dev/null
@@ -0,0 +1,36 @@
+{{!
+    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 block_rss_client/footer
+
+    Template which defines an item in an RSS Feed
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * channellink - string: The channel URL. Must be escaped.
+
+    Example context (json):
+    {
+        "channellink": "https://www.example.com/feeds/rss"
+    }
+}}
+<a href="{{{channellink}}}">{{#str}} clientchannellink, block_rss_client {{/str}}</a>
diff --git a/blocks/rss_client/templates/item.mustache b/blocks/rss_client/templates/item.mustache
new file mode 100644 (file)
index 0000000..b21bf11
--- /dev/null
@@ -0,0 +1,60 @@
+{{!
+    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 block_rss_client/item
+
+    Template which defines an item in an RSS Feed
+
+    Classes required for JS:
+    * none
+
+    Data attributes required for JS:
+    * none
+
+    Context variables required for this template:
+    * id - string: A unique id for the feed item.
+    * link - string: The URL of the feed item. Must already be escaped.
+    * title - string: The title of the feed item.
+    * description - string: The text description of the feed item.
+    * permalink - string: The permalink of the feed item. Must already be escaped.
+    * datepublished - string: The date the feed item was published.
+
+    Example context (json):
+    {
+        "id": "https://www.example.com/node",
+        "link": "https://www.example.com/my-cat-story.html",
+        "title": "My Story",
+        "description": "This is a story about my cats.",
+        "permalink": "https://www.example.com/my-cat-story.html",
+        "datepublished": "12 January 2016, 9:12 pm"
+    }
+}}
+<li>
+    {{$title}}
+        <div class="link">
+            <a href="{{{link}}}" onclick='this.target="_blank"'>{{title}}</a>
+        </div>
+    {{/title}}
+
+    {{$content}}
+        {{#description}}
+            <div class="description">
+                {{{description}}}
+            </div>
+        {{/description}}
+    {{/content}}
+</li>
index 06f691d..22471f3 100644 (file)
@@ -47,7 +47,6 @@ class block_tag_flickr extends block_base {
         global $CFG, $USER;
 
         //note: do NOT include files at the top of this file
-        require_once($CFG->dirroot.'/tag/lib.php');
         require_once($CFG->libdir . '/filelib.php');
 
         if ($this->content !== NULL) {
@@ -56,11 +55,12 @@ class block_tag_flickr extends block_base {
 
         $tagid = optional_param('id', 0, PARAM_INT);   // tag id - for backware compatibility
         $tag = optional_param('tag', '', PARAM_TAG); // tag
+        $tc = optional_param('tc', 0, PARAM_INT); // Tag collection id.
 
-        if ($tag) {
-            $tagobject = tag_get('name', $tag);
-        } else if ($tagid) {
-            $tagobject = tag_get('id', $tagid);
+        if ($tagid) {
+            $tagobject = core_tag_tag::get($tagid);
+        } else if ($tag) {
+            $tagobject = core_tag_tag::get_by_name($tc, $tag);
         }
 
         if (empty($tagobject)) {
@@ -73,7 +73,9 @@ class block_tag_flickr extends block_base {
         //include related tags in the photo query ?
         $tagscsv = $tagobject->name;
         if (!empty($this->config->includerelatedtags)) {
-            $tagscsv .= ',' . tag_get_related_tags_csv(tag_get_related_tags($tagobject->id), TAG_RETURN_TEXT);
+            foreach ($tagobject->get_related_tags() as $t) {
+                $tagscsv .= ',' . $t->get_display_name(false);
+            }
         }
         $tagscsv = urlencode($tagscsv);
 
index e67e039..da0a23f 100644 (file)
@@ -36,7 +36,7 @@ class block_tag_flickr_edit_form extends block_edit_form {
         $mform->setType('config_title', PARAM_TEXT);
 
         $mform->addElement('text', 'config_numberofphotos', get_string('numberofphotos', 'block_tag_flickr'), array('size' => 5));
-        $mform->setType('config_numberofvideos', PARAM_INT);
+        $mform->setType('config_numberofphotos', PARAM_INT);
 
         $mform->addElement('selectyesno', 'config_includerelatedtags', get_string('includerelatedtags', 'block_tag_flickr'));
         $mform->setDefault('config_includerelatedtags', 0);
index 7ab13be..9c79fe8 100644 (file)
@@ -64,7 +64,6 @@ class block_tag_youtube extends block_base {
         global $CFG;
 
         //note: do NOT include files at the top of this file
-        require_once($CFG->dirroot.'/tag/lib.php');
         require_once($CFG->libdir . '/filelib.php');
 
         if ($this->content !== NULL) {
@@ -132,11 +131,12 @@ class block_tag_youtube extends block_base {
 
         $tagid = optional_param('id', 0, PARAM_INT);   // tag id - for backware compatibility
         $tag = optional_param('tag', '', PARAM_TAG); // tag
+        $tc = optional_param('tc', 0, PARAM_INT); // Tag collection id.
 
-        if ($tag) {
-            $tagobject = tag_get('name', $tag);
-        } else if ($tagid) {
-            $tagobject = tag_get('id', $tagid);
+        if ($tagid) {
+            $tagobject = core_tag_tag::get($tagid);
+        } else if ($tag) {
+            $tagobject = core_tag_tag::get_by_name($tc, $tag);
         }
 
         if (empty($tagobject)) {
@@ -172,11 +172,12 @@ class block_tag_youtube extends block_base {
 
         $tagid = optional_param('id', 0, PARAM_INT);   // tag id - for backware compatibility
         $tag = optional_param('tag', '', PARAM_TAG); // tag
+        $tc = optional_param('tc', 0, PARAM_INT); // Tag collection id.
 
-        if ($tag) {
-            $tagobject = tag_get('name', $tag);
-        } else if ($tagid) {
-            $tagobject = tag_get('id', $tagid);
+        if ($tagid) {
+            $tagobject = core_tag_tag::get($tagid);
+        } else if ($tag) {
+            $tagobject = core_tag_tag::get_by_name($tc, $tag);
         }
 
         if (empty($tagobject)) {
diff --git a/blocks/tags/backup/moodle2/restore_tags_block_task.class.php b/blocks/tags/backup/moodle2/restore_tags_block_task.class.php
new file mode 100644 (file)
index 0000000..11d2087
--- /dev/null
@@ -0,0 +1,88 @@
+<?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/>.
+
+/**
+ * @package   block_tags
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Specialised restore task for the tags block
+ * (using execute_after_tasks for recoding of tag collection id)
+ *
+ * @package   block_tags
+ * @copyright 2016 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_tags_block_task extends restore_block_task {
+
+    protected function define_my_settings() {
+    }
+
+    protected function define_my_steps() {
+    }
+
+    public function get_fileareas() {
+        return array(); // No associated fileareas.
+    }
+
+    public function get_configdata_encoded_attributes() {
+        return array(); // No special handling of configdata.
+    }
+
+    /**
+     * This function, executed after all the tasks in the plan
+     * have been executed, will remove tag collection reference in case block was restored into another site.
+     * Also get mapping of contextid.
+     */
+    public function after_restore() {
+        global $DB;
+
+        // Get the blockid.
+        $blockid = $this->get_blockid();
+
+        // Extract block configdata and remove tag collection reference if this is another site. Also map contextid.
+        if ($configdata = $DB->get_field('block_instances', 'configdata', array('id' => $blockid))) {
+            $config = unserialize(base64_decode($configdata));
+            $changed = false;
+            if (!empty($config->tagcoll) && $config->tagcoll > 1 && !$this->is_samesite()) {
+                $config->tagcoll = 0;
+                $changed = true;
+            }
+            if (!empty($config->ctx)) {
+                if ($ctxmap = restore_dbops::get_backup_ids_record($this->get_restoreid(), 'context', $config->ctx)) {
+                    $config->ctx = $ctxmap->newitemid;
+                } else {
+                    $config->ctx = 0;
+                }
+                $changed = true;
+            }
+            if ($changed) {
+                $configdata = base64_encode(serialize($config));
+                $DB->set_field('block_instances', 'configdata', $configdata, array('id' => $blockid));
+            }
+        }
+    }
+
+    static public function define_decode_contents() {
+        return array();
+    }
+
+    static public function define_decode_rules() {
+        return array();
+    }
+}
index 329eb3f..31ced58 100644 (file)
@@ -70,6 +70,22 @@ class block_tags extends block_base {
             $this->config->numberoftags = 80;
         }
 
+        if (empty($this->config->tagtype)) {
+            $this->config->tagtype = '';
+        }
+
+        if (empty($this->config->ctx)) {
+            $this->config->ctx = 0;
+        }
+
+        if (empty($this->config->rec)) {
+            $this->config->rec = 1;
+        }
+
+        if (empty($this->config->tagcoll)) {
+            $this->config->tagcoll = 0;
+        }
+
         if ($this->content !== NULL) {
             return $this->content;
         }
@@ -85,9 +101,11 @@ class block_tags extends block_base {
 
         // Get a list of tags.
 
-        require_once($CFG->dirroot.'/tag/locallib.php');
-
-        $this->content->text = tag_print_cloud(null, $this->config->numberoftags, true);
+        $tagcloud = core_tag_collection::get_tag_cloud($this->config->tagcoll,
+                $this->config->tagtype,
+                $this->config->numberoftags,
+                'name', '', $this->page->context->id, $this->config->ctx, $this->config->rec);
+        $this->content->text = $OUTPUT->render_from_template('core_tag/tagcloud', $tagcloud->export_for_template($OUTPUT));
 
         return $this->content;
     }
index e6c80f1..89742c5 100644 (file)
@@ -30,6 +30,7 @@
  */
 class block_tags_edit_form extends block_edit_form {
     protected function specific_definition($mform) {
+        global $CFG;
         // Fields for editing HTML block title and contents.
         $mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
 
@@ -37,11 +38,63 @@ class block_tags_edit_form extends block_edit_form {
         $mform->setType('config_title', PARAM_TEXT);
         $mform->setDefault('config_title', get_string('pluginname', 'block_tags'));
 
+        $this->add_collection_selector($mform);
+
         $numberoftags = array();
         for ($i = 1; $i <= 200; $i++) {
             $numberoftags[$i] = $i;
         }
         $mform->addElement('select', 'config_numberoftags', get_string('numberoftags', 'blog'), $numberoftags);
         $mform->setDefault('config_numberoftags', 80);
+
+        $defaults = array(
+            'official' => get_string('officialonly', 'block_tags'),
+            '' => get_string('anytype', 'block_tags'));
+        $mform->addElement('select', 'config_tagtype', get_string('defaultdisplay', 'block_tags'), $defaults);
+        $mform->setDefault('config_tagtype', '');
+
+        $defaults = array(0 => context_system::instance()->get_context_name());
+        $parentcontext = context::instance_by_id($this->block->instance->parentcontextid);
+        if ($parentcontext->contextlevel > CONTEXT_COURSE) {
+            $coursecontext = $parentcontext->get_course_context();
+            $defaults[$coursecontext->id] = $coursecontext->get_context_name();
+        }
+        if ($parentcontext->contextlevel != CONTEXT_SYSTEM) {
+            $defaults[$parentcontext->id] = $parentcontext->get_context_name();
+        }
+        $mform->addElement('select', 'config_ctx', get_string('taggeditemscontext', 'block_tags'), $defaults);
+        $mform->addHelpButton('config_ctx', 'taggeditemscontext', 'block_tags');
+        $mform->setDefault('config_ctx', 0);
+
+        $mform->addElement('advcheckbox', 'config_rec', get_string('recursivecontext', 'block_tags'));
+        $mform->addHelpButton('config_rec', 'recursivecontext', 'block_tags');
+        $mform->setDefault('config_rec', 1);
+    }
+
+    /**
+     * Add the tag collection selector
+     *
+     * @param object $mform the form being built.
+     */
+    protected function add_collection_selector($mform) {
+        $tagcolls = core_tag_collection::get_collections_menu(false, false, get_string('anycollection', 'block_tags'));
+        if (count($tagcolls) <= 1) {
+            return;
+        }
+
+        $tagcollssearchable = core_tag_collection::get_collections_menu(false, true);
+        $hasunsearchable = false;
+        foreach ($tagcolls as $id => $name) {
+            if ($id && !array_key_exists($id, $tagcollssearchable)) {
+                $hasunsearchable = true;
+                $tagcolls[$id] = $name . '*';
+            }
+        }
+
+        $mform->addElement('select', 'config_tagcoll', get_string('tagcollection', 'block_tags'), $tagcolls);
+        if ($hasunsearchable) {
+            $mform->addHelpButton('config_tagcoll', 'tagcollection', 'block_tags');
+        }
+        $mform->setDefault('config_tagcoll', 0);
     }
 }
index edf9669..02dd7a1 100644 (file)
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['anycollection'] = 'Any';
+$string['anytype'] = 'All';
 $string['configtitle'] = 'Block title';
 $string['disabledtags'] = 'Tags are disabled';
 $string['defaultdisplay'] = 'Tag type to display';
+$string['officialonly'] = 'Only official';
 $string['pluginname'] = 'Tags';
+$string['recursivecontext'] = 'Include child contexts';
+$string['recursivecontext_help'] = 'If unchecked, tags of items in the context specified above will be displayed excluding underlying contexts, for example, you can search on course level only without searching inside course activities';
+$string['tagcollection'] = 'Tag collection';
+$string['tagcollection_help'] = 'Select tag collection to display tags from. If you choose "Any" '
+        . 'the tags from all collections except for those marked with * will be displayed';
+$string['taggeditemscontext'] = 'Tagged items context';
+$string['taggeditemscontext_help'] = 'You can limit the tag cloud to the tags that are present in the current course category, course or module';
 $string['tags:addinstance'] = 'Add a new tags block';
 $string['tags:myaddinstance'] = 'Add a new tags block to Dashboard';
 
-// Deprecated since 3.0
+// Deprecated since 3.0.
 
 $string['add'] = 'Add';
 $string['alltags'] = 'All tags:';
index ed80f7b..7a25490 100644 (file)
@@ -45,6 +45,6 @@ Feature: Block tags displaying tag cloud
     And I should see "Cats" in the "Tags" "block"
     And I should not see "Neverusedtag" in the "Tags" "block"
     And I click on "Dogs" "link" in the "Tags" "block"
-    And I should see "Users tagged with \"Dogs\": 1"
+    And I should see "User interests" in the ".tag-index-items h3" "css_element"
     And I should see "Teacher 1"
     And I log out
index 634c511..8248039 100644 (file)
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 require_once(dirname(dirname(__FILE__)).'/config.php');
-require_once('lib.php');
-require_once('locallib.php');
-require_once($CFG->dirroot .'/comment/lib.php');
+require_once($CFG->dirroot . '/blog/lib.php');
+require_once($CFG->dirroot . '/blog/locallib.php');
+require_once($CFG->dirroot . '/comment/lib.php');
+require_once($CFG->dirroot . '/blog/edit_form.php');
 
 $action   = required_param('action', PARAM_ALPHA);
 $id       = optional_param('entryid', 0, PARAM_INT);
@@ -185,7 +186,6 @@ if (!empty($entry->id)) {
     }
 }
 
-require_once('edit_form.php');
 $summaryoptions = array('maxfiles' => 99, 'maxbytes' => $CFG->maxbytes, 'trusttext' => true, 'context' => $sitecontext,
     'subdirs' => file_area_contains_subdirs($sitecontext, 'blog', 'post', $entry->id));
 $attachmentoptions = array('subdirs' => false, 'maxfiles' => 99, 'maxbytes' => $CFG->maxbytes);
@@ -206,9 +206,8 @@ $entry = file_prepare_standard_filemanager($entry,
                                            'attachment',
                                            $entry->id);
 
-if (!empty($CFG->usetags) && !empty($entry->id)) {
-    include_once($CFG->dirroot.'/tag/lib.php');
-    $entry->tags = tag_get_tags_array('post', $entry->id);
+if (!empty($entry->id)) {
+    $entry->tags = core_tag_tag::get_item_tags_array('core', 'post', $entry->id);
 }
 
 $entry->action = $action;
@@ -271,7 +270,6 @@ switch ($action) {
         if (empty($entry->id)) {
             print_error('wrongentryid', 'blog');
         }
-        $entry->tags = tag_get_tags_array('post', $entry->id);
         $strformheading = get_string('updateentrywithid', 'blog');
 
         break;
index 773f153..7060c93 100644 (file)
@@ -65,10 +65,11 @@ class blog_edit_form extends moodleform {
         $mform->addHelpButton('publishstate', 'publishto', 'blog');
         $mform->setDefault('publishstate', 0);
 
-        if (!empty($CFG->usetags)) {
+        if (core_tag_tag::is_enabled('core', 'post')) {
             $mform->addElement('header', 'tagshdr', get_string('tags', 'tag'));
-            $mform->addElement('tags', 'tags', get_string('tags'));
         }
+        $mform->addElement('tags', 'tags', get_string('tags'),
+                array('itemtype' => 'post', 'component' => 'core'));
 
         $allmodnames = array();
 
index 069ef96..3f615bd 100644 (file)
@@ -28,7 +28,6 @@ require_once('../config.php');
 require_once('lib.php');
 require_once('external_blog_edit_form.php');
 require_once($CFG->libdir . '/simplepie/moodle_simplepie.php');
-require_once($CFG->dirroot.'/tag/lib.php');
 
 require_login();
 $context = context_system::instance();
@@ -58,6 +57,7 @@ if (!empty($id) && !$DB->record_exists('blog_external', array('id' => $id))) {
     print_error('wrongexternalid', 'blog');
 } else if (!empty($id)) {
     $external = $DB->get_record('blog_external', array('id' => $id));
+    $external->autotags = core_tag_tag::get_item_tags_array('core', 'blog_external', $id);
 }
 
 $strformheading = ($action == 'edit') ? get_string('editexternalblog', 'blog') : get_string('addnewexternalblog', 'blog');
@@ -84,12 +84,9 @@ if ($externalblogform->is_cancelled()) {
             $newexternal->timemodified = time();
 
             $newexternal->id = $DB->insert_record('blog_external', $newexternal);
+            core_tag_tag::set_item_tags('core', 'blog_external', $newexternal->id,
+                    context_user::instance($newexternal->userid), $data->autotags);
             blog_sync_external_entries($newexternal);
-            if ($CFG->usetags) {
-                $autotags = (!empty($data->autotags)) ? $data->autotags : null;
-                tag_set('blog_external', $newexternal->id, explode(',', $autotags), 'core',
-                    context_user::instance($newexternal->userid)->id);
-            }
 
             break;
 
@@ -107,11 +104,8 @@ if ($externalblogform->is_cancelled()) {
                 $external->timemodified = time();
 
                 $DB->update_record('blog_external', $external);
-                if ($CFG->usetags) {
-                    $autotags = (!empty($data->autotags)) ? $data->autotags : null;
-                    tag_set('blog_external', $external->id, explode(',', $autotags), 'core',
-                        context_user::instance($external->userid)->id);
-                }
+                core_tag_tag::set_item_tags('core', 'blog_external', $external->id,
+                        context_user::instance($external->userid), $data->autotags);
             } else {
                 print_error('wrongexternalid', 'blog');
             }
@@ -125,6 +119,9 @@ if ($externalblogform->is_cancelled()) {
     redirect($returnurl);
 }
 
+navigation_node::override_active_url(new moodle_url('/blog/external_blogs.php'));
+$PAGE->navbar->add(get_string('addnewexternalblog', 'blog'));
+
 $PAGE->set_heading(fullname($USER));
 $PAGE->set_title("$SITE->shortname: $strblogs: $strexternalblogs");
 
index fc28e9a..8de3bdc 100644 (file)
@@ -48,14 +48,14 @@ class blog_edit_external_form extends moodleform {
         $mform->addElement('textarea', 'description', get_string('description', 'blog'), array('cols' => 50, 'rows' => 7));
         $mform->addHelpButton('description', 'description', 'blog');
 
-        if (!empty($CFG->usetags)) {
-            $mform->addElement('text', 'filtertags', get_string('filtertags', 'blog'), array('size' => 50));
-            $mform->setType('filtertags', PARAM_TAGLIST);
-            $mform->addHelpButton('filtertags', 'filtertags', 'blog');
-            $mform->addElement('text', 'autotags', get_string('autotags', 'blog'), array('size' => 50));
-            $mform->setType('autotags', PARAM_TAGLIST);
-            $mform->addHelpButton('autotags', 'autotags', 'blog');
-        }
+        // To filter external blogs by their tags we do not need to check if tags in moodle are enabled.
+        $mform->addElement('text', 'filtertags', get_string('filtertags', 'blog'), array('size' => 50));
+        $mform->setType('filtertags', PARAM_TAGLIST);
+        $mform->addHelpButton('filtertags', 'filtertags', 'blog');
+
+        $mform->addElement('tags', 'autotags', get_string('autotags', 'blog'),
+                array('itemtype' => 'blog_external', 'component' => 'core'));
+        $mform->addHelpButton('autotags', 'autotags', 'blog');
 
         $this->add_action_buttons();
 
@@ -115,7 +115,6 @@ class blog_edit_external_form extends moodleform {
         }
 
         if ($id = $mform->getElementValue('id')) {
-            $mform->setDefault('autotags', implode(',', tag_get_tags_array('blog_external', $id)));
             $mform->freeze('url');
             if ($mform->elementExists('filtertags')) {
                 $mform->freeze('filtertags');
index bc3dd1e..1b64b42 100644 (file)
@@ -24,7 +24,6 @@ require_once(dirname(dirname(__FILE__)).'/config.php');
 require_once($CFG->dirroot .'/blog/lib.php');
 require_once($CFG->dirroot .'/blog/locallib.php');
 require_once($CFG->dirroot .'/course/lib.php');
-require_once($CFG->dirroot .'/tag/lib.php');
 require_once($CFG->dirroot .'/comment/lib.php');
 
 $id       = optional_param('id', null, PARAM_INT);
index 00a1ffa..06b4af8 100644 (file)
@@ -29,7 +29,6 @@ defined('MOODLE_INTERNAL') || die();
  * Library of functions and constants for blog
  */
 require_once($CFG->dirroot .'/blog/rsslib.php');
-require_once($CFG->dirroot.'/tag/lib.php');
 
 /**
  * User can edit a blog entry if this is their own blog entry and they have
@@ -254,8 +253,8 @@ function blog_sync_external_entries($externalblog) {
             $id = $DB->insert_record('post', $newentry);
 
             // Set tags.
-            if ($tags = tag_get_tags_array('blog_external', $externalblog->id)) {
-                tag_set('post', $id, $tags, 'core', context_user::instance($externalblog->userid)->id);
+            if ($tags = core_tag_tag::get_item_tags_array('core', 'blog_external', $externalblog->id)) {
+                core_tag_tag::set_item_tags('core', 'post', $id, context_user::instance($externalblog->userid), $tags);
             }
         } else {
             $newentry->id = $postid;
@@ -1046,3 +1045,105 @@ function core_blog_myprofile_navigation(core_user\output\myprofile\tree $tree, $
     $tree->add_node($blognode);
     return true;
 }
+
+/**
+ * Returns posts tagged with a specified tag.
+ *
+ * @param core_tag_tag $tag
+ * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
+ *             are displayed on the page and the per-page limit may be bigger
+ * @param int $fromctx context id where the link was displayed, may be used by callbacks
+ *            to display items in the same context first
+ * @param int $ctx context id where to search for records
+ * @param bool $rec search in subcontexts as well
+ * @param int $page 0-based number of page being displayed
+ * @return \core_tag\output\tagindex
+ */
+function blog_get_tagged_posts($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = true, $page = 0) {
+    global $CFG, $OUTPUT;
+    require_once($CFG->dirroot.'/user/lib.php');
+
+    $systemcontext = context_system::instance();
+    $perpage = $exclusivemode ? 20 : 5;
+    $context = $ctx ? context::instance_by_id($ctx) : context_system::instance();
+
+    $content = '';
+    if (empty($CFG->enableblogs) || !has_capability('moodle/blog:view', $systemcontext)) {
+        // Blogs are not enabled or are not visible to the current user.
+        $totalpages = 0;
+    } else if ($context->contextlevel != CONTEXT_SYSTEM && empty($CFG->useblogassociations)) {
+        // No blog entries can be associated to the non-system context.
+        $totalpages = 0;
+    } else if (!$rec && $context->contextlevel != CONTEXT_COURSE && $context->contextlevel != CONTEXT_MODULE) {
+        // No blog entries can be associated with category or block context.
+        $totalpages = 0;
+    } else {
+        require_once($CFG->dirroot.'/blog/locallib.php');
+
+        $filters = array('tag' => $tag->id);
+        if ($rec) {
+            if ($context->contextlevel != CONTEXT_SYSTEM) {
+                $filters['context'] = $context->id;
+            }
+        } else if ($context->contextlevel == CONTEXT_COURSE) {
+            $filters['course'] = $context->instanceid;
+        } else if ($context->contextlevel == CONTEXT_MODULE) {
+            $filters['module'] = $context->instanceid;
+        }
+        $bloglisting = new blog_listing($filters);
+        $blogs = $bloglisting->get_entries($page * $perpage, $perpage);
+        $totalcount = $bloglisting->count_entries();
+        $totalpages = ceil($totalcount / $perpage);
+        if (!empty($blogs)) {
+            $tagfeed = new core_tag\output\tagfeed();
+            foreach ($blogs as $blog) {
+                $user = fullclone($blog);
+                $user->id = $blog->userid;
+                $user->deleted = 0;
+                $img = $OUTPUT->user_picture($user, array('size' => 35));
+                $subject = format_string($blog->subject);
+
+                if ($blog->publishstate == 'draft') {
+                    $class = 'dimmed';
+                } else {
+                    $class = '';
+                }
+
+                $url = new moodle_url('/blog/index.php', array('entryid' => $blog->id));
+                $subject = html_writer::link($url, $subject, array('class' => $class));
+
+                $fullname = fullname($user);
+                if (user_can_view_profile($user)) {
+                    $profilelink = new moodle_url('/user/view.php', array('id' => $blog->userid));
+                    $fullname = html_writer::link($profilelink, $fullname);
+                }
+                $details = $fullname . ', ' . userdate($blog->created);
+
+                $tagfeed->add($img, $subject, $details);
+            }
+
+            $items = $tagfeed->export_for_template($OUTPUT);
+            $content = $OUTPUT->render_from_template('core_tag/tagfeed', $items);
+
+            $urlparams = array('tagid' => $tag->id);
+            if ($context->contextlevel == CONTEXT_COURSE) {
+                $urlparams['courseid'] = $context->instanceid;
+            } else if ($context->contextlevel == CONTEXT_MODULE) {
+                $urlparams['modid'] = $context->instanceid;
+            }
+            $allblogsurl = new moodle_url('/blog/index.php', $urlparams);
+
+            $rv = new core_tag\output\tagindex($tag, 'core', 'post',
+                    $content,
+                    $exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
+            $rv->exclusiveurl = $allblogsurl;
+            return $rv;
+        }
+    }
+
+    $rv = new core_tag\output\tagindex($tag, 'core', 'post',
+            $content,
+            $exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
+    $rv->exclusiveurl = null;
+    return $rv;
+}
index 7968483..af1b72e 100644 (file)
@@ -256,14 +256,11 @@ class blog_entry implements renderable {
         // Insert the new blog entry.
         $this->id = $DB->insert_record('post', $this);
 
-        // Update tags.
-        $this->add_tags_info();
-
         if (!empty($CFG->useblogassociations)) {
             $this->add_associations();
         }
 
-        tag_set('post', $this->id, $this->tags, 'core', context_user::instance($this->userid)->id);
+        core_tag_tag::set_item_tags('core', 'post', $this->id, context_user::instance($this->userid), $this->tags);
 
         // Trigger an event for the new entry.
         $event = \core\event\blog_entry_created::create(array(
@@ -312,7 +309,7 @@ class blog_entry implements renderable {
 
         // Update record.
         $DB->update_record('post', $entry);
-        tag_set('post', $entry->id, $entry->tags, 'core', context_user::instance($this->userid)->id);
+        core_tag_tag::set_item_tags('core', 'post', $entry->id, context_user::instance($this->userid), $entry->tags);
 
         $event = \core\event\blog_entry_updated::create(array(
             'objectid'      => $entry->id,
@@ -336,7 +333,7 @@ class blog_entry implements renderable {
         // Get record to pass onto the event.
         $record = $DB->get_record('post', array('id' => $this->id));
         $DB->delete_records('post', array('id' => $this->id));
-        tag_set('post', $this->id, array(), 'core', context_user::instance($this->userid)->id);
+        core_tag_tag::remove_all_item_tags('core', 'post', $this->id);
 
         $event = \core\event\blog_entry_deleted::create(array(
             'objectid'      => $this->id,
@@ -424,26 +421,6 @@ class blog_entry implements renderable {
         $fs->delete_area_files(SYSCONTEXTID, 'blog', 'post', $this->id);
     }
 
-    /**
-     * function to attach tags into an entry
-     * @return void
-     */
-    public function add_tags_info() {
-
-        $tags = array();
-
-        if ($otags = optional_param('otags', '', PARAM_INT)) {
-            foreach ($otags as $tagid) {
-                // TODO : make this use the tag name in the form.
-                if ($tag = tag_get('id', $tagid)) {
-                    $tags[] = $tag->name;
-                }
-            }
-        }
-
-        tag_set('post', $this->id, $tags, 'core', context_user::instance($this->userid)->id);
-    }
-
     /**
      * User can edit a blog entry if this is their own blog entry and they have
      * the capability moodle/blog:create, or if they have the capability
@@ -570,7 +547,13 @@ class blog_listing {
      * Array of blog_entry objects.
      * @var array $entries
      */
-    public $entries = array();
+    public $entries = null;
+
+    /**
+     * Caches the total number of the entries.
+     * @var int
+     */
+    public $totalentries = null;
 
     /**
      * An array of blog_filter_* objects
@@ -608,9 +591,12 @@ class blog_listing {
     public function get_entries($start=0, $limit=10) {
         global $DB;
 
-        if (empty($this->entries)) {
+        if ($this->entries === null) {
             if ($sqlarray = $this->get_entry_fetch_sql(false, 'created DESC')) {
                 $this->entries = $DB->get_records_sql($sqlarray['sql'], $sqlarray['params'], $start, $limit);
+                if (!$start && count($this->entries) < $limit) {
+                    $this->totalentries = count($this->entries);
+                }
             } else {
                 return false;
             }
@@ -619,6 +605,23 @@ class blog_listing {
         return $this->entries;
     }
 
+    /**
+     * Finds total number of blog entries
+     *
+     * @return int
+     */
+    public function count_entries() {
+        global $DB;
+        if ($this->totalentries === null) {
+            if ($sqlarray = $this->get_entry_fetch_sql(true)) {
+                $this->totalentries = $DB->count_records_sql($sqlarray['sql'], $sqlarray['params']);
+            } else {
+                $this->totalentries = 0;
+            }
+        }
+        return $this->totalentries;
+    }
+
     public function get_entry_fetch_sql($count=false, $sort='lastmodified DESC', $userid = false) {
         global $DB, $USER, $CFG;
 
@@ -626,9 +629,9 @@ class blog_listing {
             $userid = $USER->id;
         }
 
-        $allnamefields = get_all_user_name_fields(true, 'u');
+        $allnamefields = \user_picture::fields('u', null, 'useridalias');
         // The query used to locate blog entries is complicated.  It will be built from the following components:
-        $requiredfields = "p.*, $allnamefields, u.email";  // The SELECT clause.
+        $requiredfields = "p.*, $allnamefields";  // The SELECT clause.
         $tables = array('p' => 'post', 'u' => 'user');   // Components of the FROM clause (table_id => table_name).
         // Components of the WHERE clause (conjunction).
         $conditions = array('u.deleted = 0', 'p.userid = u.id', '(p.module = \'blog\' OR p.module = \'blog_external\')');
@@ -707,13 +710,8 @@ class blog_listing {
 
         $morelink = '<br />&nbsp;&nbsp;';
 
-        if ($sqlarray = $this->get_entry_fetch_sql(true)) {
-            $totalentries = $DB->count_records_sql($sqlarray['sql'], $sqlarray['params']);
-        } else {
-            $totalentries = 0;
-        }
-
         $entries = $this->get_entries($start, $limit);
+        $totalentries = $this->count_entries();
         $pagingbar = new paging_bar($totalentries, $page, $limit, $this->get_baseurl());
         $pagingbar->pagevar = 'blogpage';
         $blogheaders = blog_get_headers();
@@ -909,13 +907,14 @@ class blog_filter_context extends blog_filter {
 
         $this->availabletypes = array('site' => get_string('site'),
                                       'course' => get_string('course'),
-                                      'module' => get_string('activity'));
+                                      'module' => get_string('activity'),
+                                      'context' => get_string('coresystem'));
 
         switch ($this->type) {
             case 'course': // Careful of site course!
                 // Ignore course filter if blog associations are not enabled.
                 if ($this->id != $SITE->id && !empty($CFG->useblogassociations)) {
-                    $this->overrides = array('site');
+                    $this->overrides = array('site', 'context');
                     $context = context_course::instance($this->id);
                     $this->tables['ba'] = 'blog_association';
                     $this->conditions[] = 'p.id = ba.blogid';
@@ -930,7 +929,7 @@ class blog_filter_context extends blog_filter {
                 break;
             case 'module':
                 if (!empty($CFG->useblogassociations)) {
-                    $this->overrides = array('course', 'site');
+                    $this->overrides = array('course', 'site', 'context');
 
                     $context = context_module::instance($this->id);
                     $this->tables['ba'] = 'blog_association';
@@ -939,6 +938,19 @@ class blog_filter_context extends blog_filter {
                     $this->params = array($context->id);
                 }
                 break;
+            case 'context':
+                if ($id != context_system::instance()->id && !empty($CFG->useblogassociations)) {
+                    $this->overrides = array('site');
+                    $context = context::instance_by_id($this->id);
+                    $this->tables['ba'] = 'blog_association';
+                    $this->tables['ctx'] = 'context';
+                    $this->conditions[] = 'p.id = ba.blogid';
+                    $this->conditions[] = 'ctx.id = ba.contextid';
+                    $this->conditions[] = 'ctx.path LIKE ?';
+                    $this->params = array($context->path . '%');
+                }
+                break;
+
         }
     }
 }
@@ -1012,6 +1024,7 @@ class blog_filter_tag extends blog_filter {
 
         $this->conditions = array('ti.tagid = t.id',
                                   "ti.itemtype = 'post'",
+                                  "ti.component = 'core'",
                                   'ti.itemid = p.id',
                                   't.id = ?');
         $this->params = array($this->id);
index 1045a89..6406865 100644 (file)
@@ -132,21 +132,7 @@ class core_blog_renderer extends plugin_renderer_base {
         }
 
         // Links to tags.
-        $officialtags = tag_get_tags_csv('post', $entry->id, TAG_RETURN_HTML, 'official');
-        $defaulttags = tag_get_tags_csv('post', $entry->id, TAG_RETURN_HTML, 'default');
-
-        if (!empty($CFG->usetags) && ($officialtags || $defaulttags) ) {
-            $o .= $this->output->container_start('tags');
-
-            if ($officialtags) {
-                $o .= get_string('tags', 'tag') .': '. $this->output->container($officialtags, 'officialblogtags');
-                if ($defaulttags) {
-                    $o .= ', ';
-                }
-            }
-            $o .= $defaulttags;
-            $o .= $this->output->container_end();
-        }
+        $o .= $this->output->tag_list(core_tag_tag::get_item_tags('core', 'post', $entry->id));
 
         // Add associations.
         if (!empty($CFG->useblogassociations) && !empty($entry->renderable->blogassociations)) {
index cad38d8..366c5cd 100644 (file)
@@ -217,10 +217,8 @@ function blog_rss_get_feed($context, $args) {
             $summary = file_rewrite_pluginfile_urls($blogentry->summary, 'pluginfile.php',
                 $sitecontext->id, 'blog', 'post', $blogentry->id);
             $item->description = format_text($summary, $blogentry->format);
-            if ( !empty($CFG->usetags) && ($blogtags = tag_get_tags_array('post', $blogentry->id)) ) {
-                if ($blogtags) {
-                    $item->tags = $blogtags;
-                }
+            if ($blogtags = core_tag_tag::get_item_tags_array('core', 'post', $blogentry->id)) {
+                $item->tags = $blogtags;
                 $item->tagscheme = $CFG->wwwroot . '/tag';
             }
             $items[] = $item;
similarity index 78%
rename from blog/tests/bloglib_test.php
rename to blog/tests/lib_test.php
index 73c81f2..81eac30 100644 (file)
@@ -30,7 +30,7 @@ require_once($CFG->dirroot . '/blog/lib.php');
 /**
  * Test functions that rely on the DB tables
  */
-class core_bloglib_testcase extends advanced_testcase {
+class core_blog_lib_testcase extends advanced_testcase {
 
     private $courseid;
     private $cmid;
@@ -65,18 +65,15 @@ class core_bloglib_testcase extends advanced_testcase {
         ));
 
         // Create default tag.
-        $tag = new stdClass();
-        $tag->userid = $user->id;
-        $tag->name = 'testtagname';
-        $tag->rawname = 'Testtagname';
-        $tag->tagtype = 'official';
-        $tag->id = $DB->insert_record('tag', $tag);
+        $tag = $this->getDataGenerator()->create_tag(array('userid' => $user->id,
+            'rawname' => 'Testtagname', 'tagtype' => 'official'));
 
         // Create default post.
         $post = new stdClass();
         $post->userid = $user->id;
         $post->groupid = $group->id;
         $post->content = 'test post content text';
+        $post->module = 'blog';
         $post->id = $DB->insert_record('post', $post);
 
         // Grab important ids.
@@ -476,5 +473,134 @@ class core_bloglib_testcase extends advanced_testcase {
         $this->assertEquals($url, $event->get_url());
         $this->assertEventContextNotUsed($event);
     }
+
+    /**
+     * Tests the core_blog_myprofile_navigation() function.
+     */
+    public function test_core_blog_myprofile_navigation() {
+        global $USER;
+
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $this->setAdminUser();
+        $iscurrentuser = true;
+        $course = null;
+
+        // Enable blogs.
+        set_config('enableblogs', true);
+
+        // Check the node tree is correct.
+        core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayHasKey('blogs', $nodes->getValue($tree));
+    }
+
+    /**
+     * Tests the core_blog_myprofile_navigation() function as a guest.
+     */
+    public function test_core_blog_myprofile_navigation_as_guest() {
+        global $USER;
+
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $iscurrentuser = false;
+        $course = null;
+
+        // Set user as guest.
+        $this->setGuestUser();
+
+        // Check the node tree is correct.
+        core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayNotHasKey('blogs', $nodes->getValue($tree));
+    }
+
+    /**
+     * Tests the core_blog_myprofile_navigation() function when blogs are disabled.
+     */
+    public function test_core_blog_myprofile_navigation_blogs_disabled() {
+        global $USER;
+
+        // Set up the test.
+        $tree = new \core_user\output\myprofile\tree();
+        $this->setAdminUser();
+        $iscurrentuser = false;
+        $course = null;
+
+        // Disable blogs.
+        set_config('enableblogs', false);
+
+        // Check the node tree is correct.
+        core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
+        $reflector = new ReflectionObject($tree);
+        $nodes = $reflector->getProperty('nodes');
+        $nodes->setAccessible(true);
+        $this->assertArrayNotHasKey('blogs', $nodes->getValue($tree));
+    }
+
+    public function test_blog_get_listing_course() {
+        $this->setAdminUser();
+        $coursecontext = context_course::instance($this->courseid);
+        $anothercourse = $this->getDataGenerator()->create_course();
+
+        // Add blog associations with a course.
+        $blog = new blog_entry($this->postid);
+        $blog->add_association($coursecontext->id);
+
+        // There is one entry associated with a course.
+        $bloglisting = new blog_listing(array('course' => $this->courseid));
+        $this->assertCount(1, $bloglisting->get_entries());
+
+        // There is no entry associated with a wrong course.
+        $bloglisting = new blog_listing(array('course' => $anothercourse->id));
+        $this->assertCount(0, $bloglisting->get_entries());
+
+        // There is no entry associated with a module.
+        $bloglisting = new blog_listing(array('module' => $this->cmid));
+        $this->assertCount(0, $bloglisting->get_entries());
+
+        // There is one entry associated with a site (id is ignored).
+        $bloglisting = new blog_listing(array('site' => 12345));
+        $this->assertCount(1, $bloglisting->get_entries());
+
+        // There is one entry associated with course context.
+        $bloglisting = new blog_listing(array('context' => $coursecontext->id));
+        $this->assertCount(1, $bloglisting->get_entries());
+    }
+
+    public function test_blog_get_listing_module() {
+        $this->setAdminUser();
+        $coursecontext = context_course::instance($this->courseid);
+        $contextmodule = context_module::instance($this->cmid);
+        $anothermodule = $this->getDataGenerator()->create_module('page', array('course' => $this->courseid));
+
+        // Add blog associations with a course.
+        $blog = new blog_entry($this->postid);
+        $blog->add_association($contextmodule->id);
+
+        // There is no entry associated with a course.
+        $bloglisting = new blog_listing(array('course' => $this->courseid));
+        $this->assertCount(0, $bloglisting->get_entries());
+
+        // There is one entry associated with a module.
+        $bloglisting = new blog_listing(array('module' => $this->cmid));
+        $this->assertCount(1, $bloglisting->get_entries());
+
+        // There is no entry associated with a wrong module.
+        $bloglisting = new blog_listing(array('module' => $anothermodule->cmid));
+        $this->assertCount(0, $bloglisting->get_entries());
+
+        // There is one entry associated with a site (id is ignored).
+        $bloglisting = new blog_listing(array('site' => 12345));
+        $this->assertCount(1, $bloglisting->get_entries());
+
+        // There is one entry associated with course context (module is a subcontext of a course).
+        $bloglisting = new blog_listing(array('context' => $coursecontext->id));
+        $this->assertCount(1, $bloglisting->get_entries());
+    }
 }
 
index 5a40c69..184997e 100644 (file)
@@ -338,7 +338,18 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
             $class = 'day';
         }
 
-        if (isset($eventsbyday[$day])) {
+        $eventids = array();
+        if (!empty($eventsbyday[$day])) {
+            $eventids = $eventsbyday[$day];
+        }
+
+        if (!empty($durationbyday[$day])) {
+            $eventids = array_unique(array_merge($eventids, $durationbyday[$day]));
+        }
+
+        $finishclass = false;
+
+        if (!empty($eventids)) {
             // There is at least one event on this day.
 
             $class .= ' hasevent';
@@ -346,7 +357,7 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
             $dayhref = calendar_get_link_href(new moodle_url(CALENDAR_URL . 'view.php', $hrefparams), 0, 0, 0, $daytime);
 
             $popupcontent = '';
-            foreach($eventsbyday[$day] as $eventid) {
+            foreach ($eventids as $eventid) {
                 if (!isset($events[$eventid])) {
                     continue;
                 }
@@ -367,26 +378,47 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
                     $popupicon = 'i/userevent';
                 }
 
+                if ($event->timeduration) {
+                    $startdate = $calendartype->timestamp_to_date_array($event->timestart);
+                    $enddate = $calendartype->timestamp_to_date_array($event->timestart + $event->timeduration - 1);
+                    if ($enddate['mon'] == $m && $enddate['year'] == $y && $enddate['mday'] == $day) {
+                        $finishclass = true;
+                    }
+                }
+
                 $dayhref->set_anchor('event_'.$event->id);
 
                 $popupcontent .= html_writer::start_tag('div');
                 $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component);
-                $name = format_string($event->name, true);
                 // Show ical source if needed.
                 if (!empty($event->subscription) && $CFG->calendar_showicalsource) {
                     $a = new stdClass();
-                    $a->name = $name;
+                    $a->name = format_string($event->name, true);
                     $a->source = $event->subscription->name;
                     $name = get_string('namewithsource', 'calendar', $a);
+                } else {
+                    if ($finishclass) {
+                        $samedate = $startdate['mon'] == $enddate['mon'] &&
+                                    $startdate['year'] == $enddate['year'] &&
+                                    $startdate['mday'] == $enddate['mday'];
+
+                        if ($samedate) {
+                            $name = format_string($event->name, true);
+                        } else {
+                            $name = format_string($event->name, true) . ' (' . get_string('eventendtime', 'calendar') . ')';
+                        }
+                    } else {
+                        $name = format_string($event->name, true);
+                    }
                 }
                 $popupcontent .= html_writer::link($dayhref, $name);
                 $popupcontent .= html_writer::end_tag('div');
             }
 
             if ($display->thismonth && $day == $d) {
-                $popupdata = calendar_get_popup(true, $events[$eventid]->timestart, $popupcontent);
+                $popupdata = calendar_get_popup(true, $daytime, $popupcontent);
             } else {
-                $popupdata = calendar_get_popup(false, $events[$eventid]->timestart, $popupcontent);
+                $popupdata = calendar_get_popup(false, $daytime, $popupcontent);
             }
             $cellattributes = array_merge($cellattributes, $popupdata);
 
@@ -400,6 +432,9 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
             } else if(isset($typesbyday[$day]['startuser'])) {
                 $class .= ' calendar_event_user';
             }
+            if ($finishclass) {
+                $class .= ' duration_finish';
+            }
             $cell = html_writer::link($dayhref, $day);
         } else {
             $cell = $day;
@@ -439,7 +474,7 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
             $class .= ' today';
             $today = get_string('today', 'calendar').' '.userdate(time(), get_string('strftimedayshort'));
 
-            if (!isset($eventsbyday[$day])) {
+            if (!isset($eventsbyday[$day]) && !isset($durationbyday[$day])) {
                 $class .= ' eventnone';
                 $popupdata = calendar_get_popup(true, false);
                 $cellattributes = array_merge($cellattributes, $popupdata);
index 505413d..fdff4bd 100644<