Merge branch 'MDL-54592-master' of git://github.com/vmdef/moodle
authorAdrian Greeve <abgreeve@gmail.com>
Tue, 19 Mar 2019 03:02:28 +0000 (11:02 +0800)
committerAdrian Greeve <abgreeve@gmail.com>
Tue, 19 Mar 2019 03:02:28 +0000 (11:02 +0800)
18 files changed:
admin/tool/customlang/classes/output/renderer.php [new file with mode: 0644]
admin/tool/customlang/classes/output/translator.php [new file with mode: 0644]
admin/tool/customlang/renderer.php [deleted file]
admin/tool/customlang/styles.css [deleted file]
admin/tool/customlang/templates/translator.mustache [new file with mode: 0644]
admin/tool/policy/classes/output/page_agreedocs.php
admin/tool/policy/tests/behat/acceptances.feature
badges/index.php
blocks/myoverview/lang/en/block_myoverview.php
blocks/myoverview/lang/en/deprecated.txt
blocks/myoverview/templates/progress-bar.mustache
mod/forum/db/services.php
mod/forum/externallib.php
mod/forum/tests/externallib_test.php
mod/forum/version.php
repository/nextcloud/lang/en/repository_nextcloud.php
theme/boost/scss/moodle/core.scss
theme/boost/style/moodle.css

diff --git a/admin/tool/customlang/classes/output/renderer.php b/admin/tool/customlang/classes/output/renderer.php
new file mode 100644 (file)
index 0000000..b183daf
--- /dev/null
@@ -0,0 +1,64 @@
+<?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/>.
+
+/**
+ * Renderer class for tool customlang
+ *
+ * @package     tool_customlang
+ * @category    output
+ * @copyright   2019 Bas Brands <bas@moodle.com>
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_customlang\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+
+/**
+ * Renderer for the customlang tool.
+ *
+ * @copyright 2019 Bas Brands <bas@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class renderer extends \plugin_renderer_base {
+
+    /**
+     * Defer to template.
+     *
+     * @param tool_customlang_translator $translator
+     * @return string Html for the translator
+     */
+    protected function render_tool_customlang_translator(\tool_customlang_translator $translator) {
+        $renderabletranslator = new translator($translator);
+        $templatevars = $renderabletranslator->export_for_template($this);
+        return $this->render_from_template('tool_customlang/translator', $templatevars);
+    }
+
+    /**
+     * Defer to template.
+     *
+     * @param tool_customlang_menu $menu
+     * @return string html the customlang menu buttons
+     */
+    protected function render_tool_customlang_menu(\tool_customlang_menu $menu) {
+        $output = '';
+        foreach ($menu->get_items() as $item) {
+            $output .= $this->single_button($item->url, $item->title, $item->method);
+        }
+        return $this->box($output, 'menu');
+    }
+}
diff --git a/admin/tool/customlang/classes/output/translator.php b/admin/tool/customlang/classes/output/translator.php
new file mode 100644 (file)
index 0000000..9b7ac7d
--- /dev/null
@@ -0,0 +1,93 @@
+<?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/>.
+
+/**
+ * customlang specific renderers.
+ *
+ * @package   tool_customlang
+ * @copyright 2019 Moodle
+ * @author    Bas Brands
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace tool_customlang\output;
+
+defined('MOODLE_INTERNAL') || die();
+
+use renderable;
+use templatable;
+use renderer_base;
+use stdClass;
+
+/**
+ * Class containing data for customlang translator page
+ *
+ * @copyright  2019 Bas Brands
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class translator implements renderable, templatable {
+
+    /**
+     * @var tool_customlang_translator $translator object.
+     */
+    private $translator;
+
+    /**
+     * Construct this renderable.
+     *
+     * @param tool_customlang_translator $translator The translator object.
+     */
+    public function __construct(\tool_customlang_translator $translator) {
+        $this->translator = $translator;
+    }
+
+    /**
+     * Export the data.
+     *
+     * @param renderer_base $output
+     * @return stdClass
+     */
+    public function export_for_template(renderer_base $output) {
+        $data = new stdClass();
+
+        $data->nostrings = $output->notification(get_string('nostringsfound', 'tool_customlang'));
+        $data->formurl = $this->translator->handler;
+        $data->currentpage = $this->translator->currentpage;
+        $data->sesskey = sesskey();
+        $data->strings = [];
+
+        if (!empty($this->translator->strings)) {
+            $data->hasstrings = true;
+            foreach ($this->translator->strings as $string) {
+                // Find strings that use placeholders.
+                if (preg_match('/\{\$a(->.+)?\}/', $string->master)) {
+                    $string->placeholderhelp = $output->help_icon('placeholder', 'tool_customlang',
+                            get_string('placeholderwarning', 'tool_customlang'));
+                }
+                if (!is_null($string->local) and $string->outdated) {
+                    $string->outdatedhelp = $output->help_icon('markinguptodate', 'tool_customlang');
+                    $string->checkupdated = true;
+                }
+                if ($string->original !== $string->master) {
+                    $string->showoriginalvsmaster = true;
+                }
+                $string->local = s($string->local);
+                $data->strings[] = $string;
+            }
+        }
+        return $data;
+    }
+}
\ No newline at end of file
diff --git a/admin/tool/customlang/renderer.php b/admin/tool/customlang/renderer.php
deleted file mode 100644 (file)
index aea7fd6..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Output rendering of Language customization admin tool
- *
- * @package    tool
- * @subpackage customlang
- * @copyright  2010 David Mudrak <david@moodle.com>
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-/**
- * Rendering methods for the tool widgets
- */
-class tool_customlang_renderer extends plugin_renderer_base {
-
-    /**
-     * Renders customlang tool menu
-     *
-     * @return string HTML
-     */
-    protected function render_tool_customlang_menu(tool_customlang_menu $menu) {
-        $output = '';
-        foreach ($menu->get_items() as $item) {
-            $output .= $this->single_button($item->url, $item->title, $item->method);
-        }
-        return $this->box($output, 'menu');
-    }
-
-    /**
-     * Renders customlang translation table
-     *
-     * @param tool_customlang_translator $translator
-     * @return string HTML
-     */
-    protected function render_tool_customlang_translator(tool_customlang_translator $translator) {
-        $output = '';
-
-        if (empty($translator->strings)) {
-            return $this->notification(get_string('nostringsfound', 'tool_customlang'));
-        }
-
-        $table = new html_table();
-        $table->id = 'translator';
-        $table->head = array(
-            get_string('headingcomponent', 'tool_customlang'),
-            get_string('headingstringid', 'tool_customlang'),
-            get_string('headingstandard', 'tool_customlang'),
-            get_string('headinglocal', 'tool_customlang'),
-        );
-
-        foreach ($translator->strings as $string) {
-            $cells = array();
-            // component name
-            $cells[0] = new html_table_cell($string->component);
-            $cells[0]->attributes['class'] = 'component';
-            // string identification code
-            $cells[1] = new html_table_cell(html_writer::tag('div', s($string->stringid), array('class' => 'stringid')));
-            $cells[1]->attributes['class'] = 'stringid';
-            // master translation of the string
-            $master = html_writer::tag('div', s($string->master), array('class' => 'preformatted'));
-            $minheight = strlen($string->master) / 200;
-            if (preg_match('/\{\$a(->.+)?\}/', $string->master)) {
-                $master .= html_writer::tag('div', $this->help_icon('placeholder', 'tool_customlang',
-                        get_string('placeholderwarning', 'tool_customlang')), array('class' => 'placeholderinfo'));
-            }
-            $cells[2] = new html_table_cell($master);
-            $cells[2]->attributes['class'] = 'standard master';
-            // local customization of the string
-            $textareaattributes = array('name'=>'cust['.$string->id.']', 'cols'=>40, 'rows'=>3);
-            if ($minheight>1) {
-               $textareaattributes['style'] = 'min-height:' . (int) 4*$minheight . 'em;';
-            }
-            $textarea = html_writer::tag('textarea', s($string->local), $textareaattributes);
-            $cells[3] = new html_table_cell($textarea);
-            if (!is_null($string->local) and $string->outdated) {
-                $mark  = html_writer::empty_tag('input', array('type' => 'checkbox', 'id' => 'update_' . $string->id,
-                                                               'name' => 'updates[]', 'value' => $string->id));
-                $help  = $this->help_icon('markinguptodate', 'tool_customlang');
-                $mark .= html_writer::tag('label', get_string('markuptodate', 'tool_customlang') . $help,
-                                          array('for' => 'update_' . $string->id));
-                $mark  = html_writer::tag('div', $mark, array('class' => 'uptodatewrapper'));
-            } else {
-                $mark  = '';
-            }
-            $cells[3] = new html_table_cell($textarea."\n".$mark);
-            $cells[3]->attributes['class'] = 'local';
-            $cells[3]->id = 'id_'.$string->id;
-            if (!is_null($string->local)) {
-                $cells[3]->attributes['class'] .= ' customized';
-            }
-            if ($string->outdated) {
-                $cells[3]->attributes['class'] .= ' outdated';
-            }
-            if ($string->modified) {
-                $cells[3]->attributes['class'] .= ' modified';
-            }
-
-            if ($string->original !== $string->master) {
-                $cells[0]->rowspan = $cells[1]->rowspan = $cells[3]->rowspan = 2;
-            }
-
-            $row = new html_table_row($cells);
-            $table->data[] = $row;
-
-            if ($string->original !== $string->master) {
-                $cells = array();
-                // original of the string
-                $cells[2] = new html_table_cell(html_writer::tag('div', s($string->original), array('class' => 'preformatted')));
-                $cells[2]->attributes['class'] = 'standard original';
-                $row = new html_table_row($cells);
-                $table->data[] = $row;
-            }
-        }
-
-        $output .= html_writer::start_tag('form', array('method'=>'post', 'action'=>$translator->handler->out()));
-        $output .= html_writer::start_tag('div');
-        $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'translatorsubmitted', 'value'=>1));
-        $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey()));
-        $output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'p', 'value'=>$translator->currentpage));
-        $save1   = html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'savecontinue',
-            'value' => get_string('savecontinue', 'tool_customlang'), 'class' => 'btn btn-secondary'));
-        $save2   = html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'savecheckin',
-            'value' => get_string('savecheckin', 'tool_customlang'), 'class' => 'btn btn-secondary'));
-        $output .= html_writer::tag('fieldset', $save1 . ' ' . $save2, array('class' => 'buttonsbar'));
-        $output .= html_writer::table($table);
-        $output .= html_writer::tag('fieldset', $save1 . ' ' . $save2, array('class' => 'buttonsbar'));
-        $output .= html_writer::end_tag('div');
-        $output .= html_writer::end_tag('form');
-
-        return $output;
-    }
-}
diff --git a/admin/tool/customlang/styles.css b/admin/tool/customlang/styles.css
deleted file mode 100644 (file)
index 9f9fa98..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-.path-admin-tool-customlang .langselectorbox,
-.path-admin-tool-customlang fieldset.buttonsbar,
-.path-admin-tool-customlang .menu {
-    margin: 5px auto;
-    text-align: center;
-}
-
-.path-admin-tool-customlang .menu .singlebutton,
-.path-admin-tool-customlang .menu .singlebutton form,
-.path-admin-tool-customlang .menu .singlebutton form div {
-    display: inline;
-}
-
-.path-admin-tool-customlang .mform.filterform {
-    width: 70%;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.path-admin-tool-customlang .mform.filterform .fitem .fitemtitle {
-    width: 30%;
-}
-
-.path-admin-tool-customlang .mform.filterform .fitem .felement {
-    width: 60%;
-    margin-left: 31%;
-}
-
-.path-admin-tool-customlang #translator {
-    width: 100%;
-}
-
-.path-admin-tool-customlang #translator .standard,
-.path-admin-tool-customlang #translator .local {
-    min-width: 35%;
-}
-
-.path-admin-tool-customlang #translator .customized {
-    background-color: #e7f1c3;
-}
-
-.path-admin-tool-customlang #translator .customized.outdated {
-    background-color: #f3f2aa;
-}
-
-.path-admin-tool-customlang #translator .modified {
-    background-color: #ffd3d9;
-}
-
-.path-admin-tool-customlang #translator .customized.modified {
-    background-color: #d2ebff;
-}
-
-.path-admin-tool-customlang #translator textarea {
-    width: 100%;
-    min-height: 4em;
-}
-
-.path-admin-tool-customlang #translator .placeholderinfo {
-    text-align: center;
-    border: 1px dotted #ddd;
-    background-color: #f6f6f6;
-    margin-top: 0.5em;
-}
-
-#page-admin-tool-customlang-index .continuebutton {
-    margin-top: 1em;
-}
-
-.path-admin-tool-customlang #translator .standard.master.cell.c2 {
-    word-break: break-all;
-}
diff --git a/admin/tool/customlang/templates/translator.mustache b/admin/tool/customlang/templates/translator.mustache
new file mode 100644 (file)
index 0000000..8864f83
--- /dev/null
@@ -0,0 +1,150 @@
+{{!
+    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 tool_customlang/translator
+
+    Template for the custom language translator page.
+
+    Classes required for JS:
+    -
+
+    Data attributes required for JS:
+    -
+
+    Context variables required for this template:
+    * strings
+
+    Example context (json):
+    {
+        "hasstrings": true,
+        "formurl": "admin/tool/customlang/edit.php?lng=en",
+        "currentpage": 0,
+        "sesskey" : "AZyeeQgmcs",
+        "strings": [
+            {
+                "id": 11,
+                "component": "core",
+                "componentid": 1,
+                "stringid": "course",
+                "original": "Course",
+                "master": "Cursus",
+                "local": "Hoofdstuk",
+                "outdated": 0,
+                "modified": 1
+            }
+        ]
+    }
+}}
+
+{{^hasstrings}}
+    {{{ nostrings }}}
+{{/hasstrings}}
+{{#hasstrings}}
+<form method="post" action="{{{formurl}}}">
+    <input type="hidden" name="translatorsubmitted" value="1">
+    <input type="hidden" name="sesskey" value="{{{ sesskey }}}">
+    <input type="hidden" name="p" value="{{ currentpage }}">
+
+    <fieldset class="m-a-1 m-3">
+        <button type="submit" name="savecontinue" class="btn btn-secondary">
+            {{#str}}savecontinue, tool_customlang{{/str}}
+        </button>
+        <button type="submit" name="savecheckin" class="btn btn-secondary">
+            {{#str}}savecheckin, tool_customlang{{/str}}
+        </button>
+    </fieldset>
+
+    <div class="list-group">
+        <div class="container-fluid d-none d-md-block list-group-item border-bottom-0">
+            <div class="row-fluid">
+                <div class="col-sm-4 col-md-2 span2">
+                    <strong>{{#str}}headingcomponent, tool_customlang{{/str}}</strong>
+                </div>
+                <div class="col-sm-4 col-md-2 span2">
+                    <strong>{{#str}}headingstringid, tool_customlang{{/str}}</strong>
+                </div>
+                <div class="col-sm-4 col-md-2 span2">
+                    <strong>{{#str}}headingstandard, tool_customlang{{/str}}</strong>
+                </div>
+                <div class="col-sm-12 col-md-6 span6">
+                    <span class="p-l-1 pl-3">
+                        <strong>{{#str}}headinglocal, tool_customlang{{/str}}</strong>
+                    </span>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="list-group">
+    {{#strings}}
+        <div class="container-fluid list-group-item
+                {{#local}}list-group-item-info{{/local}}
+                {{#outdated}}list-group-item-warning{{/outdated}}
+                {{#modified}}list-group-item-info{{/modified}}"
+            >
+            <div class="row-fluid ">
+                <div class="col-sm-4 col-md-2 span2">
+                    <div class="d-md-none">
+                        <strong>{{#str}}headingcomponent, tool_customlang{{/str}}</strong>
+                    </div>
+                    {{{ component }}}
+                </div>
+                <div class="col-sm-4 col-md-2 span2 text-break">
+                    <div class="d-md-none">
+                        <strong>{{#str}}headingstringid, tool_customlang{{/str}}</strong>
+                    </div>
+                    {{{ stringid }}}
+                </div>
+                <div class="col-sm-4 col-md-2 span2">
+                    <div class="d-md-none">
+                        <strong>{{#str}}headingstandard, tool_customlang{{/str}}</strong>
+                    </div>
+                    {{{ master }}}
+                    <div class="info">
+                        {{{ placeholderhelp }}}
+                        {{{ outdatedhelp}}}
+                    </div>
+                    {{#showoriginalvsmaster}}
+                    <div class="alert-secondary mt-3 m-t-1">
+                        {{{ original }}}
+                    </div>
+                    {{/showoriginalvsmaster}}
+                </div>
+                <div class="col-sm-12 col-md-6 mt-sm-3 mt-md-0 span6">
+                    <div class="d-md-none">
+                        <strong>{{#str}}headinglocal, tool_customlang{{/str}}</strong>
+                    </div>
+                    <div class="py-2 py-md-0 px-md-3">
+                        <textarea class="form-control w-100 border-box" name="cust[{{id}}]" cols="40" rows="3">{{{ local }}}</textarea>
+
+                        {{#checkupdated}}
+                        <div class="uptodatewrapper">
+                            <div class="form-check">
+                                <input id="update_{{id}}" class="form-check-input" name="updates[]" type="checkbox" value="{{id}}">
+                                <label for="update_{{id}}" class="form-check-label">{{#str}}markuptodate, tool_customlang{{/str}}</label>
+                                {{{ outdatedhelp }}}
+                            </div>
+                        </div>
+                        {{/checkupdated}}
+                    </div>
+                </div>
+            </div>
+        </div>
+    {{/strings}}
+    </div>
+</form>
+{{/hasstrings}}
index 9a62976..8681715 100644 (file)
@@ -301,6 +301,8 @@ class page_agreedocs implements renderable, templatable {
                 redirect(new moodle_url('/admin/tool/policy/view.php', $urlparams));
             }
         } else {
+            // Update the policyagreed for the user to avoid infinite loop because there are no policies to-be-accepted.
+            api::update_policyagreed($userid);
             $this->redirect_to_previous_url();
         }
     }
index b35a20e..c996d8b 100644 (file)
@@ -292,3 +292,23 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
     When I press "Give consent"
     Then "Accepted on user's behalf" "text" should exist in the "User One" "table_row"
     And "Accepted on user's behalf" "text" should exist in the "User Two" "table_row"
+
+  Scenario: View acceptances made by users on their own after inactivating a policy
+    Given I log in as "user1"
+    And I should see "This site policy"
+    And I should not see "Course overview"
+    And I press "Next"
+    And I set the field "I agree to the This site policy" to "1"
+    And I press "Next"
+    And I should see "Course overview"
+    And I log out
+    And I log in as "admin"
+    And I navigate to "Users > Privacy and policies > Manage policies" in site administration
+    And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
+    And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
+    And I press "Continue"
+    And I click on "Set status to \"Inactive\"" "link" in the "This privacy policy" "table_row"
+    And I press "Continue"
+    And I log out
+    When I log in as "user1"
+    Then I should see "Course overview"
index 77260f0..e0b38bd 100644 (file)
@@ -96,6 +96,7 @@ if (!has_any_capability(array(
         'moodle/badges:viewawarded',
         'moodle/badges:createbadge',
         'moodle/badges:awardbadge',
+        'moodle/badges:configurecriteria',
         'moodle/badges:configuremessages',
         'moodle/badges:configuredetails',
         'moodle/badges:deletebadge'), $PAGE->context)) {
index 910f9fb..6a79717 100644 (file)
@@ -48,7 +48,7 @@ $string['aria:sortingdropdown'] = 'Sorting drop-down menu';
 $string['card'] = 'Card';
 $string['cards'] = 'Cards';
 $string['courseprogress'] = 'Course progress:';
-$string['complete'] = 'complete';
+$string['completepercent'] = '{$a}% complete';
 $string['favourites'] = 'Starred';
 $string['future'] = 'Future';
 $string['inprogress'] = 'In progress';
@@ -93,4 +93,5 @@ $string['privacy:metadata:overviewlasttab'] = 'This stores the last tab selected
 $string['viewcourse'] = 'View course';
 
 // Deprecated since Moodle 3.7.
-$string['nocourses'] = 'No courses';
\ No newline at end of file
+$string['complete'] = 'complete';
+$string['nocourses'] = 'No courses';
index 4e22e76..fb6f86c 100644 (file)
@@ -13,4 +13,5 @@ sortbydates,block_myoverview
 timeline,block_myoverview
 viewcoursename,block_myoverview
 privacy:metadata:overviewlasttab,block_myoverview
-nocourses,block_myoverview
\ No newline at end of file
+nocourses,block_myoverview
+complete,block_myoverview
\ No newline at end of file
index 9bb0a57..02fa1f0 100644 (file)
@@ -30,5 +30,5 @@
 </div>
 <div class="small">
     <span class="sr-only">{{#str}}aria:courseprogress, block_myoverview{{/str}}</span>
-    <strong>{{progress}}%</strong> {{#str}}complete, block_myoverview{{/str}}
+    {{#str}}completepercent, block_myoverview, <strong>{{progress}}</strong>{{/str}}
 </div>
index 502b003..ce30779 100644 (file)
@@ -105,4 +105,12 @@ $functions = array(
         'type' => 'read',
         'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
     ),
+
+    'mod_forum_get_forum_access_information' => array(
+        'classname'     => 'mod_forum_external',
+        'methodname'    => 'get_forum_access_information',
+        'description'   => 'Return capabilities information for a given forum.',
+        'type'          => 'read',
+        'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+    ),
 );
index a92d3bd..db31cef 100644 (file)
@@ -1189,4 +1189,73 @@ class mod_forum_external extends external_api {
         );
     }
 
+    /**
+     * Describes the parameters for get_forum_access_information.
+     *
+     * @return external_external_function_parameters
+     * @since Moodle 3.7
+     */
+    public static function get_forum_access_information_parameters() {
+        return new external_function_parameters (
+            array(
+                'forumid' => new external_value(PARAM_INT, 'Forum instance id.')
+            )
+        );
+    }
+
+    /**
+     * Return access information for a given forum.
+     *
+     * @param int $forumid forum instance id
+     * @return array of warnings and the access information
+     * @since Moodle 3.7
+     * @throws  moodle_exception
+     */
+    public static function get_forum_access_information($forumid) {
+        global $DB;
+
+        $params = self::validate_parameters(self::get_forum_access_information_parameters(), array('forumid' => $forumid));
+
+        // Request and permission validation.
+        $forum = $DB->get_record('forum', array('id' => $params['forumid']), '*', MUST_EXIST);
+        $cm = get_coursemodule_from_instance('forum', $forum->id);
+
+        $context = context_module::instance($cm->id);
+        self::validate_context($context);
+
+        $result = array();
+        // Return all the available capabilities.
+        $capabilities = load_capability_def('mod_forum');
+        foreach ($capabilities as $capname => $capdata) {
+            // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
+            $field = 'can' . str_replace('mod/forum:', '', $capname);
+            $result[$field] = has_capability($capname, $context);
+        }
+
+        $result['warnings'] = array();
+        return $result;
+    }
+
+    /**
+     * Describes the get_forum_access_information return value.
+     *
+     * @return external_single_structure
+     * @since Moodle 3.7
+     */
+    public static function get_forum_access_information_returns() {
+
+        $structure = array(
+            'warnings' => new external_warnings()
+        );
+
+        $capabilities = load_capability_def('mod_forum');
+        foreach ($capabilities as $capname => $capdata) {
+            // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules.
+            $field = 'can' . str_replace('mod/forum:', '', $capname);
+            $structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.',
+                VALUE_OPTIONAL);
+        }
+
+        return new external_single_structure($structure);
+    }
 }
index c095db7..7056d79 100644 (file)
@@ -1248,4 +1248,57 @@ class mod_forum_external_testcase extends externallib_advanced_testcase {
         $this->assertEquals(2, $posts['ratinginfo']['ratings'][0]['count']);
         $this->assertEquals(($rating1->rating + $rating2->rating) / 2, $posts['ratinginfo']['ratings'][0]['aggregate']);
     }
+
+    /**
+     * Test mod_forum_get_forum_access_information.
+     */
+    public function test_mod_forum_get_forum_access_information() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        $student = self::getDataGenerator()->create_user();
+        $course = self::getDataGenerator()->create_course();
+        // Create the forum.
+        $record = new stdClass();
+        $record->course = $course->id;
+        $forum = self::getDataGenerator()->create_module('forum', $record);
+
+        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
+        $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
+
+        self::setUser($student);
+        $result = mod_forum_external::get_forum_access_information($forum->id);
+        $result = external_api::clean_returnvalue(mod_forum_external::get_forum_access_information_returns(), $result);
+
+        // Check default values for capabilities.
+        $enabledcaps = array('canviewdiscussion', 'canstartdiscussion', 'canreplypost', 'canviewrating', 'cancreateattachment',
+            'canexportownpost', 'candeleteownpost', 'canallowforcesubscribe');
+
+        unset($result['warnings']);
+        foreach ($result as $capname => $capvalue) {
+            if (in_array($capname, $enabledcaps)) {
+                $this->assertTrue($capvalue);
+            } else {
+                $this->assertFalse($capvalue);
+            }
+        }
+        // Now, unassign some capabilities.
+        unassign_capability('mod/forum:deleteownpost', $studentrole->id);
+        unassign_capability('mod/forum:allowforcesubscribe', $studentrole->id);
+        array_pop($enabledcaps);
+        array_pop($enabledcaps);
+        accesslib_clear_all_caches_for_unit_testing();
+
+        $result = mod_forum_external::get_forum_access_information($forum->id);
+        $result = external_api::clean_returnvalue(mod_forum_external::get_forum_access_information_returns(), $result);
+        unset($result['warnings']);
+        foreach ($result as $capname => $capvalue) {
+            if (in_array($capname, $enabledcaps)) {
+                $this->assertTrue($capvalue);
+            } else {
+                $this->assertFalse($capvalue);
+            }
+        }
+    }
 }
index f915687..73b44fb 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2018120300;       // The current module version (Date: YYYYMMDDXX)
+$plugin->version   = 2018120301;       // The current module version (Date: YYYYMMDDXX)
 $plugin->requires  = 2018112800;       // Requires this Moodle version
 $plugin->component = 'mod_forum';      // Full name of the plugin (used for diagnostics)
index 7f8299e..e83a214 100644 (file)
@@ -26,7 +26,6 @@ $string['pluginname'] = 'Nextcloud';
 $string['configplugin'] = 'Nextcloud repository configuration';
 $string['nextcloud'] = 'Nextcloud';
 $string['nextcloud:view'] = 'View Nextcloud';
-$string['configplugin'] = 'Nextcloud configuration';
 $string['pluginname_help'] = 'Nextcloud repository';
 
 // Settings.
index e4713b3..25810ae 100644 (file)
@@ -2262,3 +2262,7 @@ $switch-transition: .2s all !default;
 .overflow-hidden {
     overflow: hidden !important; /* stylelint-disable-line declaration-no-important */
 }
+
+.text-break {
+    overflow-wrap: break-word !important; /* stylelint-disable-line declaration-no-important */
+}
index f50e221..63de9db 100644 (file)
@@ -10540,6 +10540,10 @@ div.editor_atto_toolbar button .icon {
   overflow: hidden !important;
   /* stylelint-disable-line declaration-no-important */ }
 
+.text-break {
+  overflow-wrap: break-word !important;
+  /* stylelint-disable-line declaration-no-important */ }
+
 .icon {
   font-size: 16px;
   width: 16px;