Merge branch 'MDL-66113-master' of git://github.com/jleyva/moodle
authorSara Arjona <sara@moodle.com>
Tue, 17 Sep 2019 10:03:42 +0000 (12:03 +0200)
committerSara Arjona <sara@moodle.com>
Tue, 17 Sep 2019 10:03:42 +0000 (12:03 +0200)
lib/amd/build/paged_content_factory.min.js
lib/amd/build/paged_content_factory.min.js.map
lib/amd/build/paged_content_paging_bar.min.js
lib/amd/build/paged_content_paging_bar.min.js.map
lib/amd/src/paged_content_factory.js
lib/amd/src/paged_content_paging_bar.js
lib/templates/paged_content_paging_bar.mustache
mod/forum/externallib.php
mod/forum/tests/externallib_test.php

index 7988e3d..349aade 100644 (file)
Binary files a/lib/amd/build/paged_content_factory.min.js and b/lib/amd/build/paged_content_factory.min.js differ
index a3c86aa..9c4ea67 100644 (file)
Binary files a/lib/amd/build/paged_content_factory.min.js.map and b/lib/amd/build/paged_content_factory.min.js.map differ
index b13819d..ef384a4 100644 (file)
Binary files a/lib/amd/build/paged_content_paging_bar.min.js and b/lib/amd/build/paged_content_paging_bar.min.js differ
index 74e3b7c..4cdfb62 100644 (file)
Binary files a/lib/amd/build/paged_content_paging_bar.min.js.map and b/lib/amd/build/paged_content_paging_bar.min.js.map differ
index 793fe32..577ccec 100644 (file)
@@ -144,6 +144,7 @@ function(
             context.pages.push(page);
         }
 
+        context.barsize = 10;
         return context;
     };
 
index 4b693b7..fed32da 100644 (file)
  * @copyright  2018 Ryan Wyllie <ryan@moodle.com>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-define(
-    [
-        'jquery',
-        'core/custom_interaction_events',
-        'core/paged_content_events',
-        'core/str',
-        'core/pubsub'
-    ],
-    function(
-        $,
-        CustomEvents,
-        PagedContentEvents,
-        Str,
-        PubSub
-    ) {
+define([
+    'jquery',
+    'core/custom_interaction_events',
+    'core/paged_content_events',
+    'core/str',
+    'core/pubsub'
+],
+function(
+    $,
+    CustomEvents,
+    PagedContentEvents,
+    Str,
+    PubSub
+) {
 
     var SELECTORS = {
         ROOT: '[data-region="paging-bar"]',
@@ -44,7 +43,10 @@ define(
         FIRST_BUTTON: '[data-control="first"]',
         LAST_BUTTON: '[data-control="last"]',
         NEXT_BUTTON: '[data-control="next"]',
-        PREVIOUS_BUTTON: '[data-control="previous"]'
+        PREVIOUS_BUTTON: '[data-control="previous"]',
+        DOTS_BUTTONS: '[data-dots]',
+        BEGINNING_DOTS_BUTTON: '[data-dots="beginning"]',
+        ENDING_DOTS_BUTTON: '[data-dots="ending"]',
     };
 
     /**
@@ -259,6 +261,61 @@ define(
         firstButton.attr('aria-disabled', true);
     };
 
+    /**
+     * Adjusts the size of the paging bar and hides unnecessary pages.
+     *
+     * @param {object} root The root element.
+     */
+    var adjustPagingBarSize = function(root) {
+        var activePageNumber = getActivePageNumber(root);
+        var lastPageNumber = getLastPageNumber(root);
+
+        var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);
+        var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);
+        var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);
+
+        var pages = root.find(SELECTORS.PAGE);
+        var barSize = parseInt(root.attr('data-bar-size'), 10);
+
+        if (barSize && lastPageNumber > barSize) {
+
+            var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);
+            var maxpage = minpage + barSize - 1;
+
+            if (maxpage >= lastPageNumber) {
+                maxpage = lastPageNumber;
+                minpage = maxpage - barSize + 1;
+            }
+
+            if (minpage > 1) {
+                show(beginningDotsButton);
+                minpage++;
+            } else {
+                hide(beginningDotsButton);
+            }
+            if (maxpage < lastPageNumber) {
+                show(endingDotsButton);
+                maxpage--;
+            } else {
+                hide(endingDotsButton);
+            }
+            dotsButtons.addClass('disabled');
+            dotsButtons.attr('aria-disabled', true);
+
+            hide(pages);
+
+            pages.each(function(index, page) {
+                page = $(page);
+                if ((index + 1) >= minpage && (index + 1) <= maxpage) {
+                    show(page);
+                }
+            });
+
+        } else {
+            hide(dotsButtons);
+        }
+    };
+
     /**
      * Enable the previous and first buttons in the paging bar.
      *
@@ -407,6 +464,8 @@ define(
             page.addClass('active');
             page.attr('aria-current', true);
             setActivePageNumber(root, pageNumber);
+
+            adjustPagingBarSize(root);
         }
 
         // Make sure the control buttons are disabled as the user navigates
@@ -546,6 +605,8 @@ define(
             // the next button. This allows the infinite pagination to work.
             getNextButton(root).click();
         }
+
+        adjustPagingBarSize(root);
     };
 
     return {
index f9ce56a..b0b84f1 100644 (file)
         {{^arialabels.paginationactivenavitemcomponents}}
             data-aria-label-components-pagination-active-item="pagedcontentnavigationactiveitem, core"
         {{/arialabels.paginationactivenavitemcomponents}}
+        {{#barsize}}
+            data-bar-size="{{.}}"
+        {{/barsize}}
     >
 
         <ul class="pagination mb-0">
                     {{$attributes}}data-control="first"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/first}}
+            {{#barsize}}
+                {{< core/paged_content_paging_bar_item }}
+                    {{$item-content}}
+                        <span aria-hidden="true">&hellip;</span>
+                    {{/item-content}}
+                    {{$attributes}}data-dots="beginning"{{/attributes}}
+                {{/ core/paged_content_paging_bar_item }}
+            {{/barsize}}
             {{#pages}}
                 {{< core/paged_content_paging_bar_item }}
                     {{$attributes}}data-page="true"{{/attributes}}
                 {{/ core/paged_content_paging_bar_item }}
             {{/pages}}
+            {{#barsize}}
+                {{< core/paged_content_paging_bar_item }}
+                    {{$item-content}}
+                        <span aria-hidden="true">&hellip;</span>
+                    {{/item-content}}
+                    {{$attributes}}data-dots="ending"{{/attributes}}
+                {{/ core/paged_content_paging_bar_item }}
+            {{/barsize}}
             {{#last}}
                 {{< core/paged_content_paging_bar_item }}
                     {{$item-content}}
index 5a6fb60..04fb63c 100644 (file)
@@ -413,8 +413,10 @@ class mod_forum_external extends external_api {
 
             $post->subject = external_format_string($post->subject, $modcontext->id);
             // Rewrite embedded images URLs.
+            $options = array('trusted' => $post->messagetrust);
             list($post->message, $post->messageformat) =
-                external_format_text($post->message, $post->messageformat, $modcontext->id, 'mod_forum', 'post', $post->id);
+                external_format_text($post->message, $post->messageformat, $modcontext->id, 'mod_forum', 'post', $post->id,
+                    $options);
 
             // List attachments.
             if (!empty($post->attachment)) {
@@ -626,9 +628,10 @@ class mod_forum_external extends external_api {
                 $discussion->name = external_format_string($discussion->name, $modcontext->id);
                 $discussion->subject = external_format_string($discussion->subject, $modcontext->id);
                 // Rewrite embedded images URLs.
+                $options = array('trusted' => $discussion->messagetrust);
                 list($discussion->message, $discussion->messageformat) =
                     external_format_text($discussion->message, $discussion->messageformat,
-                                            $modcontext->id, 'mod_forum', 'post', $discussion->id);
+                                            $modcontext->id, 'mod_forum', 'post', $discussion->id, $options);
 
                 // List attachments.
                 if (!empty($discussion->attachment)) {
@@ -925,9 +928,10 @@ class mod_forum_external extends external_api {
                 $discussionobject->name = external_format_string($discussion->get_name(), $modcontext->id);
                 $discussionobject->subject = external_format_string($discussionobject->subject, $modcontext->id);
                 // Rewrite embedded images URLs.
+                $options = array('trusted' => $discussionobject->messagetrust);
                 list($discussionobject->message, $discussionobject->messageformat) =
                     external_format_text($discussionobject->message, $discussionobject->messageformat,
-                        $modcontext->id, 'mod_forum', 'post', $discussionobject->id);
+                        $modcontext->id, 'mod_forum', 'post', $discussionobject->id, $options);
 
                 // List attachments.
                 if (!empty($discussionobject->attachment)) {
index 97db997..28cafe8 100644 (file)
@@ -2354,4 +2354,130 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
                 ],
             ]);
     }
+
+    /**
+     * Test trusted text enabled.
+     */
+    public function test_trusted_text_enabled() {
+        global $USER, $CFG;
+
+        $this->resetAfterTest(true);
+        $CFG->enabletrusttext = 1;
+
+        $dangeroustext = '<button>Untrusted text</button>';
+        $cleantext = 'Untrusted text';
+
+        // Create courses to add the modules.
+        $course = self::getDataGenerator()->create_course();
+        $user1 = self::getDataGenerator()->create_user();
+
+        // First forum with tracking off.
+        $record = new stdClass();
+        $record->course = $course->id;
+        $record->type = 'qanda';
+        $forum = self::getDataGenerator()->create_module('forum', $record);
+        $context = context_module::instance($forum->cmid);
+
+        // Add discussions to the forums.
+        $discussionrecord = new stdClass();
+        $discussionrecord->course = $course->id;
+        $discussionrecord->userid = $user1->id;
+        $discussionrecord->forum = $forum->id;
+        $discussionrecord->message = $dangeroustext;
+        $discussionrecord->messagetrust  = trusttext_trusted($context);
+        $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($discussionrecord);
+
+        self::setAdminUser();
+        $discussionrecord->userid = $USER->id;
+        $discussionrecord->messagetrust  = trusttext_trusted($context);
+        $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($discussionrecord);
+
+        $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
+        $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
+
+        $this->assertCount(2, $discussions['discussions']);
+        $this->assertCount(0, $discussions['warnings']);
+        // Admin message is fully trusted.
+        $this->assertEquals(1, $discussions['discussions'][0]['messagetrust']);
+        $this->assertEquals($dangeroustext, $discussions['discussions'][0]['message']);
+        // Student message is not trusted.
+        $this->assertEquals(0, $discussions['discussions'][1]['messagetrust']);
+        $this->assertEquals($cleantext, $discussions['discussions'][1]['message']);
+
+        // Get posts now.
+        $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id);
+        $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+        // Admin message is fully trusted.
+        $this->assertEquals(1, $posts['posts'][0]['messagetrust']);
+        $this->assertEquals($dangeroustext, $posts['posts'][0]['message']);
+
+        $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id);
+        $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+        // Student message is not trusted.
+        $this->assertEquals(0, $posts['posts'][0]['messagetrust']);
+        $this->assertEquals($cleantext, $posts['posts'][0]['message']);
+    }
+
+    /**
+     * Test trusted text disabled.
+     */
+    public function test_trusted_text_disabled() {
+        global $USER, $CFG;
+
+        $this->resetAfterTest(true);
+        $CFG->enabletrusttext = 0;
+
+        $dangeroustext = '<button>Untrusted text</button>';
+        $cleantext = 'Untrusted text';
+
+        // Create courses to add the modules.
+        $course = self::getDataGenerator()->create_course();
+        $user1 = self::getDataGenerator()->create_user();
+
+        // First forum with tracking off.
+        $record = new stdClass();
+        $record->course = $course->id;
+        $record->type = 'qanda';
+        $forum = self::getDataGenerator()->create_module('forum', $record);
+        $context = context_module::instance($forum->cmid);
+
+        // Add discussions to the forums.
+        $discussionrecord = new stdClass();
+        $discussionrecord->course = $course->id;
+        $discussionrecord->userid = $user1->id;
+        $discussionrecord->forum = $forum->id;
+        $discussionrecord->message = $dangeroustext;
+        $discussionrecord->messagetrust  = trusttext_trusted($context);
+        $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($discussionrecord);
+
+        self::setAdminUser();
+        $discussionrecord->userid = $USER->id;
+        $discussionrecord->messagetrust  = trusttext_trusted($context);
+        $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($discussionrecord);
+
+        $discussions = mod_forum_external::get_forum_discussions($forum->id);
+        $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_returns(), $discussions);
+
+        $this->assertCount(2, $discussions['discussions']);
+        $this->assertCount(0, $discussions['warnings']);
+        // Admin message is not trusted because enabletrusttext is disabled.
+        $this->assertEquals(0, $discussions['discussions'][0]['messagetrust']);
+        $this->assertEquals($cleantext, $discussions['discussions'][0]['message']);
+        // Student message is not trusted.
+        $this->assertEquals(0, $discussions['discussions'][1]['messagetrust']);
+        $this->assertEquals($cleantext, $discussions['discussions'][1]['message']);
+
+        // Get posts now.
+        $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id);
+        $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+        // Admin message is not trusted because enabletrusttext is disabled.
+        $this->assertEquals(0, $posts['posts'][0]['messagetrust']);
+        $this->assertEquals($cleantext, $posts['posts'][0]['message']);
+
+        $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id);
+        $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
+        // Student message is not trusted.
+        $this->assertEquals(0, $posts['posts'][0]['messagetrust']);
+        $this->assertEquals($cleantext, $posts['posts'][0]['message']);
+    }
 }