Compare commits

..

227 Commits

Author SHA1 Message Date
Jun Pataleta 2caed2991e Moodle release 4.0.8 2023-04-22 16:22:46 +08:00
Eloy Lafuente (stronk7) 3552ac0622 weekly release 4.0.7+ 2023-04-21 19:19:20 +02:00
Eloy Lafuente (stronk7) b665e63be8 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-04-21 19:19:15 +02:00
Jun Pataleta 8e2239f1a7 Merge branch 'MDL-77927-400' of https://github.com/stevandoMoodle/moodle into MOODLE_400_STABLE 2023-04-21 16:52:09 +08:00
Jun Pataleta 4e9a6ef5be Merge branch 'MDL-77229-patch-400' of https://github.com/ilyatregubov/moodle into MOODLE_400_STABLE 2023-04-21 16:45:01 +08:00
Jun Pataleta c4f58034ab MDL-77927 core: mod_assignment subplugins environment check 2023-04-21 15:55:13 +08:00
Ilya Tregubov 313d3d76eb MDL-77229 mod_lesson: Black list detailed statistics in classic Behat.
The nav element to go to detailed stats page is missing in classic
2023-04-21 15:08:45 +08:00
Ilya Tregubov 881cc1da19 Merge branch 'MDL-77229-400' of https://github.com/ilyatregubov/moodle into MOODLE_400_STABLE 2023-04-21 12:10:28 +08:00
Ilya Tregubov 553ea69c3f MDL-77229 lesson: Add Behat test 2023-04-21 12:05:52 +08:00
AMOS bot 72c5bcc745 Automatically generated installer lang files 2023-04-21 00:07:38 +00:00
Juan Leyva d2a623971c MDL-77229 lesson: Fix error for empty responses (numerical pagetype) 2023-04-20 12:46:38 +02:00
Jun Pataleta b0d5d0ebc5 Merge branch 'MDL-73012-400' of https://github.com/ferranrecio/moodle into MOODLE_400_STABLE 2023-04-20 16:44:46 +08:00
Jun Pataleta 636890e5f6 Merge branch 'MDL-77922-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-04-20 16:10:21 +08:00
Ferran Recio 7fe5196a52 MDL-73012 core_courseformat: add pending to move section modal 2023-04-20 09:53:04 +02:00
Ferran Recio cc46c0158a MDL-77922 core_courseformat: add pending to move activity modal 2023-04-20 14:49:27 +08:00
Ilya Tregubov 1a2ca071eb Merge branch 'MDL-77577-400' of https://github.com/andelacruz/moodle into MOODLE_400_STABLE 2023-04-20 12:33:50 +08:00
Paul Holden b17f5b6337 MDL-77187 mod_wiki: validate external method sort parameters. 2023-04-19 12:55:22 +00:00
Paul Holden 7daac50b35 Merge branch 'MDL-77960-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-04-19 13:41:34 +01:00
Paul Holden 1ee4d7da64 Merge branch 'MDL-77944-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2023-04-19 13:06:42 +01:00
Paul Holden 9540c536d8 Merge branch 'MDL-77898-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-04-19 09:03:24 +01:00
Simey Lameze a96de1c74d MDL-77960 behat: make verification steps more specific 2023-04-19 13:33:36 +08:00
Ilya Tregubov d2790cca27 Merge branch 'MDL-77935-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-04-19 13:33:00 +08:00
Andrew Nicols 69e8820de1 weekly release 4.0.7+ 2023-04-18 22:28:15 +08:00
Andrew Nicols 8d9daa91ba Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-04-18 22:28:12 +08:00
Jun Pataleta 4027721841 MDL-77898 calendar: Add iconclass for upcoming_mini template
The icon's iconclass context data adds additional CSS class(es) to
calendar event icons to better control how the event icon is displayed.
e.g. without filtering for activity events that don't hae monologo
versions of their icons.
2023-04-18 15:58:37 +08:00
Ilya Tregubov 475256b621 Merge branch 'MDL-77916-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-04-18 14:29:07 +08:00
Andrew Nicols ddc8ddb047 Merge branch 'MDL-77829-400' of https://github.com/stevandoMoodle/moodle into MOODLE_400_STABLE 2023-04-18 12:32:46 +08:00
Andrew Nicols 7f349d6552 Merge branch 'MDL-77735-400' of https://github.com/sarjona/moodle into MOODLE_400_STABLE 2023-04-18 12:10:40 +08:00
Andrew Nicols 2bbb3d0eb4 MDL-77944 behat: Rename chrome options for w3c support
From Selenium 4.8.0, support for non-w3c browser control has ended.

We only use W3C browser control these days, and this was missed as part
of the move to W3C. All browser options must be vendor-prefixed.
2023-04-18 09:04:17 +08:00
Ilya Tregubov 68d1a0c1c0 Merge branch 'MDL-77827-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2023-04-18 08:59:41 +08:00
AMOS bot a84fb29fcb Automatically generated installer lang files 2023-04-18 00:07:35 +00:00
Paul Holden 5158c1533c Merge branch 'MDL-77878-400-enfix' of https://github.com/vmdef/moodle into MOODLE_400_STABLE 2023-04-17 19:12:38 +01:00
Shamim Rezaie c8defec8dd Merge branch 'MDL-76998-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2023-04-17 21:28:24 +10:00
Víctor Déniz 532c3eb7b0 MDL-77878 lang: Use fixed strings in tests 2023-04-17 09:29:47 +01:00
Paul Holden f1949fe80c MDL-77935 contentbank: avoid phpunit crashes during isolated tests.
Simplify the test for allowed contexts by removing problematic use of
data provider annotation.

See: https://github.com/sebastianbergmann/phpunit/issues/2739
2023-04-17 09:28:46 +01:00
Andrew Nicols 2ac6d6a7d3 Merge branch 'MDL-76995-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2023-04-17 11:15:25 +08:00
Ilya Tregubov 75226d8c9e MDL-76994 core_course: Fix version for weeks and topics course formats 2023-04-17 11:02:36 +08:00
Ilya Tregubov 6496dd5277 Merge branch 'MDL-76994-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2023-04-17 09:47:30 +08:00
Víctor Déniz 3ef7b399a8 MDL-77878 lang: Import fixed English strings (en_fix) 2023-04-16 22:04:03 +01:00
Sara Arjona 95b427d8fe Merge branch 'MDL-77913-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-04-14 14:02:23 +02:00
Sara Arjona 18886c271f MDL-77735 core: Check $CFG->lang isset
In some cases, $CFG->lang might not be set, and this is causing a
Notice to be displayed when, for instance, database connection fails.
This patch should fix this case.
2023-04-14 13:46:45 +02:00
Sara Arjona 9cae11732f weekly release 4.0.7+ 2023-04-14 10:50:13 +02:00
Sara Arjona 9600731821 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-04-14 10:50:10 +02:00
Huong Nguyen 44a8713267 MDL-77827 events: Changed JSON comparison to be less strict 2023-04-14 12:29:38 +07:00
Paul Holden 75b6190bde MDL-77916 h5p: register autoloader in helper testcase. 2023-04-13 23:17:08 +01:00
Paul Holden 53f5432d89 MDL-77913 qbank_previewquestion: deterministic ordering of versions.
Ensure the ordering of loaded question versions is consistent, avoids
random Oracle failures.
2023-04-13 21:45:30 +01:00
Amaia Anabitarte b456e7aa18 MDL-76995 core_courseindex: Apply indentation in the course index 2023-04-13 16:58:21 +02:00
Amaia Anabitarte 75bf395e47 MDL-76998 admin: Option to reset course indentation 2023-04-13 16:57:03 +02:00
Amaia Anabitarte 029457a0a6 MDL-76994 tool_mobile: Return course format indentation setting 2023-04-13 16:56:09 +02:00
Amaia Anabitarte d23ff0a5b3 MDL-76994 core_course: New course format setting to enable indentation 2023-04-13 16:53:22 +02:00
Sara Arjona a2e0dec53b Merge branch 'MDL-76859-400' of https://github.com/sarjona/moodle into MOODLE_400_STABLE 2023-04-13 16:24:32 +02:00
Sara Arjona 2867735f7e Merge branch 'MDL77833-course-content-chng-notificatn-multilang-m4' of https://github.com/Amrita1991/moodle into MOODLE_400_STABLE 2023-04-13 16:20:11 +02:00
Sara Arjona dbb0410d58 Merge branch 'MDL-77860-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-04-13 13:45:06 +02:00
Sara Arjona 4721df9f4c Merge branch 'MDL-77788-400' of https://github.com/rmady/moodle into MOODLE_400_STABLE 2023-04-13 13:18:27 +02:00
Sara Arjona 243c35b3e8 Merge branch 'MDL-77618-admin-password-autocomplete-MOODLE_400_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_400_STABLE 2023-04-13 12:19:21 +02:00
Amrita1991 4d5ea5e9a9 MDL-77833 course: content change notification multilang processing
changing context parameter
2023-04-13 11:27:00 +02:00
Sara Arjona b47fa670f0 Merge branch 'MDL-77256-400' of https://github.com/rbravod/moodle into MOODLE_400_STABLE 2023-04-13 11:20:38 +02:00
Sara Arjona e196979e09 Merge branch 'MDL-77856-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-04-13 09:43:10 +02:00
Sara Arjona 50a79addb1 Merge branch 'MDL-77468-400' of https://github.com/rmady/moodle into MOODLE_400_STABLE 2023-04-13 09:20:04 +02:00
Juan Leyva 5f7b44fe70 MDL-77468 user: Fix invalid check for group belonging 2023-04-12 20:24:43 -03:00
Juan Leyva a18deeb18b MDL-77468 user: Make user profile visibility consistent web and ws 2023-04-12 20:21:32 -03:00
Sara Arjona 893bdf2603 Merge branch 'MDL-73610_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2023-04-12 18:19:47 +02:00
Petr Skoda c08401f159 MDL-76859 h5p: Fix behat failures
- Only resize if the H5P EmbedCommunicator is defined (otherwise, it was causing a
JS error)
- An unnecessary image has been removed from the greeting-card.h5p fixture package.
That way, the text will always be displayed (even if the iframe is still not
resized). Instead of replacing the original greeting-card-887.h5p file, I've
renamed it to greeting-card.h5p, to remove these ugly and unnecessary numbers
at the end of the file name).
2023-04-12 15:47:19 +02:00
Amaia Anabitarte 26ffef4f6d MDL-76993 core_course: Recover move right/left functionality
This is a backport of MDL-76990
2023-04-12 09:56:26 +02:00
Amaia Anabitarte a066890881 MDL-76993 core_course: Functions need to backport MDL-76990
MDL-76990 will be backported to 4.1 and 4.0. This commit adds the
methods needed to backport it which were not in 4.0.
2023-04-12 09:55:00 +02:00
Sara Arjona 65532b40c9 Merge branch 'MDL-77837-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2023-04-11 12:12:57 +02:00
Sara Arjona b61400d504 Merge branch 'MDL-77552-400' of https://github.com/ferranrecio/moodle into MOODLE_400_STABLE 2023-04-11 11:13:46 +02:00
Sara Arjona 9079a52348 Merge branch 'MDL-77148_400' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_400_STABLE 2023-04-11 10:17:14 +02:00
Sara Arjona 64038bd1d2 Merge branch 'MDL-77612-400' of https://github.com/laurentdavid/moodle into MOODLE_400_STABLE 2023-04-11 10:04:48 +02:00
Laurent David dad1f86b28 MDL-77612 mod_label: Label name fix
* The @@PLUGINFILE@@ placeholder or URLs should not be displayed in the
course index for labels
2023-04-11 05:25:40 +02:00
Stevani Andolo 8ec461823a MDL-77829 core: Added environment check for mod_assignment
Decided to add an environment check before uninstalling the
mod_assignment plugin to prevent data lost.
2023-04-10 13:55:20 +08:00
AMOS bot 2397eee6cb Automatically generated installer lang files 2023-04-07 00:07:30 +00:00
Andrew Nicols 875c1d9638 MDL-77837 core: Improve usage docs for cron_setup_user 2023-04-06 23:21:29 +08:00
Andrew Nicols 46ea3269fc MDL-77837 phpunit: Ensure that the cron user setter is used
When running an adhoc task in a unit test we should use the cron variant
of the set user method to mimic the behaviour of a real cron run.
2023-04-06 23:21:29 +08:00
Andrew Nicols be8fac6291 MDL-77837 cron: Ensure user is set when running tasks
We should be proactive in ensuring that the environment is clean when
running a task. We already ensure that we have a clean renderer and
other parts of the output chain, but we were not setting a clean user.

This change adds a call to setup the cron user before each task is
actually executed.
2023-04-06 23:21:29 +08:00
Eloy Lafuente (stronk7) 7d9d0f35a0 MDL-73610 nodejs: Small updates to required packages
The main goal of this issue is to avoid scanners (Dependabot
and friends), reporting about security issues with the current
xmldom 0.6.0 package.

Note that this doesn't affect prod at all, because it's a dev
dependency, hardly exploitable. So it's not a security fix, just
a security_benefit, if something.

So here, we are updating from xmldom 0.6.0 to @xmldom/xmldom 0.8.7
(note that the package was renamed in 0.7.0, so it's the very same)

Also, when proceeding with the changes, it was detected that we
are incorrectly declaring @babel/eslint-parser as a normal dependency
instead of a development one, so we are also fixing that little detail.

The commands executed to get the changes above applied have been:

- nvm use
- npm install @xmldom/xmldom@^0.8.7 --save-dev
- npm uninstall xmldom
- npm install @babel/eslint-parser@^7.17.0 --save-dev

(we haven't run a complete re-install because we only want to modify
the minimum possible at this stage).
2023-04-06 14:59:52 +02:00
Anupama Sarjoshi 6bee956ede MDL-77148 core: Fix to export params for templates in correct format
When questions are filtered by tags in the question bank, the qtagids
params are passed in the array format. Though moodle_url handles this,
single_button::export_for_template cannot. Hence changes done in
weblib.php to provide params for export_for_template in the
suitable format.
Thanks Huong. I have added the Behat test you provided in the patch.
2023-04-06 13:57:40 +01:00
Sara Arjona 7d8f31dbe7 weekly release 4.0.7+ 2023-04-06 14:02:24 +02:00
Sara Arjona e4e7902d7c Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-04-06 14:02:19 +02:00
AMOS bot 946ff0171c Automatically generated installer lang files 2023-04-06 00:07:34 +00:00
Paul Holden 9cf38cfd39 MDL-77860 tool_moodlenet: use localised language strings for import. 2023-04-05 23:05:34 +01:00
Jun Pataleta b3eb942301 MDL-77856 qtype_multianswer: Use Bootstrap Popover for subq feedback
The YUI Overlay widget encloses the subquestion feedback in a div
which causes a div element to be enclosed in the subquestion span. This
leads to an accessibility issue in terms of HTML parsing as inline
elements (span) should not contain block elements (div)
The YUI Overlay widget is also not accessible as it does not really hide
the overlay contents via aria-hidden when the overlay is not being
shown. It's better if we stop using this and use Bootstrap's
popover component which is more accessible by default.

This patch also removes module.js for the qtype_multianswer plugin as
it only contains codes related to rendering the feedback contents in the
YUI overlay widget which is no longer necessary.
2023-04-06 05:35:19 +08:00
Sara Arjona fce3ba9b11 Merge branch 'MDL-73642_MOODLE_400_STABLE' of https://github.com/tasosb/moodle into MOODLE_400_STABLE 2023-04-05 17:17:41 +02:00
Sara Arjona 42b6a39808 Merge branch 'MDL-75301_400_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_400_STABLE 2023-04-05 12:49:34 +02:00
Shamim Rezaie df17b180f2 Merge branch 'MDL-77555-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-04-05 20:15:09 +10:00
Mark Johnson 6ff023d292 MDL-75301 quiz: Use "always latest" option for question previews
This will set the "alwayslatest" option when previewing a question from
the quiz according to the version setting used in the quiz slot.
2023-04-05 10:23:26 +01:00
Mark Johnson 8043b7838a MDL-75301 question: Add "always latest" option to previews 2023-04-05 10:23:26 +01:00
Paul Holden 60ecd6cef5 Merge branch 'MDL-69551_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-04-05 08:56:46 +01:00
AMOS bot 558585b1ed Automatically generated installer lang files 2023-04-05 00:07:39 +00:00
Juan Leyva 5292926ebb MDL-77788 mod_assign: Apply format_string to group names in WS 2023-04-04 18:12:13 -03:00
Tim Hunt e19cbda970 MDL-69551 quiz: start quiz password field should be a passwordunmask
This help accessibility and usability
2023-04-04 12:21:26 +01:00
Paul Holden b559b84774 Merge branch 'MDL-77712-400' of https://github.com/laurentdavid/moodle into MOODLE_400_STABLE 2023-04-04 12:06:43 +01:00
Andrew Nicols 4406bcd17a Merge branch 'MDL-77584-400' of https://github.com/ewallah/moodle into MOODLE_400_STABLE 2023-04-04 12:07:33 +08:00
AMOS bot f8e7a1e24b Automatically generated installer lang files 2023-04-04 00:07:40 +00:00
Paul Holden 0bfa7ee0a7 Merge branch 'MDL-75906-400' of https://github.com/mickhawkins/moodle into MOODLE_400_STABLE 2023-04-03 14:54:06 +01:00
Mark Johnson 6f61f48e20 MDL-75301 question: Add behat generator for updating questions
This adds "core_question > updated question" as an entity for `the
following "X" exist` and calls the existing update_question() generator
which will create a new question version with the supplied data.
2023-04-03 12:35:08 +01:00
Paul Holden dec59bd614 Merge branch 'MDL-77227-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2023-04-03 10:47:38 +01:00
Michael Hawkins f37baf7b59 MDL-75906 core: Updated security.txt expiry 2023-04-03 17:27:48 +08:00
Laurent David 03c1095379 MDL-77712 core_course: Fix exception with inplace editor
* On fresh install, an exception is raised when we try to modify
the name of a newly inserted activity in the front page
2023-04-03 10:44:49 +02:00
Ferran Recio 55139ae744 MDL-77552 core_courseformat: add plugin and module to cm state
Backport of MDL-77386
2023-04-03 09:34:21 +02:00
AMOS bot 6cf8bd9832 Automatically generated installer lang files 2023-04-02 00:07:33 +00:00
AMOS bot ed4e4660db Automatically generated installer lang files 2023-04-01 00:07:42 +00:00
Paul Holden 8400206468 weekly release 4.0.7+ 2023-03-31 18:11:57 +01:00
Paul Holden 32a944bac8 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-03-31 18:11:55 +01:00
Jake Dallimore d7185519c3 Merge branch 'MDL-59175-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-31 11:57:43 +08:00
Jake Dallimore 9daaca2400 Merge branch 'MDL-77794-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-31 11:48:56 +08:00
Andrew Nicols dc2b74c749 Merge branch 'MDL-77783-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-03-31 11:31:16 +08:00
Ilya Tregubov db31cd37b2 Merge branch 'MDL-70976-400' of https://github.com/laurentdavid/moodle into MOODLE_400_STABLE 2023-03-31 09:42:34 +08:00
AMOS bot d8d79addc4 Automatically generated installer lang files 2023-03-31 00:07:37 +00:00
Laurent David 178cc61b18 MDL-77456 core_courseformat: Fix highlight in course index
* When navigating to a restricted activity as a student from the course index
the item is not highlighted when refreshing the page.
2023-03-30 18:57:56 +02:00
Sara Arjona 5f87d91315 Merge branch 'MDL-77761-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-03-30 17:53:25 +02:00
Sara Arjona 3cd54831ea Merge branch 'MDL-77764-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-30 16:31:26 +02:00
Paul Holden 166c6cc61e Merge branch 'MDL-76481_400_Brickfield_TCPDF_error' of https://github.com/brickfield/moodle into MOODLE_400_STABLE 2023-03-30 12:50:11 +01:00
Sara Arjona f616930138 Merge branch 'MDL-77762-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-30 13:45:23 +02:00
Jun Pataleta 8420c58e69 Merge branch 'MDL-77333_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2023-03-30 19:03:32 +08:00
Paul Holden 4a603fe534 MDL-77794 contentbank: fix plugin type language strings.
AMOS BEGIN
 CPY [type_contentbank,core_plugin],[type_contenttype,core_plugin]
 CPY [type_contentbank_plural,core_plugin],[type_contenttype_plural,core_plugin]
AMOS END
2023-03-30 09:58:40 +01:00
Max Larkin 7956a8d814 MDL-76481 tool_brickfield: Fix PHP 8 report download 2023-03-30 09:15:28 +01:00
Paul Holden fba11f5c29 Merge branch 'MDL-75017_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-03-30 08:47:56 +01:00
Ilya Tregubov b83db3be01 Merge branch 'MDL-73771_400' of https://github.com/lostrogit/moodle into MOODLE_400_STABLE 2023-03-30 14:23:08 +08:00
AMOS bot b74ee3931c Automatically generated installer lang files 2023-03-30 00:07:41 +00:00
Amaia Anabitarte d9f694bfa8 MDL-77227 roles: Remove extra information for override page 2023-03-29 18:19:26 +02:00
Carlos Castillo bdc55fbffc MDL-73771 theme: Fix scrollbar position 2023-03-29 09:07:51 -05:00
Shamim Rezaie 4b39aecb10 Merge branch 'MDL-74452_400_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_400_STABLE 2023-03-29 15:27:36 +11:00
Jun Pataleta 2834086d07 Merge branch 'MDL-77382-400' of https://github.com/snake/moodle into MOODLE_400_STABLE 2023-03-29 09:48:11 +08:00
Jun Pataleta b6604a3a19 Merge branch 'MDL-76941-400-2' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2023-03-29 09:31:43 +08:00
Jun Pataleta 13fec4131e MDL-77783 core: Validate sublugins.json
* Validate the decoded subplugins.json before processing it.
* Log errors if subplugins.json is invalid or if plugintypes is not
defined.
2023-03-29 09:29:51 +08:00
Jun Pataleta 9ebea4011e MDL-77761 core_form: Add label for editor format selector 2023-03-29 08:09:46 +08:00
Eloy Lafuente (stronk7) 87fbf39aae MDL-77333 mod_resource: fixes generator uploading files + tests
MDL-76499 revealed a few problems with resource generators:

1. We were not covering with unit tests the upload of files from disk
   (and here it's where the problem was).
2. There was a little of confusion between disk paths (only needed
   to upload files) and file_area paths (the generator only creates
   or uploads files to the root directory of the file area.
3. It was possible to request the upload of a file to the generator
   without that file effectively existing.

This commit fixes those points  and covers 99% of the generator code.
2023-03-28 19:06:26 +02:00
Paul Holden 6273e6fdf3 weekly release 4.0.7+ 2023-03-28 15:55:22 +01:00
Paul Holden e8be539742 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-03-28 15:55:20 +01:00
Paul Holden 5b94923b7a Merge branch 'MDL-77105-400-4' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-03-28 12:39:05 +01:00
Jun Pataleta e736f80017 MDL-77105 core: Cast custom data to an array when evaluating filtericon
Since other modules may treat custom data as an object, we need to make
cast it to an array before evaluating for the `filtericon` custom data.
2023-03-28 18:54:04 +08:00
Huong Nguyen c7cc232e16 MDL-76941 tool_usertours: Fix accessibility issue when resizing 2023-03-28 12:18:24 +07:00
Jun Pataleta 07a3a15eb7 Merge branch 'MDL-77630-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2023-03-28 12:06:24 +08:00
Jake Dallimore 07f644d2ec Merge branch 'MDL-77105-400-4' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-03-28 11:42:54 +08:00
Meirza aac223ade5 MDL-77630 mod_forum: correct typo in variable names 2023-03-28 09:42:07 +07:00
Jun Pataleta c1a94a7d52 Merge branch 'MDL-77670-400' of https://github.com/juancs/moodle into MOODLE_400_STABLE 2023-03-28 07:05:30 +08:00
Paul Holden beaff418ba MDL-77762 contentbank: always provide exit button when appropriate.
If the current user can access the content bank in the context of the
current item, then provide link back to it.
2023-03-27 18:08:50 +01:00
Paul Holden ff1b86ab60 MDL-77764 contentbank: add field label to context selection element. 2023-03-27 16:55:00 +01:00
Sara Arjona 191ef569b5 Merge branch 'MDL-76376_m40' of https://github.com/jrchamp/moodle into MOODLE_400_STABLE 2023-03-27 16:56:36 +02:00
Sara Arjona 307be1189c Merge branch 'MDL-77659_400' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_400_STABLE 2023-03-27 16:50:37 +02:00
Sara Arjona 3cfe37dd29 Merge branch 'MDL-73226-400' of https://github.com/jleyva/moodle into MOODLE_400_STABLE 2023-03-27 16:08:32 +02:00
Juan Leyva bb4329278b MDL-73226 files: Add quota checks to core_user_add_user_private_files 2023-03-27 13:27:59 +02:00
Sara Arjona f6d297a920 Merge branch 'MDL-76303-400' of https://github.com/ssj365/moodle into MOODLE_400_STABLE 2023-03-27 12:41:50 +02:00
Paul Holden 36edc365ea Merge branch 'MDL-77729_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-03-27 11:09:27 +01:00
Sara Arjona ed55a94fe8 Merge branch 'MDL-77561-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-03-27 11:43:32 +02:00
Paul Holden 551edbb9a6 MDL-77555 reportbuilder: improve SQL generation within filters.
Use native ANSI SQL syntax for numeric comparisons where possible,
define filter API for the case where filters must re-use the given
field SQL while ensuring uniqueness of any field parameters.
2023-03-27 10:29:37 +01:00
Paul Holden 478861b4d1 MDL-77555 reportbuilder: method to ensure unique parameters in SQL. 2023-03-27 10:29:37 +01:00
Jun Pataleta 22768e349a MDL-77105 core: Add upgrade.txt notes 2023-03-27 14:03:48 +08:00
Jun Pataleta 6ad9bb2482 MDL-77105 mod_url: Declare filtericon custom data
* Set a custom data `filtericon` when the icon being rendered for the
URL resource is not equal to the default plugin icon.
2023-03-27 14:03:47 +08:00
Jun Pataleta fd953966d8 MDL-77105 mod_lti: Add 'nofilter' class for custom tool icons
Add a '.nofilter' class when rendering custom tool icons in order
to render them as is and without CSS filter on the activity chooser.
2023-03-27 14:03:34 +08:00
Jun Pataleta 82db828016 MDL-77105 core_course: Add 'nofilter' class for non-monologo icons
When rendering content items, check whether the plugin has monologo
icons. If so, add a 'nofilter' class so the plugin icon can be
rendered as is and without the CSS filter.
2023-03-27 14:03:21 +08:00
Jun Pataleta 6a409c4cd4 MDL-77105 block_timeline: Add 'nofilter' class when necessary
Add the `.nofilter` class for activity icons when the icon URL's
`filtericon` parameter is not set, so they get rendered as they are on
the timeline block.
2023-03-27 14:03:07 +08:00
Jun Pataleta 894a6ab5ad MDL-77105 block_recentlyaccesseditems: Add 'nofilter' class
Add the `.nofilter` class for activity icons when the icon URL's
`filtericon` parameter is not set, so they get rendered as they are on
the recently accessed items block.
2023-03-27 14:02:51 +08:00
Jun Pataleta 5b1daccb92 MDL-77105 theme_boost: Add 'nofilter' class when necessary
Add the `.nofilter` class for activity icons when the icon URL's
`filtericon` parameter is not set, so they get rendered as they are on
the context header on the activity page.
2023-03-27 13:48:47 +08:00
Jun Pataleta f005111165 MDL-77105 course_format: Add 'nofilter' class when necessary
Add the `.nofilter` class for activity icons when the icon URL's
`filtericon` parameter is not set, so they get rendered as they are on
the course homepage.
2023-03-27 13:48:46 +08:00
Jun Pataleta 1e30a80b7f MDL-77105 core: Conditionally apply icon filter
* Apply the filter CSS property only to activity icons
that don't have the ".nofilter" class. This will allow
activities with non-SVG icons to be rendered as they are.
2023-03-27 13:48:44 +08:00
Jun Pataleta 0778d512fe MDL-77105 core: Add a filtericon parameter to course mod icon URLs
* If a plugin defines a `filtericon` custom data or uses its monologo
version of the icon, a `filtericon` parameter is being added to the
icon's URL. This information can help plugins determine whether to
render the activity icon as is or with CSS filtering.
2023-03-27 13:45:35 +08:00
Jun Pataleta 8812990c85 MDL-77105 core: Method to determine whether a plugin has monolog icons 2023-03-27 13:45:32 +08:00
AMOS bot 1018c8a4c5 Automatically generated installer lang files 2023-03-26 00:07:38 +00:00
Tim Hunt 60220de680 MDL-77729 qformat_missingword: fix form of help link 2023-03-25 15:40:27 +00:00
Tim Hunt b7d7b84d30 MDL-75017 questions: give a clear error if the context type is invalid 2023-03-24 13:02:30 +00:00
Tim Hunt 8169d1da07 MDL-75017 questions: fix weird setup in qformat_xml_import_export_test 2023-03-24 13:02:28 +00:00
Sara Arjona 8af994f1f0 weekly release 4.0.7+ 2023-03-24 13:59:36 +01:00
Jun Pataleta 8ca6ffa077 Merge branch 'MDL-77669-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2023-03-24 11:51:25 +08:00
Jun Pataleta 3904547719 Merge branch 'MDL-77626_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-03-24 10:40:30 +08:00
Simey Lameze 74a28bde79 MDL-77561 behat: add step to accept dpa and enable bigbluebutton
The step i_enable_plugin cannot be used as bigbluebuttonbn_default_dpa_accepted
setting needs to be enable in order for the BigBlueButton plugin to be enabled.
2023-03-24 08:23:27 +08:00
Sara Arjona 5fb543fa45 Merge branch 'MDL-77666-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-23 17:53:53 +01:00
Shamiso.Jaravaza f19e245f29 MDL-76303 mod_bigbluebuttonbn: Fix userlimit 2023-03-23 08:22:29 -06:00
Paul Holden 922713d626 Merge branch 'MDL-77392-400' of https://github.com/srobotta/moodle into MOODLE_400_STABLE 2023-03-23 12:25:24 +00:00
Stephan Robotta ac7720b956 MDL-77392 calendar: calendar items are hidden because of settings 2023-03-23 12:52:32 +01:00
Paul Holden 712cdd0fc6 Merge branch 'MDL-77691-400' of https://github.com/roland04/moodle into MOODLE_400_STABLE 2023-03-23 11:43:42 +00:00
Sara Arjona f575d8fc82 Merge branch 'MDL-77380-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-03-22 14:06:14 +01:00
Sara Arjona 03a41fa881 Merge branch 'MDL-77692-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-22 13:50:19 +01:00
Ilya Tregubov 11a1ac8913 weekly release 4.0.7+ 2023-03-22 09:37:13 +08:00
Ilya Tregubov c35fd3566c Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-03-22 09:37:11 +08:00
Mark Johnson 6597f8f7f5 MDL-74452 quiz: Display an error if all versions are in draft status 2023-03-21 15:24:52 +00:00
Mikel Martín e04daa31e4 MDL-77691 behat: Add step to navigate to profile page directly 2023-03-21 08:10:16 +01:00
Simey Lameze bde844c57c MDL-77380 block_myoverview: improve show toggle functionality test 2023-03-21 14:47:33 +08:00
Angelia Dela Cruz 7c007b8f32 MDL-77577 Behat: Replaced the use of "Install selected language pack(s)
Evaluated usage of "Install selected language pack(s)" in Behat and
replaced the steps to use generator to install language packs as part
of test setup.
2023-03-21 12:13:20 +08:00
Jun Pataleta c68493a349 Merge branch 'MDL-75746_400_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_400_STABLE 2023-03-21 12:00:55 +08:00
Meirza 529187a82a MDL-77669 dml: Added extrainfo in the DB options config.
extrainfo is an 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.

Co-authored-by: LukeCarrier <luke@carrier.im>

This is a backport of MDL-64153.
2023-03-21 08:48:39 +08:00
Ilya Tregubov c38582b409 Merge branch 'mdl-72533-event-table-performance-MOODLE_400_STABLE' of https://github.com/petersistrom/moodle into MOODLE_400_STABLE 2023-03-21 08:24:54 +08:00
Paul Holden b0872b6aa5 Merge branch 'MDL-72124_400_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_400_STABLE 2023-03-20 17:04:56 +00:00
Paul Holden 8f296f6528 MDL-77692 reportbuilder: format custom field condition/filter names. 2023-03-20 16:32:16 +00:00
Sara Arjona 1b7f761528 Merge branch 'MDL-77574-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-03-20 17:06:11 +01:00
Anupama Sarjoshi 2d9536f980 MDL-77659 core_reportbuilder: fix user profile fields phpunit tests 2023-03-20 13:46:36 +00:00
Sara Arjona 9845799ed6 Merge branch 'MDL-77523-400' of https://github.com/juancs/moodle into MOODLE_400_STABLE 2023-03-20 13:42:55 +01:00
Mark Sharp 23e15c1ae2 MDL-72533 core_calendar: improve calendar event table peformance
- Filter searchable courses if set.
- Sites with large groups should now experience better performance.
- Applies and optimises query against a proper date range.

Co-authored-by: Mark Sharp <mark.sharp@solent.ac.uk>
Co-authored-by: Peter Sistrom <petersistrom@catalyst-au.net>
Co-authored-by: Kevin Pham <keevan.pham@gmail.com>
2023-03-20 12:17:31 +11:00
AMOS bot 5bbdf8ab51 Automatically generated installer lang files 2023-03-20 00:07:37 +00:00
Brendan Heywood f42ac85b7e MDL-77618 admin: Passwords should not auto complete 2023-03-18 13:03:38 +11:00
AMOS bot 6a566abcd9 Automatically generated installer lang files 2023-03-18 00:07:38 +00:00
Juan Segarra Montesinos c0a05c9d8a MDL-77670 course: Preserve course summary format 2023-03-17 20:53:08 +01:00
Sara Arjona a971b89389 weekly release 4.0.7+ 2023-03-17 17:58:33 +01:00
Sara Arjona 10a640c25e Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-03-17 17:58:25 +01:00
Jun Pataleta c0373ed7f7 Merge branch 'MDL-76257-400' of https://github.com/juancs/moodle into MOODLE_400_STABLE 2023-03-17 11:01:14 +08:00
Jun Pataleta 6b7b12c790 Merge branch 'MDL-77608-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-03-17 10:29:40 +08:00
AMOS bot 213935c460 Automatically generated installer lang files 2023-03-17 00:07:40 +00:00
Paul Holden 75a1e8d843 MDL-77666 contentbank: format category names for display. 2023-03-16 23:27:20 +00:00
info@eWallah.net c5bea842a9 MDL-77584 currencies: Fix outdated ISO 4217 code for Zambian Kwacha
On 2013-01-01 the ZMK code got replaced by the new ZMW code.

AMOS BEGIN
 MOV [ZMK,core_currencies],[ZMW,core_currencies]
AMOS END
2023-03-16 19:53:34 +01:00
Paul Holden 4e758d343a MDL-76339 mod_bigbluebuttonbn: correct upgrade note fix versions. 2023-03-15 19:15:53 +00:00
Paul Holden e889cc49c2 Merge branch 'MDL-76339-400' of https://github.com/call-learning/moodle into MOODLE_400_STABLE 2023-03-15 19:06:02 +00:00
Andrew Nicols 06fa0aad49 Merge branch 'MDL-77550-400' of https://github.com/dpalou/moodle into MOODLE_400_STABLE 2023-03-15 14:26:38 +08:00
Jun Pataleta 4a60dd3205 Merge branch 'MDL-77611_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-03-15 10:00:58 +08:00
AMOS bot 7c18bb6833 Automatically generated installer lang files 2023-03-15 00:07:36 +00:00
Paul Holden 5eb255f051 MDL-59175 theme_boost: style inherited permission on overide page. 2023-03-14 20:58:04 +00:00
Tim Hunt 88cedd9f99 MDL-77626 quiz statistics: Divide by zero if a random Q has max mark 0 2023-03-14 16:29:59 +00:00
Mark Johnson d1254b0c8d MDL-75746 mod_quiz: Fix backup and restore of quiz slots 2023-03-14 16:07:35 +00:00
Mark Johnson 962ab85122 MDL-72124 question: Fix system-level URLs in question events 2023-03-14 15:40:51 +00:00
Eloy Lafuente (stronk7) 264f458417 weekly release 4.0.7+ 2023-03-14 16:07:41 +01:00
Eloy Lafuente (stronk7) adc9c66e75 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2023-03-14 16:07:36 +01:00
Jun Pataleta 6ddeef9cab Merge branch 'MDL-76680/400' of https://github.com/skodak/moodle into MOODLE_400_STABLE 2023-03-14 21:44:14 +08:00
Laurent David 68456ca14f MDL-70976 core_files: Allow for draft files url inserted in content
* The file file_remove_editor_orphaned_files should take into account URL that
have been embedded in a tag content instead of an attribute (like src attribute)
* This will fix issue with inserting H5P content in calendar events.
2023-03-14 08:48:40 +01:00
Juan Segarra Montesinos 45d7645598 MDL-76257 core: Activity intro should honor user preference on creation 2023-03-14 06:06:27 +01:00
AMOS bot 2c2bd9e2af Automatically generated installer lang files 2023-03-14 00:07:38 +00:00
Tim Hunt 9cf379579b MDL-77611 tool_uploaduser: fix phpunit assumptions about profile fields 2023-03-13 13:37:52 +00:00
Paul Holden 2919cf9e1b MDL-77608 mod_h5pactivity: namespace component lib testcase. 2023-03-13 09:44:05 +00:00
Simey Lameze 136e636bf0 MDL-77574 myoverview: wait until next button exists before clicking 2023-03-13 14:12:33 +08:00
Jake Dallimore 622f98e637 MDL-77382 core: fix error handling in oauth2 callback for auth'd users
Pass the errors back to the calling code when the user is authenticated,
otherwise, fall back on the existing redirection to the login page.
2023-03-13 10:50:15 +08:00
AMOS bot aa6bfe07ef Automatically generated installer lang files 2023-03-12 00:07:44 +00:00
Petr Skoda 712391f96b MDL-76680 core: disable $USER->ignoresesskey on next page 2023-03-11 10:37:34 +01:00
Dani Palou 778840f1d7 MDL-77550 lesson: Format decimals in feedback page 2023-03-08 07:45:05 +01:00
Roberto Bravo 756f56492e MDL-77256 tool_uploaduser: fix get allowed roles for courses
During user upload the permission to assign roles is checked in the wrong context
2023-03-07 18:38:46 +01:00
Juan Segarra Montesinos 5fc2612d25 MDL-77523 mod_data: textarea field should honor editor preferred format 2023-03-05 08:53:02 +01:00
Laurent David 55620756a5 MDL-76339 mod_bigbluebuttonbn: Update dismissed recordings
* When the server is not reachable (or recordings are not reacheable)
the recording is set to RECORDING_STATUS_DISMISSED and is then
not visible in the list.
* Add a CLI script to solve potential issue with DISMISSED recordings
2023-03-03 06:38:26 +01:00
Anastasios Bithas 9079e01d44 MDL-73642 mod_assign: Disable draft option if submission already made 2023-02-04 18:49:21 +02:00
Mark Holliday 801e7d9fe4 MDL-76376 scorm: fix PHP8 TypeError (null is not Countable) 2022-11-28 17:52:33 -05:00
276 changed files with 5179 additions and 946 deletions
+1 -1
View File
@@ -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');
+78
View File
@@ -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();
+2
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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 }}"
+113
View File
@@ -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"
+4 -1
View File
@@ -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;
+19 -8
View File
@@ -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');
}
}
+19 -4
View File
@@ -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;
+2 -1
View File
@@ -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;
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+23 -1
View File
@@ -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);
};
/**
+7 -8
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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) {
+1 -1
View File
@@ -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"
+4
View File
@@ -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
+9 -13
View File
@@ -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);
}
+8 -9
View File
@@ -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"
+27 -61
View File
@@ -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)));
}
}
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -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],
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -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,"&section=").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,"&section=").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
+1
View File
@@ -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},
];
}
+59 -1
View File
@@ -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;
}
-8
View File
@@ -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.
+74
View File
@@ -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}}"
+172 -1
View File
@@ -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
);
}
}
+11
View File
@@ -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.';
+4 -2
View File
@@ -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;
}
}
+36
View File
@@ -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
));
}
+1 -1
View File
@@ -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).
+11
View File
@@ -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.';
+4 -2
View File
@@ -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;
}
}
+36
View File
@@ -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
));
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+38
View File
@@ -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"
+12 -6
View File
@@ -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:
+5 -3
View File
@@ -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}}
+7 -7
View File
@@ -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,
+1 -1
View File
@@ -605,7 +605,7 @@ class file_storage_test extends \advanced_testcase {
true,
],
'Icon not included' => [
'greeting-card-887.h5p',
'greeting-card.h5p',
false,
],
];
Binary file not shown.
Binary file not shown.
+14 -14
View File
@@ -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);
+6 -1
View File
@@ -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';
+33
View File
@@ -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';
+34
View File
@@ -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
View File
@@ -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'] = 'Веб хаяг';
+1 -1
View File
@@ -30,7 +30,7 @@
defined('MOODLE_INTERNAL') || die();
$string['language'] = 'Хэл';
$string['moodlelogo'] = 'Мүүдл лого';
$string['moodlelogo'] = 'Moodle лого';
$string['next'] = 'Дараагийн';
$string['previous'] = 'Өмнөх';
$string['reload'] = 'Дахин ачаалах';
+1 -1
View File
@@ -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>
+32
View File
@@ -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';
+1 -1
View File
@@ -30,4 +30,4 @@
defined('MOODLE_INTERNAL') || die();
$string['thisdirection'] = 'rtl';
$string['thislanguage'] = 'سنڌي';
$string['thislanguage'] = 'سنڌي';
+33
View File
@@ -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';
+44
View File
@@ -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)';
+49
View File
@@ -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';
+89
View File
@@ -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 &quot;nobody&quot; abo &quot;apache&quot;), 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 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