Compare commits
227 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2caed2991e | |||
| 3552ac0622 | |||
| b665e63be8 | |||
| 8e2239f1a7 | |||
| 4e9a6ef5be | |||
| c4f58034ab | |||
| 313d3d76eb | |||
| 881cc1da19 | |||
| 553ea69c3f | |||
| 72c5bcc745 | |||
| d2a623971c | |||
| b0d5d0ebc5 | |||
| 636890e5f6 | |||
| 7fe5196a52 | |||
| cc46c0158a | |||
| 1a2ca071eb | |||
| b17f5b6337 | |||
| 7daac50b35 | |||
| 1ee4d7da64 | |||
| 9540c536d8 | |||
| a96de1c74d | |||
| d2790cca27 | |||
| 69e8820de1 | |||
| 8d9daa91ba | |||
| 4027721841 | |||
| 475256b621 | |||
| ddc8ddb047 | |||
| 7f349d6552 | |||
| 2bbb3d0eb4 | |||
| 68d1a0c1c0 | |||
| a84fb29fcb | |||
| 5158c1533c | |||
| c8defec8dd | |||
| 532c3eb7b0 | |||
| f1949fe80c | |||
| 2ac6d6a7d3 | |||
| 75226d8c9e | |||
| 6496dd5277 | |||
| 3ef7b399a8 | |||
| 95b427d8fe | |||
| 18886c271f | |||
| 9cae11732f | |||
| 9600731821 | |||
| 44a8713267 | |||
| 75b6190bde | |||
| 53f5432d89 | |||
| b456e7aa18 | |||
| 75bf395e47 | |||
| 029457a0a6 | |||
| d23ff0a5b3 | |||
| a2e0dec53b | |||
| 2867735f7e | |||
| dbb0410d58 | |||
| 4721df9f4c | |||
| 243c35b3e8 | |||
| 4d5ea5e9a9 | |||
| b47fa670f0 | |||
| e196979e09 | |||
| 50a79addb1 | |||
| 5f7b44fe70 | |||
| a18deeb18b | |||
| 893bdf2603 | |||
| c08401f159 | |||
| 26ffef4f6d | |||
| a066890881 | |||
| 65532b40c9 | |||
| b61400d504 | |||
| 9079a52348 | |||
| 64038bd1d2 | |||
| dad1f86b28 | |||
| 8ec461823a | |||
| 2397eee6cb | |||
| 875c1d9638 | |||
| 46ea3269fc | |||
| be8fac6291 | |||
| 7d9d0f35a0 | |||
| 6bee956ede | |||
| 7d8f31dbe7 | |||
| e4e7902d7c | |||
| 946ff0171c | |||
| 9cf38cfd39 | |||
| b3eb942301 | |||
| fce3ba9b11 | |||
| 42b6a39808 | |||
| df17b180f2 | |||
| 6ff023d292 | |||
| 8043b7838a | |||
| 60ecd6cef5 | |||
| 558585b1ed | |||
| 5292926ebb | |||
| e19cbda970 | |||
| b559b84774 | |||
| 4406bcd17a | |||
| f8e7a1e24b | |||
| 0bfa7ee0a7 | |||
| 6f61f48e20 | |||
| dec59bd614 | |||
| f37baf7b59 | |||
| 03c1095379 | |||
| 55139ae744 | |||
| 6cf8bd9832 | |||
| ed4e4660db | |||
| 8400206468 | |||
| 32a944bac8 | |||
| d7185519c3 | |||
| 9daaca2400 | |||
| dc2b74c749 | |||
| db31cd37b2 | |||
| d8d79addc4 | |||
| 178cc61b18 | |||
| 5f87d91315 | |||
| 3cd54831ea | |||
| 166c6cc61e | |||
| f616930138 | |||
| 8420c58e69 | |||
| 4a603fe534 | |||
| 7956a8d814 | |||
| fba11f5c29 | |||
| b83db3be01 | |||
| b74ee3931c | |||
| d9f694bfa8 | |||
| bdc55fbffc | |||
| 4b39aecb10 | |||
| 2834086d07 | |||
| b6604a3a19 | |||
| 13fec4131e | |||
| 9ebea4011e | |||
| 87fbf39aae | |||
| 6273e6fdf3 | |||
| e8be539742 | |||
| 5b94923b7a | |||
| e736f80017 | |||
| c7cc232e16 | |||
| 07a3a15eb7 | |||
| 07f644d2ec | |||
| aac223ade5 | |||
| c1a94a7d52 | |||
| beaff418ba | |||
| ff1b86ab60 | |||
| 191ef569b5 | |||
| 307be1189c | |||
| 3cfe37dd29 | |||
| bb4329278b | |||
| f6d297a920 | |||
| 36edc365ea | |||
| ed55a94fe8 | |||
| 551edbb9a6 | |||
| 478861b4d1 | |||
| 22768e349a | |||
| 6ad9bb2482 | |||
| fd953966d8 | |||
| 82db828016 | |||
| 6a409c4cd4 | |||
| 894a6ab5ad | |||
| 5b1daccb92 | |||
| f005111165 | |||
| 1e30a80b7f | |||
| 0778d512fe | |||
| 8812990c85 | |||
| 1018c8a4c5 | |||
| 60220de680 | |||
| b7d7b84d30 | |||
| 8169d1da07 | |||
| 8af994f1f0 | |||
| 8ca6ffa077 | |||
| 3904547719 | |||
| 74a28bde79 | |||
| 5fb543fa45 | |||
| f19e245f29 | |||
| 922713d626 | |||
| ac7720b956 | |||
| 712cdd0fc6 | |||
| f575d8fc82 | |||
| 03a41fa881 | |||
| 11a1ac8913 | |||
| c35fd3566c | |||
| 6597f8f7f5 | |||
| e04daa31e4 | |||
| bde844c57c | |||
| 7c007b8f32 | |||
| c68493a349 | |||
| 529187a82a | |||
| c38582b409 | |||
| b0872b6aa5 | |||
| 8f296f6528 | |||
| 1b7f761528 | |||
| 2d9536f980 | |||
| 9845799ed6 | |||
| 23e15c1ae2 | |||
| 5bbdf8ab51 | |||
| f42ac85b7e | |||
| 6a566abcd9 | |||
| c0a05c9d8a | |||
| a971b89389 | |||
| 10a640c25e | |||
| c0373ed7f7 | |||
| 6b7b12c790 | |||
| 213935c460 | |||
| 75a1e8d843 | |||
| c5bea842a9 | |||
| 4e758d343a | |||
| e889cc49c2 | |||
| 06fa0aad49 | |||
| 4a60dd3205 | |||
| 7c18bb6833 | |||
| 5eb255f051 | |||
| 88cedd9f99 | |||
| d1254b0c8d | |||
| 962ab85122 | |||
| 264f458417 | |||
| adc9c66e75 | |||
| 6ddeef9cab | |||
| 68456ca14f | |||
| 45d7645598 | |||
| 2c2bd9e2af | |||
| 9cf379579b | |||
| 2919cf9e1b | |||
| 136e636bf0 | |||
| 622f98e637 | |||
| aa6bfe07ef | |||
| 712391f96b | |||
| 778840f1d7 | |||
| 756f56492e | |||
| 5fc2612d25 | |||
| 55620756a5 | |||
| 9079e01d44 | |||
| 801e7d9fe4 |
@@ -156,7 +156,7 @@ const getThirdPartyLibsList = relativeTo => {
|
||||
* @returns {array}
|
||||
*/
|
||||
const getThirdPartyPaths = () => {
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const DOMParser = require('@xmldom/xmldom').DOMParser;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const xpath = require('xpath');
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Reset course indentation
|
||||
*
|
||||
* @copyright 2023 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../../config.php');
|
||||
|
||||
require_admin();
|
||||
|
||||
$format = required_param('format', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$backurl = new moodle_url('/admin/settings.php', ['section' => 'formatsetting'.$format]);
|
||||
|
||||
$PAGE->set_url('/admin/course/resetindentation.php', ['format' => $format]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
$courses = $DB->get_records('course', ['format' => $format], 'id', 'id');
|
||||
if (!empty($courses)) {
|
||||
$courseids = array_keys($courses);
|
||||
list($courseinsql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'course');
|
||||
$DB->set_field_select('course_modules', 'indent', '0', "course $courseinsql AND indent <> 0", $courseparams);
|
||||
rebuild_course_cache(0, true);
|
||||
}
|
||||
redirect(
|
||||
$backurl,
|
||||
get_string('resetindentationsuccess', 'admin'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
$strtitle = get_string('resetindentation', 'admin');
|
||||
|
||||
$PAGE->set_title($strtitle);
|
||||
$PAGE->set_heading($strtitle);
|
||||
|
||||
navigation_node::override_active_url(new moodle_url(
|
||||
'/admin/course/resetindentation.php',
|
||||
['action' => 'confirm', 'format' => $format]
|
||||
));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$displayoptions = ['confirmtitle' => get_string('resetindentation_title', 'admin')];
|
||||
$confirmbutton = new single_button(
|
||||
new moodle_url('/admin/course/resetindentation.php', ['confirm' => 1, 'format' => $format, 'sesskey' => sesskey()]),
|
||||
get_string('resetindentation', 'admin'),
|
||||
'post'
|
||||
);
|
||||
$cancelbutton = new single_button($backurl, get_string('cancel'));
|
||||
echo $OUTPUT->confirm(
|
||||
get_string('resetindentation_help', 'admin', ['format' => get_string('pluginname', 'format_'.$format)]),
|
||||
$confirmbutton,
|
||||
$cancelbutton,
|
||||
$displayoptions
|
||||
);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -4109,6 +4109,8 @@
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
+23
-12
@@ -30,25 +30,36 @@
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
// Per https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1, state is required, even during error responses.
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
$error = optional_param('error', '', PARAM_RAW);
|
||||
|
||||
if ($error) {
|
||||
$message = optional_param('error_description', '', PARAM_RAW);
|
||||
if ($message) {
|
||||
$SESSION->loginerrormsg = $message;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
} else {
|
||||
$SESSION->loginerrormsg = $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
$message = optional_param('error_description', null, PARAM_RAW);
|
||||
|
||||
// Errors can occur for authenticated users, such as when a user denies authorization for some internal service call.
|
||||
// In such cases, propagate the error to the component redirect URI.
|
||||
if (isloggedin()) {
|
||||
if (isset($params['sesskey']) && confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('error', $error);
|
||||
if ($message) {
|
||||
$redirecturl->param('error_description', $message);
|
||||
}
|
||||
redirect($redirecturl);
|
||||
}
|
||||
}
|
||||
|
||||
// Not logged in or the sesskey verification failed, redirect to login + show errors.
|
||||
$SESSION->loginerrormsg = $message ?? $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
}
|
||||
|
||||
// The authorization code generated by the authorization server.
|
||||
$code = required_param('code', PARAM_RAW);
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('oauth2code', $code);
|
||||
|
||||
@@ -90,6 +90,7 @@ $title = get_string('overridepermissionsforrole', 'core_role', $a);
|
||||
$currenttab = 'permissions';
|
||||
|
||||
$PAGE->set_title($title);
|
||||
$PAGE->activityheader->disable();
|
||||
$PAGE->navbar->add($straction);
|
||||
switch ($context->contextlevel) {
|
||||
case CONTEXT_SYSTEM:
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
|
||||
<span data-passwordunmask="editor">
|
||||
<input type="password"
|
||||
autocomplete="new-password"
|
||||
name="{{ name }}"
|
||||
id="{{ id }}"
|
||||
value="{{ value }}"
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
@core @core_admin @core_course @javascript
|
||||
Feature: Reset course indentation
|
||||
In order to reset indentation in course modules
|
||||
As a admin
|
||||
I want change indent value for all the modules of a course format courses in one go
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Topics Course 1 | T1 | topics |
|
||||
| Topics Course 2 | T2 | topics |
|
||||
| Weekly Course 1 | W1 | weeks |
|
||||
| Weekly Course 2 | W2 | weeks |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| forum | Topics forum name | Topics forum description | T1 | forum1 |
|
||||
| data | Topics database name | Topics database description | T1 | data1 |
|
||||
| wiki | Topics wiki name | Topics wiki description | T2 | wiki1 |
|
||||
| forum | Weekly forum name | Weekly forum description | W1 | forum2 |
|
||||
| data | Weekly database name | Weekly database description | W1 | data2 |
|
||||
| wiki | Weekly wiki name | Weekly wiki description | W2 | wiki2 |
|
||||
And I log in as "admin"
|
||||
And I am on "Topics Course 1" course homepage with editing mode on
|
||||
And I open "Topics forum name" actions menu
|
||||
And I click on "Move right" "link" in the "Topics forum name" activity
|
||||
And I open "Topics forum name" actions menu
|
||||
And "Move right" "link" in the "Topics forum name" "activity" should not be visible
|
||||
And "Move left" "link" in the "Topics forum name" "activity" should be visible
|
||||
And I press the escape key
|
||||
And I open "Topics database name" actions menu
|
||||
And "Move right" "link" in the "Topics database name" "activity" should be visible
|
||||
And "Move left" "link" in the "Topics database name" "activity" should not be visible
|
||||
And I am on "Topics Course 2" course homepage with editing mode on
|
||||
And I open "Topics wiki name" actions menu
|
||||
And I click on "Move right" "link" in the "Topics wiki name" activity
|
||||
And I open "Topics wiki name" actions menu
|
||||
And "Move right" "link" in the "Topics wiki name" "activity" should not be visible
|
||||
And "Move left" "link" in the "Topics wiki name" "activity" should be visible
|
||||
And I am on "Weekly Course 1" course homepage with editing mode on
|
||||
And I open "Weekly forum name" actions menu
|
||||
And I click on "Move right" "link" in the "Weekly forum name" activity
|
||||
And I open "Weekly forum name" actions menu
|
||||
And "Move right" "link" in the "Weekly forum name" "activity" should not be visible
|
||||
And "Move left" "link" in the "Weekly forum name" "activity" should be visible
|
||||
And I press the escape key
|
||||
And I open "Weekly database name" actions menu
|
||||
And "Move right" "link" in the "Weekly database name" "activity" should be visible
|
||||
And "Move left" "link" in the "Weekly database name" "activity" should not be visible
|
||||
And I am on "Weekly Course 2" course homepage with editing mode on
|
||||
And I open "Weekly wiki name" actions menu
|
||||
And I click on "Move right" "link" in the "Weekly wiki name" activity
|
||||
And I open "Weekly wiki name" actions menu
|
||||
And "Move right" "link" in the "Weekly wiki name" "activity" should not be visible
|
||||
And "Move left" "link" in the "Weekly wiki name" "activity" should be visible
|
||||
|
||||
Scenario Outline: Apply course indentation reset
|
||||
Given I navigate to "Plugins > Course formats > <format> format" in site administration
|
||||
And I wait "5" seconds
|
||||
And "Reset indentation" "link" should exist
|
||||
When I click on "Reset indentation" "link"
|
||||
And I should see "Reset indentation on course page"
|
||||
And "Reset indentation" "button" should exist
|
||||
And I click on "Reset indentation" "button"
|
||||
Then I should see "Indentation reset"
|
||||
And I am on "<format> Course 1" course homepage with editing mode on
|
||||
And I open "<format> forum name" actions menu
|
||||
And "Move right" "link" in the "<format> forum name" "activity" should be visible
|
||||
And "Move left" "link" in the "<format> forum name" "activity" should not be visible
|
||||
And I press the escape key
|
||||
And I open "<format> database name" actions menu
|
||||
And "Move right" "link" in the "<format> database name" "activity" should be visible
|
||||
And "Move left" "link" in the "<format> database name" "activity" should not be visible
|
||||
And I am on "<format> Course 2" course homepage with editing mode on
|
||||
And I open "<format> wiki name" actions menu
|
||||
And "Move right" "link" in the "<format> wiki name" "activity" should be visible
|
||||
And "Move left" "link" in the "<format> wiki name" "activity" should not be visible
|
||||
# Check other course formats had not been reset
|
||||
And I am on "<other> Course 1" course homepage with editing mode on
|
||||
And I open "<other> forum name" actions menu
|
||||
And "Move right" "link" in the "<other> forum name" "activity" should not be visible
|
||||
And "Move left" "link" in the "<other> forum name" "activity" should be visible
|
||||
|
||||
Examples:
|
||||
| format | other |
|
||||
| Topics | Weekly |
|
||||
| Weekly | Topics |
|
||||
|
||||
Scenario Outline: Cancel course indentation reset
|
||||
Given I navigate to "Plugins > Course formats > <format> format" in site administration
|
||||
And "Reset indentation" "link" should exist
|
||||
When I click on "Reset indentation" "link"
|
||||
And I should see "Reset indentation on course page"
|
||||
And "Reset indentation" "button" should exist
|
||||
And "Cancel" "button" should exist
|
||||
And I click on "Cancel" "button"
|
||||
Then I should not see "Indentation reset"
|
||||
And I am on "<format> Course 1" course homepage with editing mode on
|
||||
And I open "<format> forum name" actions menu
|
||||
And "Move right" "link" in the "<format> forum name" "activity" should not be visible
|
||||
And "Move left" "link" in the "<format> forum name" "activity" should be visible
|
||||
And I press the escape key
|
||||
And I open "<format> database name" actions menu
|
||||
And "Move right" "link" in the "<format> database name" "activity" should be visible
|
||||
And "Move left" "link" in the "<format> database name" "activity" should not be visible
|
||||
And I am on "<format> Course 2" course homepage with editing mode on
|
||||
And I open "<format> wiki name" actions menu
|
||||
And "Move right" "link" in the "<format> wiki name" "activity" should not be visible
|
||||
And "Move left" "link" in the "<format> wiki name" "activity" should be visible
|
||||
|
||||
Examples:
|
||||
| format |
|
||||
| Topics |
|
||||
| Weekly |
|
||||
@@ -254,19 +254,16 @@ class renderer extends \tool_brickfield\output\renderer {
|
||||
<tr>
|
||||
<td>
|
||||
<img src="' . $this->image_path() . 'tachometer-alt-solid.svg" width="15" height="15">' .
|
||||
' <td style="line-height: 10px;"> ' .
|
||||
get_string('totalactivitiescount', manager::PLUGINNAME, $data->combodata['total']) .
|
||||
'</td></td>
|
||||
'</td>
|
||||
<td>
|
||||
<img src="' . $this->image_path() . 'check-square-regular.svg" width="15" height="15">' .
|
||||
' <td style="line-height: 10px;"> ' .
|
||||
get_string('passedcount', manager::PLUGINNAME, $data->combodata['passed']) .
|
||||
'</td></td>
|
||||
'</td>
|
||||
<td>
|
||||
<img src="' . $this->image_path() . 'times-circle-regular.svg" width="15" height="15">' .
|
||||
' <td style="line-height: 10px;"> ' .
|
||||
get_string('failedcount', manager::PLUGINNAME, $data->combodata['failed']) .
|
||||
'</td></td>
|
||||
'</td>
|
||||
</tr>
|
||||
</table>';
|
||||
|
||||
@@ -396,8 +393,8 @@ class renderer extends \tool_brickfield\output\renderer {
|
||||
foreach ($data->groupdata as $key => $group) {
|
||||
$checkgroup = area_base::checkgroup_name($key);
|
||||
$icon = $icons[$key];
|
||||
$tabledata[] = ['<img src="'.$icon.'" width="15" height="15">' . ' ' .' <td style="line-height: 10px;"> '.
|
||||
get_string('checktype:' . $checkgroup, manager::PLUGINNAME).'</td>', $group->errorinstances];
|
||||
$tabledata[] = ['<img src="'.$icon.'" width="15" height="15">' . ' ' .
|
||||
get_string('checktype:' . $checkgroup, manager::PLUGINNAME), $group->errorinstances];
|
||||
}
|
||||
|
||||
return $this->render_table(
|
||||
|
||||
@@ -147,9 +147,7 @@ Feature: Manage plan workflow
|
||||
| name | user | description | status | reviewer |
|
||||
| Test-Plan3 | user1 | Description of plan 3 for user 1 | active | manager1 |
|
||||
| Test-Plan4 | user1 | Description of plan 4 for user 1 | active | manager1 |
|
||||
And I log in as "manager1"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I am on the "user1" "user > profile" page logged in as "manager1"
|
||||
And I follow "Learning plans"
|
||||
And I should see "List of learning plans"
|
||||
When I click on "Send back to draft" of edit menu in the "Test-Plan3" row
|
||||
@@ -165,9 +163,7 @@ Feature: Manage plan workflow
|
||||
| name | user | description | status | reviewer |
|
||||
| Test-Plan3 | user1 | Description of plan 3 for user 1 | active | manager1 |
|
||||
| Test-Plan4 | user1 | Description of plan 4 for user 1 | active | manager1 |
|
||||
And I log in as "manager1"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I am on the "user1" "user > profile" page logged in as "manager1"
|
||||
And I follow "Learning plans"
|
||||
And I should see "List of learning plans"
|
||||
When I click on "Complete this learning plan" of edit menu in the "Test-Plan3" row
|
||||
@@ -186,9 +182,7 @@ Feature: Manage plan workflow
|
||||
| name | user | description | status | reviewer |
|
||||
| Test-Plan3 | user1 | Description of plan 3 for user 1 | complete | manager1 |
|
||||
| Test-Plan4 | user1 | Description of plan 4 for user 1 | complete | manager1 |
|
||||
And I log in as "manager1"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I am on the "user1" "user > profile" page logged in as "manager1"
|
||||
And I follow "Learning plans"
|
||||
And I should see "List of learning plans"
|
||||
When I click on "Reopen this learning plan" of edit menu in the "Test-Plan3" row
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
</div>
|
||||
<div class="box py-3 modal-footer">
|
||||
<div class="buttons">
|
||||
<input class="btn btn-secondary" type="submit" name="cancel" value="Cancel">
|
||||
<input class="btn btn-primary" type="submit" name="import" value="Continue">
|
||||
<input class="btn btn-secondary" type="submit" name="cancel" value="{{#str}}cancel, core{{/str}}">
|
||||
<input class="btn btn-primary" type="submit" name="import" value="{{#str}}continue, core{{/str}}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -241,9 +241,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I press "Next"
|
||||
And I log out
|
||||
And I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "Manager"
|
||||
And I am on the "manager" "user > profile" page logged in as "admin"
|
||||
And I follow "Log in as"
|
||||
And I press "Continue"
|
||||
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
|
||||
|
||||
@@ -563,9 +563,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
When I am on the "user1" "user > profile" page logged in as "admin"
|
||||
And I follow "Log in as"
|
||||
Then I should see "You are logged in as User 1"
|
||||
And I press "Continue"
|
||||
@@ -604,8 +602,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
|
||||
And I set the field "I agree to the This site policy" to "1"
|
||||
And I set the field "I agree to the This privacy policy" to "1"
|
||||
And I press "Next"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "User 1"
|
||||
And I am on the "user1" "user > profile" page
|
||||
And I follow "Log in as"
|
||||
Then I should see "You are logged in as User 1"
|
||||
And I press "Continue"
|
||||
|
||||
@@ -111,7 +111,10 @@ class cli_helper {
|
||||
$form = new \admin_uploaduser_form1();
|
||||
[$elements, $defaults] = $form->get_form_for_cli();
|
||||
$options += $this->prepare_form_elements_for_cli($elements, $defaults);
|
||||
$form = new \admin_uploaduser_form2(null, ['columns' => ['type1'], 'data' => []]);
|
||||
// Specify pseudo-column 'type1' to force the form to populate the legacy role mapping selector
|
||||
// but only if user is allowed to assign roles in courses (otherwise form validation will fail).
|
||||
$columns = uu_allowed_roles() ? ['type1'] : [];
|
||||
$form = new \admin_uploaduser_form2(null, ['columns' => $columns, 'data' => []]);
|
||||
[$elements, $defaults] = $form->get_form_for_cli();
|
||||
$options += $this->prepare_form_elements_for_cli($elements, $defaults);
|
||||
return $options;
|
||||
|
||||
@@ -123,7 +123,6 @@ class process {
|
||||
$today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
|
||||
$this->today = $today;
|
||||
|
||||
$this->rolecache = uu_allowed_roles_cache(); // Course roles lookup cache.
|
||||
$this->sysrolecache = uu_allowed_sysroles_cache(); // System roles lookup cache.
|
||||
$this->supportedauths = uu_supported_auths(); // Officially supported plugins that are enabled.
|
||||
|
||||
@@ -1140,14 +1139,18 @@ class process {
|
||||
}
|
||||
}
|
||||
|
||||
if (!array_key_exists($courseid, $this->rolecache)) {
|
||||
$this->rolecache[$courseid] = uu_allowed_roles_cache(null, (int)$courseid);
|
||||
}
|
||||
|
||||
if ($courseid == SITEID) {
|
||||
// Technically frontpage does not have enrolments, but only role assignments,
|
||||
// let's not invent new lang strings here for this rarely used feature.
|
||||
|
||||
if (!empty($user->{'role'.$i})) {
|
||||
$rolename = $user->{'role'.$i};
|
||||
if (array_key_exists($rolename, $this->rolecache)) {
|
||||
$roleid = $this->rolecache[$rolename]->id;
|
||||
if (array_key_exists($rolename, $this->rolecache[$courseid]) ) {
|
||||
$roleid = $this->rolecache[$courseid][$rolename]->id;
|
||||
} else {
|
||||
$this->upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
|
||||
continue;
|
||||
@@ -1157,7 +1160,7 @@ class process {
|
||||
|
||||
$a = new \stdClass();
|
||||
$a->course = $shortname;
|
||||
$a->role = $this->rolecache[$roleid]->name;
|
||||
$a->role = $this->rolecache[$courseid][$roleid]->name;
|
||||
$this->upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a), 'info');
|
||||
}
|
||||
|
||||
@@ -1167,8 +1170,8 @@ class process {
|
||||
$roleid = false;
|
||||
if (!empty($user->{'role'.$i})) {
|
||||
$rolename = $user->{'role'.$i};
|
||||
if (array_key_exists($rolename, $this->rolecache)) {
|
||||
$roleid = $this->rolecache[$rolename]->id;
|
||||
if (array_key_exists($rolename, $this->rolecache[$courseid])) {
|
||||
$roleid = $this->rolecache[$courseid][$rolename]->id;
|
||||
} else {
|
||||
$this->upt->track('enrolments', get_string('unknownrole', 'error', s($rolename)), 'error');
|
||||
continue;
|
||||
@@ -1187,7 +1190,15 @@ class process {
|
||||
}
|
||||
} else {
|
||||
// No role specified, use the default from manual enrol plugin.
|
||||
$roleid = $this->manualcache[$courseid]->roleid;
|
||||
$defaultenrolroleid = (int)$this->manualcache[$courseid]->roleid;
|
||||
// Validate the current user can assign this role.
|
||||
if (array_key_exists($defaultenrolroleid, $this->rolecache[$courseid]) ) {
|
||||
$roleid = $defaultenrolroleid;
|
||||
} else {
|
||||
$role = $DB->get_record('role', ['id' => $defaultenrolroleid]);
|
||||
$this->upt->track('enrolments', get_string('unknownrole', 'error', s($role->shortname)), 'error');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($roleid) {
|
||||
@@ -1230,7 +1241,7 @@ class process {
|
||||
|
||||
$a = new \stdClass();
|
||||
$a->course = $shortname;
|
||||
$a->role = $this->rolecache[$roleid]->name;
|
||||
$a->role = $this->rolecache[$courseid][$roleid]->name;
|
||||
$this->upt->track('enrolments', get_string('enrolledincourserole', 'enrol_manual', $a), 'info');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,17 +369,32 @@ function uu_allowed_roles() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns mapping of all roles using short role name as index.
|
||||
* Returns assignable roles for current user using short role name and role ID as index.
|
||||
* This function is no longer called without parameters.
|
||||
*
|
||||
* @param int|null $categoryid Id of the category to get roles for.
|
||||
* @param int|null $courseid Id of the course to get roles for.
|
||||
* @return array
|
||||
*/
|
||||
function uu_allowed_roles_cache() {
|
||||
$allowedroles = get_assignable_roles(context_course::instance(SITEID), ROLENAME_SHORT);
|
||||
function uu_allowed_roles_cache(?int $categoryid = null, ?int $courseid = null): array {
|
||||
if (!is_null($categoryid) && !is_null($courseid)) {
|
||||
return [];
|
||||
} else if (is_null($categoryid) && !is_null($courseid)) {
|
||||
$allowedroles = get_assignable_roles(context_course::instance($courseid), ROLENAME_SHORT);
|
||||
} else if (is_null($courseid) && !is_null($categoryid)) {
|
||||
$allowedroles = get_assignable_roles(context_coursecat::instance($categoryid), ROLENAME_SHORT);
|
||||
} else {
|
||||
$allowedroles = get_assignable_roles(context_course::instance(SITEID), ROLENAME_SHORT);
|
||||
}
|
||||
|
||||
$rolecache = [];
|
||||
// A role can be searched for by its ID or by its shortname.
|
||||
foreach ($allowedroles as $rid=>$rname) {
|
||||
$rolecache[$rid] = new stdClass();
|
||||
$rolecache[$rid]->id = $rid;
|
||||
$rolecache[$rid]->name = $rname;
|
||||
if (!is_numeric($rname)) { // only non-numeric shortnames are supported!!!
|
||||
// Since numeric short names are allowed, to avoid replacement of another role, we only accept non-numeric values.
|
||||
if (!is_numeric($rname)) {
|
||||
$rolecache[$rname] = new stdClass();
|
||||
$rolecache[$rname]->id = $rid;
|
||||
$rolecache[$rname]->name = $rname;
|
||||
|
||||
@@ -143,7 +143,8 @@ class cli_test extends \advanced_testcase {
|
||||
// Created users have data in the profile fields.
|
||||
$user1 = \core_user::get_user_by_username('reznort');
|
||||
$profilefields1 = profile_user_record($user1->id);
|
||||
$this->assertEquals((object)['superfield' => 'Loves cats'], $profilefields1);
|
||||
$this->assertObjectHasAttribute('superfield', $profilefields1);
|
||||
$this->assertEquals('Loves cats', $profilefields1->superfield);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
<?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/>.
|
||||
|
||||
namespace tool_uploaduser;
|
||||
|
||||
use advanced_testcase;
|
||||
use context_system;
|
||||
use context_course;
|
||||
use context_coursecat;
|
||||
use stdClass;
|
||||
use tool_uploaduser\cli_helper;
|
||||
use tool_uploaduser\local\text_progress_tracker;
|
||||
|
||||
/**
|
||||
* Class upload_users_test
|
||||
*
|
||||
* @package tool_uploaduser
|
||||
* @copyright 2020 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class upload_users_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Load required test libraries
|
||||
*/
|
||||
public static function setUpBeforeClass(): void {
|
||||
global $CFG;
|
||||
|
||||
require_once("{$CFG->dirroot}/{$CFG->admin}/tool/uploaduser/locallib.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test upload users, enrol and role assignation
|
||||
* @covers \tool_uploadusers::process
|
||||
*/
|
||||
public function test_user_can_upload_with_course_enrolment(): void {
|
||||
|
||||
$this->resetAfterTest();
|
||||
set_config('passwordpolicy', 0);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create category and course.
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = context_coursecat::instance($coursecat->id);
|
||||
$course = $this->getDataGenerator()->create_course(['shortname' => 'course01', 'category' => $coursecat->id]);
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
|
||||
// Create user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Create role with capability to upload CSV files, and assign this role to user.
|
||||
$uploadroleid = create_role('upload role', 'uploadrole', '');
|
||||
set_role_contextlevels($uploadroleid, [CONTEXT_SYSTEM]);
|
||||
$systemcontext = context_system::instance();
|
||||
assign_capability('moodle/site:uploadusers', CAP_ALLOW, $uploadroleid, $systemcontext->id);
|
||||
$this->getDataGenerator()->role_assign($uploadroleid, $user->id, $systemcontext->id);
|
||||
|
||||
// Create role with some of allowed capabilities to enrol users, and assign this role to user.
|
||||
$enrolroleid = create_role('enrol role', 'enrolrole', '');
|
||||
set_role_contextlevels($enrolroleid, [CONTEXT_COURSECAT]);
|
||||
assign_capability('enrol/manual:enrol', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
assign_capability('moodle/course:enrolreview', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
assign_capability('moodle/role:assign', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
$this->getDataGenerator()->role_assign($enrolroleid, $user->id, $coursecatcontext->id);
|
||||
|
||||
// User makes assignments.
|
||||
$studentarch = get_archetype_roles('student');
|
||||
$studentrole = array_shift($studentarch);
|
||||
core_role_set_assign_allowed($enrolroleid, $studentrole->id);
|
||||
|
||||
// Flush accesslib.
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
// Process CSV file as user.
|
||||
$csv = <<<EOF
|
||||
username,firstname,lastname,email,course1,role1
|
||||
student1,Student,One,s1@example.com,{$course->shortname},{$studentrole->shortname}
|
||||
student2,Student,Two,s2@example.com,{$course->shortname},teacher
|
||||
EOF;
|
||||
$this->setUser($user);
|
||||
$output = $this->process_csv_upload($csv, ['--uutype=' . UU_USER_ADDNEW]);
|
||||
|
||||
$this->assertStringContainsString('Enrolled in "course01" as "student"', $output);
|
||||
$this->assertStringContainsString('Unknown role "teacher"', $output);
|
||||
|
||||
// Check user creation, enrolment and role assignation.
|
||||
$this->assertEquals(1, count_enrolled_users($coursecontext));
|
||||
|
||||
$usersasstudent = get_role_users($studentrole->id, $coursecontext);
|
||||
$this->assertCount(1, $usersasstudent);
|
||||
$this->assertEquals('student1', reset($usersasstudent)->username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test upload users, enrol and assign default role from manual enrol plugin.
|
||||
* @covers \tool_uploadusers::process
|
||||
*/
|
||||
public function test_user_can_upload_with_course_enrolment_default_role(): void {
|
||||
|
||||
$this->resetAfterTest();
|
||||
set_config('passwordpolicy', 0);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create category and courses.
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = context_coursecat::instance($coursecat->id);
|
||||
$course1 = $this->getDataGenerator()->create_course(['shortname' => 'course01', 'category' => $coursecat->id]);
|
||||
$course1context = context_course::instance($course1->id);
|
||||
// Change the default role to 'teacher'.
|
||||
set_config('roleid', 4, 'enrol_manual');
|
||||
$course2 = $this->getDataGenerator()->create_course(['shortname' => 'course02', 'category' => $coursecat->id]);
|
||||
$course2context = context_course::instance($course2->id);
|
||||
|
||||
// Create user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Create role with capability to upload CSV files, and assign this role to user.
|
||||
$uploadroleid = create_role('upload role', 'uploadrole', '');
|
||||
set_role_contextlevels($uploadroleid, [CONTEXT_SYSTEM]);
|
||||
$systemcontext = context_system::instance();
|
||||
assign_capability('moodle/site:uploadusers', CAP_ALLOW, $uploadroleid, $systemcontext->id);
|
||||
$this->getDataGenerator()->role_assign($uploadroleid, $user->id, $systemcontext->id);
|
||||
|
||||
// Create role with some of allowed capabilities to enrol users, and assign this role to user.
|
||||
$enrolroleid = create_role('enrol role', 'enrolrole', '');
|
||||
set_role_contextlevels($enrolroleid, [CONTEXT_COURSECAT]);
|
||||
assign_capability('enrol/manual:enrol', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
assign_capability('moodle/course:enrolreview', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
assign_capability('moodle/role:assign', CAP_ALLOW, $enrolroleid, $coursecatcontext->id);
|
||||
$this->getDataGenerator()->role_assign($enrolroleid, $user->id, $coursecatcontext->id);
|
||||
|
||||
// User makes assignments.
|
||||
$studentarch = get_archetype_roles('student');
|
||||
$studentrole = array_shift($studentarch);
|
||||
core_role_set_assign_allowed($enrolroleid, $studentrole->id);
|
||||
|
||||
// Flush accesslib.
|
||||
accesslib_clear_all_caches_for_unit_testing();
|
||||
|
||||
// Process CSV file (no roles specified) as user.
|
||||
$csv = <<<EOF
|
||||
username,firstname,lastname,email,course1,role1
|
||||
student1,Student,One,s1@example.com,{$course1->shortname},
|
||||
student2,Student,Two,s2@example.com,{$course2->shortname},
|
||||
EOF;
|
||||
$this->setUser($user);
|
||||
$output = $this->process_csv_upload($csv, ['--uutype=' . UU_USER_ADDNEW]);
|
||||
|
||||
$this->assertStringContainsString('Enrolled in "course01" as "student"', $output);
|
||||
// This $user cannot assign teacher role.
|
||||
$this->assertStringContainsString('Unknown role "teacher"', $output);
|
||||
|
||||
// Check user creation, enrolment and role assignation.
|
||||
$this->assertEquals(1, count_enrolled_users($course1context));
|
||||
// This $user cannot enrol anyone as teacher.
|
||||
$this->assertEquals(0, count_enrolled_users($course2context));
|
||||
|
||||
// Test user is enrolled as default-manual-enrol-plugin role.
|
||||
$manualenrolinstance = new stdClass;
|
||||
$enrolinstances = enrol_get_instances($course1->id, true);
|
||||
foreach ($enrolinstances as $courseenrolinstance) {
|
||||
if ($courseenrolinstance->enrol === 'manual') {
|
||||
$manualenrolinstance = $courseenrolinstance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$defaulroleidexpected = $manualenrolinstance->roleid ?? 0;
|
||||
// The default role of course01 is student, id 5.
|
||||
$this->assertEquals(5, $defaulroleidexpected);
|
||||
|
||||
$usersasdefaultrole = get_role_users($defaulroleidexpected, $course1context);
|
||||
$this->assertCount(1, $usersasdefaultrole);
|
||||
$this->assertEquals('student1', reset($usersasdefaultrole)->username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cli_helper and mock $_SERVER['argv']
|
||||
*
|
||||
* @param string $filecontent
|
||||
* @param array $mockargv
|
||||
* @return string
|
||||
*/
|
||||
protected function process_csv_upload(string $filecontent, array $mockargv = []): string {
|
||||
$filepath = make_request_directory() . '/upload.csv';
|
||||
file_put_contents($filepath, $filecontent);
|
||||
$mockargv[] = "--file={$filepath}";
|
||||
|
||||
if (array_key_exists('argv', $_SERVER)) {
|
||||
$oldservervars = $_SERVER['argv'];
|
||||
}
|
||||
|
||||
$_SERVER['argv'] = array_merge([''], $mockargv);
|
||||
$clihelper = new cli_helper(text_progress_tracker::class);
|
||||
|
||||
if (isset($oldservervars)) {
|
||||
$_SERVER['argv'] = $oldservervars;
|
||||
} else {
|
||||
unset($_SERVER['argv']);
|
||||
}
|
||||
|
||||
ob_start();
|
||||
$clihelper->process();
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,6 +14,8 @@ import {eventTypes} from './events';
|
||||
|
||||
let currentTour = null;
|
||||
let tourId = null;
|
||||
let restartTourAndKeepProgress = false;
|
||||
let currentStepNo = null;
|
||||
|
||||
/**
|
||||
* Find the first matching tour.
|
||||
@@ -75,6 +77,20 @@ export const init = async(tourDetails, filters) => {
|
||||
resetTourState(tourId);
|
||||
}
|
||||
});
|
||||
|
||||
// Watch for the resize event.
|
||||
window.addEventListener("resize", () => {
|
||||
// Only listen for the running tour.
|
||||
if (currentTour && currentTour.tourRunning) {
|
||||
clearTimeout(window.resizedFinished);
|
||||
window.resizedFinished = setTimeout(() => {
|
||||
// Wait until the resize event has finished.
|
||||
currentStepNo = currentTour.getCurrentStepNumber();
|
||||
restartTourAndKeepProgress = true;
|
||||
resetTourState(tourId);
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -187,7 +203,13 @@ const startBootstrapTour = (tourId, template, tourConfig) => {
|
||||
});
|
||||
|
||||
currentTour = new BootstrapTour(tourConfig);
|
||||
return currentTour.startTour();
|
||||
let startAt = 0;
|
||||
if (restartTourAndKeepProgress && currentStepNo) {
|
||||
startAt = currentStepNo;
|
||||
restartTourAndKeepProgress = false;
|
||||
currentStepNo = null;
|
||||
}
|
||||
return currentTour.startTour(startAt);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,17 +18,16 @@ Feature: Test if the login form provides the correct feedback
|
||||
|
||||
Scenario: Test login language selector
|
||||
Given remote langimport tests are enabled
|
||||
And I log in as "admin"
|
||||
And I navigate to "Language > Language packs" in site administration
|
||||
And I set the field "Available language packs" to "nl,es"
|
||||
And I press "Install selected language pack(s)"
|
||||
And I trigger cron
|
||||
And I am on homepage
|
||||
And I log out
|
||||
And the following "language packs" exist:
|
||||
| language |
|
||||
| nl |
|
||||
| es |
|
||||
And the following config values are set as admin:
|
||||
| langmenu | 1 |
|
||||
And I follow "Log in"
|
||||
And I open the action menu in "region-main" "region"
|
||||
# The line below contains the unicode character U+200E before and after the brackets, please be very careful editing this line.
|
||||
And I choose "Nederlands (nl)" in the open action menu
|
||||
When I choose "Nederlands (nl)" in the open action menu
|
||||
Then I should see "Gebruikersnaam"
|
||||
|
||||
@_file_upload
|
||||
|
||||
@@ -59,9 +59,10 @@ Feature: The my overview block allows users to hide their courses
|
||||
And I click on "Removed from view" "link" in the "Course overview" "block"
|
||||
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
|
||||
And I click on "Restore to view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
|
||||
And I reload the page
|
||||
And I should not see "Course 2" in the "Course overview" "block"
|
||||
And I click on "Removed from view" "button" in the "Course overview" "block"
|
||||
When I click on "All" "link" in the "Course overview" "block"
|
||||
And I reload the page
|
||||
Then I should see "Course 2" in the "Course overview" "block"
|
||||
|
||||
Scenario: Test show toggle functionality w/ favorites
|
||||
|
||||
@@ -146,6 +146,7 @@ Feature: My overview block pagination
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
When I am on the "My courses" page logged in as "student1"
|
||||
And I wait until ".block_myoverview [data-control='next']" "css_element" exists
|
||||
And I click on "[data-control='next']" "css_element" in the "Course overview" "block"
|
||||
Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should contain "disabled"
|
||||
And I log out
|
||||
|
||||
+5
-4
@@ -51,17 +51,18 @@ class recentlyaccesseditems_item_exporter extends \core\external\exporter {
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/modinfolib.php');
|
||||
|
||||
$iconurl = get_fast_modinfo($this->data->courseid)->cms[$this->data->cmid]->get_icon_url();
|
||||
$iconclass = $iconurl->get_param('filtericon') ? '' : 'nofilter';
|
||||
return array(
|
||||
'viewurl' => (new moodle_url('/mod/'.$this->data->modname.'/view.php',
|
||||
array('id' => $this->data->cmid)))->out(false),
|
||||
'courseviewurl' => (new moodle_url('/course/view.php', array('id' => $this->data->courseid)))->out(false),
|
||||
'icon' => \html_writer::img(
|
||||
get_fast_modinfo($this->data->courseid)->cms[$this->data->cmid]->get_icon_url(),
|
||||
$iconurl,
|
||||
get_string('pluginname', $this->data->modname),
|
||||
['title' => get_string('pluginname', $this->data->modname), 'class' => 'icon']
|
||||
['title' => get_string('pluginname', $this->data->modname), 'class' => "icon $iconclass"]
|
||||
),
|
||||
'purpose' => plugin_supports('mod', $this->data->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER)
|
||||
'purpose' => plugin_supports('mod', $this->data->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="activityiconcontainer small {{purpose}} courseicon align-self-top align-self-center mx-3 mb-1 mb-sm-0 text-nowrap">
|
||||
{{#icon}}
|
||||
{{#iconurl}}
|
||||
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon ">
|
||||
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon {{iconclass}}">
|
||||
{{/iconurl}}
|
||||
{{^iconurl}}
|
||||
{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}
|
||||
|
||||
+6
-1
@@ -62,12 +62,15 @@ class event_icon_exporter extends exporter {
|
||||
$isgroupevent = ($group && !empty($groupid));
|
||||
$isuserevent = ($user && !empty($userid));
|
||||
$iconurl = '';
|
||||
$iconclass = '';
|
||||
|
||||
if ($isactivityevent) {
|
||||
$key = 'monologo';
|
||||
$component = $coursemodule->get('modname');
|
||||
|
||||
$iconurl = get_fast_modinfo($courseid)->get_cm($coursemodule->get('id'))->get_icon_url()->out(false);
|
||||
$iconurl = get_fast_modinfo($courseid)->get_cm($coursemodule->get('id'))->get_icon_url();
|
||||
$iconclass = $iconurl->get_param('filtericon') ? '' : 'nofilter';
|
||||
$iconurl = $iconurl->out(false);
|
||||
if (get_string_manager()->string_exists($event->get_type(), $component)) {
|
||||
$alttext = get_string($event->get_type(), $component);
|
||||
} else {
|
||||
@@ -121,6 +124,7 @@ class event_icon_exporter extends exporter {
|
||||
$data->component = $component;
|
||||
$data->alttext = $alttext;
|
||||
$data->iconurl = $iconurl;
|
||||
$data->iconclass = $iconclass;
|
||||
|
||||
parent::__construct($data, $related);
|
||||
}
|
||||
@@ -136,6 +140,7 @@ class event_icon_exporter extends exporter {
|
||||
'component' => ['type' => PARAM_TEXT],
|
||||
'alttext' => ['type' => PARAM_TEXT],
|
||||
'iconurl' => ['type' => PARAM_TEXT],
|
||||
'iconclass' => ['type' => PARAM_TEXT],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -179,6 +179,9 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
$whereclause = implode(' AND ', $whereconditions);
|
||||
|
||||
// Build SQL subquery and conditions for filtered events based on priorities.
|
||||
$subquerytimeconditions = array_filter($whereconditions, function($condition) {
|
||||
return (strpos($condition, 'time') !== false);
|
||||
});
|
||||
$subquerywhere = '';
|
||||
$subqueryconditions = [];
|
||||
$subqueryparams = [];
|
||||
@@ -194,7 +197,12 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
// Set calendar filters.
|
||||
list($usercourses, $usergroups, $user) = calendar_set_filters($usercourses, true, $userrecord);
|
||||
|
||||
$allusercourses = array_merge($allusercourses, $usercourses);
|
||||
$filteredcourses = is_array($courses) ? $courses : [$courses];
|
||||
$filteredcourses = array_filter($usercourses, function($course) use ($filteredcourses) {
|
||||
return in_array($course, $filteredcourses);
|
||||
});
|
||||
|
||||
$allusercourses = array_merge($allusercourses, $filteredcourses);
|
||||
|
||||
// Flag to indicate whether the query needs to exclude group overrides.
|
||||
$viewgroupsonly = false;
|
||||
@@ -203,7 +211,8 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
// Set filter condition for the user's events.
|
||||
// Even though $user is a single scalar, we still use get_in_or_equal() because we are inside a loop.
|
||||
list($inusers, $inuserparams) = $DB->get_in_or_equal($user, SQL_PARAMS_NAMED);
|
||||
$subqueryconditions[] = "(ev.userid $inusers AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
|
||||
$condition = "(ev.userid $inusers AND ev.courseid = 0 AND ev.groupid = 0 AND ev.categoryid = 0)";
|
||||
$subqueryconditions[] = $condition;
|
||||
$subqueryparams = array_merge($subqueryparams, $inuserparams);
|
||||
|
||||
foreach ($usercourses as $courseid) {
|
||||
@@ -220,11 +229,11 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
// Set filter condition for the user's group events.
|
||||
if ($usergroups === true || $viewgroupsonly) {
|
||||
// Fetch group events, but not group overrides.
|
||||
$subqueryconditions[] = "(ev.groupid != 0 AND ev.eventtype = 'group')";
|
||||
$groupconditions = "(ev.groupid != 0 AND ev.eventtype = 'group')";
|
||||
} else if (!empty($usergroups)) {
|
||||
// Fetch group events and group overrides.
|
||||
list($inusergroups, $inusergroupparams) = $DB->get_in_or_equal($usergroups, SQL_PARAMS_NAMED);
|
||||
$subqueryconditions[] = "(ev.groupid $inusergroups)";
|
||||
$groupconditions = "(ev.groupid $inusergroups)";
|
||||
$subqueryparams = array_merge($subqueryparams, $inusergroupparams);
|
||||
}
|
||||
}
|
||||
@@ -263,8 +272,20 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
// Set subquery filter condition for the courses.
|
||||
if (!empty($subquerycourses)) {
|
||||
list($incourses, $incoursesparams) = $DB->get_in_or_equal($subquerycourses, SQL_PARAMS_NAMED);
|
||||
$subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid $incourses AND ev.categoryid = 0)";
|
||||
$subqueryparams = array_merge($subqueryparams, $incoursesparams);
|
||||
if (isset($groupconditions)) {
|
||||
$groupconditions = $groupconditions." OR ";
|
||||
} else {
|
||||
$groupconditions = '';
|
||||
}
|
||||
$condition = "($groupconditions(ev.groupid = 0 AND ev.courseid $incourses AND ev.categoryid = 0))";
|
||||
$subtimesparams = [];
|
||||
if (!empty($subquerytimeconditions)) {
|
||||
$subtimes = $this->subquerytimeconditions("courses", $subquerytimeconditions, $whereparams);
|
||||
$condition .= $subtimes['where'];
|
||||
$subtimesparams = $subtimes['params'];
|
||||
}
|
||||
$subqueryconditions[] = $condition;
|
||||
$subqueryparams = array_merge($subqueryparams, $incoursesparams, $subtimesparams);
|
||||
}
|
||||
|
||||
// Set subquery filter condition for the categories.
|
||||
@@ -272,8 +293,15 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
$subqueryconditions[] = "(ev.categoryid != 0 AND ev.eventtype = 'category')";
|
||||
} else if (!empty($categories)) {
|
||||
list($incategories, $incategoriesparams) = $DB->get_in_or_equal($categories, SQL_PARAMS_NAMED);
|
||||
$subqueryconditions[] = "(ev.groupid = 0 AND ev.courseid = 0 AND ev.categoryid $incategories)";
|
||||
$subqueryparams = array_merge($subqueryparams, $incategoriesparams);
|
||||
$condition = "(ev.groupid = 0 AND ev.courseid = 0 AND ev.categoryid $incategories)";
|
||||
$subtimesparams = [];
|
||||
if (!empty($subquerytimeconditions)) {
|
||||
$subtimes = $this->subquerytimeconditions("cats", $subquerytimeconditions, $whereparams);
|
||||
$condition .= $subtimes['where'];
|
||||
$subtimesparams = $subtimes['params'];
|
||||
}
|
||||
$subqueryconditions[] = $condition;
|
||||
$subqueryparams = array_merge($subqueryparams, $incategoriesparams, $subtimesparams);
|
||||
}
|
||||
|
||||
// Build the WHERE condition for the sub-query.
|
||||
@@ -322,4 +350,36 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter
|
||||
|
||||
return $events === false ? [] : $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query fragment and params, with time constraints applied
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param array $conditions
|
||||
* @param array $params
|
||||
* @return array [<where>, <params>]
|
||||
*/
|
||||
protected function subquerytimeconditions(string $prefix, array $conditions, array $params): array {
|
||||
$outwhere = '';
|
||||
$outparams = [];
|
||||
// Most specific to least specific.
|
||||
$timeparams = ['timefromid', 'timefrom3', 'timefrom2', 'timefrom1', 'timefrom', 'timetoid', 'timeto2', 'timeto1', 'timeto'];
|
||||
$whereconditions = [];
|
||||
foreach ($conditions as $condition) {
|
||||
$where = $condition;
|
||||
// This query has been borrowed from the main WHERE clause, so the alias needs to be renamed to match the union.
|
||||
$where = str_replace('e.id', 'ev.id', $where);
|
||||
foreach ($timeparams as $timeparam) {
|
||||
if (isset($params[$timeparam])) {
|
||||
$where = str_replace(":{$timeparam}", ":{$prefix}{$timeparam}", $where);
|
||||
$outparams["{$prefix}{$timeparam}"] = $params[$timeparam];
|
||||
}
|
||||
}
|
||||
$whereconditions[] = $where;
|
||||
}
|
||||
if (count($whereconditions) > 0) {
|
||||
$outwhere = ' AND ' . implode(' AND ', $whereconditions);
|
||||
}
|
||||
return ['where' => $outwhere, 'params' => $outparams];
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2561,7 +2561,7 @@ function calendar_format_event_time($event, $now, $linkparams = null, $usecommon
|
||||
function calendar_show_event_type($type, $user = null) {
|
||||
$default = CALENDAR_EVENT_SITE + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP + CALENDAR_EVENT_USER;
|
||||
|
||||
if (get_user_preferences('calendar_persistflt', 0, $user) === 0) {
|
||||
if ((int)get_user_preferences('calendar_persistflt', 0, $user) === 0) {
|
||||
global $SESSION;
|
||||
if (!isset($SESSION->calendarshoweventtype)) {
|
||||
$SESSION->calendarshoweventtype = $default;
|
||||
@@ -2584,7 +2584,7 @@ function calendar_show_event_type($type, $user = null) {
|
||||
* @param stdClass|int $user moodle user object or id, null means current user
|
||||
*/
|
||||
function calendar_set_event_type_display($type, $display = null, $user = null) {
|
||||
$persist = get_user_preferences('calendar_persistflt', 0, $user);
|
||||
$persist = (int)get_user_preferences('calendar_persistflt', 0, $user);
|
||||
$default = CALENDAR_EVENT_SITE + CALENDAR_EVENT_COURSE + CALENDAR_EVENT_GROUP
|
||||
+ CALENDAR_EVENT_USER + CALENDAR_EVENT_COURSECAT;
|
||||
if ($persist === 0) {
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="activityiconcontainer small {{{purpose}}} courseicon mr-3">
|
||||
{{#icon}}
|
||||
{{#iconurl}}
|
||||
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon ">
|
||||
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon {{iconclass}}">
|
||||
{{/iconurl}}
|
||||
{{^iconurl}}
|
||||
{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
@core @core_calendar @javascript
|
||||
Feature: Perform calendar filter actions
|
||||
In order to test the calendar filters with preselected options
|
||||
As a user
|
||||
I need to filter calendar events by certain criteria
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | idnumber | category |
|
||||
| Year | year | |
|
||||
| Department C1 | department-c1 | year |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format | category |
|
||||
| Course 1 | C1 | topics | department-c1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "groups" exist:
|
||||
| name | course | idnumber |
|
||||
| Group 1 | C1 | G1 |
|
||||
And the following "group members" exist:
|
||||
| user | group |
|
||||
| teacher1 | G1 |
|
||||
And the following "events" exist:
|
||||
| name | eventtype |
|
||||
| Site event | site |
|
||||
And the following "events" exist:
|
||||
| name | eventtype | course |
|
||||
| C1 event | course | C1 |
|
||||
And the following "events" exist:
|
||||
| name | eventtype | category |
|
||||
| Dep1a event | category | department-c1 |
|
||||
And the following "events" exist:
|
||||
| name | eventtype | group | course |
|
||||
| Group1 event | group | G1 | C1 |
|
||||
|
||||
Scenario: Teacher of a Course can see his events and filter them
|
||||
Given I log in as "teacher1"
|
||||
When I follow "Calendar" in the user menu
|
||||
Then I should see "C1 event"
|
||||
And I should see "Dep1a event"
|
||||
And I should see "Group1 event"
|
||||
And I click on "Hide category events" "link"
|
||||
And I should see "C1 event"
|
||||
And I should not see "Dep1a event"
|
||||
And I should see "Group1 event"
|
||||
And I click on "Hide course events" "link"
|
||||
And I should not see "C1 event"
|
||||
And I should not see "Dep1a event"
|
||||
And I should see "Group1 event"
|
||||
|
||||
Scenario: Teacher of a Course can see only non filtered events from user preferences calendar_savedflt
|
||||
Given I log in as "teacher1"
|
||||
And the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| teacher1 | calendar_persistflt | 1 |
|
||||
| teacher1 | calendar_savedflt | 13 |
|
||||
When I follow "Calendar" in the user menu
|
||||
Then I should not see "C1 event"
|
||||
And I should see "Dep1a event"
|
||||
And I should not see "Group1 event"
|
||||
|
||||
Scenario: Teacher of a Course can see all events because session is used and not user preference calendar_savedflt
|
||||
Given I log in as "teacher1"
|
||||
And the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| teacher1 | calendar_persistflt | 0 |
|
||||
| teacher1 | calendar_savedflt | 13 |
|
||||
When I follow "Calendar" in the user menu
|
||||
Then I should see "C1 event"
|
||||
And I should see "Dep1a event"
|
||||
And I should see "Group1 event"
|
||||
@@ -70,6 +70,10 @@ $CFG->dboptions = array(
|
||||
// can be removed for MySQL (by default it will
|
||||
// use 'utf8mb4_unicode_ci'. This option should
|
||||
// be removed for all other databases.
|
||||
// 'extrainfo' => [], // Extra information for the DB driver, e.g. SQL Server,
|
||||
// has additional configuration according to its environment,
|
||||
// which the administrator can specify to alter and
|
||||
// override any connection options.
|
||||
// 'fetchbuffersize' => 100000, // On PostgreSQL, this option sets a limit
|
||||
// on the number of rows that are fetched into
|
||||
// memory when doing a large recordset query
|
||||
|
||||
@@ -14,26 +14,20 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* core_contentbank specific renderers
|
||||
*
|
||||
* @package core_contentbank
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_contentbank\output;
|
||||
|
||||
use context_coursecat;
|
||||
use core_contentbank\content;
|
||||
use core_contentbank\contentbank;
|
||||
use renderable;
|
||||
use templatable;
|
||||
use renderer_base;
|
||||
use stdClass;
|
||||
use core_contentbank\content;
|
||||
|
||||
/**
|
||||
* Class containing data for bank content
|
||||
*
|
||||
* @package core_contentbank
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
@@ -138,7 +132,8 @@ class bankcontent implements renderable, templatable {
|
||||
}
|
||||
$options = [];
|
||||
foreach ($this->allowedcategories as $allowedcategory) {
|
||||
$options[$allowedcategory->ctxid] = $allowedcategory->name;
|
||||
$options[$allowedcategory->ctxid] = format_string($allowedcategory->name, true,
|
||||
context_coursecat::instance($allowedcategory->ctxinstance));
|
||||
}
|
||||
if (!empty($options)) {
|
||||
$allowedcontexts['categories'] = [get_string('coursecategories') => $options];
|
||||
@@ -154,14 +149,15 @@ class bankcontent implements renderable, templatable {
|
||||
$allowedcontexts['courses'] = [get_string('courses') => $options];
|
||||
}
|
||||
if (!empty($allowedcontexts)) {
|
||||
$url = new \moodle_url('/contentbank/index.php');
|
||||
$strchoosecontext = get_string('choosecontext', 'core_contentbank');
|
||||
$singleselect = new \single_select(
|
||||
$url,
|
||||
new \moodle_url('/contentbank/index.php'),
|
||||
'contextid',
|
||||
$allowedcontexts,
|
||||
$this->context->id,
|
||||
get_string('choosecontext', 'core_contentbank')
|
||||
$strchoosecontext
|
||||
);
|
||||
$singleselect->set_label($strchoosecontext, ['class' => 'sr-only']);
|
||||
$data->allowedcontexts = $singleselect->export_for_template($output);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,16 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class containing data for a content view.
|
||||
*
|
||||
* @package core_contentbank
|
||||
* @copyright 2020 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_contentbank\output;
|
||||
|
||||
use context;
|
||||
use core_contentbank\content;
|
||||
use core_contentbank\contenttype;
|
||||
use moodle_url;
|
||||
@@ -180,8 +174,13 @@ class viewcontent implements renderable, templatable {
|
||||
$data->editcontenturl = $editcontenturl->out(false);
|
||||
}
|
||||
|
||||
$closeurl = new moodle_url('/contentbank/index.php', ['contextid' => $this->content->get_contextid()]);
|
||||
$data->closeurl = $closeurl->out(false);
|
||||
// Close/exit link for those users who can access that context.
|
||||
$context = context::instance_by_id($this->content->get_contextid());
|
||||
if (has_capability('moodle/contentbank:access', $context)) {
|
||||
$closeurl = new moodle_url('/contentbank/index.php', ['contextid' => $context->id]);
|
||||
$data->closeurl = $closeurl->out(false);
|
||||
}
|
||||
|
||||
$data->actionmenu = $this->get_edit_actions_dropdown();
|
||||
$data->heading = $this->content->get_name();
|
||||
if ($this->content->get_visibility() == content::VISIBILITY_UNLISTED) {
|
||||
|
||||
@@ -54,31 +54,28 @@ along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
}}
|
||||
{{#heading}}<h2>{{heading}}</h2>{{/heading}}
|
||||
{{#usercanedit}}
|
||||
<div class="cb-toolbar-container container-fluid my-2">
|
||||
<div class="row">
|
||||
<div class="d-flex">
|
||||
{{#usercanedit}}
|
||||
<div class="d-flex mr-3">
|
||||
<a href="{{editcontenturl}}" class="btn btn-primary" data-action="edit-content">
|
||||
{{#str}}edit{{/str}}
|
||||
</a>
|
||||
</div>
|
||||
{{/usercanedit}}
|
||||
|
||||
{{#actionmenu}}
|
||||
<div class="ml-3">
|
||||
{{> core_contentbank/contentbankmenu }}
|
||||
</div>
|
||||
{{/actionmenu}}
|
||||
{{#actionmenu}}
|
||||
<div>
|
||||
{{> core_contentbank/contentbankmenu }}
|
||||
</div>
|
||||
{{/actionmenu}}
|
||||
|
||||
{{#closeurl}}
|
||||
<div class="ml-auto">
|
||||
<a href="{{closeurl}}" class="btn btn-secondary" data-action="close-content">
|
||||
{{#str}}exit, core_contentbank{{/str}}
|
||||
</a>
|
||||
</div>
|
||||
{{/closeurl}}
|
||||
</div>
|
||||
</div>
|
||||
{{/usercanedit}}
|
||||
{{^usercanedit}}
|
||||
{{#actionmenu}}
|
||||
{{> core_contentbank/contentbankmenu }}
|
||||
{{/actionmenu}}
|
||||
{{/usercanedit}}
|
||||
|
||||
@@ -34,21 +34,20 @@ Feature: Navigate to different contexts in the content bank
|
||||
And I add the "Navigation" block if not present
|
||||
And I expand "Site pages" node
|
||||
When I click on "Content bank" "link"
|
||||
And "contextid" "select" should exist
|
||||
And the "contextid" select box should contain "System"
|
||||
And the "contextid" select box should contain "Cat 1"
|
||||
And the "contextid" select box should contain "Cat 2"
|
||||
And the "contextid" select box should contain "C0"
|
||||
And the "contextid" select box should contain "C1"
|
||||
And the "contextid" select box should contain "C2"
|
||||
And the "Choose course or category" select box should contain "System"
|
||||
And the "Choose course or category" select box should contain "Cat 1"
|
||||
And the "Choose course or category" select box should contain "Cat 2"
|
||||
And the "Choose course or category" select box should contain "C0"
|
||||
And the "Choose course or category" select box should contain "C1"
|
||||
And the "Choose course or category" select box should contain "C2"
|
||||
And I should see "santjordi.h5p"
|
||||
And I should not see "santjordi_rose.h5p"
|
||||
And I should not see "Dragon.h5p"
|
||||
And I set the field "contextid" to "Cat 1"
|
||||
And I set the field "Choose course or category" to "Cat 1"
|
||||
Then I should not see "santjordi.h5p"
|
||||
And I should see "santjordi_rose.h5p"
|
||||
And I should not see "Dragon.h5p"
|
||||
And I set the field "contextid" to "C0"
|
||||
And I set the field "Choose course or category" to "C0"
|
||||
And I should not see "santjordi.h5p"
|
||||
And I should not see "santjordi_rose.h5p"
|
||||
And I should see "Dragon.h5p"
|
||||
@@ -69,18 +68,17 @@ Feature: Navigate to different contexts in the content bank
|
||||
And I add the "Navigation" block if not present
|
||||
And I expand "Site pages" node
|
||||
When I click on "Content bank" "link"
|
||||
And "contextid" "select" should exist
|
||||
And the "contextid" select box should contain "C0"
|
||||
And the "contextid" select box should contain "C1"
|
||||
And the "contextid" select box should not contain "System"
|
||||
And the "contextid" select box should not contain "Cat 1"
|
||||
And the "contextid" select box should not contain "Cat 2"
|
||||
And the "contextid" select box should not contain "C2"
|
||||
And the "Choose course or category" select box should contain "C0"
|
||||
And the "Choose course or category" select box should contain "C1"
|
||||
And the "Choose course or category" select box should not contain "System"
|
||||
And the "Choose course or category" select box should not contain "Cat 1"
|
||||
And the "Choose course or category" select box should not contain "Cat 2"
|
||||
And the "Choose course or category" select box should not contain "C2"
|
||||
And I should see "Dragon.h5p"
|
||||
And I should not see "princess.h5p"
|
||||
And I should not see "santjordi.h5p"
|
||||
And I should not see "santjordi_rose.h5p"
|
||||
And I set the field "contextid" to "C1"
|
||||
And I set the field "Choose course or category" to "C1"
|
||||
Then I should not see "Dragon.h5p"
|
||||
And I should see "princess.h5p"
|
||||
And I should not see "santjordi.h5p"
|
||||
@@ -91,14 +89,13 @@ Feature: Navigate to different contexts in the content bank
|
||||
And I am on the "C0" "Course" page logged in as "teacher"
|
||||
And I expand "Site pages" node
|
||||
When I click on "Content bank" "link"
|
||||
And "contextid" "select" should exist
|
||||
And the "contextid" select box should contain "C0"
|
||||
And the "contextid" select box should contain "C1"
|
||||
And the "contextid" select box should contain "Cat 1"
|
||||
And the "contextid" select box should not contain "System"
|
||||
And the "contextid" select box should not contain "Cat 2"
|
||||
And the "contextid" select box should not contain "C2"
|
||||
And the "Choose course or category" select box should contain "C0"
|
||||
And the "Choose course or category" select box should contain "C1"
|
||||
And the "Choose course or category" select box should contain "Cat 1"
|
||||
And the "Choose course or category" select box should not contain "System"
|
||||
And the "Choose course or category" select box should not contain "Cat 2"
|
||||
And the "Choose course or category" select box should not contain "C2"
|
||||
And I should see "Dragon.h5p"
|
||||
And I set the field "contextid" to "Cat 1"
|
||||
And I set the field "Choose course or category" to "Cat 1"
|
||||
And I should not see "Dragon.h5p"
|
||||
And I should see "santjordi_rose.h5p"
|
||||
|
||||
@@ -11,7 +11,7 @@ Feature: Store the content bank view preference
|
||||
And I log in as "admin"
|
||||
And I follow "Manage private files..."
|
||||
And I upload "h5p/tests/fixtures/filltheblanks.h5p" file to "Files" filemanager
|
||||
And I upload "h5p/tests/fixtures/greeting-card-887.h5p" file to "Files" filemanager
|
||||
And I upload "h5p/tests/fixtures/greeting-card.h5p" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
And I am on site homepage
|
||||
And I turn editing mode on
|
||||
@@ -35,7 +35,7 @@ Feature: Store the content bank view preference
|
||||
And I click on "Upload" "link"
|
||||
And I click on "Choose a file..." "button"
|
||||
And I click on "Private files" "link" in the ".fp-repo-area" "css_element"
|
||||
And I click on "greeting-card-887.h5p" "link"
|
||||
And I click on "greeting-card.h5p" "link"
|
||||
And I set the field "Save as" to "greetingcard.h5p"
|
||||
And I click on "Select this file" "button"
|
||||
And I click on "Save changes" "button"
|
||||
|
||||
@@ -28,9 +28,12 @@ namespace core_contentbank;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use advanced_testcase;
|
||||
use context_block;
|
||||
use context_course;
|
||||
use context_coursecat;
|
||||
use context_module;
|
||||
use context_system;
|
||||
use context_user;
|
||||
use Exception;
|
||||
|
||||
global $CFG;
|
||||
@@ -364,7 +367,7 @@ class contentbank_test extends advanced_testcase {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$systemcontext = \context_system::instance();
|
||||
$name = 'greeting-card-887.h5p';
|
||||
$name = 'greeting-card.h5p';
|
||||
|
||||
// Create a dummy H5P file.
|
||||
$dummyh5p = array(
|
||||
@@ -637,72 +640,35 @@ class contentbank_test extends advanced_testcase {
|
||||
/**
|
||||
* Test the behaviour of is_context_allowed().
|
||||
*
|
||||
* @dataProvider context_provider
|
||||
* @param \Closure $getcontext Get the context to check.
|
||||
* @param bool $expectedresult Expected result.
|
||||
*
|
||||
* @covers ::is_context_allowed
|
||||
*/
|
||||
public function test_is_context_allowed(\Closure $getcontext, bool $expectedresult): void {
|
||||
public function test_is_context_allowed(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$cb = new contentbank();
|
||||
$context = $getcontext();
|
||||
$this->assertEquals($expectedresult, $cb->is_context_allowed($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_is_context_allowed().
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function context_provider(): array {
|
||||
// System context.
|
||||
$this->assertTrue($cb->is_context_allowed(context_system::instance()));
|
||||
|
||||
return [
|
||||
'System context' => [
|
||||
function (): \context {
|
||||
return \context_system::instance();
|
||||
},
|
||||
true,
|
||||
],
|
||||
'User context' => [
|
||||
function (): \context {
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
return \context_user::instance($user->id);
|
||||
},
|
||||
false,
|
||||
],
|
||||
'Course category context' => [
|
||||
function (): \context {
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
return \context_coursecat::instance($coursecat->id);
|
||||
},
|
||||
true,
|
||||
],
|
||||
'Course context' => [
|
||||
function (): \context {
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
return \context_course::instance($course->id);
|
||||
},
|
||||
true,
|
||||
],
|
||||
'Module context' => [
|
||||
function (): \context {
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$module = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
|
||||
return \context_module::instance($module->cmid);
|
||||
},
|
||||
false,
|
||||
],
|
||||
'Block context' => [
|
||||
function (): \context {
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
$block = $this->getDataGenerator()->create_block('online_users', ['parentcontextid' => $coursecontext->id]);
|
||||
return \context_block::instance($block->id);
|
||||
},
|
||||
false,
|
||||
],
|
||||
];
|
||||
// User context.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->assertFalse($cb->is_context_allowed(context_user::instance($user->id)));
|
||||
|
||||
// Category context.
|
||||
$category = $this->getDataGenerator()->create_category();
|
||||
$this->assertTrue($cb->is_context_allowed(context_coursecat::instance($category->id)));
|
||||
|
||||
// Course context.
|
||||
$course = $this->getDataGenerator()->create_course(['category' => $category->id]);
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
$this->assertTrue($cb->is_context_allowed($coursecontext));
|
||||
|
||||
// Module context.
|
||||
$module = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
|
||||
$this->assertFalse($cb->is_context_allowed(context_module::instance($module->cmid)));
|
||||
|
||||
// Block context.
|
||||
$block = $this->getDataGenerator()->create_block('online_users', ['parentcontextid' => $coursecontext->id]);
|
||||
$this->assertFalse($cb->is_context_allowed(context_block::instance($block->id)));
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -58,7 +58,7 @@ define(
|
||||
// Eventually, core_courseformat/local/content/actions will handle all actions for
|
||||
// component compatible formats and the default actions.js won't be necessary anymore.
|
||||
// Meanwhile, we filter the migrated actions.
|
||||
const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];
|
||||
const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection', 'cmMoveRight', 'cmMoveLeft'];
|
||||
|
||||
// The course reactive instance.
|
||||
const courseeditor = editor.getCurrentCourseEditor();
|
||||
@@ -79,6 +79,7 @@ define(
|
||||
TOGGLE: '.toggle-display,.dropdown-toggle',
|
||||
SECTIONLI: 'li.section',
|
||||
SECTIONACTIONMENU: '.section_action_menu',
|
||||
SECTIONITEM: '[data-for="section_title"]',
|
||||
ADDSECTIONS: '.changenumsections [data-add-sections]',
|
||||
SECTIONBADGES: '[data-region="sectionbadges"]',
|
||||
};
|
||||
@@ -978,7 +979,7 @@ define(
|
||||
|
||||
// The section and activity names are edited using inplace editable.
|
||||
// The "update" jQuery event must be captured in order to update the course state.
|
||||
$('body').on('updated', `${SELECTOR.SECTIONLI} [data-inplaceeditable]`, function(e) {
|
||||
$('body').on('updated', `${SELECTOR.SECTIONLI} ${SELECTOR.SECTIONITEM} [data-inplaceeditable]`, function(e) {
|
||||
if (e.ajaxreturn && e.ajaxreturn.itemid) {
|
||||
const state = courseeditor.state;
|
||||
const section = state.section.get(e.ajaxreturn.itemid);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace core_course\local\repository;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_component;
|
||||
use core_course\local\entity\content_item;
|
||||
use core_course\local\entity\lang_string_title;
|
||||
use core_course\local\entity\string_title;
|
||||
@@ -269,12 +270,20 @@ class content_item_readonly_repository implements content_item_readonly_reposito
|
||||
$archetype = plugin_supports('mod', $mod->name, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
|
||||
$purpose = plugin_supports('mod', $mod->name, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER);
|
||||
|
||||
$icon = 'monologo';
|
||||
// Quick check for monologo icons.
|
||||
// Plugins that don't have monologo icons will be displayed as is and CSS filter will not be applied.
|
||||
$hasmonologoicons = core_component::has_monologo_icon('mod', $mod->name);
|
||||
$iconclass = '';
|
||||
if (!$hasmonologoicons) {
|
||||
$iconclass = 'nofilter';
|
||||
}
|
||||
$contentitem = new content_item(
|
||||
$mod->id,
|
||||
$mod->name,
|
||||
new lang_string_title("modulename", $mod->name),
|
||||
new \moodle_url($urlbase, ['add' => $mod->name]),
|
||||
$OUTPUT->pix_icon('monologo', '', $mod->name, ['class' => 'icon activityicon']),
|
||||
$OUTPUT->pix_icon($icon, '', $mod->name, ['class' => "activityicon $iconclass"]),
|
||||
$help,
|
||||
$archetype,
|
||||
'mod_' . $mod->name,
|
||||
|
||||
@@ -81,7 +81,7 @@ class content_notification_task extends adhoc_task {
|
||||
// Get module names in the user's language.
|
||||
$modnames = get_module_types_names();
|
||||
$a = [
|
||||
'coursename' => get_course_display_name_for_list($course),
|
||||
'coursename' => format_string(get_course_display_name_for_list($course), true, ['context' => $modcontext]),
|
||||
'courselink' => (new \moodle_url('/course/view.php', ['id' => $course->id]))->out(false),
|
||||
'modulename' => format_string($cm->name, $modcontext->id),
|
||||
'moduletypename' => $modnames[$cm->modname],
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -8,6 +8,6 @@ define("core_courseformat/local/courseindex/cm",["exports","core_courseformat/lo
|
||||
* @class core_courseformat/local/courseindex/cm
|
||||
* @copyright 2021 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_dndcmitem=_interopRequireDefault(_dndcmitem),_templates=_interopRequireDefault(_templates),_prefetch=_interopRequireDefault(_prefetch),_config=_interopRequireDefault(_config);_prefetch.default.prefetchTemplate("core_courseformat/local/courseindex/cmcompletion");class Component extends _dndcmitem.default{create(){this.name="courseindex_cm",this.selectors={CM_NAME:"[data-for='cm_name']",CM_COMPLETION:"[data-for='cm_completion']"},this.classes={CMHIDDEN:"dimmed",LOCKED:"editinprogress",RESTRICTIONS:"restrictions",PAGEITEM:"pageitem"},this.id=this.element.dataset.id}static init(target,selectors){return new Component({element:document.getElementById(target),selectors:selectors})}stateReady(state){this.configDragDrop(this.id);const cm=state.cm.get(this.id),course=state.course;this._refreshCompletion({state:state,element:cm}),window.location.href!=cm.url&&window.location.href!="".concat(course.baseurl,"#").concat(cm.anchor)||(this.reactive.dispatch("setPageItem","cm",this.id),this.element.scrollIntoView({block:"center"})),_config.default.contextid!=_config.default.courseContextId&&_config.default.contextInstanceId==this.id&&(this.reactive.dispatch("setPageItem","cm",this.id,!0),this.element.scrollIntoView({block:"center"})),cm.uservisible||this.addEventListener(this.getElement(this.selectors.CM_NAME),"click",this._activityAnchor)}getWatchers(){return[{watch:"cm[".concat(this.id,"]:deleted"),handler:this.remove},{watch:"cm[".concat(this.id,"]:updated"),handler:this._refreshCm},{watch:"cm[".concat(this.id,"].completionstate:updated"),handler:this._refreshCompletion},{watch:"course.pageItem:updated",handler:this._refreshPageItem}]}_refreshCm(_ref){var _element$dragging,_element$locked,_element$hascmrestric;let{element:element}=_ref;this.element.classList.toggle(this.classes.CMHIDDEN,!element.visible),this.getElement(this.selectors.CM_NAME).innerHTML=element.name,this.element.classList.toggle(this.classes.DRAGGING,null!==(_element$dragging=element.dragging)&&void 0!==_element$dragging&&_element$dragging),this.element.classList.toggle(this.classes.LOCKED,null!==(_element$locked=element.locked)&&void 0!==_element$locked&&_element$locked),this.element.classList.toggle(this.classes.RESTRICTIONS,null!==(_element$hascmrestric=element.hascmrestrictions)&&void 0!==_element$hascmrestric&&_element$hascmrestric),this.locked=element.locked}_refreshPageItem(_ref2){let{element:element}=_ref2;if(!element.pageItem)return;const isPageId="cm"==element.pageItem.type&&element.pageItem.id==this.id;this.element.classList.toggle(this.classes.PAGEITEM,isPageId),isPageId&&!this.reactive.isEditing&&this.element.scrollIntoView({block:"nearest"})}async _refreshCompletion(_ref3){let{state:state,element:element}=_ref3;if(this.reactive.isEditing||!element.istrackeduser)return;const completionElement=this.getElement(this.selectors.CM_COMPLETION);if(completionElement.dataset.value==element.completionstate)return;const data=this.reactive.getExporter().cmCompletion(state,element);try{const{html:html,js:js}=await _templates.default.renderForPromise("core_courseformat/local/courseindex/cmcompletion",data);_templates.default.replaceNode(completionElement,html,js)}catch(error){throw error}}_activityAnchor(event){const cm=this.reactive.get("cm",this.id);if(document.getElementById(cm.anchor))return void setTimeout((()=>{this.reactive.dispatch("setPageItem","cm",cm.id)}),50);const course=this.reactive.get("course"),section=this.reactive.get("section",cm.sectionid);if(!section)return;const url="".concat(course.baseurl,"§ion=").concat(section.number,"#").concat(cm.anchor);event.preventDefault(),window.location=url}}return _exports.default=Component,_exports.default}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_dndcmitem=_interopRequireDefault(_dndcmitem),_templates=_interopRequireDefault(_templates),_prefetch=_interopRequireDefault(_prefetch),_config=_interopRequireDefault(_config);_prefetch.default.prefetchTemplate("core_courseformat/local/courseindex/cmcompletion");class Component extends _dndcmitem.default{create(){this.name="courseindex_cm",this.selectors={CM_NAME:"[data-for='cm_name']",CM_COMPLETION:"[data-for='cm_completion']"},this.classes={CMHIDDEN:"dimmed",LOCKED:"editinprogress",RESTRICTIONS:"restrictions",PAGEITEM:"pageitem",INDENTED:"indented"},this.id=this.element.dataset.id}static init(target,selectors){return new Component({element:document.getElementById(target),selectors:selectors})}stateReady(state){this.configDragDrop(this.id);const cm=state.cm.get(this.id),course=state.course;this._refreshCompletion({state:state,element:cm});const anchor=new URL(window.location.href).hash.replace("#","");(window.location.href==cm.url||window.location.href.includes(course.baseurl)&&anchor==cm.anchor)&&(this.reactive.dispatch("setPageItem","cm",this.id),this.element.scrollIntoView({block:"center"})),_config.default.contextid!=_config.default.courseContextId&&_config.default.contextInstanceId==this.id&&(this.reactive.dispatch("setPageItem","cm",this.id,!0),this.element.scrollIntoView({block:"center"})),cm.uservisible||this.addEventListener(this.getElement(this.selectors.CM_NAME),"click",this._activityAnchor)}getWatchers(){return[{watch:"cm[".concat(this.id,"]:deleted"),handler:this.remove},{watch:"cm[".concat(this.id,"]:updated"),handler:this._refreshCm},{watch:"cm[".concat(this.id,"].completionstate:updated"),handler:this._refreshCompletion},{watch:"course.pageItem:updated",handler:this._refreshPageItem}]}_refreshCm(_ref){var _element$dragging,_element$locked,_element$hascmrestric;let{element:element}=_ref;this.element.classList.toggle(this.classes.CMHIDDEN,!element.visible),this.getElement(this.selectors.CM_NAME).innerHTML=element.name,this.element.classList.toggle(this.classes.DRAGGING,null!==(_element$dragging=element.dragging)&&void 0!==_element$dragging&&_element$dragging),this.element.classList.toggle(this.classes.LOCKED,null!==(_element$locked=element.locked)&&void 0!==_element$locked&&_element$locked),this.element.classList.toggle(this.classes.RESTRICTIONS,null!==(_element$hascmrestric=element.hascmrestrictions)&&void 0!==_element$hascmrestric&&_element$hascmrestric),this.element.classList.toggle(this.classes.INDENTED,element.indent),this.locked=element.locked}_refreshPageItem(_ref2){let{element:element}=_ref2;if(!element.pageItem)return;const isPageId="cm"==element.pageItem.type&&element.pageItem.id==this.id;this.element.classList.toggle(this.classes.PAGEITEM,isPageId),isPageId&&!this.reactive.isEditing&&this.element.scrollIntoView({block:"nearest"})}async _refreshCompletion(_ref3){let{state:state,element:element}=_ref3;if(this.reactive.isEditing||!element.istrackeduser)return;const completionElement=this.getElement(this.selectors.CM_COMPLETION);if(completionElement.dataset.value==element.completionstate)return;const data=this.reactive.getExporter().cmCompletion(state,element);try{const{html:html,js:js}=await _templates.default.renderForPromise("core_courseformat/local/courseindex/cmcompletion",data);_templates.default.replaceNode(completionElement,html,js)}catch(error){throw error}}_activityAnchor(event){const cm=this.reactive.get("cm",this.id);if(document.getElementById(cm.anchor))return void setTimeout((()=>{this.reactive.dispatch("setPageItem","cm",cm.id)}),50);const course=this.reactive.get("course"),section=this.reactive.get("section",cm.sectionid);if(!section)return;const url="".concat(course.baseurl,"§ion=").concat(section.number,"#").concat(cm.anchor);event.preventDefault(),window.location=url}}return _exports.default=Component,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=cm.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -233,6 +233,7 @@ export default class Component extends BaseComponent {
|
||||
// State changes thaty require to reload course modules.
|
||||
{watch: `cm.visible:updated`, handler: this._reloadCm},
|
||||
{watch: `cm.sectionid:updated`, handler: this._reloadCm},
|
||||
{watch: `cm.indent:updated`, handler: this._reloadCm},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,14 @@ import jQuery from 'jquery';
|
||||
// Load global strings.
|
||||
prefetchStrings('core', ['movecoursesection', 'movecoursemodule', 'confirm', 'delete']);
|
||||
|
||||
// Mutations are dispatched by the course content actions.
|
||||
// Formats can use this module addActions static method to add custom actions.
|
||||
// Direct mutations can be simple strings (mutation) name or functions.
|
||||
const directMutations = {
|
||||
cmMoveRight: 'cmMoveRight',
|
||||
cmMoveLeft: 'cmMoveLeft',
|
||||
};
|
||||
|
||||
export default class extends BaseComponent {
|
||||
|
||||
/**
|
||||
@@ -68,6 +76,20 @@ export default class extends BaseComponent {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extra actions to the module.
|
||||
*
|
||||
* @param {array} actions array of methods to execute
|
||||
*/
|
||||
static addActions(actions) {
|
||||
for (const [action, mutationReference] of Object.entries(actions)) {
|
||||
if (typeof mutationReference !== 'function' && typeof mutationReference !== 'string') {
|
||||
throw new Error(`${action} action must be a mutation name or a function`);
|
||||
}
|
||||
directMutations[action] = mutationReference;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial state ready method.
|
||||
*
|
||||
@@ -114,10 +136,23 @@ export default class extends BaseComponent {
|
||||
}
|
||||
|
||||
// Invoke proper method.
|
||||
const methodName = this._actionMethodName(target.dataset.action);
|
||||
const actionName = target.dataset.action;
|
||||
const methodName = this._actionMethodName(actionName);
|
||||
|
||||
// Invoke proper method.
|
||||
if (this[methodName] !== undefined) {
|
||||
this[methodName](target, event);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check direct mutations or mutations handlers.
|
||||
if (directMutations[actionName] !== undefined) {
|
||||
if (typeof directMutations[actionName] === 'function') {
|
||||
directMutations[actionName](target, event);
|
||||
return;
|
||||
}
|
||||
this._requestMutationAction(target, event, directMutations[actionName]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +188,8 @@ export default class extends BaseComponent {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const pendingModalReady = new Pending(`courseformat/actions:prepareMoveSectionModal`);
|
||||
|
||||
// The section edit menu to refocus on end.
|
||||
const editTools = this._getClosestActionMenuToogler(target);
|
||||
|
||||
@@ -205,6 +242,8 @@ export default class extends BaseComponent {
|
||||
this.reactive.dispatch('sectionMove', [sectionId], target.dataset.id);
|
||||
this._destroyModal(modal, editTools);
|
||||
});
|
||||
|
||||
pendingModalReady.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +262,8 @@ export default class extends BaseComponent {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const pendingModalReady = new Pending(`courseformat/actions:prepareMoveCmModal`);
|
||||
|
||||
// The section edit menu to refocus on end.
|
||||
const editTools = this._getClosestActionMenuToogler(target);
|
||||
|
||||
@@ -298,6 +339,8 @@ export default class extends BaseComponent {
|
||||
this.reactive.dispatch('cmMove', [cmId], targetSectionId, targetCmId);
|
||||
this._destroyModal(modal, editTools);
|
||||
});
|
||||
|
||||
pendingModalReady.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,6 +399,21 @@ export default class extends BaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic mutation action helper.
|
||||
*
|
||||
* @param {Element} target the dispatch action element
|
||||
* @param {Event} event the triggered event
|
||||
* @param {string} mutationName the mutation name
|
||||
*/
|
||||
async _requestMutationAction(target, event, mutationName) {
|
||||
if (!target.dataset.id) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
this.reactive.dispatch(mutationName, [target.dataset.id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all add sections actions.
|
||||
*
|
||||
|
||||
@@ -56,6 +56,49 @@ export default class {
|
||||
return JSON.parse(ajaxresult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a basic section state action.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {string} action the action name
|
||||
* @param {array} sectionIds the section ids
|
||||
* @param {number} targetSectionId optional target section id (for moving actions)
|
||||
* @param {number} targetCmId optional target cm id (for moving actions)
|
||||
*/
|
||||
async _sectionBasicAction(stateManager, action, sectionIds, targetSectionId, targetCmId) {
|
||||
const course = stateManager.get('course');
|
||||
this.sectionLock(stateManager, sectionIds, true);
|
||||
const updates = await this._callEditWebservice(
|
||||
action,
|
||||
course.id,
|
||||
sectionIds,
|
||||
targetSectionId,
|
||||
targetCmId
|
||||
);
|
||||
stateManager.processUpdates(updates);
|
||||
this.sectionLock(stateManager, sectionIds, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a basic course module state action.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {string} action the action name
|
||||
* @param {array} cmIds the cm ids
|
||||
* @param {number} targetSectionId optional target section id (for moving actions)
|
||||
* @param {number} targetCmId optional target cm id (for moving actions)
|
||||
*/
|
||||
async _cmBasicAction(stateManager, action, cmIds, targetSectionId, targetCmId) {
|
||||
const course = stateManager.get('course');
|
||||
this.cmLock(stateManager, cmIds, true);
|
||||
const updates = await this._callEditWebservice(
|
||||
action,
|
||||
course.id,
|
||||
cmIds,
|
||||
targetSectionId,
|
||||
targetCmId
|
||||
);
|
||||
stateManager.processUpdates(updates);
|
||||
this.cmLock(stateManager, cmIds, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutation module initialize.
|
||||
@@ -194,6 +237,24 @@ export default class {
|
||||
this._setElementsValue(stateManager, 'cm', cmIds, 'completionstate', newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move cms to the right: indent = 1.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {array} cmIds the list of cm ids
|
||||
*/
|
||||
async cmMoveRight(stateManager, cmIds) {
|
||||
await this._cmBasicAction(stateManager, 'cm_moveright', cmIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move cms to the left: indent = 0.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {array} cmIds the list of cm ids
|
||||
*/
|
||||
async cmMoveLeft(stateManager, cmIds) {
|
||||
await this._cmBasicAction(stateManager, 'cm_moveleft', cmIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock or unlock course modules.
|
||||
*
|
||||
|
||||
@@ -52,6 +52,7 @@ export default class Component extends DndCmItem {
|
||||
LOCKED: 'editinprogress',
|
||||
RESTRICTIONS: 'restrictions',
|
||||
PAGEITEM: 'pageitem',
|
||||
INDENTED: 'indented',
|
||||
};
|
||||
// We need our id to watch specific events.
|
||||
this.id = this.element.dataset.id;
|
||||
@@ -85,8 +86,12 @@ export default class Component extends DndCmItem {
|
||||
state,
|
||||
element: cm,
|
||||
});
|
||||
const url = new URL(window.location.href);
|
||||
const anchor = url.hash.replace('#', '');
|
||||
// Check if the current url is the cm url.
|
||||
if (window.location.href == cm.url || window.location.href == `${course.baseurl}#${cm.anchor}`) {
|
||||
if (window.location.href == cm.url
|
||||
|| (window.location.href.includes(course.baseurl) && anchor == cm.anchor)
|
||||
) {
|
||||
this.reactive.dispatch('setPageItem', 'cm', this.id);
|
||||
this.element.scrollIntoView({block: "center"});
|
||||
}
|
||||
@@ -132,6 +137,7 @@ export default class Component extends DndCmItem {
|
||||
this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);
|
||||
this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);
|
||||
this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrestrictions ?? false);
|
||||
this.element.classList.toggle(this.classes.INDENTED, element.indent);
|
||||
this.locked = element.locked;
|
||||
}
|
||||
|
||||
|
||||
@@ -456,14 +456,6 @@ abstract class base {
|
||||
/**
|
||||
* Returns true if this course format uses activity indentation.
|
||||
*
|
||||
* Indentation is not supported by core formats anymore and may be deprecated in the future.
|
||||
* This method will keep a default return "true" for legacy reasons but new formats should override
|
||||
* it with a return false to prevent future deprecations.
|
||||
*
|
||||
* A message in a bottle: if indentation is finally deprecated, both behat steps i_indent_right_activity
|
||||
* and i_indent_left_activity should be removed as well. Right now no core behat uses them but indentation
|
||||
* is not officially deprecated so they are still available for the contrib formats.
|
||||
*
|
||||
* @return bool if the course format uses indentation.
|
||||
*/
|
||||
public function uses_indentation(): bool {
|
||||
|
||||
@@ -98,9 +98,12 @@ class cmname implements named_templatable, renderable {
|
||||
return [];
|
||||
}
|
||||
|
||||
$iconurl = $mod->get_icon_url();
|
||||
$iconclass = $iconurl->get_param('filtericon') ? '' : 'nofilter';
|
||||
$data = [
|
||||
'url' => $mod->url,
|
||||
'icon' => $mod->get_icon_url(),
|
||||
'icon' => $iconurl,
|
||||
'iconclass' => $iconclass,
|
||||
'modname' => $mod->modname,
|
||||
'textclasses' => $displayoptions['textclasses'] ?? '',
|
||||
'purpose' => plugin_supports('mod', $mod->modname, FEATURE_MOD_PURPOSE, MOD_PURPOSE_OTHER),
|
||||
|
||||
@@ -106,6 +106,7 @@ class cmitem implements named_templatable, renderable {
|
||||
'extraclasses' => $mod->extraclasses,
|
||||
'cmformat' => $item->export_for_template($output),
|
||||
'hasinfo' => $hasinfo,
|
||||
'indent' => ($format->uses_indentation()) ? $mod->indent : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,9 @@ class cm implements renderable {
|
||||
'sectionnumber' => $section->section,
|
||||
'uservisible' => $cm->uservisible,
|
||||
'hascmrestrictions' => $this->get_has_restrictions(),
|
||||
'module' => $cm->modname,
|
||||
'plugin' => 'mod_' . $cm->modname,
|
||||
'indent' => ($format->uses_indentation()) ? $cm->indent : 0,
|
||||
];
|
||||
|
||||
// Check the user access type to this cm.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace core_courseformat;
|
||||
|
||||
use core\event\course_module_updated;
|
||||
use core_courseformat\base as course_format;
|
||||
use core_courseformat\stateupdates;
|
||||
use cm_info;
|
||||
@@ -258,6 +259,79 @@ class stateactions {
|
||||
$this->course_state($updates, $course);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move course cms to the right. Indent = 1.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $targetsectionid not used
|
||||
* @param int $targetcmid not used
|
||||
*/
|
||||
public function cm_moveright(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
): void {
|
||||
$this->set_cm_indentation($updates, $course, $ids, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move course cms to the left. Indent = 0.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $targetsectionid not used
|
||||
* @param int $targetcmid not used
|
||||
*/
|
||||
public function cm_moveleft(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
): void {
|
||||
$this->set_cm_indentation($updates, $course, $ids, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to define the cm indentation level.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $indent new value for indentation
|
||||
*/
|
||||
protected function set_cm_indentation(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids,
|
||||
int $indent
|
||||
): void {
|
||||
global $DB;
|
||||
|
||||
$this->validate_cms($course, $ids, __FUNCTION__);
|
||||
|
||||
// Check capabilities on every activity context.
|
||||
foreach ($ids as $cmid) {
|
||||
$modcontext = context_module::instance($cmid);
|
||||
require_capability('moodle/course:manageactivities', $modcontext);
|
||||
}
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
$cms = $this->get_cm_info($modinfo, $ids);
|
||||
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($cms), SQL_PARAMS_NAMED);
|
||||
$DB->set_field_select('course_modules', 'indent', $indent, "id $insql", $inparams);
|
||||
rebuild_course_cache($course->id, false, true);
|
||||
foreach ($cms as $cm) {
|
||||
$modcontext = context_module::instance($cm->id);
|
||||
course_module_updated::create_from_cm($cm, $modcontext)->trigger();
|
||||
$updates->add_cm_put($cm->id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract several cm_info from the course_modinfo.
|
||||
*
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"modstealth": true
|
||||
"modstealth": true,
|
||||
"indent": 1
|
||||
}
|
||||
}}
|
||||
<div class="activity-item {{#modstealth}}hiddenactivity{{/modstealth}}{{!
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
{
|
||||
"url": "#",
|
||||
"icon": "../../../pix/help.svg",
|
||||
"iconclass": "",
|
||||
"pluginname": "File",
|
||||
"textclasses": "",
|
||||
"purpose": "content",
|
||||
@@ -47,7 +48,7 @@
|
||||
<div class="activity-instance d-flex flex-column">
|
||||
<div class="activitytitle media {{textclasses}} modtype_{{modname}} position-relative align-self-start">
|
||||
<div class="activityiconcontainer {{purpose}} courseicon align-self-start mr-3">
|
||||
<img src="{{{icon}}}" class="activityicon " alt="{{{modname}}} icon">
|
||||
<img src="{{{icon}}}" class="activityicon {{iconclass}}" alt="{{{modname}}} icon">
|
||||
</div>
|
||||
<div class="media-body align-self-center">
|
||||
{{#pluginname}}
|
||||
|
||||
@@ -34,11 +34,12 @@
|
||||
"id": 3,
|
||||
"anchor": "module-3",
|
||||
"module": "forum",
|
||||
"extraclasses": "newmessages"
|
||||
"extraclasses": "newmessages",
|
||||
"indent": 0
|
||||
}
|
||||
}}
|
||||
<li
|
||||
class="activity activity-wrapper {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}}"
|
||||
class="activity activity-wrapper {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}} {{#indent}}indented{{/indent}}"
|
||||
id="{{anchor}}"
|
||||
data-for="cmitem"
|
||||
data-id="{{id}}"
|
||||
|
||||
@@ -28,14 +28,16 @@
|
||||
"isactive": 1,
|
||||
"uniqid": "0",
|
||||
"accessvisible": 1,
|
||||
"hascmrestrictions": 0
|
||||
"hascmrestrictions": 0,
|
||||
"indent": 1
|
||||
}
|
||||
}}
|
||||
<li class="courseindex-item
|
||||
{{#isactive}}active{{/isactive}}
|
||||
{{#hascmrestrictions}}restrictions{{/hascmrestrictions}}
|
||||
{{^accessvisible}}dimmed{{/accessvisible}}
|
||||
{{#url}} d-flex {{/url}} {{^url}} d-flex-noedit {{/url}}"
|
||||
{{#url}} d-flex {{/url}} {{^url}} d-flex-noedit {{/url}}
|
||||
{{#indent}} indented {{/indent}}"
|
||||
id="{{uniqid}}-course-index-cm-{{id}}"
|
||||
data-for="cm"
|
||||
data-id="{{id}}"
|
||||
|
||||
@@ -180,7 +180,6 @@ class stateactions_test extends \advanced_testcase {
|
||||
* @param array $params the ids, targetsection and targetcm to use as params
|
||||
* @param array $expectedresults List of the course module names expected after calling the method.
|
||||
* @param bool $expectedexception If this call will raise an exception.
|
||||
|
||||
*/
|
||||
public function test_get_state(
|
||||
string $format,
|
||||
@@ -578,4 +577,176 @@ class stateactions_test extends \advanced_testcase {
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method for testing a specific state action.
|
||||
*
|
||||
* @param string $method the method to test
|
||||
* @param string $role the user role
|
||||
* @param string[] $idrefs the sections or cms id references to be used as method params
|
||||
* @param bool $expectedexception whether the call should throw an exception
|
||||
* @param int $expectedtotal the expected total number of state puts
|
||||
* @param string|null $coursefield the course field to check
|
||||
* @param int|string|null $coursevalue the section field value
|
||||
* @param string|null $sectionfield the section field to check
|
||||
* @param int|string|null $sectionvalue the section field value
|
||||
* @param string|null $cmfield the cm field to check
|
||||
* @param int|string|null $cmvalue the cm field value
|
||||
* @return array the state update summary
|
||||
*/
|
||||
protected function basic_state_text(
|
||||
string $method = 'section_hide',
|
||||
string $role = 'editingteacher',
|
||||
array $idrefs = [],
|
||||
bool $expectedexception = false,
|
||||
int $expectedtotal = 0,
|
||||
?string $coursefield = null,
|
||||
$coursevalue = 0,
|
||||
?string $sectionfield = null,
|
||||
$sectionvalue = 0,
|
||||
?string $cmfield = null,
|
||||
$cmvalue = 0
|
||||
): array {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a course with 3 sections, 1 of them hidden.
|
||||
$course = $this->create_course('topics', 3, [2]);
|
||||
|
||||
$references = $this->course_references($course);
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
|
||||
$this->setUser($user);
|
||||
|
||||
// Add some activities to the course. One visible and one hidden in both sections 1 and 2.
|
||||
$references["cm0"] = $this->create_activity($course->id, 'assign', 1, true);
|
||||
$references["cm1"] = $this->create_activity($course->id, 'book', 1, false);
|
||||
$references["cm2"] = $this->create_activity($course->id, 'glossary', 2, true);
|
||||
$references["cm3"] = $this->create_activity($course->id, 'page', 2, false);
|
||||
|
||||
if ($expectedexception) {
|
||||
$this->expectException(moodle_exception::class);
|
||||
}
|
||||
|
||||
// Initialise stateupdates.
|
||||
$courseformat = course_get_format($course->id);
|
||||
$updates = new stateupdates($courseformat);
|
||||
|
||||
// Execute the method.
|
||||
$actions = new stateactions();
|
||||
$actions->$method(
|
||||
$updates,
|
||||
$course,
|
||||
$this->translate_references($references, $idrefs),
|
||||
);
|
||||
|
||||
// Format results in a way we can compare easily.
|
||||
$results = $this->summarize_updates($updates);
|
||||
|
||||
// Most state actions does not use create or remove actions because they are designed
|
||||
// to refresh parts of the state.
|
||||
$this->assertEquals(0, $results['create']['count']);
|
||||
$this->assertEquals(0, $results['remove']['count']);
|
||||
|
||||
// Validate we have all the expected entries.
|
||||
$this->assertEquals($expectedtotal, $results['put']['count']);
|
||||
|
||||
// Validate course, section and cm.
|
||||
if (!empty($coursefield)) {
|
||||
foreach ($results['put']['course'] as $courseid) {
|
||||
$this->assertEquals($coursevalue, $results['put']['course'][$courseid][$coursefield]);
|
||||
}
|
||||
}
|
||||
if (!empty($sectionfield)) {
|
||||
foreach ($results['put']['section'] as $section) {
|
||||
$this->assertEquals($sectionvalue, $section->$sectionfield);
|
||||
}
|
||||
}
|
||||
if (!empty($cmfield)) {
|
||||
foreach ($results['put']['cm'] as $cm) {
|
||||
$this->assertEquals($cmvalue, $cm->$cmfield);
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for basic role tests.
|
||||
*
|
||||
* @return array the testing scenarios
|
||||
*/
|
||||
public function basic_role_provider() {
|
||||
return [
|
||||
'editingteacher' => [
|
||||
'role' => 'editingteacher',
|
||||
'expectedexception' => false,
|
||||
],
|
||||
'teacher' => [
|
||||
'role' => 'teacher',
|
||||
'expectedexception' => true,
|
||||
],
|
||||
'student' => [
|
||||
'role' => 'student',
|
||||
'expectedexception' => true,
|
||||
],
|
||||
'guest' => [
|
||||
'role' => 'guest',
|
||||
'expectedexception' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for cm_moveright
|
||||
*
|
||||
* @covers ::cm_moveright
|
||||
* @dataProvider basic_role_provider
|
||||
* @param string $role the user role
|
||||
* @param bool $expectedexception if it will expect an exception.
|
||||
*/
|
||||
public function test_cm_moveright(
|
||||
string $role = 'editingteacher',
|
||||
bool $expectedexception = false
|
||||
): void {
|
||||
$this->basic_state_text(
|
||||
'cm_moveright',
|
||||
$role,
|
||||
['cm0', 'cm1', 'cm2', 'cm3'],
|
||||
$expectedexception,
|
||||
4,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'indent',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for cm_moveleft
|
||||
*
|
||||
* @covers ::cm_moveleft
|
||||
* @dataProvider basic_role_provider
|
||||
* @param string $role the user role
|
||||
* @param bool $expectedexception if it will expect an exception.
|
||||
*/
|
||||
public function test_cm_moveleft(
|
||||
string $role = 'editingteacher',
|
||||
bool $expectedexception = false
|
||||
): void {
|
||||
$this->basic_state_text(
|
||||
'cm_moveleft',
|
||||
$role,
|
||||
['cm0', 'cm1', 'cm2', 'cm3'],
|
||||
$expectedexception,
|
||||
4,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'indent',
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,5 +48,16 @@ function xmldb_format_topics_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v4.0.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2022041901) {
|
||||
// For sites migrating from 4.0.x or 4.1.x where the indentation was removed,
|
||||
// we are disabling 'indentation' value by default.
|
||||
if ($oldversion >= 2022041900) {
|
||||
set_config('indentation', 0, 'format_topics');
|
||||
} else {
|
||||
set_config('indentation', 1, 'format_topics');
|
||||
}
|
||||
upgrade_plugin_savepoint(true, 2022041901, 'format', 'topics');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,3 +36,5 @@ $string['page-course-view-topics-x'] = 'Any course page in topics format';
|
||||
$string['hidefromothers'] = 'Hide topic';
|
||||
$string['showfromothers'] = 'Show topic';
|
||||
$string['privacy:metadata'] = 'The Topics format plugin does not store any personal data.';
|
||||
$string['indentation'] = 'Allow indentation on course page';
|
||||
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
|
||||
|
||||
@@ -51,7 +51,7 @@ class format_topics extends core_courseformat\base {
|
||||
}
|
||||
|
||||
public function uses_indentation(): bool {
|
||||
return false;
|
||||
return (get_config('format_topics', 'indentation')) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -453,7 +453,9 @@ class format_topics extends core_courseformat\base {
|
||||
*/
|
||||
public function get_config_for_external() {
|
||||
// Return everything (nothing to hide).
|
||||
return $this->get_format_options();
|
||||
$formatoptions = $this->get_format_options();
|
||||
$formatoptions['indentation'] = get_config('format_topics', 'indentation');
|
||||
return $formatoptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Settings for format_topics
|
||||
*
|
||||
* @package format_topics
|
||||
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($ADMIN->fulltree) {
|
||||
$url = new moodle_url('/admin/course/resetindentation.php', ['format' => 'topics']);
|
||||
$link = html_writer::link($url, get_string('resetindentation', 'admin'));
|
||||
$settings->add(new admin_setting_configcheckbox(
|
||||
'format_topics/indentation',
|
||||
new lang_string('indentation', 'format_topics'),
|
||||
new lang_string('indentation_help', 'format_topics').'<br />'.$link,
|
||||
1
|
||||
));
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2022041900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2022041901; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2022041200; // Requires this Moodle version.
|
||||
$plugin->component = 'format_topics'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -48,5 +48,16 @@ function xmldb_format_weeks_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v4.0.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2022041901) {
|
||||
// For sites migrating from 4.0.x or 4.1.x where the indentation was removed,
|
||||
// we are disabling 'indentation' value by default.
|
||||
if ($oldversion >= 2022041900) {
|
||||
set_config('indentation', 0, 'format_weeks');
|
||||
} else {
|
||||
set_config('indentation', 1, 'format_weeks');
|
||||
}
|
||||
upgrade_plugin_savepoint(true, 2022041901, 'format', 'weeks');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,3 +39,5 @@ $string['showfromothers'] = 'Show week';
|
||||
$string['automaticenddate'] = 'Calculate the end date from the number of sections';
|
||||
$string['automaticenddate_help'] = 'If enabled, the end date for the course will be automatically calculated from the number of sections and the course start date.';
|
||||
$string['privacy:metadata'] = 'The Weekly format plugin does not store any personal data.';
|
||||
$string['indentation'] = 'Allow indentation on course page';
|
||||
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
|
||||
|
||||
@@ -50,7 +50,7 @@ class format_weeks extends core_courseformat\base {
|
||||
}
|
||||
|
||||
public function uses_indentation(): bool {
|
||||
return false;
|
||||
return (get_config('format_weeks', 'indentation')) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,7 +615,9 @@ class format_weeks extends core_courseformat\base {
|
||||
*/
|
||||
public function get_config_for_external() {
|
||||
// Return everything (nothing to hide).
|
||||
return $this->get_format_options();
|
||||
$formatoptions = $this->get_format_options();
|
||||
$formatoptions['indentation'] = get_config('format_weeks', 'indentation');
|
||||
return $formatoptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Settings for format_weeks
|
||||
*
|
||||
* @package format_weeks
|
||||
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($ADMIN->fulltree) {
|
||||
$url = new moodle_url('/admin/course/resetindentation.php', ['format' => 'weeks']);
|
||||
$link = html_writer::link($url, get_string('resetindentation', 'admin'));
|
||||
$settings->add(new admin_setting_configcheckbox(
|
||||
'format_weeks/indentation',
|
||||
new lang_string('indentation', 'format_weeks'),
|
||||
new lang_string('indentation_help', 'format_weeks').'<br />'.$link,
|
||||
1
|
||||
));
|
||||
}
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2022041900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2022041901; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2022041200; // Requires this Moodle version.
|
||||
$plugin->component = 'format_weeks'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
+23
-10
@@ -1642,6 +1642,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
$coursecontext = context_course::instance($mod->course);
|
||||
$modcontext = context_module::instance($mod->id);
|
||||
$courseformat = course_get_format($mod->get_course());
|
||||
$usecomponents = $courseformat->supports_components();
|
||||
|
||||
$editcaps = array('moodle/course:manageactivities', 'moodle/course:activityvisibility', 'moodle/role:assign');
|
||||
$dupecaps = array('moodle/backup:backuptargetimport', 'moodle/restore:restoretargetimport');
|
||||
@@ -1700,7 +1701,9 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
if ($hasmanageactivities && $indent >= 0) {
|
||||
$indentlimits = new stdClass();
|
||||
$indentlimits->min = 0;
|
||||
$indentlimits->max = 16;
|
||||
// Legacy indentation could continue using a limit of 16,
|
||||
// but components based formats will be forced to use one level indentation only.
|
||||
$indentlimits->max = ($usecomponents) ? 1 : 16;
|
||||
if (right_to_left()) { // Exchange arrows on RTL
|
||||
$rightarrow = 't/left';
|
||||
$leftarrow = 't/right';
|
||||
@@ -1715,11 +1718,16 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
$enabledclass = '';
|
||||
}
|
||||
$actions['moveright'] = new action_menu_link_secondary(
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')),
|
||||
new pix_icon($rightarrow, '', 'moodle', array('class' => 'iconsmall')),
|
||||
new moodle_url($baseurl, ['id' => $mod->id, 'indent' => '1']),
|
||||
new pix_icon($rightarrow, '', 'moodle', ['class' => 'iconsmall']),
|
||||
$str->moveright,
|
||||
array('class' => 'editing_moveright ' . $enabledclass, 'data-action' => 'moveright',
|
||||
'data-keepopen' => true, 'data-sectionreturn' => $sr)
|
||||
[
|
||||
'class' => 'editing_moveright ' . $enabledclass,
|
||||
'data-action' => ($usecomponents) ? 'cmMoveRight' : 'moveright',
|
||||
'data-keepopen' => true,
|
||||
'data-sectionreturn' => $sr,
|
||||
'data-id' => $mod->id,
|
||||
]
|
||||
);
|
||||
|
||||
if ($indent <= $indentlimits->min) {
|
||||
@@ -1728,11 +1736,16 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
$enabledclass = '';
|
||||
}
|
||||
$actions['moveleft'] = new action_menu_link_secondary(
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')),
|
||||
new pix_icon($leftarrow, '', 'moodle', array('class' => 'iconsmall')),
|
||||
new moodle_url($baseurl, ['id' => $mod->id, 'indent' => '0']),
|
||||
new pix_icon($leftarrow, '', 'moodle', ['class' => 'iconsmall']),
|
||||
$str->moveleft,
|
||||
array('class' => 'editing_moveleft ' . $enabledclass, 'data-action' => 'moveleft',
|
||||
'data-keepopen' => true, 'data-sectionreturn' => $sr)
|
||||
[
|
||||
'class' => 'editing_moveleft ' . $enabledclass,
|
||||
'data-action' => ($usecomponents) ? 'cmMoveLeft' : 'moveleft',
|
||||
'data-keepopen' => true,
|
||||
'data-sectionreturn' => $sr,
|
||||
'data-id' => $mod->id,
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
@@ -2191,7 +2204,7 @@ function create_course($data, $editoroptions = NULL) {
|
||||
if ($editoroptions) {
|
||||
// summary text is updated later, we need context to store the files first
|
||||
$data->summary = '';
|
||||
$data->summary_format = FORMAT_HTML;
|
||||
$data->summary_format = $data->summary_editor['format'];
|
||||
}
|
||||
|
||||
// Get default completion settings as a fallback in case the enablecompletion field is not set.
|
||||
|
||||
+1
-1
@@ -853,7 +853,7 @@ function prepare_new_moduleinfo_data($course, $modulename, $section) {
|
||||
if (plugin_supports('mod', $data->modulename, FEATURE_MOD_INTRO, true)) {
|
||||
$draftid_editor = file_get_submitted_draft_itemid('introeditor');
|
||||
file_prepare_draft_area($draftid_editor, null, null, null, null, array('subdirs'=>true));
|
||||
$data->introeditor = array('text'=>'', 'format'=>FORMAT_HTML, 'itemid'=>$draftid_editor); // TODO: add better default
|
||||
$data->introeditor = array('text' => '', 'format' => editors_get_preferred_format(), 'itemid' => $draftid_editor);
|
||||
}
|
||||
|
||||
if (plugin_supports('mod', $data->modulename, FEATURE_ADVANCED_GRADING, false)
|
||||
|
||||
@@ -53,3 +53,41 @@ Feature: Add activities to courses
|
||||
And I add a "Database" to section "3" and I fill the form with:
|
||||
| Name | Test name |
|
||||
Then I should see "Required"
|
||||
|
||||
@javascript
|
||||
Scenario: The activity description should use the user's preferred editor on creation
|
||||
Given the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| admin | htmleditor | textarea |
|
||||
And I am logged in as admin
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
When I add a "Database" to section "3"
|
||||
Then the field "Description format" matches value "0"
|
||||
|
||||
@javascript
|
||||
Scenario: The activity description should preserve the format used once edited (markdown version)
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | introformat | course |
|
||||
| assign | A4 | Desc 4 | 4 | Course 1 |
|
||||
And the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| admin | htmleditor | textarea |
|
||||
And I am logged in as admin
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "A4" actions menu
|
||||
When I click on "Edit settings" "link" in the "A4" activity
|
||||
Then the field "Description format" matches value "4"
|
||||
|
||||
@javascript
|
||||
Scenario: The activity description should preserve the format used once edited (plain text version)
|
||||
Given the following "activities" exist:
|
||||
| activity | name | intro | introformat | course |
|
||||
| assign | A2 | Desc 2 | 2 | Course 1 |
|
||||
And the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| admin | htmleditor | textarea |
|
||||
And I am logged in as admin
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "A2" actions menu
|
||||
When I click on "Edit settings" "link" in the "A2" activity
|
||||
Then the field "Description format" matches value "2"
|
||||
|
||||
@@ -145,3 +145,62 @@ Feature: Course activity controls works as expected
|
||||
| weeks | 0 | "General" | should | should | "8 January - 14 January" |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
|
||||
| weeks | 1 | "General" | should | should not | "8 January - 14 January" |
|
||||
|
||||
@javascript
|
||||
Scenario Outline: Indentation should allow one level only
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format | coursedisplay | numsections | startdate |
|
||||
| Course 1 | C1 | <courseformat> | <coursedisplay> | 5 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| forum | Test forum name | Test forum description | C1 | forum1 |
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "Test forum name" actions menu
|
||||
Then "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
And I click on "Move right" "link" in the "Test forum name" activity
|
||||
And I open "Test forum name" actions menu
|
||||
And "Move right" "link" should not be visible
|
||||
And "Move left" "link" should be visible
|
||||
And I click on "Move left" "link" in the "Test forum name" activity
|
||||
And I open "Test forum name" actions menu
|
||||
And "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
|
||||
Examples:
|
||||
| courseformat |
|
||||
| topics |
|
||||
| weeks |
|
||||
|
||||
@javascript
|
||||
Scenario Outline: Admins could disable indentation
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format | coursedisplay | numsections | startdate |
|
||||
| Course 1 | C1 | <courseformat> | <coursedisplay> | 5 | 0 |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| forum | Test forum name | Test forum description | C1 | forum1 |
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "Test forum name" actions menu
|
||||
And "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
And I click on "Move right" "link" in the "Test forum name" activity
|
||||
When the following config values are set as admin:
|
||||
| indentation | 0 | format_<courseformat> |
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "Test forum name" actions menu
|
||||
Then "Move right" "link" should not exist
|
||||
And "Move left" "link" should not exist
|
||||
|
||||
Examples:
|
||||
| courseformat |
|
||||
| topics |
|
||||
| weeks |
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
@core @core_course
|
||||
Feature: Summary text format should be preserved on edit and set by preferred editor format on creation
|
||||
In order to edit the course summary
|
||||
As a course creator
|
||||
The format specified for the summary must be honored
|
||||
|
||||
Scenario: Preferred editor format should be used for summary field on course creation
|
||||
Given the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| admin | htmleditor | textarea |
|
||||
And I log in as "admin"
|
||||
And I go to the courses management page
|
||||
When I click on "Create new course" "link"
|
||||
Then the field "Course summary format" matches value "0"
|
||||
|
||||
Scenario: Summary format must be preserved on course edit
|
||||
Given the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| admin | htmleditor | textarea |
|
||||
And I log in as "admin"
|
||||
And I go to the courses management page
|
||||
And I click on "Create new course" "link"
|
||||
And I set the following fields to these values:
|
||||
| Course full name | C1 |
|
||||
| Course short name | C1 |
|
||||
| Course summary | Course description |
|
||||
# 4 is assumed to be Markdown format.
|
||||
And I set the field with xpath "//select[@name='summary_editor[format]']" to "4"
|
||||
And I press "Save and display"
|
||||
When I click on "Settings" "link"
|
||||
Then the field "Course summary format" matches value "4"
|
||||
@@ -2725,13 +2725,19 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
// Expect to receive all the fields.
|
||||
$this->assertCount(41, $result['courses'][0]);
|
||||
// Check default values for course format topics.
|
||||
$this->assertCount(2, $result['courses'][0]['courseformatoptions']);
|
||||
$this->assertCount(3, $result['courses'][0]['courseformatoptions']);
|
||||
foreach ($result['courses'][0]['courseformatoptions'] as $option) {
|
||||
if ($option['name'] == 'hiddensections') {
|
||||
$this->assertEquals(1, $option['value']);
|
||||
} else {
|
||||
$this->assertEquals('coursedisplay', $option['name']);
|
||||
$this->assertEquals(0, $option['value']);
|
||||
switch ($option['name']) {
|
||||
case 'hiddensections':
|
||||
$this->assertEquals(1, $option['value']);
|
||||
break;
|
||||
case 'coursedisplay':
|
||||
$this->assertEquals(0, $option['value']);
|
||||
break;
|
||||
case 'indentation':
|
||||
$this->assertEquals(1, $option['value']);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Feature: Inline editing H5P content anywhere
|
||||
| student1 | C1 | student |
|
||||
And the following "contentbank content" exist:
|
||||
| contextlevel | reference | contenttype | user | contentname | filepath |
|
||||
| Course | C1 | contenttype_h5p | admin | Greeting card | /h5p/tests/fixtures/greeting-card-887.h5p |
|
||||
| Course | C1 | contenttype_h5p | admin | Greeting card | /h5p/tests/fixtures/greeting-card.h5p |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | introformat | course | content | contentformat | idnumber |
|
||||
| page | PageName1 | PageDesc1 | 1 | C1 | H5Ptest | 1 | 1 |
|
||||
@@ -42,7 +42,7 @@ Feature: Inline editing H5P content anywhere
|
||||
And I log in as "teacher1"
|
||||
# Upload the H5P to private user files.
|
||||
And I follow "Manage private files..."
|
||||
And I upload "h5p/tests/fixtures/greeting-card-887.h5p" file to "Files" filemanager
|
||||
And I upload "h5p/tests/fixtures/greeting-card.h5p" file to "Files" filemanager
|
||||
And I click on "Save changes" "button"
|
||||
# Add H5P content to the page.
|
||||
And I am on "Course 1" course homepage
|
||||
@@ -51,7 +51,7 @@ Feature: Inline editing H5P content anywhere
|
||||
And I click on "Insert H5P" "button" in the "#fitem_id_page" "css_element"
|
||||
And I click on "Browse repositories..." "button" in the "Insert H5P" "dialogue"
|
||||
And I select "Private files" repository in file picker
|
||||
And I click on "greeting-card-887.h5p" "file" in repository content area
|
||||
And I click on "greeting-card.h5p" "file" in repository content area
|
||||
And I click on "Link to the file" "radio"
|
||||
And I click on "Select this file" "button"
|
||||
And I click on "Insert H5P" "button" in the "Insert H5P" "dialogue"
|
||||
|
||||
@@ -43,24 +43,24 @@ Feature: We can change what we are viewing on the grader report
|
||||
And I click on "Hide" "link" in the "Test assignment name 2" activity
|
||||
And I am on "Course 1" course homepage with editing mode off
|
||||
And I navigate to "View > Grader report" in the course gradebook
|
||||
And I should see "Test assignment name 1"
|
||||
And I should see "Test assignment name 2"
|
||||
And I should see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should see "Manual grade"
|
||||
And I should see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -6- | -7- |
|
||||
| Student 1 | 80 | 90 | 30 | 170 |
|
||||
And I click on "Change to aggregates only" "link"
|
||||
And I should not see "Test assignment name 1"
|
||||
And I should not see "Test assignment name 2"
|
||||
And I should not see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should not see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should not see "Manual grade"
|
||||
And I should see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- |
|
||||
| Student 1 | 170 |
|
||||
And I click on "Change to grades only" "link"
|
||||
And I should see "Test assignment name 1"
|
||||
And I should see "Test assignment name 2"
|
||||
And I should see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should see "Manual grade"
|
||||
And I should not see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
@@ -68,7 +68,7 @@ Feature: We can change what we are viewing on the grader report
|
||||
| Student 1 | 80 | 90 | 30 |
|
||||
|
||||
@javascript @skip_chrome_zerosize
|
||||
Scenario: View and minimise the grader report containing hidden activities without the 'moodle/grade:viewhidden' capability
|
||||
Scenario: Minimise the grader report containing hidden activities without the 'moodle/grade:viewhidden' capability
|
||||
When I am on "Course 1" course homepage with editing mode on
|
||||
And I open "Test assignment name 2" actions menu
|
||||
And I click on "Hide" "link" in the "Test assignment name 2" activity
|
||||
@@ -81,24 +81,24 @@ Feature: We can change what we are viewing on the grader report
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "View > Grader report" in the course gradebook
|
||||
And I should see "Test assignment name 1"
|
||||
And I should see "Test assignment name 2"
|
||||
And I should see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should see "Manual grade"
|
||||
And I should see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- | -5- | -6- | -7- |
|
||||
| Student 1 | 80 | - | 30 | 105.71 |
|
||||
And I click on "Change to aggregates only" "link"
|
||||
And I should not see "Test assignment name 1"
|
||||
And I should not see "Test assignment name 2"
|
||||
And I should not see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should not see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should not see "Manual grade"
|
||||
And I should see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
| -1- | -4- |
|
||||
| Student 1 | 105.71 |
|
||||
And I click on "Change to grades only" "link"
|
||||
And I should see "Test assignment name 1"
|
||||
And I should see "Test assignment name 2"
|
||||
And I should see "Test assignment name 1" in the "user-grades" "table"
|
||||
And I should see "Test assignment name 2" in the "user-grades" "table"
|
||||
And I should see "Manual grade"
|
||||
And I should not see "Course total"
|
||||
And the following should exist in the "user-grades" table:
|
||||
|
||||
@@ -60,8 +60,10 @@
|
||||
</div>
|
||||
{{#js}}
|
||||
(function() {
|
||||
H5PEmbedCommunicator.send('resize', {
|
||||
scrollHeight: document.body.scrollHeight
|
||||
});
|
||||
if (typeof H5PEmbedCommunicator !== 'undefined') {
|
||||
H5PEmbedCommunicator.send('resize', {
|
||||
scrollHeight: document.body.scrollHeight
|
||||
});
|
||||
}
|
||||
})();
|
||||
{{/js}}
|
||||
|
||||
@@ -349,7 +349,7 @@ class api_test extends \advanced_testcase {
|
||||
$syscontext = \context_system::instance();
|
||||
|
||||
// Create the original file.
|
||||
$filename = 'greeting-card-887.h5p';
|
||||
$filename = 'greeting-card.h5p';
|
||||
$path = __DIR__ . '/fixtures/' . $filename;
|
||||
$originalfile = helper::create_fake_stored_file_from_path($path);
|
||||
$originalfilerecord = [
|
||||
@@ -491,7 +491,7 @@ class api_test extends \advanced_testcase {
|
||||
}
|
||||
|
||||
// Create the file.
|
||||
$filename = 'greeting-card-887.h5p';
|
||||
$filename = 'greeting-card.h5p';
|
||||
$path = __DIR__ . '/fixtures/' . $filename;
|
||||
if ($filecomponent === 'contentbank') {
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
|
||||
@@ -1197,33 +1197,33 @@ class api_test extends \advanced_testcase {
|
||||
public function is_valid_package_provider(): array {
|
||||
return [
|
||||
'Valid H5P file (as admin)' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'filename' => '/fixtures/greeting-card.h5p',
|
||||
'expected' => true,
|
||||
'isadmin' => true,
|
||||
],
|
||||
'Valid H5P file (as user) without library update and checking content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'filename' => '/fixtures/greeting-card.h5p',
|
||||
'expected' => false, // Libraries are missing and user hasn't the right permissions to upload them.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => false,
|
||||
'skipcontent' => false,
|
||||
],
|
||||
'Valid H5P file (as user) with library update and checking content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'filename' => '/fixtures/greeting-card.h5p',
|
||||
'expected' => false, // Libraries are missing and user hasn't the right permissions to upload them.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => true,
|
||||
'skipcontent' => false,
|
||||
],
|
||||
'Valid H5P file (as user) without library update and skipping content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'filename' => '/fixtures/greeting-card.h5p',
|
||||
'expected' => true, // Content check is skipped so the package will be considered valid.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => false,
|
||||
'skipcontent' => true,
|
||||
],
|
||||
'Valid H5P file (as user) with library update and skipping content' => [
|
||||
'filename' => '/fixtures/greeting-card-887.h5p',
|
||||
'filename' => '/fixtures/greeting-card.h5p',
|
||||
'expected' => true, // Content check is skipped so the package will be considered valid.
|
||||
'isadmin' => false,
|
||||
'onlyupdatelibs' => true,
|
||||
|
||||
@@ -605,7 +605,7 @@ class file_storage_test extends \advanced_testcase {
|
||||
true,
|
||||
],
|
||||
'Icon not included' => [
|
||||
'greeting-card-887.h5p',
|
||||
'greeting-card.h5p',
|
||||
false,
|
||||
],
|
||||
];
|
||||
|
||||
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
+14
-14
@@ -14,30 +14,30 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Testing the H5P helper.
|
||||
*
|
||||
* @package core_h5p
|
||||
* @category test
|
||||
* @copyright 2019 Sara Arjona <sara@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_h5p;
|
||||
|
||||
use advanced_testcase;
|
||||
use core_h5p\local\library\autoloader;
|
||||
|
||||
/**
|
||||
* Test class covering the H5P helper.
|
||||
*
|
||||
* @package core_h5p
|
||||
* @category test
|
||||
* @copyright 2019 Sara Arjona <sara@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \core_h5p\helper
|
||||
*/
|
||||
class helper_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Register the H5P autoloader
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
autoloader::register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour of get_display_options().
|
||||
*
|
||||
@@ -137,7 +137,7 @@ class helper_test extends \advanced_testcase {
|
||||
$this->setUser($user);
|
||||
|
||||
// This is a valid .H5P file.
|
||||
$path = __DIR__ . '/fixtures/greeting-card-887.h5p';
|
||||
$path = __DIR__ . '/fixtures/greeting-card.h5p';
|
||||
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
|
||||
$factory->get_framework()->set_file($file);
|
||||
|
||||
@@ -173,7 +173,7 @@ class helper_test extends \advanced_testcase {
|
||||
$this->setUser($user);
|
||||
|
||||
// This is a valid .H5P file.
|
||||
$path = __DIR__ . '/fixtures/greeting-card-887.h5p';
|
||||
$path = __DIR__ . '/fixtures/greeting-card.h5p';
|
||||
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
|
||||
$factory->get_framework()->set_file($file);
|
||||
|
||||
@@ -247,7 +247,7 @@ class helper_test extends \advanced_testcase {
|
||||
$admin = get_admin();
|
||||
|
||||
// Prepare a valid .H5P file.
|
||||
$path = __DIR__ . '/fixtures/greeting-card-887.h5p';
|
||||
$path = __DIR__ . '/fixtures/greeting-card.h5p';
|
||||
|
||||
// Files created by users can't be deployed.
|
||||
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
|
||||
@@ -275,7 +275,7 @@ class helper_test extends \advanced_testcase {
|
||||
$admin = get_admin();
|
||||
|
||||
// Prepare a valid .H5P file.
|
||||
$path = __DIR__ . '/fixtures/greeting-card-887.h5p';
|
||||
$path = __DIR__ . '/fixtures/greeting-card.h5p';
|
||||
|
||||
// Libraries can't be updated when the file has been created by users.
|
||||
$file = helper::create_fake_stored_file_from_path($path, (int)$user->id);
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['cannotcreatedboninstall'] = '<p>Tietokantaa ei voi luoda.</p>
|
||||
<p>Määritettyä tietokantaa ei ole olemassa, eikä kyseisellä käyttäjällä ole oikeutta luoda tietokantaa.</p>
|
||||
<p>Sivuston järjestelmänvalvojan tulee tarkistaa tietokannan määritykset.</p>';
|
||||
$string['cannotcreatelangdir'] = 'Kielihakemistoa ei voida luoda';
|
||||
$string['cannotcreatetempdir'] = 'Temp-hakemistoa ei voitu luoda';
|
||||
$string['cannotdownloadcomponents'] = 'Komponentteja ei voitu ladata';
|
||||
@@ -38,10 +41,12 @@ $string['cannotsavemd5file'] = 'MD5-tiedostoa ei voitu tallentaa';
|
||||
$string['cannotsavezipfile'] = 'Zip-tiedostoa ei voitu tallentaa';
|
||||
$string['cannotunzipfile'] = 'Zip-tiedostoa ei voitu purkaa';
|
||||
$string['componentisuptodate'] = 'Komponentti on ajan tasalla';
|
||||
$string['dmlexceptiononinstall'] = '<p>Tapahtui tietokantavirhe [{$a->errorcode}].<br />{$a->debuginfo}</p>';
|
||||
$string['downloadedfilecheckfailed'] = 'Ladatun tiedoston tarkistus epäonnistui';
|
||||
$string['invalidmd5'] = 'Tarkistusmuuttuja oli väärin - yritä uudelleen';
|
||||
$string['missingrequiredfield'] = 'Joitakin vaadituista kentistä puuttuu';
|
||||
$string['remotedownloaderror'] = 'Komponentin lataaminen palvelimelle epäonnistui, ole hyvä ja varmista välityspalvelimen asetukset, PHP cURL -laajennus on suositeltu.<br /><br />Sinun täytyy ladata <a href="{$a->url}">{$a->url}</a> -tiedosto manuaalisesti, kopioi se kohteeseen "{$a->dest}" serverilläsi ja pura se sinne.';
|
||||
$string['remotedownloaderror'] = '<p>Komponentin lataaminen palvelimellesi epäonnistui. Tarkista välityspalvelimen asetukset: PHP cURL -laajennus on erittäin suositeltavaa.</p>
|
||||
<p>Sinun on ladattava <a href="{$a->url}">{$a->url}</a>-tiedosto manuaalisesti, kopioitava se palvelimellesi kohteeseen "{$a->dest}" ja purettava se sinne.</p>';
|
||||
$string['wrongdestpath'] = 'Virheellinen kohdekansio';
|
||||
$string['wrongsourcebase'] = 'Väärä lähteen web-osoitteen kanta';
|
||||
$string['wrongzipfilename'] = 'Virheellinen zip-tiedoston nimi';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'fr_ca';
|
||||
$string['thislanguage'] = 'Francais Canada – Épicène';
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['language'] = 'Langue';
|
||||
$string['next'] = 'Suivant';
|
||||
$string['previous'] = 'Précédent';
|
||||
+59
-29
@@ -29,38 +29,68 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['admindirname'] = 'Админ директор';
|
||||
$string['availablelangs'] = 'Боломжит хэлний багцууд';
|
||||
$string['chooselanguagehead'] = 'Хэлээ сонго';
|
||||
$string['chooselanguagesub'] = 'Зөвхөн суулгах үед ашиглагдах хэлээ сонго. Та дараа нь сайтны болон хэрэглэгчийн хэлийг сонгож болно.';
|
||||
$string['dataroot'] = 'Өгөгдлийн директор';
|
||||
$string['dbprefix'] = 'Хүснэгтний угтвар';
|
||||
$string['dirroot'] = 'Моодл хавтас';
|
||||
$string['environmenthead'] = 'Таны орчиныг шалгаж байна ...';
|
||||
$string['installation'] = 'Суулгах';
|
||||
$string['langdownloaderror'] = 'Харамсалтай нь "{$a}" хэл суусангүй. Суулгах үйл ажиллагаа Англи хэл дээр үргэлжлэх болно.';
|
||||
$string['memorylimithelp'] = '<p>Таны серверийн PHP санах ойн хязгаар нь {$a} гэж тохируулсан байна.</p>
|
||||
$string['admindirname'] = 'Админ лавлах';
|
||||
$string['availablelangs'] = 'Боломжит хэлний багц';
|
||||
$string['chooselanguagehead'] = 'Хэл сонгох';
|
||||
$string['chooselanguagesub'] = 'Суулгах хэлээ сонгоно уу. Энэ хэлийг сайтын өгөгдмөл хэл болгон ашиглах боловч дараа нь өөрчилж болно.';
|
||||
$string['clialreadyconfigured'] = 'config.php тохиргооны файл байна. Энэ сайтад Moodle системийг суулгахын тулд admin/cli/install_database.php ашиглана уу.';
|
||||
$string['clialreadyinstalled'] = 'config.php тохиргооны файл байна. Энэ сайтад Moodle системийг шинэчлэхийн тулд admin/cli/install_database.php ашиглана уу.';
|
||||
$string['cliinstallheader'] = 'Moodle {$a} командын мөр суулгах програм';
|
||||
$string['clitablesexist'] = 'Өгөгдлийн сангийн хүснэгтүүд байна; CLI суурилуултыг үргэлжлүүлэх боломжгүй.';
|
||||
$string['databasehost'] = 'Өгөгдлийн сангийн хост';
|
||||
$string['databasename'] = 'Өгөгдлийн сангийн нэр';
|
||||
$string['databasetypehead'] = 'Өгөгдлийн сангийн драйвер сонгох';
|
||||
$string['dataroot'] = 'Өгөгдлийн лавлах';
|
||||
$string['datarootpermission'] = 'Өгөгдлийн лавлахын зөвшөөрөл';
|
||||
$string['dbprefix'] = 'Хүснэгтийн угтвар';
|
||||
$string['dirroot'] = 'Moodle лавлах';
|
||||
$string['environmenthead'] = 'Таны орчныг шалгаж байна ...';
|
||||
$string['environmentsub2'] = 'Moodle системийн хувилбар бүр нь PHP хувилбарын хамгийн наад захын шаардлагыг хангаж, PHP гол гол өргөтгөлтэй байдаг.
|
||||
Суурилуулах, шинэчлэхээс өмнө орчны бүрэн шалгалтыг хийдэг. Шинэ хувилбар суулгах эсвэл PHP өргөтгөлийг хэрхэн идэвхжүүлэхийг мэдэхгүй байгаа бол серверийн админтай холбогдоно уу.';
|
||||
$string['errorsinenvironment'] = 'Орчны шалгалт амжилтгүй боллоо!';
|
||||
$string['installation'] = 'Суурилуулалт';
|
||||
$string['langdownloaderror'] = 'Харамсалтай нь "{$a}" хэлийг татаж авч чадсангүй. Суулгах үйл явц англи хэл дээр үргэлжилнэ.';
|
||||
$string['memorylimithelp'] = '<p>Таны серверийн PHP санах ойн хязгаарлалтыг {$a} гэж тохируулсан байна.</p>
|
||||
|
||||
<p>Энэ нь Моодл сүүлд санах ойн асуудлууд ялангуяа олон модуль ба/эсвэл олон хэрэглэгч идэвхжүүлсэн үед учирч болзошгүй. </p>
|
||||
<p>Энэ нь Moodle системд хожим санах ойн асуудал, ялангуяа олон модулийг идэвхжүүлсэн ба/буюу олон хэрэглэгчтэй үед үүсгэж болзошгүй.</p>
|
||||
|
||||
<p>Бид танд зөвлөхөд РНР-гээ боломжит дээд хязгаартайгаар жишээ нь 16М болгож тохируул. Үүний тулд хэд хэдэн арга байна: </p>
|
||||
<p>Бид танд PHP-г боломжтой бол 40M гэх мэт өндөр хязгаартайгаар тохируулахыг зөвлөж байна.
|
||||
Үүнд хэд хэдэн арга байдаг ба тэдгээрийг ашиглаж болно:</p>
|
||||
<ol>
|
||||
<li>Хэрвээ та PHP-г <i>--enable-memory-limit</i>-тай дахин хөрвүүлэх боломжтой бол. Энэ нь Моодлийг санах ойн хязгаарыг өөрөө тогтоох боломжтой болгоно. </li>
|
||||
<li>Хэрвээ та php.ini файлдаа хандаж чадвал, <b>memory_limit</b> гэсэн тохиргоог 16M гэх мэтээр өөрчилж болно. Хэрвээ хандалт байхгүй бол админаараа үүнийг хийлгэнэ үү.</li>
|
||||
<li>Зарим PHP сервер дээр Моодл хавтсан дотроо дараах мөр агуулсан .htaccess файл үүсгэж болно: <p><blockquote>php_value memory_limit 16M</blockquote></p>
|
||||
<p>Зарим сервер дээр энэ нь <b>бүх</b> PHP хуудсуудыг ажиллахгүй болгоно (та хуудаснууд руу орох юм бол алдааг нь харах болно). Тиймээс .htaccess файлыг устгах хэрэгтэй болно.</p></li>
|
||||
<li>Хэрэв боломжтой бол PHP-г <i>--enable-memory-limit</i> ашиглан дахин хөрвүүлээрэй.
|
||||
Энэ нь Moodle системд санах ойн хязгаарыг өөрөө тохируулах боломжийг олгоно.</li>
|
||||
<li>Хэрэв та өөрийн php.ini файлд хандах эрхтэй бол <b>memory_limit</b> тохиргоог 40M гэх зэргээр өөрчлөх боломжтой. Хандах эрхгүй бол администратортоо хандаж болно.</li>
|
||||
<li>Зарим PHP серверт дараах мөрийг агуулсан Moodle санд .htaccess файлыг үүсгэж болно: <blockquote><div>php_value memory_limit 40M</div></blockquote>
|
||||
<p>Гэвч зарим серверт энэ нь <b>бүх</b> PHP хуудас ажиллахаас сэргийлдэг (хуудсыг харахад алдаа гарах болно) тул та .htaccess файлыг устгах шаардлагатай.</p> </li>
|
||||
</ol>';
|
||||
$string['paths'] = 'Замууд';
|
||||
$string['pathserrcreatedataroot'] = 'Суурилуулагч нь өгөгдлийн лавлахыг ({$a->dataroot}) үүсгэх боломжгүй';
|
||||
$string['pathshead'] = 'Замыг баталгаажуулах';
|
||||
$string['pathsrodataroot'] = 'Dataroot лавлах нь бичилт хийх боломжгүй.';
|
||||
$string['pathsroparentdataroot'] = 'Үндсэн лавлах ({$a->parent}) нь бичилт хийх боломжгүй. Суурилуулагч нь өгөгдлийн санг ({$a->dataroot}) үүсгэх боломжгүй.';
|
||||
$string['pathssubadmindir'] = 'Маш цөөн веб хост /админыг хянах самбар эсвэл өөр зүйлд нэвтрэхийн тулд тусгай URL болгон ашигладаг. Харамсалтай нь энэ нь Moodle админ хуудасны стандарт байршилтай зөрчилддөг. Та үүнийг засах боломжтой
|
||||
Суурилуулалтад админ лавлахын нэрийг өөрчилж, энд шинэ нэрийг оруулах замаар засаж болно. Жишээ нь: <em>moodleadmin</em>. Энэ нь Moodle дээрх админ холбоосыг засах болно.';
|
||||
$string['pathssubdataroot'] = '<p>Moodle нь хэрэглэгчийн байршуулсан бүх файлын агуулгыг хадгалах лавлах.</p>
|
||||
<p>Энэ лавлах нь веб серверийн хэрэглэгч (ихэвчлэн \'www-data\', \'nobody\' эсвэл \'apache\') унших, бичих боломжтой байх ёстой.</p>
|
||||
<p>Энэ нь вебээр шууд хандах боломжгүй байх ёстой.</p>
|
||||
<p>Одоогоор лавлах байхгүй бол үүнийг суурилуулах процесс үүсгэх болно.</p>';
|
||||
$string['pathssubdirroot'] = '<p>Moodle код агуулсан лавлахад хандах бүрэн зам.</p>';
|
||||
$string['pathssubwwwroot'] = '<p>Moodle системд хандах бүрэн хаяг, өөрөөр хэлбэл хэрэглэгч Moodle системд хандахын тулд хөтчийн хаягийн мөрөнд оруулах хаяг.</p>
|
||||
<p>Олон хаяг ашиглан Moodle системд хандах боломжгүй. Таны сайтад олон хаягаар хандах боломжтой бол хамгийн хялбарыг сонгож, бусад хаяг руугаа байнгын дахин чиглүүлэлт хийхээр тохируулна уу.</p>
|
||||
<p>Таны сайтад интернэт, дотоод сүлжээнээс (заримдаа интранэт гэж нэрлэдэг) нэвтрэх боломжтой бол энд нийтийн хаягийг ашиглана уу.</p>
|
||||
<p>Одоогийн хаяг буруу байвал хөтчийн хаягийн мөрөнд байгаа URL хаягийг өөрчлөөд суурилуулалтыг дахин эхлүүлнэ үү.</p>';
|
||||
$string['pathsunsecuredataroot'] = 'Dataroot байршил аюулгүй биш байна';
|
||||
$string['pathswrongadmindir'] = 'Админ лавлах байхгүй байна';
|
||||
$string['phpextension'] = '{$a} PHP өргөтгөл';
|
||||
$string['phpversion'] = 'РНР хувилбар';
|
||||
$string['phpversionhelp'] = '<p>Mooдл нь РНР хувилбарын хамгийн багадаа 4.3.0 эсвэл 5.1.0 байхыг шаарддаг (5.0.x нь алдаануудтай).</p>
|
||||
<p>Та одоо {$a} хувилбар ажиллуулж байна</p>
|
||||
<p>Та PHP-гээ шинэчлэх эсвэл PHP-ийн шинэ хувилбар бүхий хост руу шилжүүл!<br/>
|
||||
(5.0.x тохиолдолд доошоо 4.4.x хувилбар руу орж болно)</p>';
|
||||
$string['phpversionhelp'] = '<p>Moodle системд хамгийн багадаа 5.6.5 эсвэл 7.1 PHP хувилбар шаардлагатай (7.0.x нь системийн зарим хязгаарлалттай).</p>
|
||||
<p>Та одоогоор {$a} хувилбарыг ажиллуулж байна.</p>
|
||||
<p>Та PHP-г шинэчлэх эсвэл шинэ PHP хувилбартай хостод шилжих шаардлагатай.</p>';
|
||||
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
|
||||
$string['welcomep20'] = 'Та <strong>{$a->packname} {$a->packversion}</strong> багцыг компьютер дээрээ амжилттай суулгаж ажиллуулсан тул энэ хуудсыг харж байна. Баяр хүргэе!';
|
||||
$string['welcomep30'] = '<strong>{$a->installername}</strong> -ний энэ хувилбар нь <strong>Mooдл</strong> ажиллах орчныг үүсгэх програмууд агуулсан, тэдгээр нь:';
|
||||
$string['welcomep40'] = 'Энэ багц нь мөн <strong>Mooдл {$a->moodlerelease} ({$a->moodleversion})</strong>-г агуулсан.';
|
||||
$string['welcomep50'] = 'Энэ багц доторх бүх програмууд нь өөрсдийн лизенцтэй. Бүрэн <strong>{$a->installername}</strong> багц нь
|
||||
<a href="http://www.opensource.org/docs/definition_plain.html">open source</a> бөгөөд <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> -ийн лизенцийн дор түгээгддэг.';
|
||||
$string['welcomep60'] = 'Дараагийн хуудсууд нь компьютер дээрээ <strong>Mooдл</strong> тохируулах тааруулах энгийн алхмуудыг агуулсан байгаа. Та анхны утгын тохиргоонуудыг хүлээн авч болно, эсвэл өөрийн хэрэгцээнд нийцүүлэн өөрчилж болно.';
|
||||
$string['welcomep70'] = '<strong>Mooдлээ</strong> тохируулахын тулд доорх “Үргэлжлүүлэх” товчин дээр дарж цааж явна уу.';
|
||||
$string['wwwroot'] = 'Вэб хаяг';
|
||||
$string['welcomep20'] = 'Та <strong>{$a->packname} {$a->packversion}</strong> багцыг компьютертоо амжилттай суулгаж, эхлүүлсэн тул та энэ хуудсыг харж байна. Баяр хүргэе!';
|
||||
$string['welcomep30'] = '<strong>{$a->installername}</strong> энэхүү хувилбарт <strong>Moodle</strong> ажиллах орчныг бүрдүүлэх аппликейшнүүд багтсан болно, тухайлбал:';
|
||||
$string['welcomep40'] = 'Түүнчлэн энэ багц нь <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>-г агуулдаг.';
|
||||
$string['welcomep50'] = 'Энэ багцад буй бүх аппликейшны хэрэглээг тэдгээрийн лицензээр зохицуулдаг. Бүрэн <strong>{$a->installername}</strong> багц нь <a href="https://www.opensource.org/docs/definition_plain.html">нээлттэй эх сурвалж</a> бөгөөд <a href="https://www.gnu.org/copyleft/gpl.html">GPL</a> лиценз дор түгээгддэг.';
|
||||
$string['welcomep60'] = 'Дараах хуудсууд нь таны компьютерт <strong>Moodle</strong> системийг тохируулах, тохируулахад хялбар алхмыг хийх болно. Та өгөгдмөл тохиргоог хүлээн зөвшөөрөх эсвэл өөрийн хэрэгцээнд тохируулан өөрчилж болно.';
|
||||
$string['welcomep70'] = 'Доорх "Дараах" товчийг дарж <strong>Moodle</strong> системийн тохиргоог үргэлжлүүлнэ үү.';
|
||||
$string['wwwroot'] = 'Веб хаяг';
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['language'] = 'Хэл';
|
||||
$string['moodlelogo'] = 'Мүүдл лого';
|
||||
$string['moodlelogo'] = 'Moodle лого';
|
||||
$string['next'] = 'Дараагийн';
|
||||
$string['previous'] = 'Өмнөх';
|
||||
$string['reload'] = 'Дахин ачаалах';
|
||||
|
||||
@@ -73,7 +73,7 @@ $string['pathssubdataroot'] = '<p>Um diretório em que Moodle armazenará todo o
|
||||
<p>Este diretório deve ser legível e gravável pelo usuário do servidor web (geralmente "www-data \',\' nobody \', ou\' apache\'). </p>
|
||||
<p>Não deve ser diretamente acessível através da web. </p>
|
||||
<p>Se o diretório não existir atualmente, o processo de instalação tentará criá-lo. </p>';
|
||||
$string['pathssubdirroot'] = '<p>Caminho completo do diretório para instalação do Moddle.</p>';
|
||||
$string['pathssubdirroot'] = '<p>Caminho completo do diretório para instalação do Moodle.</p>';
|
||||
$string['pathssubwwwroot'] = '<p>O endereço completo em que Moodle pode ser acessado ou seja, o endereço que os usuários vão digitar na barra de endereços do seu navegador para acessar Moodle. </p>
|
||||
<p>Não é possível acessar Moodle usando múltiplos endereços. Se o seu site é acessível através de múltiplos endereços, em seguida, escolher o mais fácil e configurar um redirecionamento permanente para cada um dos outros endereços. </p>
|
||||
<p>Se o seu site é acessível tanto a partir da Internet e, a partir de uma rede interna (às vezes chamado de Intranet), em seguida, use o endereço público aqui. </p>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['thislanguage'] = 'Kichwa - Cañar Highland';
|
||||
@@ -30,4 +30,4 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['thisdirection'] = 'rtl';
|
||||
$string['thislanguage'] = 'سنڌي';
|
||||
$string['thislanguage'] = 'سنڌي';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'sv';
|
||||
$string['thislanguage'] = 'Svenska för Workplace';
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['clianswerno'] = 'n';
|
||||
$string['cliansweryes'] = 't';
|
||||
$string['cliincorrectvalueerror'] = 'Błōnd, niynŏleżny wert "{$a->value}" dlŏ "{$a->option}"';
|
||||
$string['cliincorrectvalueretry'] = 'Niynŏleżny wert, sprōbuj zaś';
|
||||
$string['clitypevalue'] = 'wert zorty';
|
||||
$string['clitypevaluedefault'] = 'Zorta wertu, naciś Ynter, coby użyć wertu wychodnyj ({$a})';
|
||||
$string['cliunknowoption'] = 'Niyznōme ôpcyje:
|
||||
{$a}
|
||||
Proszã użyć ôpcyje --help.';
|
||||
$string['cliyesnoprompt'] = 'wpisz y (to znaczy tak) abo n (to znaczy niy)';
|
||||
$string['environmentrequireinstall'] = 'je zdatne, coby było zainstalowane i włōnczōne';
|
||||
$string['environmentrequireversion'] = 'wymŏganŏ je wersyjŏ {$a->needed}, a ty używŏsz wersyje {$a->current}';
|
||||
$string['upgradekeyset'] = 'Zaktualizuj klucz (ôstŏw prōzne jeźli niy ma to skōnfigurowane)';
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['cannotcreatedboninstall'] = '<p>Niy idzie utworzić bazy danych.</p> <p>Ôkryślōnŏ baza danych niy istnieje, a dany używŏcz niy mŏ uprawniyń do tworzyniŏ bazy danych.</p> <p>Administratōr strōny winiyn wybadać kōnfiguracyjõ bazy danych.</p>';
|
||||
$string['cannotcreatelangdir'] = 'Niy idzie utworzić katalogu lang/';
|
||||
$string['cannotcreatetempdir'] = 'Niy idzie utworzić katalogu tymczasowego';
|
||||
$string['cannotdownloadcomponents'] = 'Niy idzie pobrać skłŏdowych (kōmpōnyntōw)';
|
||||
$string['cannotdownloadzipfile'] = 'Niy idzie pobrać zbioru ZIP';
|
||||
$string['cannotfindcomponent'] = 'Niy idzie znojś kōmpōnyntu';
|
||||
$string['cannotsavemd5file'] = 'Niy idzie zapisać zbioru md5';
|
||||
$string['cannotsavezipfile'] = 'Niy idzie zapisać zbioru ZIP';
|
||||
$string['cannotunzipfile'] = 'Niy idzie ôzpakować (unzip) zbioru';
|
||||
$string['componentisuptodate'] = 'Kōmpōnynt je terŏźny';
|
||||
$string['dmlexceptiononinstall'] = '<p> Wystōmpiōł błōnd bazy danych [{$a->errorcode}]. <br /> {$a->debuginfo} </p>';
|
||||
$string['downloadedfilecheckfailed'] = 'Wybadanie pobranego zbioru zakōńczyło sie #niypowodzynie';
|
||||
$string['invalidmd5'] = 'Niynŏleżny md5';
|
||||
$string['missingrequiredfield'] = 'Brak wymŏganego pola';
|
||||
$string['remotedownloaderror'] = 'Pobiyranie skłŏdniku na serwer niy podarziło sie. Wybadej ustawiyniŏ proxy. Rozszyrzynie PHP cURL je barzo zalycane. <br /><br />Musisz pobrać następująćy zbiōr <a href="{$a->url}">{$a->url}</a> ryncznie, skopiyrować go do lokalizacyje "{$a->dest}" i ôzpakować nakŏzaniym unzip.';
|
||||
$string['wrongdestpath'] = 'Błyndny chodnik docelowa';
|
||||
$string['wrongsourcebase'] = 'Błyndne zdrzōdło bazy URL';
|
||||
$string['wrongzipfilename'] = 'Błyndne miano zbioru ZIP';
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['admindirname'] = 'Katalog admin';
|
||||
$string['availablelangs'] = 'Przistympne paketu gŏdkowe';
|
||||
$string['chooselanguagehead'] = 'Ôbier gŏdka';
|
||||
$string['chooselanguagesub'] = 'Proszã ôbrać gŏdka do instalacyje. Ta gŏdka bydzie tyż użyty za wychodnŏ gŏdka placu, przi czym może być niyskorzij zmiyniōny.';
|
||||
$string['clialreadyconfigured'] = 'Zbiōr config.php już istnieje. Użyj admin/cli/install_database.php jeźli chcesz zainstalować Moodle dlŏ tyj strōny.';
|
||||
$string['clialreadyinstalled'] = 'Zbiōr config.php już istnieje. Użyj admin/cli/install_database.php jeźli chcesz zaktualizować Moodle dlŏ tyj strōny.';
|
||||
$string['cliinstallheader'] = 'Program instalacyjny Moodle {$a} z lynije nakŏzań';
|
||||
$string['clitablesexist'] = 'Tabule bazy danych już istniejōm, instalacyjŏ niy może kōntynuować.';
|
||||
$string['databasehost'] = 'Host bazy danych';
|
||||
$string['databasename'] = 'Miano bazy danych';
|
||||
$string['databasetypehead'] = 'Ôbier kludzŏcz bazy danych';
|
||||
$string['dataroot'] = 'Katalog danych';
|
||||
$string['datarootpermission'] = 'Prawa katalogōw danych';
|
||||
$string['dbprefix'] = 'Prefiks tabulōw';
|
||||
$string['dirroot'] = 'Katalog Moodle';
|
||||
$string['environmenthead'] = 'Wybadujã strzodowisko (ustawiyniŏ) ...';
|
||||
$string['environmentsub2'] = 'Kożde wydanie Moodle mŏ pewne minimalne wymŏganiŏ wersyje PHP i pewnõ liczbã musowych rozszyrzyń PHP. Połnŏ kōntrola strzodowiska ôdbywŏ sie przed kożdõ instalacyjōm i aktualizacyjōm. Proszymy ô kōntakt z administratorym serwera, jeźli niy wiysz jak zainstalować nowõ wersyjõ abo włōnczyć rozszyrzynie PHP.';
|
||||
$string['errorsinenvironment'] = 'Kōntrola strzodowiska zakōńczōnōm #niypowodzynie!';
|
||||
$string['installation'] = 'Instalacyjŏ';
|
||||
$string['langdownloaderror'] = 'Niystety gŏdka "{$a}" niy może ôstać pobrany. Proces instalacyje bydzie kōntynuowany w gŏdce angelskim.';
|
||||
$string['memorylimithelp'] = '<p>Limit pamiyńci PHP dlŏ Twojigo serwera je ustawiōny terŏźnie na {$a}.</p>
|
||||
|
||||
<p> Może to stworzić sytuacyjõ, co w nij Moodle bydzie mioł w prziszłości problymy z pamiyńciōm, ôsobliwie jeźli mŏsz udostympniōnych moc modułōw i/abo moc używŏczōw.</p>
|
||||
|
||||
<p>Jeźli je to możliwe, zalycōmy ustawiynie kōnfiguracyje PHP z wyższym limitym, bp. 40M.
|
||||
Istnieje pŏrã spōsobōw przekludzyniŏ tyj ôperacyje, co możesz sprōbować:</p>
|
||||
<ol>
|
||||
<li>Jeźli możesz przekompiluj PHP za pōmocōm <i>--enable-memory-limit</i>.
|
||||
Przizwoli to Moodle ustawić samoczynnie limit pamiyńci.</li>
|
||||
<li>Jeźli mŏsz przistymp do zbioru konfiguracyjnego php.ini, możesz w nim zmiynić ustawiynie <b>memory_limit</b> do srogości bp. 40M. W przipŏdku, kej niy posiadŏsz przistympu możesz poprosić swojigo administratora coby zrobiōł to za Ciebie.</li>
|
||||
<li>Na niykerych serwerach PHP idzie stworzić zbiōr. htaccess w katalogu Moodle zawiyrajōncy miyniōnõ lynijõ:
|
||||
<blockquote><div>php_value memory_limit 40M</div></blockquote>
|
||||
<p>A dyć na niykerych serwerach bydzie niy dozwolało to nŏleżne fungowanie <b>wszyjskich</b> strōn PHP (ujzdrzisz błyndy na wyświytlanych strōnach), tedy bydziesz musioł wychrōnić zbiōr .htaccess.</p></li>
|
||||
</ol>';
|
||||
$string['paths'] = 'Chodnika';
|
||||
$string['pathserrcreatedataroot'] = 'Katalog danych ({$a->dataroot}) niy może ôstać utworzōny bez instalatōr.';
|
||||
$string['pathshead'] = 'Potwiyrdź chodnika';
|
||||
$string['pathsrodataroot'] = 'Głowny katalog danych niy ma uprawniyń do zŏpisu.';
|
||||
$string['pathsroparentdataroot'] = 'Nadrzyndny katalog ({$a->parent}) je ino do ôdczytu. Katalog danych ({$a->dataroot}) niy może ôstać utworzōny bez instalatōr.';
|
||||
$string['pathssubadmindir'] = 'Niyliczne portale używajōm URL /admin za ekstra adresy panelu sterowaniŏ. Niystety je to sporne ze sztandardowyj lokalizacyjōm folderu strōn administratora Moodle. Idzie to sprawić bez pōmianã miana katalogu administratora w instalacyje i podanie tego miana sam, bp.: <em>moodleadmin.</em> Powroza administratora Moodle bydōm autōmatycznie poprawiōne.';
|
||||
$string['pathssubdataroot'] = 'Potrzebny je przestrzyństwo, kaj Moodle może zapisować ladowane dō niego zbiory. Katalog tyn winiyn mieć prawo do ôdczyt i ZŎPISU bez używŏcza serwera WWW (porzōnd "nobody" abo "apache"), ale może być być przistympny bezpostrzednio bez nec. Instalatōr sprōbuje go utworzić, jeźli niy istnieje.';
|
||||
$string['pathssubdirroot'] = 'Połny chodnik do katalogu z instalacyjōm Moodle.';
|
||||
$string['pathssubwwwroot'] = 'Połnŏ adresa internetowy, pod kerym Moodle bydzie przistympny. Moodle niy może być przistympny przi użyciu moc adres. Jeźli twōj plac mŏ pŏrã adres publicznych, przinŏleży skōnfigurować trwałe przekierowania ze wszyjskich z nich na jedyn. Jeźli Twōj plac je przistympny tak z intranetu i Internetu, używej z publicznyj adresy i gezecōw DNS tak, coby używŏcze Intranetu używali tyż z adresy publicznego. Jeźli adresa niy ma nŏleżny, przinŏleży zaś sztartnōńć instalacyjõ z inkszym adresōm.';
|
||||
$string['pathsunsecuredataroot'] = 'Lokalizacyjŏ głownego katalogu danych niy ma bezpiecznŏ';
|
||||
$string['pathswrongadmindir'] = 'Katalog admin niy istnieje';
|
||||
$string['phpextension'] = 'rozszyrzynie PHP {$a}';
|
||||
$string['phpversion'] = 'Wersyjŏ PHP';
|
||||
$string['phpversionhelp'] = '<p>Moodle wymŏgŏ wersyje PHP aby 5.6.5 abo 7.1 (7.0.x mŏ pewne ôgraniczyniŏ motora).</p>
|
||||
<p>Aktualnie używŏsz wersyje {$a}.</p>
|
||||
<p>Musisz zaktualizować PHP abo przeniyś na host z nowszõ wersyjōm PHP.</p>';
|
||||
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
|
||||
$string['welcomep20'] = 'Widzisz tã strōnã, pōniywŏż z powodzyniym zainstalowołś i sztartnōłś <strong>{$a->packname} {$a->packversion}</strong> na swojim kōmputrze.';
|
||||
$string['welcomep30'] = 'Tyn instalatōr <strong>{$a->installername}</strong> zawiyrŏ aplikacyje, by stworzić strzodowisko, co w niymu bydzie fungować <strong>Moodle</strong>, to znaczy';
|
||||
$string['welcomep40'] = 'Paket zawiyrŏ <strong>Moodle {$a->moodlerelease} ({$a->moodleversion})</strong>.';
|
||||
$string['welcomep50'] = 'Wszyjske aplikacyje w tym pakecie mŏja włŏsne, ôsobne licyncyje. Kōmpletny paket <strong>{$a->installername}</strong> je <a href="http://www.opensource.org/docs/definition_plain.html">open source</a> i je dystrybuowany na <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a> licyncyje.';
|
||||
$string['welcomep60'] = 'Nastepujące strōny przekludzōm cie bez instalacyjõ <strong>Moodle</strong> na twojim kōmputrze. Możesz zaakceptować ustawiyniŏ wychodne, abo ôpcyjōnalnie, przipasować jy do swojich potrzeb.';
|
||||
$string['welcomep70'] = 'Kliknij knefel "Dalij" coby kōntynuować instalacyjõ <strong>Moodle</strong>.';
|
||||
$string['wwwroot'] = 'Adresa w necu';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user