Compare commits

..

347 Commits

Author SHA1 Message Date
Jun Pataleta b864c78a31 Moodle release 4.0.6 2023-01-14 14:17:09 +08:00
Jun Pataleta 5b81c07712 weekly release 4.0.5+ 2023-01-13 10:52:19 +08:00
Andrew Nicols 7299eb910d Merge branch 'MDL-76820-400' of https://github.com/cameron1729/moodle into MOODLE_400_STABLE 2023-01-12 12:09:48 +08:00
Jun Pataleta 43bfcc4c77 Merge branch 'MDL-76649_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2023-01-12 12:06:54 +08:00
Michael Hawkins 044e23f691 MDL-76861 blog: Ensure correct escaping applied to search string 2023-01-12 11:43:22 +08:00
Jake Dallimore 8a5563445d MDL-76862 user: Unit test for setting user home page preferences 2023-01-12 11:30:46 +08:00
Paul Holden 8de0b97f7d MDL-76862 user: ensure user can only update own preferred start page. 2023-01-12 11:17:00 +08:00
Cameron Ball 8ee9748839 MDL-76820 core_search: Reset manager::$coursedeleting between tests 2023-01-12 10:54:50 +08:00
Jun Pataleta 2d82b93072 Merge branch 'MDL-76739-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-01-12 10:17:52 +08:00
Jun Pataleta a387d795f7 MDL-76739 mod_data: Replace "Author surname" with "Author last name"
For consistency with the rest of the lang strings
2023-01-12 09:59:50 +08:00
Jun Pataleta 80d8f7f1be MDL-76739 behat: Replace occurrences of "surname" in Behat tests
Replace occurrences of "surname" in Behat tests with "last name".
2023-01-12 09:49:57 +08:00
David Mudrák bb82843548 MDL-76739 lang: Use the fixed strings in the tests, too 2023-01-11 18:54:57 +01:00
Helen Foster 3463f7fa5d MDL-76739 lang: Import fixed English strings (en_fix) 2023-01-11 18:54:57 +01:00
Ilya Tregubov 005814360f Merge branch 'MDL-76607-400' of https://github.com/davewoloszyn/moodle into MOODLE_400_STABLE 2023-01-11 19:18:48 +07:00
Andrew Nicols 8e9e4ca362 Merge branch '66924-view-own-private-reply-400' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_400_STABLE 2023-01-11 15:53:40 +08:00
Tim Hunt 799f7fb18f MDL-76810 redirect handling: ensure return URLs are properly sanitised 2023-01-11 11:43:45 +08:00
Jake Dallimore 978a6bb8ec Merge branch 'MDL-76597-400-2' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-01-11 10:12:33 +08:00
Paul Holden 7405121cd2 Merge branch 'MDL-76811-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2023-01-10 16:40:06 +00:00
Paul Holden aa40f64f98 Merge branch 'MDL-76803-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-01-10 16:24:04 +00:00
Paul Holden b7baec898a Merge branch 'MDL-76653-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2023-01-10 15:29:16 +00:00
Paul Holden aeabe6324b Merge branch 'MDL-76833-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2023-01-10 12:29:18 +00:00
Jun Pataleta c445846da4 MDL-76803 lang: Update usages of reworded email display options 2023-01-10 16:01:51 +08:00
Jun Pataleta 8376eec99d MDL-76803 lang: Make email display options more concise 2023-01-10 16:01:51 +08:00
Andrew Nicols a20c78d894 MDL-76833 core: Bump phpunit/php-code-coverage version
This includes a bug fix for a display issue with code coverage reporting
in phpunit's HTML output report.
2023-01-10 12:09:01 +08:00
Andrew Nicols fe6d102184 MDL-76811 mod_data: Remove duplicate tests 2023-01-10 11:39:40 +08:00
Andrew Nicols e719cbb687 MDL-76811 mod_data: strpos check should be strict 2023-01-10 11:39:40 +08:00
Andrew Nicols b5cce2514d MDL-76811 mod_data: Generator test cleanup 2023-01-10 11:39:40 +08:00
Simey Lameze 81ff190dfb MDL-76653 behat: add coverage for SCORM availability 2023-01-10 10:25:55 +08:00
Jun Pataleta 7268fe0424 Merge branch 'MDL-76061-MOODLE_400_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_400_STABLE 2023-01-10 09:42:10 +08:00
Philipp Memmel c2b7e33b5d MDL-76061 core_calendar: Fix changing event type from 'user' 2023-01-09 15:06:09 +01:00
Tim Hunt 0dcd79d2e8 MDL-76649 quiz statistics task: output more useful trace info
At the moment, quiz_statistics\task\recalculate gives no useful
information about what it is doing, which makes it hard to investigate
if the task fails. This commit makes it more usefully verbose.

Also, following this change, one instance of this task will not
run for more than one hour at a time.

As part of this commit, I have added a new helper mtrace_exception.
to consistently log exceptions in scheduled tasks. It is sad to
add a new function to moodlelib.php, but that seemed the logical place.
Looking at other tasks, this method is badly needed. Many are just
logging the ->getMessage() which is normaly insufficient for proper
debugging. However, swiching all existing tasks to use the new function
will need to wait for a future MDL.
2023-01-09 13:46:29 +00:00
Julien Boulen 918b7c9c87 MDL-66924 mod_forum: Allow users to see their own private messages
Allow users to see their own private messages even if they don't have
mod/forum:readprivatereplies capability

Add behat test to avoid MDL-67109 issue.

Co-authored-by: Martin Putzlocher <mputzi@users.noreply.github.com>
2023-01-09 14:43:45 +01:00
Paul Holden 06634f0add Merge branch 'MDL-75532-400' of https://github.com/snake/moodle into MOODLE_400_STABLE 2023-01-09 11:51:00 +00:00
Paul Holden d7ba5b5d6f Merge branch 'MDL-76601-400' of https://github.com/junpataleta/moodle into MOODLE_400_STABLE 2023-01-09 10:11:07 +00:00
Jun Pataleta a61a86c61d MDL-76597 mod_quiz: Add a default heading name for Behat tests 2023-01-09 15:42:57 +08:00
Jake Dallimore 673faab506 MDL-75532 enrol_lti: fix optional lineitemsurl in grade sync task
As in MDL-74691, we need either or both of these fields, meaning either
one could be omitted. This just supports that as per the fix made in
MDL-74691.
2023-01-09 11:37:14 +08:00
Jake Dallimore 3a8149ccc2 MDL-75532 enrol_lti: add tests for coupled and decoupled line items
This covers the following cases:
1. Where only the 'lineitem' service endpoint is provided
2. Where only the 'lineitems' service endpoint is provided.
Existing tests already cover the case where both are provided.
2023-01-09 11:37:14 +08:00
Jun Pataleta 4d64b0b5fe MDL-76597 mod_quiz: Set presentation role for the question list
Since the <ul> and <li> elements for listing the quiz questions and
elements are mainly used for layout purposes, it is better to set the
role of these elements to presentation only.
The aria-label for the <li> element is inappropriate and can also cause
confusion to screen reader users. Better to remove this. Though this is
being used in the confirmation modal so better to just change it to a
data attribute.
2023-01-06 22:55:13 +08:00
Jun Pataleta 58d350d53d MDL-76597 question: Add question version lang string 2023-01-06 22:55:12 +08:00
Jun Pataleta 7ad4bc126b MDL-76597 mod_quiz: Add label for question checkboxes 2023-01-06 22:55:12 +08:00
Jun Pataleta dac806d47d MDL-76597 mod_quiz: Darken section heading on quiz questions page 2023-01-06 22:55:12 +08:00
Jun Pataleta 5ea303bacb MDL-76597 mod_quiz: Add label for version selector 2023-01-06 22:55:12 +08:00
Jun Pataleta d597211fa6 MDL-76597 mod_quiz: Add a default sr-only section heading
Add a default sr-only section heading in order to prevent having an
empty heading for the quiz section which is not good for accessibility.

Plus:
- There's also an existing issue where filters are never applied to
section headings on load. This has been fixed in this commit as well.
- Button role added for the edit section button which enables it to
take advantage of the theme highlighting when it receives focus.
2023-01-06 22:55:12 +08:00
Paul Holden fcea42b77e Merge branch 'MDL-32114-400' of https://github.com/srobotta/moodle into MOODLE_400_STABLE 2023-01-06 11:20:48 +00:00
Paul Holden 9b7854dbad Merge branch 'MDL-76578-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2023-01-06 10:41:37 +00:00
Ilya Tregubov 500bde134f Merge branch 'MDL-76251-patch-400' of https://github.com/ilyatregubov/moodle into MOODLE_400_STABLE 2023-01-06 16:15:06 +07:00
Ilya Tregubov dc230cf98e MDL-76251 mod_forum: Fix illegal whitespace. 2023-01-06 16:13:37 +07:00
Ilya Tregubov dc516a038e Merge branch 'MDL-76251-400' of https://github.com/aya-saad1/moodle into MOODLE_400_STABLE 2023-01-06 15:38:19 +07:00
Stephan Robotta bd1d89a94a MDL-32114 form: markdown must be preserved on saving post
- Markdown is saved to the DB, no conversion to HTML to keep
  ability to reedit the content without beaking it.
- Blockquote element is styled that it's distingishable from
  normal text.
2023-01-05 18:36:58 +01:00
Andrew Nicols 7d4104a8eb Merge branch 'MDL-76508-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2023-01-05 21:31:14 +08:00
Paul Holden da216a5545 weekly release 4.0.5+ 2023-01-05 10:53:13 +00:00
Aya Saad 08d0ea0aad MDL-76251 mod_forum: fix responsive issues in discussion 2023-01-05 11:35:44 +02:00
David Woloszyn 50c1e2507d MDL-76607 timeline: Reordered message to account for long course name 2023-01-05 12:13:39 +11:00
David Woloszyn ec71e226d4 MDL-76607 css: Fixed various classes where long strings break layout 2023-01-05 12:13:39 +11:00
Sara Arjona 9b11c29932 Merge branch 'MDL-76375-400' of https://github.com/lucaboesch/moodle into MOODLE_400_STABLE 2023-01-04 16:21:51 +01:00
Luca Bösch 2af81f271d MDL-76375 quiz generator: Allow more than one attempt by Behat tests. 2023-01-04 15:16:30 +01:00
Sara Arjona 1fa5b0c03c Merge branch 'MDL-76221-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-01-04 13:09:46 +01:00
Paul Holden 160019f2e3 MDL-76657 grade: load required test libraries for grade helper. 2023-01-04 11:22:51 +00:00
Paul Holden 8412f2adb0 Merge branch 'MDL-76657-400' of https://github.com/rezaies/moodle into MOODLE_400_STABLE 2023-01-04 11:10:43 +00:00
Jun Pataleta 1d3bd4e102 Merge branch 'MDL-74822-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2023-01-04 17:29:11 +08:00
Jun Pataleta 54e2850687 MDL-76601 block_myoverview: Remove hover action before clicking on menu
With the course card menu now always displayed, there's no need to hover
first before clicking on the menus on block_myoverview Behat tests.
2023-01-04 17:22:46 +08:00
Jun Pataleta 1c1f42d5d3 MDL-76601 blocks: Always display course card menus
Displaying the course card menu only on hover is bad in terms of
accessibility as it prevents keyboard-only users from accessing the
menu. So it's better to always display them.
2023-01-04 17:22:46 +08:00
Sara Arjona d070caea1a Merge branch 'MDL-76181-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-01-04 09:20:25 +01:00
Sara Arjona dd6549e0be Merge branch 'MDL-76308-400' of https://github.com/BruceGoodGuy/moodle into MOODLE_400_STABLE 2023-01-03 14:13:05 +01:00
Paul Holden 0b66c7a43a Merge branch 'MDL-53137-400' of https://github.com/lucisgit/moodle into MOODLE_400_STABLE 2023-01-03 12:14:43 +00:00
Sara Arjona 093b2d9eb5 Merge branch 'MDL-71506-400' of https://github.com/lucaboesch/moodle into MOODLE_400_STABLE 2023-01-03 13:10:22 +01:00
Paul Holden 7172bf1f73 Merge branch 'MDL-75346-reset_dashboard_error-400' of https://github.com/leonstr/moodle into MOODLE_400_STABLE 2023-01-03 11:28:33 +00:00
Shamim Rezaie 540ce30050 MDL-76657 gradebook: Remove hard-coded plugin names from unit test 2023-01-03 20:33:17 +11:00
Andrew Nicols 4fb6de6324 MDL-32105 mod_glossary: Improve behat test 2023-01-03 15:32:39 +08:00
Andrew Nicols d9d1cd7c55 Merge branch 'MDL-32105-400' of https://github.com/Chocolate-lightning/moodle into MOODLE_400_STABLE 2023-01-03 15:32:36 +08:00
Peter 6774281d65 MDL-32105 mod_glossary: Restrict glossary aliases by set of keywords 2023-01-03 13:49:09 +08:00
Huong Nguyen e22131aa8f MDL-74822 usertours: Fix accessibility issues with user tours
Including in this commit:
 - Prevent the tour to be displayed if the CSS is disabled by the browser
 - Removed redundant tabindex=0 attribute on the target
 - Created extra code to re-calculate the suitable position of the tour
 - Fixed tour issue in 200% and 400% zoom
 - Fixed tour highlight is not correct in 200% and 400%
2023-01-03 10:35:32 +07:00
Sara Arjona 81ecef2c1b Merge branch 'MDL-60038-400' of https://github.com/aneno-m-e/moodle into MOODLE_400_STABLE 2023-01-02 16:35:30 +01:00
Luca Bösch d0e3eb464a MDL-71506 mod_choice: suppress non respondents in downloads if set so. 2023-01-02 15:52:47 +01:00
Sara Arjona 5e439eefde Merge branch 'MDL-76106-400' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_400_STABLE 2023-01-02 13:07:45 +01:00
Sara Arjona d066f500bf Merge branch 'MDL-76760-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2023-01-02 12:27:46 +01:00
Paul Holden bb898838d6 MDL-76221 reportbuilder: improve report test generator methods.
Test generators for creating report columns, filters and conditions
now allow for setting all persistent properties.
2022-12-29 14:02:32 +00:00
Paul Holden 81cc2e6b41 MDL-76181 reportbuilder: sort columns during stress testing. 2022-12-29 13:57:42 +00:00
Sara Arjona fcfc240a77 weekly release 4.0.5+ 2022-12-29 12:57:50 +01:00
Sara Arjona f3fee9f4d2 Merge branch 'MDL-76399-patch-400' of https://github.com/ilyatregubov/moodle into MOODLE_400_STABLE 2022-12-29 09:13:39 +01:00
Ilya Tregubov 302610302a MDL-76399 behat: switch to appropriate Behat step for selects. 2022-12-29 14:45:00 +07:00
Ilya Tregubov fa417ba8a3 Merge branch 'MDL-76399-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-29 09:44:00 +07:00
Sara Arjona 9d14b80f5b Merge branch 'MDL-76004-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2022-12-28 18:22:40 +01:00
Sara Arjona bdbd1b3af0 Merge branch 'MDL-72523-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-28 13:01:45 +01:00
Paul Holden 2b6ca7e207 MDL-72523 calendar: return original focus from event modals. 2022-12-28 11:14:50 +00:00
Huong Nguyen 023ac9229f MDL-72523 javascript: Introduce setReturnElement for core/modal 2022-12-28 11:14:50 +00:00
Sara Arjona 5f02141a7a Merge branch 'MDL-72563-400' of https://github.com/KepaUrzelai/moodle into MOODLE_400_STABLE 2022-12-28 12:13:21 +01:00
Sara Arjona 54cffd7c2e Merge branch 'MDL-69071-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-28 11:41:18 +01:00
Paul Holden 5e80881587 MDL-76760 tool_behat: defer library loading until service execution.
Ensures that API documentation can be generated without requiring
the presence of the `vendor/` directory.
2022-12-28 10:39:54 +00:00
Ilya Tregubov c6c77554ef Merge branch 'MDL-76731_400' of https://github.com/PhilippImhof/moodle into MOODLE_400_STABLE 2022-12-28 15:14:35 +07:00
Sara Arjona dcfd3b29a9 Merge branch 'MDL-76679-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-27 16:55:31 +01:00
Amaia Anabitarte 293bc2d615 MDL-76578 core_course: One section per page summary information 2022-12-26 16:02:51 +01:00
Meirza eeccbf0ebd MDL-76508 templates: Handling non-JSON string
When the param string contains a left curly bracket as the first character,
the system will assume the string is a JSON string and will be parsed and returned as an object.
But in some cases, the string is not JSON and will return an error if the system parses it.
For example, a user might have used the course name with a left curly bracket as the first character.
Adding a double quote after the left curly bracket to differentiate between string and JSON string,
so it can be safe to parse the string.
2022-12-24 05:24:24 +07:00
Noemie Ariste 8cded7cd9f MDL-60038 moodlelib: ignore site policy if user auth type = 'webservice' 2022-12-23 10:03:41 +13:00
Philipp Imhof 652d8971ec MDL-76731 behat: add steps to check for version
Co-authored-by: Andrew Nicols <andrew@nicols.co.uk>
2022-12-22 17:12:29 +01:00
Tony Butler 8fbede49ae MDL-53137 qtype_numerical: Swap geo tolerance limits for -ve answers 2022-12-22 15:32:00 +00:00
Ilya Tregubov 37e16d4da2 weekly release 4.0.5+ 2022-12-22 19:16:34 +07:00
Ilya Tregubov 5b325dc2e9 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2022-12-22 19:16:32 +07:00
Ilya Tregubov 06d3ff9ea2 Merge branch 'MDL-76667-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-22 12:30:08 +07:00
Paul Holden 6aa9d215c8 Merge branch 'MDL-75965-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-12-22 12:30:08 +07:00
Andrew Nicols 0faa70e56a MDL-75105 tool_behat: Coding style fixes 2022-12-22 12:30:08 +07:00
Andrew Nicols 0ab77c7287 Merge branch 'MDL-75105_400_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_400_STABLE 2022-12-22 12:30:07 +07:00
Paul Holden 3d0bbf1a0f Merge branch 'MDL-75914-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-22 12:30:07 +07:00
AMOS bot 9287e1e0ea Automatically generated installer lang files 2022-12-22 00:07:39 +00:00
Meirza e4bf4cf37e MDL-75914 webservice: Added fake URL to avoid debugging output.
Webservice doesn't need to set the page URL. Hence,
any function that requires a page URL will raise debugging output.
The patch fixes it by adding a fake URL for the webservice.
The patch also removed assertDebuggingCalled because it is no longer needed.
2022-12-21 16:32:54 +07:00
Mark Johnson 4dfb5cf6e7 MDL-75105 tool_behat: List available data generators
This will find all data generators that can be used in behat via the
'the following "something" exist:' step, and display them in a select
list on the step definitions page.

When a generator is selected, it will fetch the required fields for that
generator and display them on the page.
2022-12-21 08:38:20 +00:00
Huong Nguyen 4fc412b538 MDL-75965 question_multichoice: Misalignment of feedback icons 2022-12-21 14:15:50 +07:00
Ilya Tregubov 9e6b6b4925 Merge branch 'MDL-76727-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-21 09:50:45 +07:00
Paul Holden 0e52ea009d Merge branch 'MDL-75279-400' of https://github.com/spvickers/moodle into MOODLE_400_STABLE 2022-12-20 10:27:42 +00:00
Andrew Nicols 7a5389f1cc MDL-76727 core: Allow phpcs configuration to be overridden locally
This change reduces the priority of the shipped phpcs configuration to
allow for local overrides.

This is beneficial in several situations:
- when users wish to apply stricter or additional standards
- when the integration team wishes to trial new rules
2022-12-20 09:35:51 +08:00
Stephen Vickers e7a5867a88 MDL-75279 mod_lti: Add username to NRPS response 2022-12-19 17:11:04 +00:00
Paul Holden 741c9e003d Merge branch 'MDL-72906-400' of https://github.com/tdjones/moodle into MOODLE_400_STABLE 2022-12-19 10:23:16 +00:00
Ilya Tregubov f464b00ab8 Merge branch 'MDL-74779-400' of https://github.com/ssj365/moodle into MOODLE_400_STABLE 2022-12-19 09:45:54 +07:00
Leon Stringer 2f4fa118db MDL-75346 core_my: Handle missing blocks on reset
If the default dashboard contained a block that was missing from disk
then "Exception - Call to a member function instance_copy() on bool"
was shown to users.  This change only shows an error with debugging
enabled which now includes the name of the missing block.
2022-12-17 17:40:38 +00:00
Paul Holden 2144007387 MDL-76399 question: switch to appropriate Behat step for selects. 2022-12-16 13:09:54 +00:00
Paul Holden 6176c8fc88 MDL-76399 behat: improvements to "should exist in" thrown exception. 2022-12-16 12:29:19 +00:00
Paul Holden e62f86b983 Merge branch 'MDL-76026_400' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_400_STABLE 2022-12-16 09:54:54 +00:00
Andrew Nicols 089260dae2 weekly release 4.0.5+ 2022-12-16 09:05:57 +08:00
Andrew Nicols 661e595500 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2022-12-16 09:05:56 +08:00
Paul Holden 1aba16cbea MDL-69071 core: retrieve full result from remote content.
Use the full result from download_file_content within the component
installer to ensure that spurious debugging is not emitted during
operation. Handle validation of the returned data consistently.
2022-12-15 17:19:08 +00:00
Paul Holden c9a5b23d7a MDL-76679 admin: correct password config field template.
The template changes were missed as part of 0795b579, update them
to match so that they continue to work with the unmask JS module.
2022-12-14 19:12:11 +00:00
Sara Arjona 636ad3d3a0 Merge branch 'MDL-76674_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2022-12-14 18:34:56 +01:00
Amaia Anabitarte 3f39fcf27e MDL-76004 core_h5p: Ensure the browser is serving updated file 2022-12-14 16:22:59 +01:00
Eloy Lafuente (stronk7) 1097414910 MDL-76674 core_lang: Add string for new America/Ciudad_Juarez 2022-12-14 15:51:36 +01:00
Paul Holden 364c3b1fa9 Merge branch 'MDL-76666_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2022-12-14 13:22:07 +00:00
Eloy Lafuente (stronk7) 27ebb8fa2d MDL-76666 local_langimport: Better handling of long locales
Under some linux versions, and depending of the configured
locale categories, it's possible to get a current locally
which length > 255 when calling to setlocale(LC_ALL, 0).

Later, if that long locale is tried to be restored, there
is a "setlocale(): Specified locale name is too long" warning
error.

When that happens we need to split the long locale into
individual chunks and set all the (six) locale categories
supported one by one.

Covered with tests, note that, in practice, this only
happens with linux because it supports 12 locale categories
@ OS level. Both BSD (6) and Windows (5) hardly can reach the limit.

No matter of that, the tests have been designed to ensure that
they pass on all OSs, just the new code only will be executed
on linux.
2022-12-14 12:25:37 +01:00
Sara Arjona 08c8e9bba2 Merge branch 'MDL-75441-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2022-12-14 09:57:19 +01:00
AMOS bot b4ab42a911 Automatically generated installer lang files 2022-12-14 00:07:39 +00:00
Anupama Sarjoshi a85ff11cba MDL-76026 Question bank: Fix errors related to categories renaming
This part of the code in 'question_category_object.php' 'update_category' method was used before Moodle 4.0 version for renaming
the random questions in an updated category. For Moodle 4.0, it is unnecessary as the details of random questions are no more
stored in 'question' table but in 'question_set_references' table. The method call move_question_set_references handles the same.
2022-12-13 19:21:19 +00:00
Amaia Anabitarte 9d2ddbf7fe MDL-75441 mod_forum: Show add new post button to guest users 2022-12-13 18:48:01 +01:00
Paul Holden 34eee61037 MDL-76667 forms: mark modal form as submitted upon success.
Ensure the form change checker module doesn't warn user about it.
2022-12-13 14:48:16 +00:00
Andrew Nicols ff72ae15f3 Merge branch 'MDL-76509-400' of https://github.com/safatshahin/moodle into MOODLE_400_STABLE 2022-12-13 20:32:01 +08:00
Andrew Nicols 8a4a9fc096 Merge branch 'MDL-76536-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-13 11:42:57 +08:00
Andrew Nicols 4ab2e98a64 MDL-76293 gradebook: Address coding violations
This includes a data provider which had the 'test_' prefix and was
therefore run as a test.
2022-12-13 11:07:37 +08:00
Andrew Nicols e5ed497363 Merge branch 'MDL-76293_400' of https://github.com/mkassaei/moodle into MOODLE_400_STABLE 2022-12-13 11:07:33 +08:00
Safat 26ed26289d MDL-76509 core: Upgrade error resolve for slot tags 2022-12-13 13:40:33 +11:00
Shamiso.Jaravaza fdcc78fee0 MDL-74779 mod_bigbluebuttonbn: Fix recording sort
AMOS BEGIN
 MOV [config_recordings_sortorder,mod_bigbluebuttonbn],[config_recordings_asc_sort,mod_bigbluebuttonbn]
 MOV [config_recordings_sortorder_description,mod_bigbluebuttonbn],[config_recordings_asc_sort_description,mod_bigbluebuttonbn]
AMOS END
2022-12-12 13:32:09 -07:00
Sara Arjona 43e0217956 Merge branch 'MDL-75571-400' of https://github.com/jacdsouza/moodle into MOODLE_400_STABLE 2022-12-12 11:23:24 +01:00
Khoa Nguyen Dang 7ae8b4dbed MDL-76308 Question\D&D: The draggable area is slim characters to select 2022-12-12 13:49:39 +07:00
hieuvu 097b706970 MDL-76106 qtype_ddmarker: fix the missing maker issue.
We will not calculate old maker position again and using old data.
This will make sure the position of makers is correct
when the background image is smaller than dropzone.
2022-12-12 11:10:18 +07:00
Andrew Nicols 2d3acb52df Merge branch 'MDL-76398-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-11 20:21:00 +08:00
Jackson D'souza 118240ef22 MDL-75571 tool_componentlibrary: Custom activity icon 2022-12-09 15:51:33 +00:00
Jackson D'souza d7b3d443aa MDL-75571 theme_boost: Activity icon
* Use Activity get_icon_url helper method to fetch icon.
2022-12-09 15:51:33 +00:00
Jackson D'souza 75247caff8 MDL-75571 block_timeline: Display custom activity icon if available. 2022-12-09 15:51:33 +00:00
Jackson D'souza bb23523870 MDL-75571 calendar: Activity icon
* Use Activity get_icon_url helper method to fetch icon.
2022-12-09 15:51:33 +00:00
Sara Arjona e4b7d8b323 Merge branch 'MDL-76274-400' of https://github.com/cameron1729/moodle into MOODLE_400_STABLE 2022-12-09 16:18:14 +01:00
Paul Holden 93ac861ec5 MDL-76536 enrol: prevent invalid role assignments in course creation.
Upgrade step to fixup existing bad data.
2022-12-09 11:39:51 +00:00
Sara Arjona ce6131e6f7 weekly release 4.0.5+ 2022-12-09 08:57:06 +01:00
Sara Arjona 3e0a29dee5 Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2022-12-09 08:57:01 +01:00
Jun Pataleta c1fb24274e Merge branch 'MDL-76556-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-08 10:07:41 +08:00
Andrew Nicols ec6d835341 Merge branch 'MDL-76491-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-08 08:12:55 +08:00
AMOS bot 73d873e752 Automatically generated installer lang files 2022-12-08 00:07:38 +00:00
Andrew Nicols 623ca576bd Merge branch 'MDL-76550_400' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_400_STABLE 2022-12-08 08:07:20 +08:00
Andrew Nicols df2fe09963 Merge branch 'MDL-76074-400' of https://github.com/srobotta/moodle into MOODLE_400_STABLE 2022-12-08 07:29:05 +08:00
Andrew Nicols 4b31bb97f5 Merge branch 'MDL-76116-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-08 06:17:25 +08:00
Sara Arjona b6355c6490 Merge branch 'MDL-75588-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-12-07 19:31:18 +01:00
Trevor Jones 40c59b5865 MDL-72906 Quiz: Prevent scrollbar on multichoice
Remove negative margin from the "clear my choice" anchor.
With the negative margin, when the containing box height is calculated
the anchor's hidden style overflows beyond the boundary and triggers
the overflow:auto to add a scroll bar.
2022-12-07 11:22:27 -07:00
Sara Arjona 814fc9cbc1 Merge branch 'MDL-76500-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-07 18:27:59 +01:00
Sara Arjona 77ef43cb2e Merge branch 'MDL-76193-400' of https://github.com/JBThong/moodle into MOODLE_400_STABLE 2022-12-07 17:26:30 +01:00
Sara Arjona 0ab8dfd19f Merge branch 'MDL-76571_400' of https://github.com/timhunt/moodle into MOODLE_400_STABLE 2022-12-07 17:17:50 +01:00
Tim Hunt 38bad90a7e MDL-76571 quiz reports: should not show description items
... or anything else with length = 0. This got broken in MDL-71696.

The only way to fix this kind-of involves and API change to
quiz_report_get_significant_questions. However, it is only changing
the external API of this function back to how it was before the 4.0 release,
and the chnages in 4.0 were never documented, nor, I would guess, intended,
since they just broke things.
2022-12-07 14:51:42 +00:00
Jun Pataleta 85ca739855 Merge branch 'MDL-76559-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-07 22:40:44 +08:00
Andrew Nicols 57f473425a MDL-76559 core: validate_email does not take false either 2022-12-07 21:40:18 +08:00
Sara Arjona 982427b990 Merge branch 'MDL-76273-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-07 12:51:49 +01:00
Huong Nguyen 15a855e371 MDL-75588 assign: Reset completion status when resetting a submission 2022-12-07 16:16:07 +07:00
Jun Pataleta 72ceec4d94 Merge branch 'MDL-73017-M400_add-environment-check-for-versions-not-supporting-php-8-1' of https://github.com/ziegenberg/moodle into MOODLE_400_STABLE 2022-12-07 13:47:21 +08:00
Meirza fd89171c91 MDL-76116 mnet: styling the delete key confirmation window properly 2022-12-07 11:28:15 +07:00
Jun Pataleta 9e06598722 Merge branch 'MDL-75635-MOODLE_40_STABLE' of https://github.com/catalyst/moodle into MOODLE_400_STABLE 2022-12-07 11:04:00 +08:00
Thong Bui 25ca760ccd MDL-76193 Questions: Backup and Restore with tags fails 2022-12-06 22:32:30 +07:00
Jun Pataleta 8cca821b62 Merge branch 'MDL-76559-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-06 23:19:28 +08:00
Andrew Nicols 7c28bd0d36 MDL-76559 core: validate_email should not accept empty values 2022-12-06 20:53:54 +08:00
Jun Pataleta 743fe53e6b Merge branch 'MDL-75381-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-06 19:24:28 +08:00
Ilya Tregubov af51642584 Merge branch 'MDL-76490-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-06 13:10:21 +03:00
Paul Holden 0dc67b9d10 MDL-76500 grade: fix grade form when item cannot be overridden. 2022-12-06 09:19:52 +00:00
Ilya Tregubov 8966d10fd6 Merge branch 'MDL-76446-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-06 12:19:34 +03:00
Mahmoud Kassaei 8ee6c1b4ed MDL-76293 Gradebook: PHPUnit fails when plugins are not expected 2022-12-06 08:39:56 +00:00
Cameron Ball f4dba7ab54 MDL-76274 assignfeedback_editpdf: Fix upgrade step for stale conversions 2022-12-06 16:07:50 +08:00
Ilya Tregubov 42d71d6502 Merge branch 'MDL-75516_400' of https://github.com/larsbonczek/moodle into MOODLE_400_STABLE 2022-12-06 10:38:40 +03:00
Andrew Nicols 34c8e455ea Merge branch 'MDL-75446-400' of https://github.com/andelacruz/moodle into MOODLE_400_STABLE 2022-12-06 15:20:01 +08:00
Andrew Nicols e81a91d18f Merge branch 'MDL-75573-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-06 13:56:47 +08:00
Andrew Nicols c877d579e7 Merge branch 'MDL-76145-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-06 13:36:30 +08:00
Paul Holden ef9310d1e7 MDL-76273 core: multi-byte character filename support for TCPDF.
See: https://github.com/tecnickcom/TCPDF/pull/562
2022-12-05 15:03:09 +00:00
Paul Holden 64439605c6 MDL-76490 behat: use defined step for interaction with autocomplete. 2022-12-05 14:22:27 +00:00
Marina Glancy 7ae00a1542 MDL-76490 behat: correct step for opening autocomplete in container. 2022-12-05 14:22:02 +00:00
Anupama Sarjoshi 8576612fbb MDL-76550 Quiz and qbank: Fix display of Category and question names 2022-12-05 12:09:26 +00:00
Sara Arjona 4fc0a470fb Merge branch 'MDL-75789-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-05 12:53:50 +01:00
Sara Arjona f05f5b909f Merge branch 'MDL-76166-username-logging-MOODLE_400_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_400_STABLE 2022-12-05 12:44:30 +01:00
Ilya Tregubov 90829a7550 Merge branch 'MDL-75788-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2022-12-05 14:32:22 +03:00
Sara Arjona afafcca723 Merge branch 'MDL-76482-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-05 12:04:09 +01:00
Daniel Ziegenberg 02663758fb MDL-73017 env: Moodle 3.9.x, 3.11.x and 4.0.x do not support PHP 8.1
This commit adds an additional environment check for the unsupported
PHP 8.1 version to Moodle 3.9.x, 3.11.x and 4.0.x.

It also updates the lang string for unsupported PHP version.

Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
2022-12-05 11:39:53 +01:00
Angelia Dela Cruz 1bec71f1b6 MDL-75446 behat: Workshop behat generators use UI
Replace steps that manually add Workshop instances via the UI and use
Behat generators. This improves the speed of the Behat test runs.
2022-12-05 16:37:06 +08:00
Ilya Tregubov 507d27ba9b Merge branch 'MDL-76330-MOODLE_400_STABLE' of https://github.com/sh-csg/moodle into MOODLE_400_STABLE 2022-12-05 09:22:37 +03:00
Jun Pataleta 65397a0a86 Merge branch 'MDL-76225-400' of https://github.com/ferranrecio/moodle into MOODLE_400_STABLE 2022-12-05 13:47:37 +08:00
AMOS bot a916576147 Automatically generated installer lang files 2022-12-04 00:08:29 +00:00
Andrew Nicols 258c8ca75c MDL-76556 tool_log: Set the store property correctly 2022-12-03 11:49:24 +08:00
Lars Bonczek 3afa59e702 MDL-75516 core: Perform proper JSON encoding in mustache quote helper 2022-12-02 13:37:33 +01:00
Paul Holden b729d36baf MDL-76491 javascript: add missing core/notification imports. 2022-12-02 10:06:27 +00:00
Paul Holden f5bb4eebce MDL-76491 javascript: prevent eslint undefined Notification import. 2022-12-02 10:06:10 +00:00
Paul Holden 91e96925c9 MDL-76398 reportbuilder: use improved action menu steps in Behat.
Improved steps for using actions menus were added in 232ebac3, so
make use of them here for consistency/reliability.
2022-12-02 09:54:58 +00:00
Paul Holden b903d21ea2 MDL-76398 behat: broader action menu partial matching by element.
For action menu elements whose trigger element isn't plain text
(e.g. a pix icon), we should be able to match via the title of
that element.
2022-12-02 09:54:58 +00:00
Stephan Robotta 1ad4c0e91c MDL-76074 completion: fixed filter in reports with custom user fields
When the site uses custom user text fields that would show up in a
user list, the filter for firstname or lastname didnt work anymore.
If a filter was used, no result would show up. Users where shown only
when the course reports where used without filters.
2022-12-02 09:42:29 +01:00
Dani Palou 6aafd5fa61 MDL-75788 behat: Use profile field generators in existing tests 2022-12-02 14:58:38 +08:00
Dani Palou e2d166e526 MDL-75788 testing: Handle new lines in menu profile field generator 2022-12-02 14:58:38 +08:00
hieuvu ae949341cd MDL-76106 qtype_ddmarker: Improve loading consistency.
Wait for the image to load completely before running the js.
2022-12-02 12:34:43 +07:00
Paul Holden ef5112211b MDL-75573 backup: translate async operation type in messages. 2022-12-01 19:48:36 +00:00
Stefan Hanauska ea6c1d65af MDL-76330 enrol: Check permission to show edit icon 2022-12-01 20:07:10 +01:00
Sara Arjona bdba78514f weekly release 4.0.5+ 2022-12-01 16:08:04 +01:00
Andrew Nicols 1d35066ba5 Merge branch 'MDL-75604-400' of https://github.com/ssj365/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Andrew Nicols cb26fec31f Merge branch 'MDL-75281-400' of https://github.com/call-learning/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Sara Arjona 1e6be54edd Merge branch 'MDL-76226-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Jun Pataleta 1fc5e599c5 Merge branch 'MDL-76250-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Jun Pataleta 53c1445753 Merge branch 'MDL-76483-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Andrew Nicols 53e5b88001 Merge branch 'MDL-75826-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Jun Pataleta 17e976a2a7 Merge branch 'MDL-68981-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Jun Pataleta 230c3cedc6 Merge branch 'MDL-76284-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Jun Pataleta 09d76ce833 Merge branch 'MDL-76429_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Andrew Nicols 3b504d259b Merge branch 'MDL-76380-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-12-01 09:02:48 +03:00
Andrew Nicols a24b426062 Merge branch 'MDL-76218-m400' of https://github.com/sammarshallou/moodle into MOODLE_400_STABLE 2022-12-01 09:02:47 +03:00
Andrew Nicols e8c58c9a3b Merge branch 'MDL-76127-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-01 09:02:47 +03:00
Ilya Tregubov f51798f962 Merge branch 'MDL-72019-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-12-01 09:02:47 +03:00
Laurent David 46e658d506 MDL-75281 mod_bigbluebuttonbn: Upgrade failure when table exists
* Fix several upgrade script issue when the recording table exists or plugin has been
downgraded prior to 4.x upgrade
2022-11-30 20:15:13 +01:00
Shamiso.Jaravaza c72574f800 MDL-75604 mod_bigbluebuttonbn: Fix welcome section
* Removed welcome message from General settings
* Cleaned settings.php file to remove hardcoded add($item) after adding conditional element
2022-11-30 10:08:37 -07:00
Ferran Recio 70abc44e05 MDL-76225 core_courseformat: fix section title id 2022-11-30 16:47:09 +01:00
Meirza 966b0dd3df MDL-76145 course: Avoid long course names that exceed available space
Co-authored-by: Stephen Sharpe <stephen.sharpe@synergy-learning.com>
2022-11-30 11:36:16 +07:00
Andrew Nicols ad770fe215 MDL-76482 output: The javascript mustache helper should return a string 2022-11-30 12:18:54 +08:00
Huong Nguyen 832d237c94 MDL-68981 tool_recyclebin: Force necessary settings when restoring
Created code to force the necessary settings for restore_item in:
  + course_bin class
  + category_bin class
2022-11-30 10:20:09 +07:00
Huong Nguyen cb8b72034e MDL-68981 tool_recyclebin: Extra PHPUnit with General restore config 2022-11-30 10:20:09 +07:00
Huong Nguyen 31c047d2d3 MDL-68981 tool_recyclebin: Extra Behat test with General restore config
Including in this commit:
 - Convert existing Behat scenario to use Data generators
 - Convert existing Behat scenario to use Provider
 - Add new scenario for Include users setting in General restore page
2022-11-30 10:20:06 +07:00
Brendan Heywood acf152ca8b MDL-76166 calendar: Ensure user is in server access logs 2022-11-30 13:26:11 +11:00
Brendan Heywood 4dc23af4ad MDL-76166 auth: Ensure user is in server access logs 2022-11-30 13:26:11 +11:00
Paul Holden d24c88543d MDL-76446 user: correct logic for multiple keyword search.
When the keyword participant filter was used with multiple values
in conjunction with other participants filters, the boolean logic
was effectively:

 X AND Y OR Z

When what we actually wanted was:

 X AND (Y OR Z)
2022-11-29 16:30:41 +00:00
Andrew Nicols 382f91cf8c Merge branch 'MDL-75960-400' of https://github.com/andelacruz/moodle into MOODLE_400_STABLE 2022-11-29 17:05:18 +08:00
Paul Holden 109b772c06 MDL-75381 gradereport_grader: ensure valid paging preference value.
Set type of the report paging setting to integer, to ensure usage
of it is predictable. Unsupported operated type errors were thrown
on PHP8.0 when it's value contained a string or was empty.
2022-11-29 08:41:27 +00:00
Paul Holden 937c47e90e MDL-75789 restore: multi-byte safe substring calculating course names.
Co-authored-by: Leon Stringer <leon.stringer@ntlworld.com>
2022-11-29 08:32:13 +00:00
Andrew Nicols 1735591d32 Merge branch 'MDL-65939-400' of https://github.com/ewallah/moodle into MOODLE_400_STABLE 2022-11-29 15:41:51 +08:00
Andrew Nicols 6846a839f5 Merge branch 'MDL-76058-400' of https://github.com/lameze/moodle into MOODLE_400_STABLE 2022-11-29 15:37:24 +08:00
Andrew Nicols 11123d3aba Merge branch 'MDL-74454-MOODLE_400_STABLE' of https://github.com/pabloamayab/moodle into MOODLE_400_STABLE 2022-11-29 14:19:05 +08:00
Andrew Nicols eb61b04180 MDL-76258 mod_lti: Codign style fixes 2022-11-29 12:29:06 +08:00
Andrew Nicols 9fa5637b56 Merge branch 'MDL-76258-MOODLE_400_STABLE' of https://github.com/sh-csg/moodle into MOODLE_400_STABLE 2022-11-29 12:29:03 +08:00
Andrew Nicols ab112ec2b7 MDL-69570 assignfeedback_editpdf: Whitespace fix 2022-11-29 11:52:01 +08:00
Andrew Nicols 801ca38d89 Merge branch 'MDL-69570-400' of https://github.com/abgreeve/moodle into MOODLE_400_STABLE 2022-11-29 11:51:05 +08:00
Adrian Greeve fa0e0b9a39 MDL-69570 assignfeedback_editpdf: Upgrade step to remove files.
This upgrade step removes all orphaned editpdf feedback files and
records.
2022-11-29 09:48:47 +08:00
Adrian Greeve df99098fb6 MDL-69570 assignfeedback_editpdf: Remove temp pdf files
This adds a new method to the assignfeedback edit pdf library
to specify user data file areas that will return just the meaningful
annotated feedback pdf.

get_file_areas has been updated for this plugin to return all
file areas related to assignfeedback_editpdf, and should stop
producing orphaned files and records when a course reset is done.

Thanks to @toniginard who provided a base solution for me to work
off.
2022-11-29 09:47:48 +08:00
Paul Holden a63ddc2ec3 MDL-76380 tool_oauth2: remove double persistent load on update.
The method already loaded the validated persistent model data on the
previous line, there's no need to do it again (while also trying to
load unvalidated properties).
2022-11-28 19:39:00 +00:00
Paul Holden 740d11fb43 MDL-76250 mod_assign: disable form change checker for grading options.
This was previously fixed in 8e9efe60, but seems to have regressed
somewhere along the way.
2022-11-28 16:07:04 +00:00
Paul Holden e4bdc416d8 MDL-76226 admin: account for preset config checkboxes other than bool.
The assumption that the settings checkbox always stores boolean values
(e.g. 0/1) isn't correct. The `perfdebug` configuration instead uses
the values 7/15.
2022-11-28 16:04:14 +00:00
Paul Holden 7030ec9af2 MDL-76284 webservice: early exit if no users for missing capabilities. 2022-11-28 11:52:52 +00:00
Meirza 34f8f8fe90 MDL-75826 profile: Redirect to profile page if returnto is profile. 2022-11-28 16:16:23 +07:00
Angelia Dela Cruz aeebd7a189 MDL-75960 behat: Survey behat generators use UI
Replace steps that manually add Survey instances via the UI and use
Behat generators. This improves the speed of the Behat test runs.
2022-11-28 10:01:16 +08:00
Eloy Lafuente (stronk7) ffbb559293 MDL-76429 composer: Bump to phpwebdriver 1.2.1 for php81 compat
This fix is really only required for Moodle 4.1 and up, that will
be the one supporting php81, but we always apply composer changes
to all branches (supported and security), so we keep them running
the same stuff.

Note this comes with a bunch of other small updates, all them
pretty minor and should not be problematic. Better we get them
than keeping them apart.
2022-11-25 16:27:24 +01:00
Andrew Nicols 6687efe4d5 MDL-76483 core: Handle default value for get_docs_url() 2022-11-25 22:19:20 +08:00
Ilya Tregubov efdaed1f70 weekly release 4.0.5+ 2022-11-25 15:38:30 +03:00
Jun Pataleta 56143593c4 Merge branch 'MDL-76468-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-11-24 17:51:43 +08:00
Andrew Nicols 1a5322ab4b MDL-76468 output: Correct slasharg URL for theme stylesheet 2022-11-24 16:41:07 +08:00
Andrew Nicols 449104d62a Merge branch 'MDL-76395-400-enfix' of https://github.com/vmdef/moodle into MOODLE_400_STABLE 2022-11-24 16:25:17 +08:00
Ilya Tregubov 437f447816 Merge branch 'MDL-76291-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-24 10:59:47 +03:00
Víctor Déniz ef8fdb4762 Merge branch 'MDL-76324-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-11-23 14:22:40 +00:00
Víctor Déniz 476474da69 MDL-76395 lang: Use fixed strings in tests 2022-11-23 12:45:54 +00:00
Paul Holden 2e534d0c99 MDL-76291 mod_bigbluebuttonbn: tell Behat to wait while polling.
While fetching recording data, and updating room info. Should reduce
random scenario failures.
2022-11-23 10:15:39 +00:00
Jun Pataleta c09e748a9a Merge branch 'MDL-76365-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-11-23 14:51:34 +08:00
Huong Nguyen 8a0f9db07f MDL-76324 webdav: Fix error for PHP 8.0 2022-11-23 09:12:02 +07:00
Helen Foster 0487f8ed9a MDL-76395 lang: Import fixed English strings (en_fix) 2022-11-23 00:14:28 +00:00
Ilya Tregubov bb7e105ca9 weekly release 4.0.5+ 2022-11-22 15:58:21 +03:00
Huong Nguyen cca0bc9ec5 MDL-76365 mod_data: Fix export with empty template
If the template is not created, we need to use the default template for the export
2022-11-22 12:08:45 +07:00
Jun Pataleta 65886c04da Merge branch 'MDL-76390_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2022-11-22 11:20:05 +08:00
Jun Pataleta 472ea45f92 Merge branch 'MDL-76367-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-11-22 11:08:31 +08:00
Jun Pataleta b62844e26c Merge branch 'MDL-76389_400' of https://github.com/stronk7/moodle into MOODLE_400_STABLE 2022-11-22 09:49:42 +08:00
Ilya Tregubov e72dd8c3d9 Merge branch 'MDL-76341-400' of https://github.com/stevandoMoodle/moodle into MOODLE_400_STABLE 2022-11-21 16:54:36 +03:00
Meirza 4419deedab MDL-76127 Profiling: Make the breadcrumb of the profiling URL clickable
Boost has the behavior to remove the last item action.
To avoid that, we need to add an action item.
2022-11-21 14:28:14 +07:00
Stevani Andolo 3bd0fd816f MDL-76341 tool_lp: Fixed learning plan's header not containing user name 2022-11-21 14:35:19 +08:00
Eloy Lafuente (stronk7) c5569f2965 MDL-76390 tool_lp: Remove magic getter call
Since Moodle 3.3 (see MDL-57273), the magix getters and setters
for persistent classes are deprecated, instead get() and set()
must be used.
2022-11-20 14:53:17 +01:00
Eloy Lafuente (stronk7) 5d16d55949 MDL-76389 output: Ensure we don't try to iterate over null
Just convert nulls to empty array before trying to iterate it.
2022-11-20 11:42:02 +01:00
Paul Holden 2da8a31849 weekly release 4.0.5+ 2022-11-18 11:43:11 +00:00
Paul Holden f9460201fd Merge branch 'install_400_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_400_STABLE 2022-11-18 11:43:08 +00:00
Andrew Nicols 5851941cef MDL-76367 core: Apply RTL transformations to editors too 2022-11-18 15:14:42 +08:00
Jun Pataleta 28a2586852 Merge branch 'MDL-76332-400' of https://github.com/call-learning/moodle into MOODLE_400_STABLE 2022-11-18 11:58:12 +08:00
Jun Pataleta 6579bdbdb7 Merge branch 'MDL-75903-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-18 11:29:09 +08:00
AMOS bot 12e4a722bd Automatically generated installer lang files 2022-11-18 00:07:39 +00:00
Sara Arjona 7d2d64a559 Merge branch 'MDL-73620-400_grouperror' of https://github.com/alexmorrisnz/moodle into MOODLE_400_STABLE 2022-11-17 18:00:27 +01:00
Sara Arjona cef970f6d5 Merge branch 'MDL-74780-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-17 17:40:15 +01:00
Paul Holden 7fb8631e3e Merge branch 'MDL-76105-400-enfix' of https://github.com/vmdef/moodle into MOODLE_400_STABLE 2022-11-17 16:30:18 +00:00
Sara Arjona 40d67d22b2 Merge branch 'MDL-70491-400_take2' of https://github.com/lucaboesch/moodle into MOODLE_400_STABLE 2022-11-17 17:25:54 +01:00
Sara Arjona 2700e9b29f Merge branch 'MDL-75627_m400_v1' of https://github.com/sbourget/moodle into MOODLE_400_STABLE 2022-11-17 17:22:30 +01:00
info@eWallah.net 0f6bed1637 MDL-65939 phpunit: Maildigest tests can query a wrong adhoc task 2022-11-17 15:53:41 +01:00
Paul Holden 9c9b10b709 Merge branch 'MDL-75569-400' of https://github.com/justusdieckmann/moodle into MOODLE_400_STABLE 2022-11-17 14:34:55 +00:00
Víctor Déniz 02a066b847 Merge branch 'MDL-76326-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-11-17 13:19:34 +00:00
Sara Arjona 1d8d3ba456 Merge branch 'MDL-75567-400' of https://github.com/justusdieckmann/moodle into MOODLE_400_STABLE 2022-11-17 13:06:33 +01:00
Víctor Déniz 18f6f90021 Merge branch 'MDL-73804-make-category-filter-context-400' of https://github.com/Peterburnett/moodle into MOODLE_400_STABLE 2022-11-17 11:56:33 +00:00
Paul Holden d2215442ac Merge branch 'MDL-75665_MOODLE_400_STABLE' of https://github.com/tasosb/moodle into MOODLE_400_STABLE 2022-11-17 11:42:28 +00:00
Meirza 591305c989 MDL-72019 user: Allows data to be formatted when exporting. 2022-11-17 16:23:58 +07:00
Jun Pataleta 0cc918fbce Merge branch 'MDL-76310-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-17 14:39:40 +08:00
Bas Brands 1085ea44b8 MDL-70491 theme_boost: improve form autocomplete badge styles 2022-11-17 07:04:51 +01:00
Huong Nguyen 424992eeff MDL-76326 oauth2: Update Nextcloud logo to the new one 2022-11-17 11:32:17 +07:00
Andrew Nicols 359d436178 Merge branch 'MDL-75651-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-17 10:07:07 +08:00
Andrew Nicols 222af18607 Merge branch 'MDL-76083-400' of https://github.com/aanabit/moodle into MOODLE_400_STABLE 2022-11-17 10:00:33 +08:00
David Mudrák 37f2404bd0 MDL-76105 lang: Use fixed strings in tests, too. 2022-11-16 17:33:18 +00:00
Laurent David bfedfcbc4a MDL-76332 mod_bigbluebuttonbn: Fix JS exception, recording only room
* The room updater should only run on room that have the join button
2022-11-16 18:16:54 +01:00
Paul Holden 3faffbc882 Merge branch 'MDL-73078-400' of https://github.com/lucaboesch/moodle into MOODLE_400_STABLE 2022-11-16 16:37:03 +00:00
Paul Holden eb0b6e7619 Merge branch 'MDL-76271-400' of https://github.com/davewoloszyn/moodle into MOODLE_400_STABLE 2022-11-16 16:25:01 +00:00
Sara Arjona b8cf30d2e9 Merge branch 'MDL-75380_400' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_400_STABLE 2022-11-16 16:23:46 +01:00
Kepa Urzelai 441afd68b0 MDL-72563 theme_boost: rubric area style fix 2022-11-16 15:31:33 +01:00
Laurent David 09ed58c5a1 MDL-76083 mod_data: Fix preset importer
* We should delete fields that have not been marked as to preserve.
2022-11-16 13:15:28 +01:00
Helen Foster f9022d9fa9 MDL-76105 lang: Import fixed English strings (en_fix) 2022-11-16 10:21:38 +00:00
Jun Pataleta ce4bdc144e Merge branch 'MDL-75415-400' of https://github.com/ssj365/moodle into MOODLE_400_STABLE 2022-11-16 17:51:39 +08:00
Jun Pataleta 2d4fb04857 Merge branch 'MDL-74558-400' of https://github.com/ssj365/moodle into MOODLE_400_STABLE 2022-11-16 17:51:17 +08:00
Jake Dallimore f2b007ee49 Merge branch 'MDL-76220-400' of https://github.com/ferranrecio/moodle into MOODLE_400_STABLE 2022-11-16 16:34:03 +08:00
Jun Pataleta c70361bd9b Merge branch 'MDL-75365-400' of https://github.com/andrewnicols/moodle into MOODLE_400_STABLE 2022-11-16 12:38:00 +08:00
David Woloszyn eb9de04a11 MDL-76271 dndupload: Corrected layout when uploading to course via dnd 2022-11-16 11:20:05 +11:00
Víctor Déniz 0c15fe263e Merge branch 'MDL-75781-400' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_400_STABLE 2022-11-15 22:32:02 +00:00
Sara Arjona bd8e040536 Merge branch 'MDL-76039-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-15 17:57:12 +01:00
Ilya Tregubov d652929260 weekly release 4.0.5+ 2022-11-15 18:09:28 +03:00
Paul Holden fc09484ec1 MDL-76310 enrol_lti: fix consumer key upgrade steps for Oracle.
Avoids CLOB comparison exceptions, related to ORA-00932.
2022-11-15 11:50:00 +00:00
Peter Burnett 028dc3ff0a MDL-73804 category: Use system context for category name filtering 2022-11-15 14:48:58 +10:00
Jun Pataleta b1926ad5f2 Merge branch 'MDL-76230-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-11-15 11:48:46 +08:00
Jun Pataleta 882a63d966 Merge branch 'MDL-76196-400' of https://github.com/HuongNV13/moodle into MOODLE_400_STABLE 2022-11-15 11:06:34 +08:00
Víctor Déniz 707ff5a4f2 Merge branch 'MDL-76229-400' of https://github.com/meirzamoodle/moodle into MOODLE_400_STABLE 2022-11-14 23:40:59 +00:00
Víctor Déniz a76a02901f Merge branch 'MDL-76192-400' of https://github.com/mihailges/moodle into MOODLE_400_STABLE 2022-11-14 22:35:47 +00:00
Paul Holden bc220f8d72 MDL-75903 output: increase precision of primary active node matching.
Co-authored-by: Mikel Martín <mikel@moodle.com>
2022-11-14 17:31:32 +00:00
Paul Holden 6b412c403b MDL-74780 grade: account for absence of course grade items on import. 2022-11-14 17:30:20 +00:00
Paul Holden cb20f32f46 MDL-75651 mod_feedback: remove duplicated activity heading. 2022-11-14 17:28:56 +00:00
Sara Arjona 7d96732e31 Merge branch '75792-moodle400-fix-grouping-sort-order' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_400_STABLE 2022-11-14 16:07:26 +01:00
Sara Arjona 47d6bbcb9e Merge branch 'MDL-75300-400' of https://github.com/paulholden/moodle into MOODLE_400_STABLE 2022-11-14 16:04:11 +01:00
sam marshall 7731cb8127 MDL-76218 cachestore_redis: delete_many can fail with no keys
In some cases, we get an error message such as:

Wrong parameter count for Redis::zRem()

Within the delete_many function. This function requires at least one
key to be supplied, but if delete_many is called with an empty array,
we will call it with no keys.
2022-11-14 14:39:12 +00:00
Paul Holden eb80cbd249 MDL-76039 forms: account for null values in serialize util method.
Co-authored-by: Marina Glancy <marina@moodle.com>
2022-11-14 14:20:40 +00:00
Julien Boulen 43f1e99dac MDL-75792 availability: sort groupings list by name 2022-11-14 13:16:58 +01:00
Huong Nguyen 4fca1452d4 MDL-76230 block_tag_flickr: Change User-agent value for API calls 2022-11-14 09:35:29 +07:00
Huong Nguyen e4af35b9b8 MDL-76230 block_tag_flickr: Extra Behat test for a specific tag 2022-11-14 09:35:29 +07:00
Meirza c2f415e57c MDL-76229 core_form: Show frozen text editor in a more accessible way. 2022-11-12 18:46:42 +07:00
Luca Bösch 872f3a03dc MDL-73078 workshop: align 'Edit subm' 'Delete subm' 'Export this page' 2022-11-11 16:43:36 +01:00
David Woloszyn cac3162bf3 MDL-76196 mod_folder: Display manual completion if inline display set 2022-11-11 15:50:06 +07:00
Andrew Nicols eab0470f4f MDL-75365 javascript: Support ES6 in all JS except YUI 2022-11-10 17:04:23 +08:00
Stefan Hanauska 229da267a6 MDL-76258 mod_lti: Reset clientid after restore 2022-11-09 19:33:52 +01:00
Mihail Geshoski a616371921 MDL-76192 mod_glossary: Export all entry aliases to the portfolio 2022-11-10 00:33:03 +08:00
Simey Lameze a1df353c67 MDL-76058 behat: send message using data generator 2022-11-09 09:52:07 +08:00
Ferran Recio bc794a82a2 MDL-76220 mod_wiki: fix extend_navigation
The wiki_extend_navigation is using $PAGE->url when it is not allowed
to. Extending navigation can be invoked in an Ajax request so it should
not use $PAGE global.
2022-11-08 14:41:35 +01:00
hieuvu 497c7ee517 MDL-75781 javascript: Centering when resize for dialog 2022-11-08 18:10:12 +07:00
Shamiso.Jaravaza 1f2f41a2d9 MDL-75415 mod_bigbluebuttonbn: Fix session times 2022-11-03 11:21:33 -06:00
Paul Holden 76d6feb23e MDL-75300 mod_h5pactivity: check whether reviewer join matches rows.
Return original capability join if so, to prevent generating invalid
SQL.
2022-11-02 19:25:47 +00:00
Anupama Sarjoshi 432628f3a3 MDL-75380 customfields: Fix incorrect links sent when enrolling users 2022-10-20 18:50:16 +01:00
Shamiso.Jaravaza ebc4a00bca MDL-74558 mod_bigbluebuttonbn: Fix deletion error 2022-10-14 08:58:28 -06:00
Andrew Madden 3a60aec87d MDL-75635 quizaccess_seb: Implement Safe Exam Browser JS API
This is a backport of MDL-72188

* Replaces checking header for SEB config keys to assess quiz access.
* Adds new web service accessible via Ajax
* Forces the use of the new API where available
* Stores access in Moodle SESSION for quiz instead of checking every
page.
2022-10-11 08:33:30 +11:00
Alex Morris 7ee9daa15e MDL-73620 mod_forum: Fix issue with discussion permission check
Users with access to some groups but not all would receive an error
page when creating a discussion topic that was set to send to all
groups
2022-10-11 08:29:42 +13:00
Justus Dieckmann f98da613d6 MDL-75567 core_course: Other hidden badges remain when adding new one 2022-10-08 23:05:38 +02:00
Pablo Amaya 0c2b15935c MDL-74454 mod_scorm: Fixed problems in lateral navigation.
Fixed problems in lateral navigation and grading when
a SCORM has more than three levels

The SCORM module has problems with full screen display,
completion tracking and grading in SCORM.

Also resolves issues MDL-74992, MDL-73249, MDL-75407
2022-10-05 12:44:14 +02:00
Justus Dieckmann 8763bba518 MDL-75569 course: fix non-functional search bar in course index page
For users who are not allowed to access course/management.php, the
normal course search is used instead.
2022-09-20 12:34:45 +02:00
Stephen Bourget 3bb3afdcab MDL-75627 Calendar: Fix calendar imports from Office 365 2022-09-19 15:51:03 -04:00
Anastasios Bithas 098cf7b38d MDL-75665 gradereport_overview: Format strings in grade report overview 2022-09-07 12:36:59 +03:00
424 changed files with 6487 additions and 1882 deletions
+9 -5
View File
@@ -6,6 +6,10 @@
],
'env': {
'browser': true,
// Enable ES6+ features by default.
// See http://eslint.org/docs/user-guide/configuring#specifying-environments
// Note: The YUI override must exactly match this when disabling the ES6+ version because those features are not supported by Shifter.
'es2020': true,
'amd': true
},
'globals': {
@@ -83,6 +87,7 @@
'no-octal-escape': 'error',
'no-proto': 'error',
'no-redeclare': 'warn',
'no-restricted-globals': ['error', { 'name': 'Notification' }],
'no-return-assign': 'error',
'no-script-url': 'error',
'no-self-assign': 'error',
@@ -196,6 +201,10 @@
overrides: [
{
files: ["**/yui/src/**/*.js"],
'env': {
// Disable ES6+ for YUI files.
'es2020': false,
},
// Disable some rules which we can't safely define for YUI rollups.
rules: {
'no-undef': 'off',
@@ -221,10 +230,6 @@
},
{
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
// We support es6 now. Woot!
env: {
es6: true
},
// We're using babel transpiling so use their parser
// for linting.
parser: '@babel/eslint-parser',
@@ -299,7 +304,6 @@
],
},
parserOptions: {
'ecmaVersion': 9,
'sourceType': 'module',
'requireConfigFile': false,
}
+1 -1
View File
@@ -54,5 +54,5 @@ moodle-plugin-ci.phar
/admin/tool/componentlibrary/docs
/admin/tool/componentlibrary/hugo/site/data/my-index.json
.hugo_build.lock
.phpcs.xml
phpcs.xml
jsconfig.json
+2 -2
View File
@@ -39,7 +39,7 @@ module.exports = grunt => {
{
rule: {
_attrs: {
ref: './.phpcs.xml.dist',
ref: './phpcs.xml.dist',
},
},
},
@@ -52,7 +52,7 @@ module.exports = grunt => {
});
});
grunt.file.write('.phpcs.xml', toXML(config, {
grunt.file.write('phpcs.xml', toXML(config, {
header: true,
indent: ' ',
}) + "\n");
+2
View File
@@ -3371,6 +3371,7 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3557,6 +3558,7 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
+18 -3
View File
@@ -46,11 +46,23 @@
$formcontinue = new single_button(new moodle_url('index.php', array('confirm' => md5($mnet->public_key))), get_string('yes'));
$formcancel = new single_button(new moodle_url('index.php', array()), get_string('no'));
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string("deletekeycheck", "mnet"), $formcontinue, $formcancel);
echo $OUTPUT->footer();
exit;
} else {
// We're deleting
// If no/cancel then redirect back to the network setting page.
if (!isset($form->confirm)) {
redirect(
new moodle_url('/admin/mnet/index.php'),
get_string('keydeletedcancelled', 'mnet'),
null,
\core\output\notification::NOTIFY_SUCCESS
);
}
if (!isset($SESSION->mnet_confirm_delete_key)) {
// fail - you're being attacked?
@@ -63,8 +75,12 @@
if($time < time() - 60) {
// fail - you're out of time.
print_error ('deleteoutoftime', 'mnet', 'index.php');
exit;
redirect(
new moodle_url('/admin/mnet/index.php'),
get_string('deleteoutoftime', 'mnet'),
null,
\core\output\notification::NOTIFY_WARNING
);
}
if ($key != md5(sha1($mnet->keypair['keypair_PEM']))) {
@@ -75,7 +91,6 @@
$mnet->replace_keys();
redirect('index.php', get_string('keydeleted','mnet'));
exit;
}
}
$hosts = $DB->get_records_select('mnet_host', "id <> ? AND deleted = 0", array($CFG->mnet_localhost_id), 'wwwroot ASC');
@@ -16,6 +16,8 @@
namespace core_adminpresets\local\setting;
use admin_setting_configcheckbox;
/**
* Checkbox setting.
*
@@ -26,15 +28,15 @@ namespace core_adminpresets\local\setting;
*/
class adminpresets_admin_setting_configcheckbox extends adminpresets_setting {
protected function set_value($value) {
$this->value = clean_param($value, PARAM_BOOL);
$this->set_visiblevalue();
return true;
}
/**
* Sets the visible name for the setting selected value
*/
protected function set_visiblevalue() {
if ($this->value) {
/** @var admin_setting_configcheckbox $settingdata */
$settingdata = $this->get_settingdata();
// We need to compare the "yes" value of the inner checkbox, which isn't necessarily boolean.
if ($this->value == $settingdata->yes) {
$str = get_string('yes');
} else {
$str = get_string('no');
@@ -51,12 +51,12 @@
<div class="form-password">
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
<span data-passwordunmask="editor">
<input type="hidden"
<input type="password"
name="{{ name }}"
id="{{ id }}"
value="{{ value }}"
data-size="{{ size }}"
class="form-control d-inline-block"
class="form-control d-none"
>
</span>
<a href="#" data-passwordunmask="edit" title="{{ edithint }}">
+3 -3
View File
@@ -18,7 +18,7 @@ Feature: An administrator can browse user accounts
When I navigate to "Users > Accounts > Browse list of users" in site administration
# Name field always present, email field is default for showidentity.
Then the following should exist in the "users" table:
| First name / Surname | Email address |
| First name / Last name | Email address |
| User One | one@example.com |
| User Two | two@example.com |
# Should not see other identity fields or non-default name fields.
@@ -34,7 +34,7 @@ Feature: An administrator can browse user accounts
| alternativefullnameformat | firstnamephonetic lastname |
When I navigate to "Users > Accounts > Browse list of users" in site administration
Then the following should exist in the "users" table:
| First name - phonetic / Surname | Email address |
| First name - phonetic / Last name | Email address |
| Yewzer One | one@example.com |
| Yoozare Two | two@example.com |
@@ -43,7 +43,7 @@ Feature: An administrator can browse user accounts
| showuseridentity | department,profile_field_frog |
When I navigate to "Users > Accounts > Browse list of users" in site administration
Then the following should exist in the "users" table:
| First name / Surname | Favourite frog | Department |
| First name / Last name | Favourite frog | Department |
| User One | Kermit | Attack |
| User Two | Tree | Defence |
And I should not see "Email address" in the "table" "css_element"
@@ -15,7 +15,7 @@ Feature: Allowing multiple accounts to have the same email address
And I set the following fields to these values:
| Username | s2 |
| First name | Jane |
| Surname | Doe |
| Last name | Doe |
| Email address | <email> |
| New password | test |
And I press "Create user"
@@ -8,7 +8,7 @@ Feature: An administrator can configure the available user list filters
When I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should not see "Username" in the "New filter" "fieldset"
And I should not see "Email address" in the "New filter" "fieldset"
@@ -30,7 +30,7 @@ Feature: An administrator can configure the available user list filters
And I should not see "MNet ID provider" in the "New filter" "fieldset"
And I navigate to "Users > Accounts > Bulk user actions" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should not see "Username" in the "New filter" "fieldset"
And I should not see "Email address" in the "New filter" "fieldset"
@@ -57,7 +57,7 @@ Feature: An administrator can configure the available user list filters
And I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should see "Username" in the "New filter" "fieldset"
And I should see "Email address" in the "New filter" "fieldset"
@@ -79,7 +79,7 @@ Feature: An administrator can configure the available user list filters
And I should not see "MNet ID provider" in the "New filter" "fieldset"
And I navigate to "Users > Accounts > Bulk user actions" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should see "Username" in the "New filter" "fieldset"
And I should see "Email address" in the "New filter" "fieldset"
@@ -106,7 +106,7 @@ Feature: An administrator can configure the available user list filters
And I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should not see "Username" in the "New filter" "fieldset"
And I should not see "Email address" in the "New filter" "fieldset"
@@ -128,7 +128,7 @@ Feature: An administrator can configure the available user list filters
And I should not see "MNet ID provider" in the "New filter" "fieldset"
And I navigate to "Users > Accounts > Bulk user actions" in site administration
Then I should see "User full name"
And I should not see "Surname" in the "New filter" "fieldset"
And I should not see "Last name" in the "New filter" "fieldset"
And I should not see "Firstname" in the "New filter" "fieldset"
And I should not see "Username" in the "New filter" "fieldset"
And I should not see "Email address" in the "New filter" "fieldset"
+11
View File
@@ -0,0 +1,11 @@
define("tool_behat/steps",["exports","core/ajax","core/templates","core/pending"],(function(_exports,_ajax,_templates,_pending){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Enhancements for the step definitions page.
*
* @module tool_behat/steps
* @copyright 2022 Catalyst IT EU
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_templates=_interopRequireDefault(_templates),_pending=_interopRequireDefault(_pending);_exports.init=()=>{document.addEventListener("change",(async e=>{const entityElement=e.target.closest(".entities"),stepElement=e.target.closest(".stepcontent");if(!entityElement||!stepElement)return;const pendingPromise=new _pending.default("tool_behat/steps:change"),entityData=await(entityType=e.target.value,_ajax.default.call([{methodname:"tool_behat_get_entity_generator",args:{entitytype:entityType}}])[0]);var entityType;const{html:html,js:js}=await(entityData=>{var _entityData$required;return null!==(_entityData$required=entityData.required)&&void 0!==_entityData$required&&_entityData$required.length?_templates.default.renderForPromise("tool_behat/steprequiredfields",{fields:entityData.required}):Promise.resolve({html:"",js:""})})(entityData),stepRequiredFields=stepElement.querySelector(".steprequiredfields");stepRequiredFields?await _templates.default.replaceNode(stepRequiredFields,html,js):await _templates.default.appendNodeContents(stepElement,html,js),pendingPromise.resolve()}))}}));
//# sourceMappingURL=steps.min.js.map
@@ -0,0 +1 @@
{"version":3,"file":"steps.min.js","sources":["../src/steps.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\nimport Ajax from 'core/ajax';\nimport Templates from 'core/templates';\nimport PendingJS from 'core/pending';\n\n/**\n * Enhancements for the step definitions page.\n *\n * @module tool_behat/steps\n * @copyright 2022 Catalyst IT EU\n * @author Mark Johnson <mark.johnson@catalyst-eu.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Call the get_entity_generator web service function\n *\n * Takes the name of an entity generator and returns an object containing a list of the required fields.\n *\n * @param {String} entityType\n * @returns {Promise}\n */\nconst getGeneratorEntities = (entityType) => Ajax.call([{\n methodname: 'tool_behat_get_entity_generator',\n args: {entitytype: entityType}\n}])[0];\n\n/**\n * Render HTML for required fields\n *\n * Takes the entity data returned from getGeneratorEntities and renders the HTML to display the required fields.\n *\n * @param {String} entityData\n * @return {Promise}\n */\nconst getRequiredFieldsContent = (entityData) => {\n if (!entityData.required?.length) {\n return Promise.resolve({\n html: '',\n js: ''\n });\n }\n return Templates.renderForPromise('tool_behat/steprequiredfields', {fields: entityData.required});\n};\n\nexport const init = () => {\n // When an entity is selected in the \"the following exist\" step, fetch and display the required fields.\n document.addEventListener('change', async(e) => {\n const entityElement = e.target.closest('.entities');\n const stepElement = e.target.closest('.stepcontent');\n if (!entityElement || !stepElement) {\n return;\n }\n\n const pendingPromise = new PendingJS('tool_behat/steps:change');\n\n const entityData = await getGeneratorEntities(e.target.value);\n const {html, js} = await getRequiredFieldsContent(entityData);\n\n const stepRequiredFields = stepElement.querySelector('.steprequiredfields');\n if (stepRequiredFields) {\n await Templates.replaceNode(stepRequiredFields, html, js);\n } else {\n await Templates.appendNodeContents(stepElement, html, js);\n }\n pendingPromise.resolve();\n });\n};\n"],"names":["document","addEventListener","async","entityElement","e","target","closest","stepElement","pendingPromise","PendingJS","entityData","entityType","value","Ajax","call","methodname","args","entitytype","html","js","required","_entityData$required","length","Templates","renderForPromise","fields","Promise","resolve","getRequiredFieldsContent","stepRequiredFields","querySelector","replaceNode","appendNodeContents"],"mappings":";;;;;;;;4NA2DoB,KAEhBA,SAASC,iBAAiB,UAAUC,MAAAA,UAC1BC,cAAgBC,EAAEC,OAAOC,QAAQ,aACjCC,YAAcH,EAAEC,OAAOC,QAAQ,oBAChCH,gBAAkBI,yBAIjBC,eAAiB,IAAIC,iBAAU,2BAE/BC,iBAlCgBC,WAkCwBP,EAAEC,OAAOO,MAlClBC,cAAKC,KAAK,CAAC,CACpDC,WAAY,kCACZC,KAAM,CAACC,WAAYN,eACnB,IAH0BA,IAAAA,iBAmChBO,KAACA,KAADC,GAAOA,SAtBaT,CAAAA,0EACzBA,WAAWU,0CAAXC,qBAAqBC,OAMnBC,mBAAUC,iBAAiB,gCAAiC,CAACC,OAAQf,WAAWU,WAL5EM,QAAQC,QAAQ,CACnBT,KAAM,GACNC,GAAI,MAkBiBS,CAAyBlB,YAE5CmB,mBAAqBtB,YAAYuB,cAAc,uBACjDD,yBACMN,mBAAUQ,YAAYF,mBAAoBX,KAAMC,UAEhDI,mBAAUS,mBAAmBzB,YAAaW,KAAMC,IAE1DX,eAAemB"}
+82
View File
@@ -0,0 +1,82 @@
// 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/>.
import Ajax from 'core/ajax';
import Templates from 'core/templates';
import PendingJS from 'core/pending';
/**
* Enhancements for the step definitions page.
*
* @module tool_behat/steps
* @copyright 2022 Catalyst IT EU
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Call the get_entity_generator web service function
*
* Takes the name of an entity generator and returns an object containing a list of the required fields.
*
* @param {String} entityType
* @returns {Promise}
*/
const getGeneratorEntities = (entityType) => Ajax.call([{
methodname: 'tool_behat_get_entity_generator',
args: {entitytype: entityType}
}])[0];
/**
* Render HTML for required fields
*
* Takes the entity data returned from getGeneratorEntities and renders the HTML to display the required fields.
*
* @param {String} entityData
* @return {Promise}
*/
const getRequiredFieldsContent = (entityData) => {
if (!entityData.required?.length) {
return Promise.resolve({
html: '',
js: ''
});
}
return Templates.renderForPromise('tool_behat/steprequiredfields', {fields: entityData.required});
};
export const init = () => {
// When an entity is selected in the "the following exist" step, fetch and display the required fields.
document.addEventListener('change', async(e) => {
const entityElement = e.target.closest('.entities');
const stepElement = e.target.closest('.stepcontent');
if (!entityElement || !stepElement) {
return;
}
const pendingPromise = new PendingJS('tool_behat/steps:change');
const entityData = await getGeneratorEntities(e.target.value);
const {html, js} = await getRequiredFieldsContent(entityData);
const stepRequiredFields = stepElement.querySelector('.steprequiredfields');
if (stepRequiredFields) {
await Templates.replaceNode(stepRequiredFields, html, js);
} else {
await Templates.appendNodeContents(stepElement, html, js);
}
pendingPromise.resolve();
});
};
@@ -0,0 +1,92 @@
<?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/>.
/**
* Return data about an entity generator.
*
* @package tool_behat
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_behat\external;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/externallib.php');
/**
* External function for getting properties of entity generators.
*/
class get_entity_generator extends \external_api {
/**
* Define parameters for external function.
*
* The parameter is either in the format 'entity' or 'component_name > entity'. There is no appropriate param type for a
* string like this containing angle brackets, so we will do PARAM_RAW. The value will be parsed by
* behat_data_generators::parse_entity_type, which validates the format of the parameter and throws an exception if it is not
* correct.
*
* @return \external_function_parameters
*/
public static function execute_parameters(): \external_function_parameters {
return new \external_function_parameters([
'entitytype' => new \external_value(PARAM_RAW, 'Entity type that can be created by a generator.'),
]);
}
/**
* Return a list of the required fields for a given entity type.
*
* @param string $entitytype
* @return array
*/
public static function execute(string $entitytype): array {
global $CFG;
// Ensure we can load Behat and Facebook namespaces in behat libraries.
require_once("{$CFG->dirroot}/vendor/autoload.php");
require_once("{$CFG->libdir}/tests/behat/behat_data_generators.php");
$params = self::validate_parameters(self::execute_parameters(), ['entitytype' => $entitytype]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
$generators = new \behat_data_generators();
$entity = $generators->get_entity($params['entitytype']);
return ['required' => $entity['required']];
}
/**
* Define return values.
*
* Return required fields
*
* @return \external_single_structure
*/
public static function execute_returns(): \external_single_structure {
return new \external_single_structure([
'required' => new \external_multiple_structure(
new \external_value(PARAM_TEXT, 'Required field'),
'Required fields',
VALUE_OPTIONAL
),
]);
}
}
+37
View File
@@ -0,0 +1,37 @@
<?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/>.
/**
* Define web service functions for tool_behat
*
* @package tool_behat
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$functions = [
'tool_behat_get_entity_generator' => [
'classname' => 'tool_behat\\external\\get_entity_generator',
'methodname' => 'execute',
'description' => 'Get the generator details for an entity',
'type' => 'read',
'ajax' => true,
'capabilities' => 'moodle/site:config'
]
];
+1
View File
@@ -56,6 +56,7 @@ if ($components) {
$form = new steps_definitions_form(null, array('components' => $componentswithsteps));
// Output contents.
$PAGE->requires->js_call_amd('tool_behat/steps', 'init');
$renderer = $PAGE->get_renderer('tool_behat');
echo $renderer->render_stepsdefinitions($steps, $form);
+28
View File
@@ -24,6 +24,8 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/behat/classes/behat_generator_base.php');
/**
* Renderer for behat tool web features
*
@@ -106,6 +108,32 @@ class tool_behat_renderer extends plugin_renderer_base {
},
$stepsdefinitions
);
$elementstrings = [];
$count = 1;
$stepsdefinitions = preg_replace_callback('/(the following ")ELEMENT\d?_STRING(" exist:)/',
function($matches) use (&$elementstrings, &$count) {
// Replace element type arguments with a user-friendly select.
if (empty($elementstrings)) {
$behatgenerators = new behat_data_generators();
$componententities = $behatgenerators->get_all_entities();
ksort($componententities);
$elementstrings = [];
foreach ($componententities as $component => $entities) {
asort($entities);
foreach ($entities as $entity) {
$string = ($component === 'core') ? $entity : $component . ' > ' . $entity;
$elementstrings[$string] = $string;
}
}
}
$select = html_writer::select($elementstrings, 'entities' . $count, '', ['' => 'choosedots'],
['class' => 'entities']);
$count++;
return $matches[1] . $select . $matches[2];
},
$stepsdefinitions
);
}
// Steps definitions.
+6
View File
@@ -29,3 +29,9 @@
#page-admin-tool-behat-index .steps-definitions .stepregex {
color: #060;
}
#page-admin-tool-behat-index .steprequiredfields {
font-weight: bold;
font-size: 1em;
margin-top: 1em;
}
@@ -0,0 +1,33 @@
{{!
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 <http://www.gnu.org/licenses/>.
}}
{{!
@template tool_behat/steprequiredfields
Display a Gherkin-style table row showing required columns for a step.
Example context (json):
{
"fields": [
"user",
"role",
"context"
]
}
}}
<pre class="steprequiredfields">
|{{#fields}} {{{.}}} |{{/fields}}
</pre>
@@ -13,6 +13,10 @@ Feature: List the system steps definitions
Scenario: Accessing the list
Then I should see "Step definitions"
And I should not see "There aren't steps definitions matching this filter"
And I should not see "the following \"ELEMENT_STRING\" exist:"
And "entities1" "select" should exist
And the "entities1" select box should contain "users"
And the "entities1" select box should contain "mod_assign > submissions"
@javascript
Scenario: Filtering by type
@@ -34,3 +38,11 @@ Feature: List the system steps definitions
Then I should not see "There aren't steps definitions matching this filter"
And I should see "Checks the provided element and selector type exists in the current page."
And I should see "Checks that an element and selector type exists in another element and selector type on the current page."
@javascript
Scenario: Get required fields
Given I set the field "entities1" to "users"
And I should see "| username |"
When I set the field "entities1" to "mod_quiz > user overrides"
Then I should not see "| username |"
And I should see "| quiz | user |"
@@ -13,24 +13,24 @@ Feature: Transform steps arguments
And I open my profile in edit mode
Scenario: Use nasty strings on steps arguments
When I set the field "Surname" to "$NASTYSTRING1"
When I set the field "Last name" to "$NASTYSTRING1"
And I set the field "Description" to "$NASTYSTRING2"
And I set the field "City/town" to "$NASTYSTRING3"
And I press "Update profile"
And I click on "Edit profile" "link" in the "region-main" "region"
Then I should not see "NASTYSTRING"
And the field "Surname" matches value "$NASTYSTRING1"
And the field "Last name" matches value "$NASTYSTRING1"
And the field "City/town" matches value "$NASTYSTRING3"
Scenario: Use nasty strings on table nodes
When I set the following fields to these values:
| Surname | $NASTYSTRING1 |
| Last name | $NASTYSTRING1 |
| Description | $NASTYSTRING2 |
| City/town | $NASTYSTRING3 |
And I press "Update profile"
And I click on "Edit profile" "link" in the "region-main" "region"
Then I should not see "NASTYSTRING"
And the field "Surname" matches value "$NASTYSTRING1"
And the field "Last name" matches value "$NASTYSTRING1"
And the field "City/town" matches value "$NASTYSTRING3"
Scenario: Use double quotes
@@ -48,11 +48,11 @@ Feature: Transform steps arguments
Scenario: Nasty strings with other contents
When I set the field "First name" to "My Firstname $NASTYSTRING1"
And I set the following fields to these values:
| Surname | My Surname $NASTYSTRING2 |
| Last name | My Last name $NASTYSTRING2 |
And I press "Update profile"
And I click on "Edit profile" "link" in the "region-main" "region"
Then I should not see "NASTYSTRING"
And I should see "My Firstname"
And I should see "My Surname"
And I should see "My Last name"
And the field "First name" matches value "My Firstname $NASTYSTRING1"
And the field "Surname" matches value "My Surname $NASTYSTRING2"
And the field "Last name" matches value "My Last name $NASTYSTRING2"
@@ -0,0 +1,104 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for get_entity_generator web service
*
* @package tool_behat
* @copyright 2022 onwards Catalyst IT EU {@link https://catalyst-eu.net}
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_behat\external;
/**
* Tests for get_entity_generator web service
*
* @covers \tool_behat\external\get_entity_generator
*/
class get_entity_generator_test extends \advanced_testcase {
/**
* Log in as admin
*
* @return void
*/
public function setUp(): void {
$this->resetAfterTest();
$this->setAdminUser();
}
/**
* Get the generator for a core entity.
*
* @return void
*/
public function test_execute_core_entity(): void {
$generator = get_entity_generator::execute('users');
$this->assertEquals(['required' => ['username']], $generator);
}
/**
* Get the generator for the plugin entity.
*
* @return void
*/
public function test_execute_plugin_entity(): void {
$generator = get_entity_generator::execute('mod_book > chapters');
$this->assertEquals(['required' => ['book', 'title', 'content']], $generator);
}
/**
* Get the generator for an entity with no required fields.
*
* @return void
*/
public function test_execute_no_requried(): void {
$generator = get_entity_generator::execute('mod_forum > posts');
$this->assertEquals(['required' => []], $generator);
}
/**
* Attempt to get the generator for a core entity that does not exist.
*
* @return void
*/
public function test_execute_invalid_entity(): void {
$this->expectException('coding_exception');
get_entity_generator::execute('foo');
}
/**
* Attempt to get a generator form a plugin that does not exist.
*
* @return void
*/
public function test_execute_invalid_plugin(): void {
$this->expectException('coding_exception');
get_entity_generator::execute('foo > bar');
}
/**
* Attempt to get a generator for an entity that does not exist, from a plugin that does.
*
* @return void
*/
public function test_execute_invalid_plugin_entity(): void {
$this->expectException('coding_exception');
get_entity_generator::execute('mod_book > bar');
}
}
+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 = 'tool_behat'; // Full name of the plugin (used for diagnostics)
@@ -81,6 +81,30 @@ $activity-icon-colors: (
);
{{</ highlight >}}
### Custom activity icons
Some activities allow icons to be customised. This can be done by implementing callback XXX_get_coursemodule_info() returning instance of object e.g. mod/lti/lib.php
{{< php >}}
$info = new cached_cm_info();
$info->iconurl = new moodle_url('https://moodle.org/theme/moodleorg/pix/moodle_logo_small.svg');
{{< /php >}}
To get this customised icon, use:
{{< php >}}
$iconurl = get_fast_modinfo($courseid)->get_cm($cmid)->get_icon_url()->out(false);
{{< /php >}}
<div class="media mb-3">
<div class="activityiconcontainer lti mr-3">
<img alt="lti icon" title="lti icon" src="https://moodle.org/theme/moodleorg/pix/moodle_logo_small.svg" class="activityicon "> </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">external</div>
<div class="activityname"><a href="#">External tool module</a></div>
</div>
</div>
## Examples
<div class="media mb-3">
+1 -1
View File
@@ -5,6 +5,6 @@
* @copyright 2018 Adrian Greeve
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("tool_dataprivacy/expand_contract",["jquery","core/url","core/str"],(function($,url,str){var expandedImage=$('<img alt="" src="'+url.imageUrl("t/expanded")+'"/>'),collapsedImage=$('<img alt="" src="'+url.imageUrl("t/collapsed")+'"/>'),CLASSES_EXPAND="fa-caret-right",CLASSES_COLLAPSE="fa-caret-down";return{expandCollapse:function(targetnode,thisnode){targetnode.hasClass("hide")?(targetnode.removeClass("hide"),targetnode.addClass("visible"),targetnode.attr("aria-expanded",!0),thisnode.find(":header i.fa").removeClass(CLASSES_EXPAND),thisnode.find(":header i.fa").addClass(CLASSES_COLLAPSE),thisnode.find(":header img.icon").attr("src",expandedImage.attr("src"))):(targetnode.removeClass("visible"),targetnode.addClass("hide"),targetnode.attr("aria-expanded",!1),thisnode.find(":header i.fa").removeClass(CLASSES_COLLAPSE),thisnode.find(":header i.fa").addClass(CLASSES_EXPAND),thisnode.find(":header img.icon").attr("src",collapsedImage.attr("src")))},expandCollapseAll:function(nextstate){var currentstate="visible"==nextstate?"hide":"visible",ariaexpandedstate="visible"==nextstate,iconclassnow="visible"==nextstate?CLASSES_EXPAND:CLASSES_COLLAPSE,iconclassnext="visible"==nextstate?CLASSES_COLLAPSE:CLASSES_EXPAND,imagenow="visible"==nextstate?expandedImage.attr("src"):collapsedImage.attr("src");$("."+currentstate).each((function(){$(this).removeClass(currentstate),$(this).addClass(nextstate),$(this).attr("aria-expanded",ariaexpandedstate)})),$(".tool_dataprivacy-expand-all").data("visibilityState",currentstate),str.get_string(currentstate,"tool_dataprivacy").then((function(langString){$(".tool_dataprivacy-expand-all").html(langString)})).catch(Notification.exception),$(":header i.fa").each((function(){$(this).removeClass(iconclassnow),$(this).addClass(iconclassnext)})),$(":header img.icon").each((function(){$(this).attr("src",imagenow)}))}}}));
define("tool_dataprivacy/expand_contract",["jquery","core/url","core/str","core/notification"],(function($,url,str,Notification){var expandedImage=$('<img alt="" src="'+url.imageUrl("t/expanded")+'"/>'),collapsedImage=$('<img alt="" src="'+url.imageUrl("t/collapsed")+'"/>'),CLASSES_EXPAND="fa-caret-right",CLASSES_COLLAPSE="fa-caret-down";return{expandCollapse:function(targetnode,thisnode){targetnode.hasClass("hide")?(targetnode.removeClass("hide"),targetnode.addClass("visible"),targetnode.attr("aria-expanded",!0),thisnode.find(":header i.fa").removeClass(CLASSES_EXPAND),thisnode.find(":header i.fa").addClass(CLASSES_COLLAPSE),thisnode.find(":header img.icon").attr("src",expandedImage.attr("src"))):(targetnode.removeClass("visible"),targetnode.addClass("hide"),targetnode.attr("aria-expanded",!1),thisnode.find(":header i.fa").removeClass(CLASSES_COLLAPSE),thisnode.find(":header i.fa").addClass(CLASSES_EXPAND),thisnode.find(":header img.icon").attr("src",collapsedImage.attr("src")))},expandCollapseAll:function(nextstate){var currentstate="visible"==nextstate?"hide":"visible",ariaexpandedstate="visible"==nextstate,iconclassnow="visible"==nextstate?CLASSES_EXPAND:CLASSES_COLLAPSE,iconclassnext="visible"==nextstate?CLASSES_COLLAPSE:CLASSES_EXPAND,imagenow="visible"==nextstate?expandedImage.attr("src"):collapsedImage.attr("src");$("."+currentstate).each((function(){$(this).removeClass(currentstate),$(this).addClass(nextstate),$(this).attr("aria-expanded",ariaexpandedstate)})),$(".tool_dataprivacy-expand-all").data("visibilityState",currentstate),str.get_string(currentstate,"tool_dataprivacy").then((function(langString){$(".tool_dataprivacy-expand-all").html(langString)})).catch(Notification.exception),$(":header i.fa").each((function(){$(this).removeClass(iconclassnow),$(this).addClass(iconclassnext)})),$(":header img.icon").each((function(){$(this).attr("src",imagenow)}))}}}));
//# sourceMappingURL=expand_contract.min.js.map
File diff suppressed because one or more lines are too long
@@ -21,7 +21,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/url', 'core/str'], function($, url, str) {
define(['jquery', 'core/url', 'core/str', 'core/notification'], function($, url, str, Notification) {
var expandedImage = $('<img alt="" src="' + url.imageUrl('t/expanded') + '"/>');
var collapsedImage = $('<img alt="" src="' + url.imageUrl('t/collapsed') + '"/>');
+14 -1
View File
@@ -79,6 +79,19 @@ class locale {
* @return string|false Returns the new current locale, or FALSE on error.
*/
protected function set_locale(int $category = LC_ALL, string $locale = '0') {
return setlocale($category, $locale);
if (strlen($locale) <= 255 || PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
// We can set the whole locale all together.
return setlocale($category, $locale);
}
// Too long locale with linux or windows, let's split it into known and supported categories.
$split = explode(';', $locale);
foreach ($split as $element) {
[$category, $value] = explode('=', $element);
if (defined($category)) { // Only if the category exists, there are OS differences.
setlocale(constant($category), $value);
}
}
return setlocale(LC_ALL, 0); // Finally, return the complete configured locale.
}
}
+101 -11
View File
@@ -14,14 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for \tool_langimport\locale class.
*
* @package tool_langimport
* @copyright 2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_langimport;
/**
@@ -29,6 +21,7 @@ namespace tool_langimport;
*
* @package tool_langimport
* @category test
* @coversDefaultClass \tool_langimport\locale
* @copyright 2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -36,6 +29,7 @@ class locale_test extends \advanced_testcase {
/**
* Test that \tool_langimport\locale::check_locale_availability() works as expected.
*
* @covers ::check_locale_availability
* @return void
*/
public function test_check_locale_availability() {
@@ -43,7 +37,7 @@ class locale_test extends \advanced_testcase {
// - first setlocale() call which backup current locale
// - second setlocale() call which try to set new 'es' locale
// - third setlocale() call which restore locale.
$mock = $this->getMockBuilder(\tool_langimport\locale::class)
$mock = $this->getMockBuilder(locale::class)
->onlyMethods(['set_locale'])
->getMock();
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', 'es', 'en'));
@@ -56,7 +50,7 @@ class locale_test extends \advanced_testcase {
// - first setlocale() call which backup current locale
// - second setlocale() call which fail to set new locale
// - third setlocale() call which restore locale.
$mock = $this->getMockBuilder(\tool_langimport\locale::class)
$mock = $this->getMockBuilder(locale::class)
->onlyMethods(['set_locale'])
->getMock();
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', false, 'en'));
@@ -66,8 +60,104 @@ class locale_test extends \advanced_testcase {
$this->assertFalse($result);
// Test an invalid parameter.
$locale = new \tool_langimport\locale();
$locale = new locale();
$this->expectException(\coding_exception::class);
$locale->check_locale_availability('');
}
/**
* Test \tool_langimport\locale::set_locale() own logic.
*
* We have to explicitly test set_locale() own logic and results,
* that effectively sets the current locale, so we need to restore
* the original locale after every test (ugly, from a purist unit test
* point of view, but needed).
*
* @dataProvider set_locale_provider
* @covers ::set_locale
*
* @param string $set locale string to be set.
* @param string $ret expected results returned after setting the locale.
*/
public function test_set_locale(string $set, string $ret) {
// Make set_locale() public.
$loc = new locale();
$rc = new \ReflectionClass(locale::class);
$rm = $rc->getMethod('set_locale');
$rm->setAccessible(true);
// Capture current locale for later restore (funnily, using the set_locale() method itself.
$originallocale = $rm->invokeArgs($loc, [LC_ALL, 0]);
// Assert we get the locale defined as expected.
$this->assertEquals($ret, $rm->invokeArgs($loc, [LC_ALL, $set]));
// We have finished, restore the original locale, so this doesn't affect other tests at distance.
// (again, funnily, using the very same set_locale() method).
$rm->invokeArgs($loc, [LC_ALL, $originallocale]);
}
/**
* Data provider for test_set_locale().
*
* Provides a locale to be set (as 'set') and a expected return value (as 'ret'). Note that
* some of the locales are OS dependent, so only the ones matching the OS will be provided.
*
* We make extensive use of the en_AU.UTF-8/English_Australia.1252 locale that is mandatory to
* be installed in any system running PHPUnit tests.
*/
public function set_locale_provider(): array {
// Let's list the allowed categories by OS.
$bsdallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
$winallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
$linuxallowed = [
'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME',
'LC_PAPER', 'LC_NAME', 'LC_ADDRESS', 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'
];
// The base locale name is also OS dependent.
$baselocale = get_string('locale', 'langconfig');
if (PHP_OS_FAMILY === 'Windows') {
$baselocale = get_string('localewin', 'langconfig');
}
// Here we'll go accumulating cases to be provided.
$cases = [];
// First, the simplest case, just pass a locale name, without categories.
$cases['rawlocale'] = [
'set' => $baselocale,
'ret' => $baselocale,
];
// Now, let's fill ALL LC categories, we should get back the locale name if all them are set with same value.
// Note that this case is the one that, under Linux only, covers the changes performed to the set_locale() method.
// Pick the correct categories depending on the OS.
$oscategories = $bsdallowed; // Default to BSD/Dawrwin ones because they are the standard 6 supported by PHP.
if (PHP_OS_FAMILY === 'Windows') {
$oscategories = $winallowed;
} else if (PHP_OS_FAMILY === 'Linux') {
$oscategories = $linuxallowed;
}
$localestr = '';
foreach ($oscategories as $category) {
// Format is different by OS too, so let build the string conditionally.
if (PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
// BSD uses slashes (/) separated list of the 6 values in exact order.
$localestr .= '/' . $baselocale;
} else {
// Linux/Windows use semicolon (;) separated list of category=value pairs.
$localestr .= ';' . $category . '=' . $baselocale;
}
}
$cases['allcategories'] = [
'set' => trim($localestr, ';/'),
'ret' => $baselocale,
];
// Return all the built cases.
return $cases;
}
}
+1 -1
View File
@@ -57,7 +57,7 @@ trait store {
throw new \coding_exception("Store $called doesn't define classes in correct namespaces.");
}
$this->component = $parts[0];
$this->store = str_replace('logstore_', '', $this->store);
$this->store = str_replace('logstore_', '', $this->component);
}
/**
+1 -1
View File
@@ -278,7 +278,7 @@ class external extends external_api {
));
$competency = api::read_competency($params['competencyid']);
$framework = api::read_framework($competency->get_competencyframeworkid());
$framework = api::read_framework($competency->get('competencyframeworkid'));
self::validate_context($framework->get_context());
$renderable = new output\competency_summary($competency, $framework, $params['includerelated'], $params['includecourses']);
$renderer = $PAGE->get_renderer('tool_lp');
+2 -2
View File
@@ -229,7 +229,7 @@ class page_helper {
$PAGE->set_pagelayout('standard');
$PAGE->set_url($url);
$PAGE->set_title($title);
$PAGE->set_heading($title);
$PAGE->set_heading(fullname($user));
if (!empty($plan)) {
$PAGE->navbar->add($title, $planurl);
@@ -303,7 +303,7 @@ class page_helper {
$PAGE->set_pagelayout('standard');
$PAGE->set_url($url);
$PAGE->set_title($title);
$PAGE->set_heading($title);
$PAGE->set_heading(fullname($user));
if (!empty($evidence)) {
$PAGE->navbar->add($title, $evidenceurl);
+1 -1
View File
@@ -125,7 +125,7 @@ $string['qrcodetypeurl'] = 'QR code with site URL';
$string['qrcodetypelogin'] = 'QR code with automatic login';
$string['qrkeyttl'] = 'QR authentication key duration';
$string['qrkeyttl_desc'] = 'The length of time for which a QR code for automatic login is valid.';
$string['readingthisemailgettheapp'] = 'Reading this in an email? <a href="{$a}">Download the mobile app and receive notifications on your mobile device</a>.';
$string['readingthisemailgettheapp'] = 'Are you reading this in an email? <a href="{$a}">Download the mobile app and receive notifications on your mobile device</a>.';
$string['remoteaddons'] = 'Remote add-ons';
$string['scanqrcode'] = 'Scan QR code';
$string['selfsignedoruntrustedcertificatewarning'] = 'It seems that the HTTPS certificate is self-signed or not trusted. The mobile app will only work with trusted sites. Please use any online SSL checker to diagnose the problem. If it indicates that your certificate is OK, you can ignore this warning.';
@@ -19,7 +19,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -53,7 +53,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -98,7 +98,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -157,7 +157,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -210,7 +210,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -522,7 +522,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
When I press "Create my new account"
Then I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -647,7 +647,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -716,7 +716,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -858,7 +858,7 @@ Feature: User must accept policy managed by this plugin when logging in and sign
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -86,7 +86,7 @@ Feature: Optional policies
| Email address | user3@address.invalid |
| Email (again) | user3@address.invalid |
| First name | User3 |
| Surname | L3 |
| Last name | L3 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user3@address.invalid"
+6
View File
@@ -51,6 +51,12 @@ if ($listurl) {
$PAGE->navbar->add($listurl, $listurlnav);
}
// Add a new nav item to make $listurl clickable for the Boost theme.
if (isset($script)) {
$lastrunnav = get_string('lastrun', 'tool_profiling');
$PAGE->navbar->add($lastrunnav);
}
// Header
echo $OUTPUT->header();
@@ -41,6 +41,7 @@ $string['importok'] = 'File "{$a}" imported successfully.';
$string['importprefix'] = 'Import prefix';
$string['importproblem'] = 'Some problem happened importing the file "{$a}".';
$string['lastrunof'] = 'Summary of last run of {$a}';
$string['lastrun'] = 'Summary of last run';
$string['markreferencerun'] = 'Mark as reference run/comment';
$string['memory'] = 'Memory used';
$string['pluginname'] = 'Profiling runs';
@@ -243,6 +243,16 @@ class category_bin extends base_bin {
throw new \moodle_exception("Could not create course to restore into.");
}
// As far as recycle bin is using MODE_AUTOMATED, it observes the General restore settings.
// For recycle bin we want to ensure that backup files are always restore the users and groups information.
// In order to achieve that, we hack the setting here via $CFG->forced_plugin_settings,
// so it won't interfere other operations.
// See MDL-65218 and MDL-35773 for more information.
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% separate from MOODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$CFG->forced_plugin_settings['restore'] = ['restore_general_users' => 1, 'restore_general_groups' => 1];
// Define the import.
$controller = new \restore_controller(
$tempdir,
@@ -277,6 +287,10 @@ class category_bin extends base_bin {
// Run the import.
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['restore']);
// Have finished with the controller, let's destroy it, freeing mem and resources.
$controller->destroy();
@@ -234,6 +234,16 @@ class course_bin extends base_bin {
$fb = get_file_packer('application/vnd.moodle.backup');
$fb->extract_to_pathname($file, $fulltempdir);
// As far as recycle bin is using MODE_AUTOMATED, it observes the General restore settings.
// For recycle bin we want to ensure that backup files are always restore the users and groups information.
// In order to achieve that, we hack the setting here via $CFG->forced_plugin_settings,
// so it won't interfere other operations.
// See MDL-65218 and MDL-35773 for more information.
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% separate from MOODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$CFG->forced_plugin_settings['restore'] = ['restore_general_users' => 1, 'restore_general_groups' => 1];
// Define the import.
$controller = new \restore_controller(
$tempdir,
@@ -264,6 +274,10 @@ class course_bin extends base_bin {
// Run the import.
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['restore']);
// Have finished with the controller, let's destroy it, freeing mem and resources.
$controller->destroy();
@@ -22,35 +22,30 @@ Feature: Backup user data
And the following "activities" exist:
| activity | course | section | name | intro |
| quiz | C1 | 1 | Quiz 1 | Test quiz description |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | TF1 | First question |
| Test questions | truefalse | TF2 | Second question |
And quiz "Quiz 1" contains the following questions:
| question | page |
| TF1 | 1 |
| TF2 | 1 |
@javascript
Scenario: Delete and restore a quiz with user data
Given I am on the "Quiz 1" "quiz activity" page logged in as teacher1
And I add a "True/False" question to the "Quiz 1" quiz with:
| Question name | TF1 |
| Question text | First question |
| General feedback | Thank you, this is the general feedback |
| Correct answer | False |
| Feedback for the response 'True'. | So you think it is true |
| Feedback for the response 'False'. | So you think it is false |
And I add a "True/False" question to the "Quiz 1" quiz with:
| Question name | TF2 |
| Question text | Second question |
| General feedback | Thank you, this is the general feedback |
| Correct answer | False |
| Feedback for the response 'True'. | So you think it is true |
| Feedback for the response 'False'. | So you think it is false |
And I set the field "maxgrade" to "10.0"
And I press "savechanges"
And I log out
When I am on the "Quiz 1" "quiz activity" page logged in as student1
Scenario Outline: Delete and restore a quiz with user data
Given the following config values are set as admin:
| restore_general_users | <include_user> | restore |
And I am on the "Quiz 1" "quiz activity" page logged in as student1
And I press "Attempt quiz"
And I click on "True" "radio" in the "First question" "question"
And I click on "False" "radio" in the "Second question" "question"
And I press "Finish attempt"
And I press "Submit all and finish"
And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
And I should see "5.00 out of 10.00"
And I should see "50.00 out of 100.00"
And I log out
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
@@ -63,5 +58,10 @@ Feature: Backup user data
And I log in as "student1"
And I am on "Course 1" course homepage
When I navigate to "User report" in the course gradebook
Then "Quiz 1" row "Grade" column of "user-grade" table should contain "5"
Then "Quiz 1" row "Grade" column of "user-grade" table should contain "50"
And "Quiz 1" row "Percentage" column of "user-grade" table should contain "50"
Examples:
| include_user | case_explanation |
| 1 | Checked |
| 1 | Unchecked |
@@ -190,6 +190,11 @@ class category_bin_test extends \advanced_testcase {
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 2],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
'restore/restore_general_users moodle' => [[
(object)['plugin' => 'restore', 'name' => 'restore_general_users', 'value' => 0],
(object)['plugin' => 'restore', 'name' => 'restore_general_groups', 'value' => 0],
]],
];
}
@@ -187,6 +187,11 @@ class course_bin_test extends \advanced_testcase {
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 2],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
'restore/restore_general_users moodle' => [[
(object)['plugin' => 'restore', 'name' => 'restore_general_users', 'value' => 0],
(object)['plugin' => 'restore', 'name' => 'restore_general_groups', 'value' => 0],
]],
];
}
@@ -66,14 +66,10 @@ Feature: Upload users
@javascript
Scenario: Upload users with custom profile fields
# Create user profile field.
Given I log in as "admin"
And I navigate to "Users > Accounts > User profile fields" in site administration
And I click on "Create a new profile field" "link"
And I click on "Text area" "link"
And I set the following fields to these values:
| Short name | superfield |
| Name | Super field |
And I click on "Save changes" "button"
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | superfield | Super field |
And I log in as "admin"
# Upload users.
When I navigate to "Users > Accounts > Upload users" in site administration
And I upload "lib/tests/fixtures/upload_users_profile.csv" file to "File" filemanager
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+127 -4
View File
@@ -44,7 +44,7 @@ import {prefetchStrings} from 'core/prefetch';
* @constant
* @type {number}
*/
const MINSPACING = 50;
const MINSPACING = 10;
/**
* A user tour.
@@ -83,6 +83,12 @@ const Tour = class {
// Apply configuration.
this.configure.apply(this, arguments);
// Unset recalculate state.
this.possitionNeedToBeRecalculated = false;
// Unset recalculate count.
this.recalculatedNo = 0;
try {
this.storage = window.sessionStorage;
this.storageKey = 'tourstate_' + this.tourName;
@@ -396,6 +402,11 @@ const Tour = class {
return false;
}
// Check if the CSS styles are allowed on the browser or not.
if (!this.isCSSAllowed()) {
return false;
}
let target = this.getStepTarget(stepConfig);
if (target && target.length && target.is(':visible')) {
// Without a target, there can be no step.
@@ -405,6 +416,22 @@ const Tour = class {
return false;
}
/**
* Is the browser actually allow CSS styles?
*
* @returns {boolean} True if the browser is allowing CSS styles
*/
isCSSAllowed() {
const testCSSElement = document.createElement('div');
testCSSElement.classList.add('hide');
document.body.appendChild(testCSSElement);
const styles = window.getComputedStyle(testCSSElement);
const isAllowed = styles.display === 'none';
testCSSElement.remove();
return isAllowed;
}
/**
* Go to the next step in the tour.
*
@@ -924,6 +951,7 @@ const Tour = class {
// Configure ARIA attributes on the target.
let target = this.getStepTarget(stepConfig);
if (target) {
target.data('original-tabindex', target.attr('tabindex'));
if (!target.attr('tabindex')) {
target.attr('tabindex', 0);
}
@@ -1150,6 +1178,12 @@ const Tour = class {
if (target.data('original-tabindex')) {
target.attr('tabindex', target.data('tabindex'));
} else {
// If the target does not have the tabindex attribute at the beginning. We need to remove it.
// We should wait a little here before removing the attribute to prevent the browser from adding it again.
window.setTimeout(() => {
target.removeAttr('tabindex');
}, 400);
}
}
@@ -1296,6 +1330,7 @@ const Tour = class {
*/
positionStep(stepConfig) {
let content = this.currentStepNode;
let thisT = this;
if (!content || !content.length) {
// Unable to find the step node.
return this;
@@ -1335,9 +1370,15 @@ const Tour = class {
},
onCreate: function(data) {
recalculateArrowPosition(data);
recalculateStepPosition(data);
},
onUpdate: function(data) {
recalculateArrowPosition(data);
if (thisT.possitionNeedToBeRecalculated) {
thisT.recalculatedNo++;
thisT.possitionNeedToBeRecalculated = false;
recalculateStepPosition(data);
}
},
};
@@ -1387,6 +1428,90 @@ const Tour = class {
}
};
const recalculateStepPosition = function(data) {
const placement = data.placement.split('-')[0];
const isVertical = ['left', 'right'].indexOf(placement) !== -1;
const popperElement = $(data.instance.popper);
const targetElement = $(data.instance.reference);
const arrowElement = popperElement.find('[data-role="arrow"]');
const stepElement = popperElement.find('[data-role="flexitour-step"]');
const viewportHeight = $(window).height();
const viewportWidth = $(window).width();
const arrowHeight = parseFloat(arrowElement.outerHeight(true));
const popperHeight = parseFloat(popperElement.outerHeight(true));
const targetHeight = parseFloat(targetElement.outerHeight(true));
const arrowWidth = parseFloat(arrowElement.outerWidth(true));
const popperWidth = parseFloat(popperElement.outerWidth(true));
const targetWidth = parseFloat(targetElement.outerWidth(true));
let maxHeight;
if (thisT.recalculatedNo > 1) {
// The current screen is too small, and cannot fit with the original placement.
// We should set the placement to auto so the PopperJS can calculate the perfect placement.
thisT.currentStepPopper.options.placement = isVertical ? 'auto-left' : 'auto-bottom';
}
if (thisT.recalculatedNo > 2) {
// Return here to prevent recursive calling.
return;
}
if (isVertical) {
// Find the best place to put the tour: Left of right.
const leftSpace = targetElement.offset().left > 0 ? targetElement.offset().left : 0;
const rightSpace = viewportWidth - leftSpace - targetWidth;
const remainingSpace = leftSpace >= rightSpace ? leftSpace : rightSpace;
maxHeight = viewportHeight - MINSPACING * 2;
if (remainingSpace < (popperWidth + arrowWidth)) {
const maxWidth = remainingSpace - MINSPACING - arrowWidth;
if (maxWidth > 0) {
popperElement.css({
'max-width': maxWidth + 'px',
});
// Not enough space, flag true to make Popper to recalculate the position.
thisT.possitionNeedToBeRecalculated = true;
}
} else if (maxHeight < popperHeight) {
// Check if the Popper's height can fit the viewport height or not.
// If not, set the correct max-height value for the Popper element.
popperElement.css({
'max-height': maxHeight + 'px',
});
}
} else {
// Find the best place to put the tour: Top of bottom.
const topSpace = targetElement.offset().top > 0 ? targetElement.offset().top : 0;
const bottomSpace = viewportHeight - topSpace - targetHeight;
const remainingSpace = topSpace >= bottomSpace ? topSpace : bottomSpace;
maxHeight = remainingSpace - MINSPACING - arrowHeight;
if (remainingSpace < (popperHeight + arrowHeight)) {
// Not enough space, flag true to make Popper to recalculate the position.
thisT.possitionNeedToBeRecalculated = true;
}
}
// Check if the Popper's height can fit the viewport height or not.
// If not, set the correct max-height value for the body.
const currentStepBody = stepElement.find('[data-placeholder="body"]').first();
const headerEle = stepElement.find('.modal-header').first();
const footerEle = stepElement.find('.modal-footer').first();
const headerHeight = headerEle.outerHeight(true) ?? 0;
const footerHeight = footerEle.outerHeight(true) ?? 0;
maxHeight = maxHeight - headerHeight - footerHeight;
if (maxHeight > 0) {
headerEle.removeClass('minimal');
footerEle.removeClass('minimal');
currentStepBody.css({
'max-height': maxHeight + 'px',
'overflow': 'auto',
});
} else {
headerEle.addClass('minimal');
footerEle.addClass('minimal');
}
// Call the Popper update method to update the position.
thisT.currentStepPopper.update();
};
let background = $('[data-flexitour="step-background"]');
if (background.length) {
target = background;
@@ -1503,9 +1628,7 @@ const Tour = class {
}
let targetPosition = this.calculatePosition(targetNode);
if (targetPosition === 'fixed') {
background.css('top', 0);
} else if (targetPosition === 'absolute') {
if (targetPosition === 'absolute') {
background.css('position', 'fixed');
}
+6
View File
@@ -14,6 +14,12 @@ span[data-flexitour="container"] .modal-dialog .modal-content .modal-header {
border-bottom: 0;
}
span[data-flexitour="container"] .modal-dialog .modal-content .modal-header.minimal,
span[data-flexitour="container"] .modal-dialog .modal-content .modal-footer.minimal {
padding-top: 0;
padding-bottom: 0;
}
span[data-flexitour="container"] .modal-dialog .modal-content .modal-footer {
justify-content: flex-start;
border-top: 0;
+23 -6
View File
@@ -22,6 +22,8 @@
* @package core
*/
use core_user\fields;
define('NO_OUTPUT_BUFFERING', true);
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
@@ -37,7 +39,7 @@ if (empty($SESSION->bulk_users)) {
}
if ($dataformat) {
$fields = array('id' => 'id',
$originfields = array('id' => 'id',
'username' => 'username',
'email' => 'email',
'firstname' => 'firstname',
@@ -51,8 +53,10 @@ if ($dataformat) {
'country' => 'country');
$extrafields = profile_get_user_fields_with_data(0);
$profilefields = [];
foreach ($extrafields as $formfield) {
$fields['profile_field_'.$formfield->get_shortname()] = 'profile_field_'.$formfield->get_shortname();
$profilefields[fields::PROFILE_FIELD_PREFIX . $formfield->get_shortname()] = fields::PROFILE_FIELD_PREFIX .
$formfield->get_shortname();
}
$filename = clean_filename(get_string('users'));
@@ -60,17 +64,17 @@ if ($dataformat) {
$downloadusers = new ArrayObject($SESSION->bulk_users);
$iterator = $downloadusers->getIterator();
\core\dataformat::download_data($filename, $dataformat, $fields, $iterator, function($userid, $supportshtml)
use ($extrafields, $fields) {
\core\dataformat::download_data($filename, $dataformat, array_merge($originfields, $profilefields), $iterator,
function($userid, $supportshtml) use ($originfields) {
global $DB;
if (!$user = $DB->get_record('user', array('id' => $userid))) {
return null;
}
profile_load_data($user);
$userprofiledata = array();
foreach ($fields as $field => $unused) {
foreach ($originfields as $field) {
// Custom user profile textarea fields come in an array
// The first element is the text and the second is the format.
// We only take the text.
@@ -82,6 +86,19 @@ if ($dataformat) {
$userprofiledata[$field] = $user->$field;
}
}
// Formatting extra field if transform is true.
$extrafields = profile_get_user_fields_with_data($userid);
foreach ($extrafields as $field) {
$fieldkey = fields::PROFILE_FIELD_PREFIX . $field->get_shortname();
if ($field->is_transform_supported()) {
$userprofiledata[$fieldkey] = $field->display_data();
} else {
$userprofiledata[$fieldkey] = $field->data;
}
}
return $userprofiledata;
});
+3 -3
View File
@@ -18,7 +18,7 @@ Feature: User must accept policy when logging in and signing up
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
And I press "Create my new account"
And I should see "Confirm your account"
And I should see "An email should have been sent to your address at user1@address.invalid"
@@ -48,7 +48,7 @@ Feature: User must accept policy when logging in and signing up
| Email address | user1@address.invalid |
| Email (again) | user1@address.invalid |
| First name | User1 |
| Surname | L1 |
| Last name | L1 |
| I understand and agree | 1 |
And I press "Create my new account"
And I should see "Confirm your account"
@@ -81,7 +81,7 @@ Feature: User must accept policy when logging in and signing up
| Email address | <email1> |
| Email (again) | <email2> |
| First name | Jane |
| Surname | Doe |
| Last name | Doe |
And I press "Create my new account"
Then I should <expect> "This email address is already registered. Perhaps you created an account in the past?"
And I should <expect2> "Invalid email address"
+2 -2
View File
@@ -59,8 +59,8 @@ $string['privacy:metadata:mnet_external:institution'] = 'The institution that th
$string['privacy:metadata:mnet_external:lang'] = 'A user preference for the language shown.';
$string['privacy:metadata:mnet_external:lastaccess'] = 'The time that the user last accessed the site.';
$string['privacy:metadata:mnet_external:lastlogin'] = 'The last login of this user.';
$string['privacy:metadata:mnet_external:lastname'] = 'The surname of the user.';
$string['privacy:metadata:mnet_external:lastnamephonetic'] = 'The phonetic details about the user\'s surname.';
$string['privacy:metadata:mnet_external:lastname'] = 'The last name of the user.';
$string['privacy:metadata:mnet_external:lastnamephonetic'] = 'The phonetic details of the user\'s last name.';
$string['privacy:metadata:mnet_external:maildigest'] = 'A setting for the mail digest for this user.';
$string['privacy:metadata:mnet_external:maildisplay'] = 'A preference for the user about displaying their email address to other users.';
$string['privacy:metadata:mnet_external:middlename'] = 'The middle name of the user';
+2 -2
View File
@@ -86,7 +86,7 @@ Please log in as before, using the link on the login page.
{$a->admin}';
$string['emailpasswordchangeinfosubject'] = '{$a}: Change password information';
$string['info'] = 'External account';
$string['issuer'] = 'OAuth 2 Service';
$string['issuer'] = 'OAuth 2 service';
$string['issuernologin'] = 'This issuer can not be used to login';
$string['linkedlogins'] = 'Linked logins';
$string['linkedloginshelp'] = 'Help with linked logins';
@@ -95,7 +95,7 @@ $string['loginerror_nouserinfo'] = 'No user information was returned. The OAuth
$string['loginerror_invaliddomain'] = 'The email address is not allowed at this site.';
$string['loginerror_authenticationfailed'] = 'The authentication process failed.';
$string['loginerror_cannotcreateaccounts'] = 'An account with your email address could not be found.';
$string['noissuersavailable'] = 'None of the configured OAuth2 services allow you to link login accounts';
$string['noissuersavailable'] = 'None of the configured OAuth 2 services allow you to link login accounts.';
$string['notloggedindebug'] = 'The login attempt failed. Reason: {$a}';
$string['notwhileloggedinas'] = 'Linked logins cannot be managed while logged in as another user.';
$string['oauth2:managelinkedlogins'] = 'Manage own linked login accounts';
@@ -32,7 +32,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -58,7 +58,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -83,7 +83,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -112,7 +112,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -138,7 +138,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
Then the "Activity or resource" select box should not contain "Previous activity with completion"
# Set Page2 restriction to Previous Activity with completion and delete Page1.
@@ -148,7 +148,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -170,7 +170,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -184,7 +184,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed greyed-out if user does not meet this condition Click to hide" "link"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -34,11 +34,11 @@ $string['option_min'] = 'must be &#x2265;';
$string['option_max'] = 'must be <';
$string['pluginname'] = 'Restriction by grades';
$string['requires_any'] = 'You have a grade in <strong>{$a}</strong>';
$string['requires_max'] = 'You get an appropriate score in <strong>{$a}</strong>';
$string['requires_min'] = 'You achieve a required score in <strong>{$a}</strong>';
$string['requires_max'] = 'You achieve lower than a certain score in <strong>{$a}</strong>';
$string['requires_min'] = 'You achieve higher than a certain score in <strong>{$a}</strong>';
$string['requires_notany'] = 'You do not have a grade in <strong>{$a}</strong>';
$string['requires_notgeneral'] = 'You do not get certain scores in <strong>{$a}</strong>';
$string['requires_range'] = 'You get a particular score in <strong>{$a}</strong>';
$string['requires_range'] = 'You achieve a score within a certain range in <strong>{$a}</strong>';
$string['missing'] = '(missing activity)';
$string['title'] = 'Grade';
$string['privacy:metadata'] = 'The Restriction by grades plugin does not store any personal data.';
@@ -159,5 +159,5 @@ Feature: availability_grade
# Student sees information about no access to group, with group name in correct language.
When I am on the "C1" "Course" page logged in as "student1"
Then I should see "Not available unless: You achieve a required score in A-One"
Then I should see "Not available unless: You achieve higher than a certain score in A-One"
And I should not see "A-Un"
@@ -77,7 +77,7 @@ class condition_test extends \advanced_testcase {
$this->assertFalse($cond->is_available(false, $info, true, $user->id));
$information = $cond->get_description(false, false, $info);
$information = \core_availability\info::format_info($information, $course);
$this->assertMatchesRegularExpression('~achieve a required score.*Test!~', $information);
$this->assertMatchesRegularExpression('~achieve higher than.*Test!~', $information);
$this->assertTrue($cond->is_available(true, $info, true, $user->id));
// Min grade (success).
@@ -95,7 +95,7 @@ class condition_test extends \advanced_testcase {
$this->assertFalse($cond->is_available(false, $info, true, $user->id));
$information = $cond->get_description(false, false, $info);
$information = \core_availability\info::format_info($information, $course);
$this->assertMatchesRegularExpression('~get an appropriate score.*Test!~', $information);
$this->assertMatchesRegularExpression('~achieve lower than a certain score in.*Test!~', $information);
$this->assertTrue($cond->is_available(true, $info, true, $user->id));
// Max grade (success).
@@ -113,7 +113,7 @@ class condition_test extends \advanced_testcase {
$this->assertFalse($cond->is_available(false, $info, true, $user->id));
$information = $cond->get_description(false, false, $info);
$information = \core_availability\info::format_info($information, $course);
$this->assertMatchesRegularExpression('~get a particular score.*Test!~', $information);
$this->assertMatchesRegularExpression('~achieve a score within a certain range.*Test!~', $information);
$this->assertTrue($cond->is_available(true, $info, true, $user->id));
// Still fail (other end).
@@ -64,7 +64,7 @@ class frontend extends \core_availability\frontend {
global $DB;
if ($courseid != $this->allgroupingscourseid) {
$this->allgroupings = $DB->get_records('groupings',
array('courseid' => $courseid), 'id, name');
['courseid' => $courseid], 'name');
$this->allgroupingscourseid = $courseid;
}
return $this->allgroupings;
@@ -62,15 +62,10 @@ Feature: availability_profile
@javascript
Scenario: Test with custom user profile field
# Add custom field.
Given I log in as "admin"
And I navigate to "Users > Accounts > User profile fields" in site administration
And I click on "Create a new profile field" "link"
And I click on "Text input" "link"
And I set the following fields to these values:
| Short name | superfield |
| Name | Super field |
And I click on "Save changes" "button"
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | superfield | Super field |
And I log in as "admin"
# Set field value for user.
And I navigate to "Users > Accounts > Browse list of users" in site administration
@@ -86,13 +86,13 @@ Feature: edit_availability
And I should see "Date" in the "Restrict access" "fieldset"
And ".availability-item .availability-eye img" "css_element" should be visible
And ".availability-item .availability-delete img" "css_element" should be visible
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed greyed-out"
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed if student"
# Toggle the eye icon.
When I click on ".availability-item .availability-eye img" "css_element"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Hidden entirely"
When I click on ".availability-item .availability-eye img" "css_element"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed greyed-out"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed if student"
# Click the delete button.
When I click on ".availability-item .availability-delete img" "css_element"
+1 -1
View File
@@ -48,7 +48,7 @@ class backup_files_edit_form extends moodleform {
$mform->setType('component', PARAM_COMPONENT);
$mform->addElement('hidden', 'returnurl', $this->_customdata['returnurl']);
$mform->setType('returnurl', PARAM_URL);
$mform->setType('returnurl', PARAM_LOCALURL);
$this->add_action_buttons(true, get_string('savechanges'));
$this->set_data($this->_customdata['data']);
+26
View File
@@ -5261,6 +5261,7 @@ class restore_move_module_questions_categories extends restore_execution_step {
AND parentitemid = ?", array($this->get_restoreid(), $contextid));
$top = question_get_top_category($newcontext->newitemid, true);
$oldtopid = 0;
$categoryids = [];
foreach ($modulecats as $modulecat) {
// Before 3.5, question categories could be created at top level.
// From 3.5 onwards, all question categories should be a child of a special category called the "top" category.
@@ -5276,6 +5277,7 @@ class restore_move_module_questions_categories extends restore_execution_step {
$cat->parent = $top->id;
}
$DB->update_record('question_categories', $cat);
$categoryids[] = (int)$cat->id;
}
// And set new contextid (and maybe update newitemid) also in question_category mapping (will be
@@ -5284,6 +5286,30 @@ class restore_move_module_questions_categories extends restore_execution_step {
$modulecat->newitemid, $newcontext->newitemid);
}
// Update the context id of any tags applied to any questions in these categories.
if ($categoryids) {
[$categorysql, $categoryidparams] = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED);
$sqlupdate = "UPDATE {tag_instance}
SET contextid = :newcontext
WHERE component = :component
AND itemtype = :itemtype
AND itemid IN (SELECT DISTINCT bi.newitemid as questionid
FROM {backup_ids_temp} bi
JOIN {question} q ON q.id = bi.newitemid
JOIN {question_versions} qv ON qv.questionid = q.id
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
WHERE bi.backupid = :backupid AND bi.itemname = 'question_created'
AND qbe.questioncategoryid {$categorysql}) ";
$params = [
'newcontext' => $newcontext->newitemid,
'component' => 'core_question',
'itemtype' => 'question',
'backupid' => $this->get_restoreid(),
];
$params += $categoryidparams;
$DB->execute($sqlupdate, $params);
}
// Now set the parent id for the question categories that were in the top category in the course context
// and have been moved now.
if ($oldtopid) {
@@ -0,0 +1,24 @@
@core @core_backup
Feature: Backup and restore of the question that was tagged
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
@javascript @_file_upload
Scenario: Restore the quiz containing the question that was tagged
Given I am on the "Course 1" "restore" page logged in as "admin"
And I press "Manage backup files"
And I upload "backup/moodle2/tests/fixtures/test_tags_backup.mbz" file to "Files" filemanager
And I press "Save changes"
And I restore "test_tags_backup.mbz" backup into a new course using this options:
| Schema | Course name | Course 2 |
| Schema | Course short name | C2 |
When I am on the "TF1" "core_question > edit" page logged in as admin
And I expand all fieldsets
Then I should see "Tag1-TF1"
And I should see "Tag2-TF1"
And I am on the "TF2" "core_question > edit" page logged in as admin
And I expand all fieldsets
And I should see "Tag1-TF2"
Binary file not shown.
+7 -5
View File
@@ -1806,10 +1806,9 @@ abstract class restore_dbops {
public static function calculate_course_names($courseid, $fullname, $shortname) {
global $CFG, $DB;
$currentfullname = '';
$currentshortname = '';
$counter = 0;
// Iteratere while the name exists
// Iterate while fullname or shortname exist.
do {
if ($counter) {
$suffixfull = ' ' . get_string('copyasnoun') . ' ' . $counter;
@@ -1818,8 +1817,11 @@ abstract class restore_dbops {
$suffixfull = '';
$suffixshort = '';
}
$currentfullname = $fullname.$suffixfull;
$currentshortname = substr($shortname, 0, 100 - strlen($suffixshort)).$suffixshort; // < 100cc
// Ensure we don't overflow maximum length of name fields, in multi-byte safe manner.
$currentfullname = core_text::substr($fullname, 0, 254 - strlen($suffixfull)) . $suffixfull;
$currentshortname = core_text::substr($shortname, 0, 100 - strlen($suffixshort)) . $suffixshort;
$coursefull = $DB->get_record_select('course', 'fullname = ? AND id != ?',
array($currentfullname, $courseid), '*', IGNORE_MULTIPLE);
$courseshort = $DB->get_record_select('course', 'shortname = ? AND id != ?', array($currentshortname, $courseid));
+16 -1
View File
@@ -96,6 +96,21 @@ class async_helper {
return $user;
}
/**
* Return appropriate description for current async operation {@see async_helper::type}
*
* @return string
*/
private function get_operation_description(): string {
$operations = [
'backup' => new lang_string('backup'),
'copy' => new lang_string('copycourse'),
'restore' => new lang_string('restore'),
];
return (string) ($operations[$this->type] ?? $this->type);
}
/**
* Callback for preg_replace_callback.
* Replaces message placeholders with real values.
@@ -105,7 +120,7 @@ class async_helper {
*/
private function lookup_message_variables($matches) {
$options = array(
'operation' => $this->type,
'operation' => $this->get_operation_description(),
'backupid' => $this->backupid,
'user_username' => $this->user->username,
'user_email' => $this->user->email,
+11 -8
View File
@@ -30,6 +30,7 @@ require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
* Asyncronhous helper tests.
*
* @package core_backup
* @covers \async_helper
* @copyright 2018 Matt Porritt <mattp@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -47,7 +48,7 @@ class async_helper_test extends \advanced_testcase {
set_config('backup_async_message_users', '1', 'backup');
set_config('backup_async_message_subject', 'Moodle {operation} completed sucessfully', 'backup');
set_config('backup_async_message',
'Dear {user_firstname} {user_lastname}, <br/> Your {operation} (ID: {backupid}) has completed successfully!',
'Dear {user_firstname} {user_lastname}, your {operation} (ID: {backupid}) has completed successfully!',
'backup');
set_config('allowedemaildomains', 'example.com');
@@ -76,15 +77,17 @@ class async_helper_test extends \advanced_testcase {
$this->assertCount(1, $emails);
$email = reset($emails);
$this->assertSame($USER->email, $email->from);
$this->assertSame($user2->email, $email->to);
$this->assertSame('Moodle backup completed sucessfully', $email->subject);
$this->assertNotEmpty($email->header);
$this->assertNotEmpty($email->body);
$this->assertMatchesRegularExpression("/$backupid/", $email->body);
$this->assertThat($email->body, $this->logicalNot($this->stringContains('{')));
$this->assertGreaterThan(0, $messageid);
$sink->clear();
$this->assertSame($USER->email, $email->from);
$this->assertSame($user2->email, $email->to);
$this->assertSame('Moodle Backup completed sucessfully', $email->subject);
// Assert body placeholders have all been replaced.
$this->assertStringContainsString('Dear test human, your Backup', $email->body);
$this->assertStringContainsString("(ID: {$backupid})", $email->body);
$this->assertStringNotContainsString('{', $email->body);
}
/**
@@ -130,7 +130,6 @@ Feature: The my overview block allows users to easily access their courses
Scenario: View favourite courses - w/ persistence
Given I am on the "My courses" page logged in as "student1"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All" "button" in the "Course overview" "block"
@@ -201,7 +200,6 @@ Feature: The my overview block allows users to easily access their courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "In progress" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I reload the page
@@ -215,7 +213,6 @@ Feature: The my overview block allows users to easily access their courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "Past" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 1')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 1')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 1')]" "xpath_element"
And I reload the page
@@ -229,7 +226,6 @@ Feature: The my overview block allows users to easily access their courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "Future" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I reload the page
@@ -243,7 +239,6 @@ Feature: The my overview block allows users to easily access their courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I reload the page
@@ -261,7 +256,6 @@ Feature: The my overview block allows users to easily access their courses
And I click on "All" "button" in the "Course overview" "block"
# We have to click on the data attribute instead of the button element text as we might risk to click on the false positive "All (including removed from view)" element instead
When I click on "[data-value='allincludinghidden']" "css_element" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I reload the page
@@ -25,7 +25,6 @@ Feature: The my overview block allows users to favourite their courses
Scenario: Favourite a course on a course card
Given I am on the "My courses" page logged in as "student1"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I reload the page
@@ -36,7 +35,6 @@ Feature: The my overview block allows users to favourite their courses
Scenario: Star a course and switch display to list
Given I am on the "My courses" page logged in as "student1"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
@@ -48,7 +46,6 @@ Feature: The my overview block allows users to favourite their courses
Scenario: Star a course and switch display to summary
Given I am on the "My courses" page logged in as "student1"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 5')]" "xpath_element"
And I click on "Display drop-down menu" "button" in the "Course overview" "block"
@@ -27,7 +27,6 @@ Feature: The my overview block allows users to hide their courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I reload the page
@@ -36,33 +35,29 @@ Feature: The my overview block allows users to hide their courses
Scenario: Test hide toggle functionality w/ favorites
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All" "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 "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
When I reload the page
Then I should not see "Course 2" in the "Course overview" "block"
And I should not see "Course 2" in the "Course overview" "block"
And I click on "All" "button" in the "Course overview" "block"
And I click on "Starred" "link" in the "Course overview" "block"
Then I should not see "Course 2" in the "Course overview" "block"
And I click on "Starred" "button" in the "Course overview" "block"
And I click on "Removed from view" "link" in the "Course overview" "block"
Then I should see "Course 2" in the "Course overview" "block"
And I should see "Course 2" in the "Course overview" "block"
Scenario: Test show toggle functionality
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All" "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 "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
When I click on "All" "button" in the "Course overview" "block"
And I click on "All" "button" in the "Course overview" "block"
And I click on "Removed from view" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
When I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
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 click on "Removed from view" "button" in the "Course overview" "block"
@@ -72,33 +67,29 @@ Feature: The my overview block allows users to hide their courses
Scenario: Test show toggle functionality w/ favorites
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All" "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 "Star this course" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "All" "button" in the "Course overview" "block"
And I click on "Removed from view" "link" in the "Course overview" "block"
And I should see "Course 2" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
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"
When I reload the page
Then I should not see "Course 2" in the "Course overview" "block"
And I click on "Removed from view" "button" in the "Course overview" "block"
And I click on "All" "link" in the "Course overview" "block"
Then I should see "Course 2" in the "Course overview" "block"
And I should see "Course 2" in the "Course overview" "block"
And I click on "All" "button" in the "Course overview" "block"
And I click on "Starred" "link" in the "Course overview" "block"
Then I should see "Course 2" in the "Course overview" "block"
And I should see "Course 2" in the "Course overview" "block"
Scenario: Test a course is hidden directly with "All" courses
Given I am on the "My courses" page logged in as "student1"
And I click on "All" "button" in the "Course overview" "block"
When I click on "All" "link" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
Then I should not see "Course 2" in the "Course overview" "block"
@@ -111,17 +102,14 @@ Feature: The my overview block allows users to hide their courses
And I click on "All" "button" in the "Course overview" "block"
# We have to click on the data attribute instead of the button element text as we might risk to click on the false positive "All (except hidden)" element instead
When I click on "[data-value='allincludinghidden']" "css_element" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on "Remove from view" "link" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
Then I should see "Course 2" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I click on ".coursemenubtn" "css_element" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I should not see "Remove from view" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I should see "Restore to view" 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"
Then I should see "Course 2" in the "Course overview" "block"
And I hover "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I should see "Course 2" 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 should see "Remove from view" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
And I should not see "Restore to view" in the "//div[@class='card dashboard-card' and contains(.,'Course 2')]" "xpath_element"
+17 -2
View File
@@ -22,9 +22,12 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
define('FLICKR_DEV_KEY', '4fddbdd7ff2376beec54d7f6afad425e');
define('DEFAULT_NUMBER_OF_PHOTOS', 6);
require_once("{$CFG->libdir}/flickrclient.php");
class block_tag_flickr extends block_base {
function init() {
@@ -102,7 +105,11 @@ class block_tag_flickr extends block_base {
$response = $this->fetch_request($request);
$search = unserialize($response);
$search = @unserialize($response);
if ($search === false && $search != serialize(false)) {
// The response didn't appear to be anything serialized, exit...
return;
}
foreach ($search['photoset']['photo'] as $p){
$p['owner'] = $search['photoset']['owner'];
@@ -123,7 +130,11 @@ class block_tag_flickr extends block_base {
$response = $this->fetch_request($request);
$search = unserialize($response);
$search = @unserialize($response);
if ($search === false && $search != serialize(false)) {
// The response didn't appear to be anything serialized, exit...
return;
}
$photos = array_values($search['photos']['photo']);
}
@@ -147,6 +158,10 @@ class block_tag_flickr extends block_base {
function fetch_request($request){
$c = new curl(array('cache' => true, 'module_cache'=> 'tag_flickr'));
// Set custom user agent as Flickr blocks our "MoodleBot" agent string.
$c->setopt([
'CURLOPT_USERAGENT' => flickr_client::user_agent(),
]);
$response = $c->get($request);
@@ -4,20 +4,36 @@ Feature: Adding and configuring Flickr block
As a admin
I need to add the Flickr block to the tags site page
@javascript
Scenario: Adding Flickr block to the tags site page
Given I log in as "admin"
Background:
# We need to create a user to use tag here because the tags site page only shows the tag that currently being used.
Given the following "users" exist:
| username | interests |
| student1 | Cats |
And I log in as "admin"
And I turn editing mode on
And the following config values are set as admin:
| unaddableblocks | | theme_boost|
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| tag_flickr | System | 1 | tag-search | side-post |
| tag_flickr | System | 1 | tag-index | side-post |
# TODO MDL-57120 site "Tags" link not accessible without navigation block.
And I add the "Navigation" block if not present
And I click on "Site pages" "list_item" in the "Navigation" "block"
And I click on "Tags" "link" in the "Navigation" "block"
And I add the "Flickr" block
And I configure the "Flickr" block
@javascript
Scenario: Adding Flickr block to the tags site page
Given "block_tag_flickr" "block" should exist
When I configure the "Flickr" block
Then I should see "Flickr block title"
And I set the field "Flickr block title" to "The Flickr block header"
And I press "Save changes"
And "block_tag_flickr" "block" should exist
Then "The Flickr block header" "block" should exist
And "The Flickr block header" "block" should exist
@javascript
Scenario: Adding Flickr block to a specific tag page
Given I click on "Cats" "link"
Then "block_tag_flickr" "block" should exist
And ".flickr-photos" "css_element" should exist in the "block_tag_flickr" "block"
+5 -12
View File
@@ -15,25 +15,18 @@ Feature: Block appearances
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activities" exist:
| activity | name | description | course | idnumber | section |
| survey | Test survey name | Test survey description | C1 | survey1 | 1 |
| book | Test book name | Test book description | C1 | book1 | 1 |
| activity | name | description | course | idnumber | section | template |
| survey | Test survey name | | C1 | survey1 | 1 | 4 |
| book | Test book name | Test book description | C1 | book1 | 1 | |
And I log in as "admin"
And I am on "Course 1" course homepage
And I click on "Test survey name" "link" in the "region-main" "region"
And I navigate to "Settings" in current page administration
And I set the following fields to these values:
| Survey type | ATTLS (20 item version) |
And I press "Save and return to course"
And I am on "Course 1" course homepage with editing mode on
And I click on "Test book name" "link" in the "region-main" "region"
And I set the following fields to these values:
| Chapter title | Book title |
| Content | Book content test test |
And I press "Save changes"
And I log out
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I am on the "Course 1" course page logged in as teacher1
And I turn editing mode on
And I add the "Comments" block
And I configure the "Comments" block
And I set the following fields to these values:
+3 -4
View File
@@ -14,12 +14,11 @@ Feature: Block region moving
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "activities" exist:
| activity | course | name | template |
| survey | C1 | Test survey name | 4 |
And I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
And I add a "Survey" to section "1" and I fill the form with:
| Name | Test survey name |
| Survey type | ATTLS (20 item version) |
| Description | Test survey description |
And I add a "Book" to section "1" and I fill the form with:
| Name | Test book name |
| Description | Test book description |
@@ -40,7 +40,8 @@
"icon": {
"key": "icon",
"component": "mod_assign",
"alttext": "Assignment icon"
"alttext": "Assignment icon",
"iconurl": "#"
},
"overdue": false,
"purpose": "assessment"
@@ -54,7 +55,14 @@
{{#userdate}} {{timesort}}, {{#str}} strftimetime24, core_langconfig {{/str}} {{/userdate}}
</small>
<div class="activityiconcontainer small {{purpose}} courseicon align-self-top align-self-center mx-3 mb-1 mb-sm-0 text-nowrap">
{{#icon}}{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}{{/icon}}
{{#icon}}
{{#iconurl}}
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon ">
{{/iconurl}}
{{^iconurl}}
{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}
{{/iconurl}}
{{/icon}}
</div>
<div class="event-name-container flex-grow-1 line-height-3 nowrap text-truncate">
<div class="d-flex">
@@ -71,7 +79,7 @@
{{activitystr}}
{{/courseview}}
{{^courseview}}
{{#course.fullnamedisplay}}{{{course.fullnamedisplay}}} &middot; {{/course.fullnamedisplay}}{{activitystr}}
{{activitystr}}{{#course.fullnamedisplay}} &middot; {{{course.fullnamedisplay}}}{{/course.fullnamedisplay}}
{{/courseview}}
</small>
</div>
@@ -39,23 +39,23 @@ Feature: The timeline block allows users to see upcoming activities
And I click on "Filter timeline by date" "button" in the "Timeline" "block"
When I click on "Next 7 days" "link" in the "Timeline" "block"
Then "Test choice 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Choice closes" in the "Timeline" "block"
And I should see "Choice closes · Course 2" in the "Timeline" "block"
And "Test feedback 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 2" in the "Timeline" "block"
And "Test assign 2" "link" should exist in the "Timeline" "block"
And "Test feedback 4" "link" should exist in the "Timeline" "block"
And "Test choice 2" "link" should not exist in the "Timeline" "block"
And "Test choice 3" "link" should not exist in the "Timeline" "block"
And "Test feedback 3" "link" should not exist in the "Timeline" "block"
And "Test assign 1" "link" should not exist in the "Timeline" "block"
And I should not see "Course 1 · Assignment is due" in the "Timeline" "block"
And I should not see "Assignment is due · Course 1" in the "Timeline" "block"
Scenario: Overdue in date view
Given I log in as "student1"
And I click on "Filter timeline by date" "button" in the "Timeline" "block"
When I click on "Overdue" "link" in the "Timeline" "block"
Then "Test assign 1" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 1" in the "Timeline" "block"
And "Test assign 2" "link" should exist in the "Timeline" "block"
And "Test choice 2" "link" should not exist in the "Timeline" "block"
And "Test feedback 1" "link" should not exist in the "Timeline" "block"
@@ -69,20 +69,20 @@ Feature: The timeline block allows users to see upcoming activities
And I click on "Filter timeline by date" "button" in the "Timeline" "block"
When I click on "All" "link" in the "Timeline" "block"
Then "Test assign 1" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 1" in the "Timeline" "block"
And "Test assign 2" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 2" in the "Timeline" "block"
And "Test feedback 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 2" in the "Timeline" "block"
And "Test choice 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Choice closes" in the "Timeline" "block"
And I should see "Choice closes · Course 2" in the "Timeline" "block"
And "Test feedback 4" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 2" in the "Timeline" "block"
And "Test choice 2" "link" should not exist in the "Timeline" "block"
And "Test feedback 2" "link" should not exist in the "Timeline" "block"
And I click on "Show more activities" "button"
And "Test feedback 2" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 1" in the "Timeline" "block"
And "Test choice 3" "link" should exist in the "Timeline" "block"
And I should see "Test assign 1" in the "Timeline" "block"
And I should see "Test feedback 1" in the "Timeline" "block"
@@ -97,20 +97,20 @@ Feature: The timeline block allows users to see upcoming activities
When I click on "All" "link" in the "Timeline" "block"
And I reload the page
Then "Test assign 1" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 1" in the "Timeline" "block"
And "Test assign 2" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 2" in the "Timeline" "block"
And "Test feedback 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 2" in the "Timeline" "block"
And "Test choice 1" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Choice closes" in the "Timeline" "block"
And I should see "Choice closes · Course 2" in the "Timeline" "block"
And "Test feedback 4" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 2" in the "Timeline" "block"
And I should not see "Test choice 2" in the "Timeline" "block"
And I should not see "Test feedback 2" in the "Timeline" "block"
And I click on "Show more activities" "button"
And "Test feedback 2" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Feedback closes" in the "Timeline" "block"
And I should see "Feedback closes · Course 1" in the "Timeline" "block"
And I should see "Test assign 1" in the "Timeline" "block"
And I should see "Test feedback 1" in the "Timeline" "block"
And I should see "Test feedback 3" in the "Timeline" "block"
@@ -124,9 +124,9 @@ Feature: The timeline block allows users to see upcoming activities
When I click on "Overdue" "link" in the "Timeline" "block"
And I reload the page
Then "Test assign 1" "link" should exist in the "Timeline" "block"
And I should see "Course 1 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 1" in the "Timeline" "block"
And "Test assign 2" "link" should exist in the "Timeline" "block"
And I should see "Course 2 · Assignment is due" in the "Timeline" "block"
And I should see "Assignment is due · Course 2" in the "Timeline" "block"
And "Test feedback 1" "link" should not exist in the "Timeline" "block"
And "Test feedback 3" "link" should not exist in the "Timeline" "block"
And "Test feedback 4" "link" should not exist in the "Timeline" "block"
+1 -1
View File
@@ -64,7 +64,7 @@ class blog_edit_external_form extends moodleform {
$mform->setDefault('id', 0);
$mform->addElement('hidden', 'returnurl');
$mform->setType('returnurl', PARAM_URL);
$mform->setType('returnurl', PARAM_LOCALURL);
$mform->setDefault('returnurl', 0);
}
+1 -1
View File
@@ -903,7 +903,7 @@ function blog_get_headers($courseid=null, $groupid=null, $userid=null, $tagid=nu
if (!empty($search) && has_capability('moodle/blog:search', $sitecontext)) {
$headers['filters']['search'] = $search;
$blogurl->param('search', $search);
$PAGE->navbar->add(get_string('searchterm', 'blog', $search), $blogurl->out());
$PAGE->navbar->add(get_string('searchterm', 'blog', s($search)), $blogurl->out());
}
}
+4
View File
@@ -440,6 +440,10 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
* @return int The number of keys successfully deleted.
*/
public function delete_many(array $keys) {
// If there are no keys to delete, do nothing.
if (!$keys) {
return 0;
}
$count = $this->redis->hDel($this->hash, ...$keys);
if ($this->definition->get_ttl()) {
// When TTL is enabled, also remove the keys from the TTL list.
+59 -4
View File
@@ -34,6 +34,7 @@ require_once(__DIR__.'/../lib.php');
* define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');
*
* @package cachestore_redis
* @covers \cachestore_redis
* @copyright Copyright (c) 2015 Moodlerooms Inc. (http://www.moodlerooms.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -70,13 +71,28 @@ class store_test extends \cachestore_tests {
* Creates the required cachestore for the tests to run against Redis.
*
* @param array $extraconfig Extra configuration options for Redis instance, if any
* @param bool $ttl True to use a cache definition with TTL enabled
* @return cachestore_redis
*/
protected function create_cachestore_redis(array $extraconfig = []): cachestore_redis {
/** @var cache_definition $definition */
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_redis', 'phpunit_test');
protected function create_cachestore_redis(array $extraconfig = [], bool $ttl = false): cachestore_redis {
if ($ttl) {
/** @var cache_definition $definition */
$definition = cache_definition::load('core/wibble', [
'mode' => 1,
'simplekeys' => true,
'simpledata' => true,
'ttl' => 10,
'component' => 'core',
'area' => 'wibble',
'selectedsharingoption' => 2,
'userinputsharingkey' => '',
'sharingoptions' => 15,
]);
} else {
/** @var cache_definition $definition */
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_redis', 'phpunit_test');
}
$configuration = array_merge(cachestore_redis::unit_test_configuration(), $extraconfig);
$store = new cachestore_redis('Test', $configuration);
$store->initialise($definition);
@@ -165,4 +181,43 @@ class store_test extends \cachestore_tests {
]);
$this->assertEquals(111, $store->get_last_io_bytes());
}
/**
* Data provider for whether cache uses TTL or not.
*
* @return array Array with true and false options
*/
public static function ttl_or_not(): array {
return [
[false],
[true]
];
}
/**
* Tests the delete_many function.
*
* The behaviour is different with TTL enabled so we need to test with that kind of definition
* as well as a 'normal' one.
*
* @param bool $ttl True to test using a TTL definition
* @dataProvider ttl_or_not
*/
public function test_delete_many(bool $ttl): void {
$store = $this->create_cachestore_redis([], $ttl);
// Check it works to delete selected items.
$store->set('foo', 'frog');
$store->set('bar', 'amphibian');
$store->set('hmm', 'undead');
$this->store->delete_many(['foo', 'bar']);
$this->assertFalse($store->get('foo'));
$this->assertFalse($store->get('bar'));
$this->assertEquals('undead', $store->get('hmm'));
// If called with no keys it should do nothing.
$store->delete_many([]);
$this->assertEquals('undead', $store->get('hmm'));
}
}
+1 -1
View File
@@ -5,6 +5,6 @@
* @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/crud",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending"],(function($,Str,Notification,CustomEvents,Modal,ModalRegistry,ModalFactory,ModalEvents,ModalEventForm,CalendarRepository,CalendarEvents,ModalDelete,CalendarSelectors,Pending){return{registerRemove:function(root){root.on("click",CalendarSelectors.actions.remove,(function(e){var eventSource=$(this).closest(CalendarSelectors.eventItem);!function(eventId,eventTitle,eventCount){var deletePromise,pendingPromise=new Pending("core_calendar/crud:confirmDeletion"),deleteStrings=[{key:"deleteevent",component:"calendar"}],isRepeatedEvent=(eventCount=parseInt(eventCount,10))>1;isRepeatedEvent?(deleteStrings.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:eventTitle,count:eventCount}}),deletePromise=ModalFactory.create({type:ModalDelete.TYPE})):(deleteStrings.push({key:"confirmeventdelete",component:"calendar",param:eventTitle}),deletePromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}));var stringsPromise=Str.get_strings(deleteStrings);$.when(stringsPromise,deletePromise).then((function(strings,deleteModal){return deleteModal.setRemoveOnClose(!0),deleteModal.setTitle(strings[0]),deleteModal.setBody(strings[1]),isRepeatedEvent||deleteModal.setSaveButtonText(strings[0]),deleteModal.show(),deleteModal.getRoot().on(ModalEvents.save,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedevent");CalendarRepository.deleteEvent(eventId,!1).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!1])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal.getRoot().on(CalendarEvents.deleteAll,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedallevent");CalendarRepository.deleteEvent(eventId,!0).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!0])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)}(eventSource.data("eventId"),eventSource.data("eventTitle"),eventSource.data("eventCount")),e.preventDefault()}))},registerEditListeners:function(root,eventFormModalPromise){var pendingPromise=new Pending("core_calendar/crud:registerEditListeners");return eventFormModalPromise.then((function(modal){return $("body").on(CalendarEvents.editEvent,(function(e,eventId){var calendarWrapper=root.find(CalendarSelectors.wrapper);modal.setEventId(eventId),modal.setContextId(calendarWrapper.data("contextId")),modal.show(),e.stopImmediatePropagation()})),modal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)},registerEventFormModal:function(root){var eventFormPromise=ModalFactory.create({type:ModalEventForm.TYPE,large:!0});return root.on("click",CalendarSelectors.actions.create,(function(e){eventFormPromise.then((function(modal){var wrapper=root.find(CalendarSelectors.wrapper),categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId);var today=root.find(CalendarSelectors.today),firstDay=root.find(CalendarSelectors.day);!today.length&&firstDay.length&&modal.setStartTime(firstDay.data("newEventTimestamp")),modal.setContextId(wrapper.data("contextId")),modal.setCourseId(wrapper.data("courseid")),modal.show()})).fail(Notification.exception),e.preventDefault()})),root.on("click",CalendarSelectors.actions.edit,(function(e){e.preventDefault();var target=$(e.currentTarget),calendarWrapper=target.closest(CalendarSelectors.wrapper),eventWrapper=target.closest(CalendarSelectors.eventItem);eventFormPromise.then((function(modal){modal.setEventId(eventWrapper.data("eventId")),modal.setContextId(calendarWrapper.data("contextId")),modal.setCourseId(eventWrapper.data("courseId")),modal.show(),e.stopImmediatePropagation()})).fail(Notification.exception)})),eventFormPromise}}}));
define("core_calendar/crud",["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending"],(function($,Str,Notification,CustomEvents,Modal,ModalRegistry,ModalFactory,ModalEvents,ModalEventForm,CalendarRepository,CalendarEvents,ModalDelete,CalendarSelectors,Pending){return{registerRemove:function(root){root.on("click",CalendarSelectors.actions.remove,(function(e){var eventSource=$(this).closest(CalendarSelectors.eventItem);!function(eventId,eventTitle,eventCount){var deletePromise,pendingPromise=new Pending("core_calendar/crud:confirmDeletion"),deleteStrings=[{key:"deleteevent",component:"calendar"}],isRepeatedEvent=(eventCount=parseInt(eventCount,10))>1;isRepeatedEvent?(deleteStrings.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:eventTitle,count:eventCount}}),deletePromise=ModalFactory.create({type:ModalDelete.TYPE})):(deleteStrings.push({key:"confirmeventdelete",component:"calendar",param:eventTitle}),deletePromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}));var stringsPromise=Str.get_strings(deleteStrings);$.when(stringsPromise,deletePromise).then((function(strings,deleteModal){return deleteModal.setRemoveOnClose(!0),deleteModal.setTitle(strings[0]),deleteModal.setBody(strings[1]),isRepeatedEvent||deleteModal.setSaveButtonText(strings[0]),deleteModal.show(),deleteModal.getRoot().on(ModalEvents.save,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedevent");CalendarRepository.deleteEvent(eventId,!1).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!1])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal.getRoot().on(CalendarEvents.deleteAll,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedallevent");CalendarRepository.deleteEvent(eventId,!0).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!0])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)}(eventSource.data("eventId"),eventSource.data("eventTitle"),eventSource.data("eventCount")),e.preventDefault()}))},registerEditListeners:function(root,eventFormModalPromise){var pendingPromise=new Pending("core_calendar/crud:registerEditListeners");return eventFormModalPromise.then((function(modal){return $("body").on(CalendarEvents.editEvent,(function(e,eventId){var target=root.find("[data-event-id=".concat(eventId,"]")),calendarWrapper=root.find(CalendarSelectors.wrapper);modal.setEventId(eventId),modal.setContextId(calendarWrapper.data("contextId")),modal.setReturnElement(target),modal.show(),e.stopImmediatePropagation()})),modal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)},registerEventFormModal:function(root){var eventFormPromise=ModalFactory.create({type:ModalEventForm.TYPE,large:!0});return root.on("click",CalendarSelectors.actions.create,(function(e){eventFormPromise.then((function(modal){var wrapper=root.find(CalendarSelectors.wrapper),categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId);var today=root.find(CalendarSelectors.today),firstDay=root.find(CalendarSelectors.day);!today.length&&firstDay.length&&modal.setStartTime(firstDay.data("newEventTimestamp")),modal.setContextId(wrapper.data("contextId")),modal.setCourseId(wrapper.data("courseid")),modal.show()})).fail(Notification.exception),e.preventDefault()})),root.on("click",CalendarSelectors.actions.edit,(function(e){e.preventDefault();var target=$(e.currentTarget),calendarWrapper=target.closest(CalendarSelectors.wrapper),eventWrapper=target.closest(CalendarSelectors.eventItem);eventFormPromise.then((function(modal){modal.setEventId(eventWrapper.data("eventId")),modal.setContextId(calendarWrapper.data("contextId")),modal.setCourseId(eventWrapper.data("courseId")),modal.show(),e.stopImmediatePropagation()})).fail(Notification.exception)})),eventFormPromise}}}));
//# sourceMappingURL=crud.min.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -5,6 +5,6 @@
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/event_form",["jquery","core_calendar/repository"],(function($,CalendarRepository){var SELECTORS_EVENT_GROUP_COURSE_ID='[name="groupcourseid"]',SELECTORS_EVENT_GROUP_ID='[name="groupid"]',SELECTORS_SELECT_OPTION="option",addCourseGroupSelectListeners=function(formElement){var courseGroupSelect=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID);courseGroupSelect.on("change",(function(){var courseId=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID).val();CalendarRepository.getCourseGroupsData(courseId).then((function(groups){return function(groups){var groupSelect=formElement.find(SELECTORS_EVENT_GROUP_ID),groupSelectOptions=groupSelect.find(SELECTORS_SELECT_OPTION),courseGroups=$(groups);groupSelectOptions.remove(),groupSelect.prop("disabled",!1),courseGroups.each((function(id,group){$(groupSelect).append($("<option></option>").attr("value",group.id).text(group.name))}))}(groups)})).catch(Notification.exception)}))};return{init:function(formId){var formElement=$("#"+formId);addCourseGroupSelectListeners(formElement)}}}));
define("core_calendar/event_form",["jquery","core_calendar/repository","core/notification"],(function($,CalendarRepository,Notification){var SELECTORS_EVENT_GROUP_COURSE_ID='[name="groupcourseid"]',SELECTORS_EVENT_GROUP_ID='[name="groupid"]',SELECTORS_SELECT_OPTION="option",addCourseGroupSelectListeners=function(formElement){var courseGroupSelect=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID);courseGroupSelect.on("change",(function(){var courseId=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID).val();CalendarRepository.getCourseGroupsData(courseId).then((function(groups){return function(groups){var groupSelect=formElement.find(SELECTORS_EVENT_GROUP_ID),groupSelectOptions=groupSelect.find(SELECTORS_SELECT_OPTION),courseGroups=$(groups);groupSelectOptions.remove(),groupSelect.prop("disabled",!1),courseGroups.each((function(id,group){$(groupSelect).append($("<option></option>").attr("value",group.id).text(group.name))}))}(groups)})).catch(Notification.exception)}))};return{init:function(formId){var formElement=$("#"+formId);addCourseGroupSelectListeners(formElement)}}}));
//# sourceMappingURL=event_form.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"event_form.min.js","sources":["../src/event_form.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to enhance the event form.\n *\n * @module core_calendar/event_form\n * @copyright 2017 Ryan Wyllie <ryan@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core_calendar/repository'], function($, CalendarRepository) {\n\n var SELECTORS = {\n EVENT_GROUP_COURSE_ID: '[name=\"groupcourseid\"]',\n EVENT_GROUP_ID: '[name=\"groupid\"]',\n SELECT_OPTION: 'option'\n };\n\n /**\n * Listen for when the user changes the group course when configuring\n * a group event and filter the options in the group select to only\n * show the groups available within the course the user has selected.\n *\n * @method addCourseGroupSelectListeners\n * @param {object} formElement The root form element\n */\n var addCourseGroupSelectListeners = function(formElement) {\n var courseGroupSelect = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID);\n\n var loadGroupSelectOptions = function(groups) {\n var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID),\n groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION),\n courseGroups = $(groups);\n\n // Let's clear all options first.\n groupSelectOptions.remove();\n groupSelect.prop(\"disabled\", false);\n courseGroups.each(function(id, group) {\n $(groupSelect).append($(\"<option></option>\").attr(\"value\", group.id).text(group.name));\n });\n };\n\n // If the user choose a course in the selector do a WS request to get groups.\n courseGroupSelect.on('change', function() {\n var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();\n CalendarRepository.getCourseGroupsData(courseId)\n .then(function(groups) {\n return loadGroupSelectOptions(groups);\n })\n .catch(Notification.exception);\n });\n };\n\n /**\n * Initialise all of the form enhancements.\n *\n * @method init\n * @param {string} formId The value of the form's id attribute\n */\n var init = function(formId) {\n var formElement = $('#' + formId);\n addCourseGroupSelectListeners(formElement);\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CalendarRepository","SELECTORS","addCourseGroupSelectListeners","formElement","courseGroupSelect","find","on","courseId","val","getCourseGroupsData","then","groups","groupSelect","groupSelectOptions","courseGroups","remove","prop","each","id","group","append","attr","text","name","loadGroupSelectOptions","catch","Notification","exception","init","formId"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,6BAA6B,SAASC,EAAGC,wBAEnDC,gCACuB,yBADvBA,yBAEgB,mBAFhBA,wBAGe,SAWfC,8BAAgC,SAASC,iBACrCC,kBAAoBD,YAAYE,KAAKJ,iCAgBzCG,kBAAkBE,GAAG,UAAU,eACvBC,SAAWJ,YAAYE,KAAKJ,iCAAiCO,MACjER,mBAAmBS,oBAAoBF,UAClCG,MAAK,SAASC,eAjBM,SAASA,YAC9BC,YAAcT,YAAYE,KAAKJ,0BAC/BY,mBAAqBD,YAAYP,KAAKJ,yBACtCa,aAAef,EAAEY,QAGrBE,mBAAmBE,SACnBH,YAAYI,KAAK,YAAY,GAC7BF,aAAaG,MAAK,SAASC,GAAIC,OAC3BpB,EAAEa,aAAaQ,OAAOrB,EAAE,qBAAqBsB,KAAK,QAASF,MAAMD,IAAII,KAAKH,MAAMI,UASrEC,CAAuBb,WAEjCc,MAAMC,aAAaC,qBAezB,CACHC,KANO,SAASC,YACZ1B,YAAcJ,EAAE,IAAM8B,QAC1B3B,8BAA8BC"}
{"version":3,"file":"event_form.min.js","sources":["../src/event_form.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * A javascript module to enhance the event form.\n *\n * @module core_calendar/event_form\n * @copyright 2017 Ryan Wyllie <ryan@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core_calendar/repository', 'core/notification'], function($, CalendarRepository, Notification) {\n\n var SELECTORS = {\n EVENT_GROUP_COURSE_ID: '[name=\"groupcourseid\"]',\n EVENT_GROUP_ID: '[name=\"groupid\"]',\n SELECT_OPTION: 'option'\n };\n\n /**\n * Listen for when the user changes the group course when configuring\n * a group event and filter the options in the group select to only\n * show the groups available within the course the user has selected.\n *\n * @method addCourseGroupSelectListeners\n * @param {object} formElement The root form element\n */\n var addCourseGroupSelectListeners = function(formElement) {\n var courseGroupSelect = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID);\n\n var loadGroupSelectOptions = function(groups) {\n var groupSelect = formElement.find(SELECTORS.EVENT_GROUP_ID),\n groupSelectOptions = groupSelect.find(SELECTORS.SELECT_OPTION),\n courseGroups = $(groups);\n\n // Let's clear all options first.\n groupSelectOptions.remove();\n groupSelect.prop(\"disabled\", false);\n courseGroups.each(function(id, group) {\n $(groupSelect).append($(\"<option></option>\").attr(\"value\", group.id).text(group.name));\n });\n };\n\n // If the user choose a course in the selector do a WS request to get groups.\n courseGroupSelect.on('change', function() {\n var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();\n CalendarRepository.getCourseGroupsData(courseId)\n .then(function(groups) {\n return loadGroupSelectOptions(groups);\n })\n .catch(Notification.exception);\n });\n };\n\n /**\n * Initialise all of the form enhancements.\n *\n * @method init\n * @param {string} formId The value of the form's id attribute\n */\n var init = function(formId) {\n var formElement = $('#' + formId);\n addCourseGroupSelectListeners(formElement);\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CalendarRepository","Notification","SELECTORS","addCourseGroupSelectListeners","formElement","courseGroupSelect","find","on","courseId","val","getCourseGroupsData","then","groups","groupSelect","groupSelectOptions","courseGroups","remove","prop","each","id","group","append","attr","text","name","loadGroupSelectOptions","catch","exception","init","formId"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,2BAA4B,sBAAsB,SAASC,EAAGC,mBAAoBC,kBAE5FC,gCACuB,yBADvBA,yBAEgB,mBAFhBA,wBAGe,SAWfC,8BAAgC,SAASC,iBACrCC,kBAAoBD,YAAYE,KAAKJ,iCAgBzCG,kBAAkBE,GAAG,UAAU,eACvBC,SAAWJ,YAAYE,KAAKJ,iCAAiCO,MACjET,mBAAmBU,oBAAoBF,UAClCG,MAAK,SAASC,eAjBM,SAASA,YAC9BC,YAAcT,YAAYE,KAAKJ,0BAC/BY,mBAAqBD,YAAYP,KAAKJ,yBACtCa,aAAehB,EAAEa,QAGrBE,mBAAmBE,SACnBH,YAAYI,KAAK,YAAY,GAC7BF,aAAaG,MAAK,SAASC,GAAIC,OAC3BrB,EAAEc,aAAaQ,OAAOtB,EAAE,qBAAqBuB,KAAK,QAASF,MAAMD,IAAII,KAAKH,MAAMI,UASrEC,CAAuBb,WAEjCc,MAAMzB,aAAa0B,qBAezB,CACHC,KANO,SAASC,YACZzB,YAAcL,EAAE,IAAM8B,QAC1B1B,8BAA8BC"}
+4 -1
View File
@@ -246,9 +246,12 @@ function(
// When something within the calendar tells us the user wants
// to edit an event then show the event form modal.
$('body').on(CalendarEvents.editEvent, function(e, eventId) {
var calendarWrapper = root.find(CalendarSelectors.wrapper);
var target = root.find(`[data-event-id=${eventId}]`),
calendarWrapper = root.find(CalendarSelectors.wrapper);
modal.setEventId(eventId);
modal.setContextId(calendarWrapper.data('contextId'));
modal.setReturnElement(target);
modal.show();
e.stopImmediatePropagation();
+1 -1
View File
@@ -20,7 +20,7 @@
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core_calendar/repository'], function($, CalendarRepository) {
define(['jquery', 'core_calendar/repository', 'core/notification'], function($, CalendarRepository, Notification) {
var SELECTORS = {
EVENT_GROUP_COURSE_ID: '[name="groupcourseid"]',
+4
View File
@@ -61,11 +61,13 @@ class event_icon_exporter extends exporter {
$iscourseevent = ($course && !empty($courseid) && $courseid != SITEID && empty($groupid));
$isgroupevent = ($group && !empty($groupid));
$isuserevent = ($user && !empty($userid));
$iconurl = '';
if ($isactivityevent) {
$key = 'monologo';
$component = $coursemodule->get('modname');
$iconurl = get_fast_modinfo($courseid)->get_cm($coursemodule->get('id'))->get_icon_url()->out(false);
if (get_string_manager()->string_exists($event->get_type(), $component)) {
$alttext = get_string($event->get_type(), $component);
} else {
@@ -118,6 +120,7 @@ class event_icon_exporter extends exporter {
$data->key = $key;
$data->component = $component;
$data->alttext = $alttext;
$data->iconurl = $iconurl;
parent::__construct($data, $related);
}
@@ -132,6 +135,7 @@ class event_icon_exporter extends exporter {
'key' => ['type' => PARAM_TEXT],
'component' => ['type' => PARAM_TEXT],
'alttext' => ['type' => PARAM_TEXT],
'iconurl' => ['type' => PARAM_TEXT],
];
}
+35 -7
View File
@@ -1,7 +1,30 @@
<?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/>.
/**
* Calendar export
*
* @package core_calendar
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_MOODLE_COOKIES', true);
require_once('../config.php');
//require_once($CFG->dirroot.'/course/lib.php');
require_once($CFG->dirroot.'/calendar/lib.php');
require_once($CFG->libdir.'/bennu/bennu.inc.php');
@@ -16,23 +39,28 @@ if (empty($CFG->enablecalendarexport)) {
die('no export');
}
//Fetch user information
$checkuserid = !empty($userid) && $user = $DB->get_record('user', array('id' => $userid), 'id,password');
//allowing for fallback check of old url - MDL-27542
$checkusername = !empty($username) && $user = $DB->get_record('user', array('username' => $username), 'id,password');
// Fetch basic user information to correctly log the user.
$fields = 'id,username,password,firstname,lastname';
$checkuserid = !empty($userid) && $user = $DB->get_record('user', array('id' => $userid), $fields);
// Allowing for fallback check of old url - MDL-27542.
$checkusername = !empty($username) && $user = $DB->get_record('user', array('username' => $username), $fields);
if ((!$checkuserid && !$checkusername) || !$user) {
//No such user
die('Invalid authentication');
}
//Check authentication token
// Check authentication token.
$authuserid = !empty($userid) && $authtoken == calendar_get_export_token($user);
//allowing for fallback check of old url - MDL-27542
// Allowing for fallback check of old url - MDL-27542.
$authusername = !empty($username) && $authtoken == sha1($username . $user->password . $CFG->calendar_exportsalt);
if (!$authuserid && !$authusername) {
die('Invalid authentication');
}
// Setup up the user including web access logging.
\core\session\manager::set_user($user);
$PAGE->set_context(context_system::instance());
// Get the calendar type we are using.
+14 -3
View File
@@ -2360,7 +2360,8 @@ function calendar_edit_event_allowed($event, $manualedit = false) {
return has_capability('moodle/calendar:manageentries', $event->context);
} else if (!empty($event->userid) && $event->userid == $USER->id) {
// If course is not set, but userid id set, it's a user event.
return (has_capability('moodle/calendar:manageownentries', $event->context));
return (has_capability('moodle/calendar:manageownentries',
context_user::instance($event->userid)));
} else if (!empty($event->userid)) {
return calendar_can_manage_user_event($event);
}
@@ -3072,11 +3073,21 @@ function calendar_import_events_from_ical(iCalendar $ical, int $subscriptionid =
\core_php_time_limit::raise(300);
}
// Start with a safe default timezone.
$timezone = 'UTC';
// Grab the timezone from the iCalendar file to be used later.
if (isset($ical->properties['X-WR-TIMEZONE'][0]->value)) {
$timezone = $ical->properties['X-WR-TIMEZONE'][0]->value;
} else {
$timezone = 'UTC';
} else if (isset($ical->properties['PRODID'][0]->value)) {
// If the timezone was not found, check to se if this is MS exchange / Office 365 which uses Windows timezones.
if (strncmp($ical->properties['PRODID'][0]->value, 'Microsoft', 9) == 0) {
if (isset($ical->components['VTIMEZONE'][0]->properties['TZID'][0]->value)) {
$tzname = $ical->components['VTIMEZONE'][0]->properties['TZID'][0]->value;
$timezone = IntlTimeZone::getIDForWindowsID($tzname);
}
}
}
$icaluuids = [];
+2 -1
View File
@@ -41,7 +41,8 @@
"icon": {
"key": "i/courseevent",
"component": "core",
"alttext": "Some course event"
"alttext": "Some course event",
"iconurl": "#"
},
"editurl": "#",
"url": "#"
+8 -1
View File
@@ -45,7 +45,14 @@
}} data-region="event-item"{{!
}}>
<div class="activityiconcontainer small {{{purpose}}} courseicon mr-3">
{{#icon}}{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}{{/icon}}
{{#icon}}
{{#iconurl}}
<img alt="{{alttext}}" title="{{alttext}}" src="{{{ iconurl }}}" class="icon ">
{{/iconurl}}
{{^iconurl}}
{{#pix}} {{key}}, {{component}}, {{alttext}} {{/pix}}
{{/iconurl}}
{{/icon}}
</div>
<div class="overflow-auto">
<h6 class="d-flex mb-1">
+93
View File
@@ -334,3 +334,96 @@ Feature: Perform basic calendar functionality
And I press "Save"
And I click on "Category event" "link"
And I should see "Category event"
@javascript
Scenario: Changing the event type from user to anything else should work
Given I log in as "teacher1"
# We need this so we can see the groups.
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
# We need this so we can make a category event.
And the following "categories" exist:
| name | category | idnumber |
| CatA | 0 | cata |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| teacher1 | manager | Category | cata |
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I set the field "course" to "C1"
And I press "New event"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I click on "type change test event" "link"
And I should see "User event"
When I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Course |
And I expand the "Course" autocomplete
And I click on "Course 1" item in the autocomplete list
And I press "Save"
And I click on "type change test event" "link"
Then I should see "Course event"
# Reset to user event
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to group event.
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I click on "type change test event" "link"
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Group |
And I click on "#fitem_id_groupcourseid .form-autocomplete-downarrow" "css_element"
And I click on "Course 1" item in the autocomplete list
And I set the following fields to these values:
| Group | Group 1 |
And I press "Save"
And I click on "type change test event" "link"
And I should see "Group event"
# Reset to user event
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to course event.
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | Course 1 event |
| Type of event | Course |
And I expand the "Course" autocomplete
And I click on "Course 1" item in the autocomplete list
And I press "Save"
And I click on "Course 1 event" "link"
And I should see "Course event"
# Reset to user event
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I click on "type change test event" "link"
And I should see "User event"
# Now test changing from user to category event.
And I click on "Edit" "button"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | Category |
And I press "Save"
And I click on "type change test event" "link"
And I should see "Category event"
+7 -7
View File
@@ -83,15 +83,15 @@ Feature: Manage custom reports for cohorts
| My report | user:lastname |
And I change window size to "large"
And I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
And I set the field "Rename column 'Surname'" to "Member count"
And I set the "Surname" column aggregation to "Count"
And I set the field "Rename column 'Last name'" to "Member count"
And I set the "Last name" column aggregation to "Count"
And I click on "Show/hide 'Sorting'" "button"
And I click on "Move sorting for column 'Surname'" "button"
And I click on "To the top of the list" "link" in the "Move sorting for column 'Surname'" "dialogue"
And I click on "Enable sorting for column 'Surname'" "checkbox"
And I click on "Move sorting for column 'Last name'" "button"
And I click on "To the top of the list" "link" in the "Move sorting for column 'Last name'" "dialogue"
And I click on "Enable initial sorting for column Last name" "checkbox"
# "New system cohort" has fewer members than "Another one" cohort.
And "New system cohort" "table_row" should appear before "Another one" "table_row"
When I click on "Sort column 'Surname' descending" "button"
Then I should see "Updated sorting for column 'Surname'"
When I click on "Sort column 'Last name' descending" "button"
Then I should see "Updated sorting for column 'Last name'"
# Switching sort direction should now show "Another one" cohort ahead of "New system cohort".
And "Another one" "table_row" should appear before "New system cohort" "table_row"
@@ -135,7 +135,7 @@ Feature: Allow to mark course as completed without cron for activity completion
And I am on "Completion course" course homepage
And I navigate to "View > Grader report" in the course gradebook
And I follow "Single view"
And I select "Student First" from the "Select user..." singleselect
And I select "Student First" from the "Select a user above to view all their grades" singleselect
And I set the field "Override for Test assignment name" to "1"
When I set the following fields to these values:
| Grade for Test assignment name | 10.00 |
@@ -43,7 +43,7 @@ Feature: Restrict activity availability through grade conditions
And I log out
When I am on the "Course 1" course page logged in as student1
Then I should see "Not available unless: You achieve a required score in Grade assignment"
Then I should see "Not available unless: You achieve higher than a certain score in Grade assignment"
And I should see "Test page name"
And "Test page name" "link" should not exist in the "region-main" "region"
And I am on the "Grade assignment" "assign activity" page
@@ -65,4 +65,4 @@ Feature: Restrict activity availability through grade conditions
And I am on the "Course 1" course page logged in as student1
And "Test page name" activity should be visible
And I should not see "Not available unless: You achieve a required score in Grade assignment"
And I should not see "Not available unless: You achieve higher than a certain score in Grade assignment"
@@ -78,7 +78,7 @@ Feature: Restrict sections availability through completion or grade conditions
And I log out
When I log in as "student1"
And I am on "Course 1" course homepage
Then I should see "Not available unless: You achieve a required score in Grade assignment"
Then I should see "Not available unless: You achieve higher than a certain score in Grade assignment"
And "Test page name" activity should be hidden
And I am on the "Grade assignment" "assign activity" page
And I press "Add submission"
@@ -97,4 +97,4 @@ Feature: Restrict sections availability through completion or grade conditions
And I log out
And I am on the "Course 1" Course page logged in as student1
And "Test page name" activity should be visible
And I should not see "Not available unless: You achieve a required score in Grade assignment"
And I should not see "Not available unless: You achieve higher than a certain score in Grade assignment"
+1 -1
View File
@@ -18,7 +18,7 @@
"behat/mink-goutte-driver": "^1.3",
"symfony/process": "^4.0 || ^5.0",
"behat/behat": "3.11.*",
"oleg-andreyev/mink-phpwebdriver": "^1.0.1"
"oleg-andreyev/mink-phpwebdriver": "^1.2.1"
},
"autoload-dev": {
"psr-0": {
Generated
+139 -134
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "981107a64c8c10d5afa79fd05b49af17",
"content-hash": "7897c25160d1ab3b2ad956387eabccf6",
"packages": [],
"packages-dev": [
{
@@ -1005,16 +1005,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"version": "v4.15.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"shasum": ""
},
"require": {
@@ -1055,22 +1055,22 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
},
"time": "2022-09-04T07:30:47+00:00"
"time": "2022-11-12T15:38:23+00:00"
},
{
"name": "oleg-andreyev/mink-phpwebdriver",
"version": "v1.0.1",
"version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/oleg-andreyev/MinkPhpWebDriver.git",
"reference": "66207ad04b45ad4348dd68ab2a918da2875ae46f"
"reference": "e265917faf79b649f4e5d4419325e02c096caec2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/oleg-andreyev/MinkPhpWebDriver/zipball/66207ad04b45ad4348dd68ab2a918da2875ae46f",
"reference": "66207ad04b45ad4348dd68ab2a918da2875ae46f",
"url": "https://api.github.com/repos/oleg-andreyev/MinkPhpWebDriver/zipball/e265917faf79b649f4e5d4419325e02c096caec2",
"reference": "e265917faf79b649f4e5d4419325e02c096caec2",
"shasum": ""
},
"require": {
@@ -1079,11 +1079,12 @@
"php-webdriver/webdriver": "^1.8"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8",
"behat/mink-extension": "^2.3",
"ext-json": "*",
"mink/driver-testsuite": "dev-integration-branch",
"roave/security-advisories": "dev-master",
"symfony/phpunit-bridge": "^5.2"
"symfony/phpunit-bridge": "^4.4 || ^5.4 || ^6.0"
},
"type": "mink-driver",
"extra": {
@@ -1119,9 +1120,9 @@
],
"support": {
"issues": "https://github.com/oleg-andreyev/MinkPhpWebDriver/issues",
"source": "https://github.com/oleg-andreyev/MinkPhpWebDriver/tree/v1.0.1"
"source": "https://github.com/oleg-andreyev/MinkPhpWebDriver/tree/v1.2.1"
},
"time": "2021-01-30T23:07:29+00:00"
"time": "2022-11-21T15:35:27+00:00"
},
{
"name": "phar-io/manifest",
@@ -1236,16 +1237,16 @@
},
{
"name": "php-webdriver/webdriver",
"version": "1.12.1",
"version": "1.13.1",
"source": {
"type": "git",
"url": "https://github.com/php-webdriver/php-webdriver.git",
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a"
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
"reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a",
"url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/6dfe5f814b796c1b5748850aa19f781b9274c36c",
"reference": "6dfe5f814b796c1b5748850aa19f781b9274c36c",
"shasum": ""
},
"require": {
@@ -1295,22 +1296,22 @@
],
"support": {
"issues": "https://github.com/php-webdriver/php-webdriver/issues",
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.1"
"source": "https://github.com/php-webdriver/php-webdriver/tree/1.13.1"
},
"time": "2022-05-03T12:16:34+00:00"
"time": "2022-10-11T11:49:44+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"version": "9.2.23",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"shasum": ""
},
"require": {
@@ -1366,7 +1367,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
},
"funding": [
{
@@ -1374,7 +1375,7 @@
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
"time": "2022-12-28T12:41:10+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -1619,16 +1620,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.24",
"version": "9.5.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5"
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
"reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
"shasum": ""
},
"require": {
@@ -1650,14 +1651,14 @@
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.5",
"sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.3",
"sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.1",
"sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
@@ -1701,7 +1702,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
},
"funding": [
{
@@ -1711,9 +1712,13 @@
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
"type": "tidelift"
}
],
"time": "2022-08-30T07:42:16+00:00"
"time": "2022-10-28T06:00:21+00:00"
},
{
"name": "psr/container",
@@ -3027,16 +3032,16 @@
},
{
"name": "symfony/console",
"version": "v5.4.12",
"version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1"
"reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/c072aa8f724c3af64e2c7a96b796a4863d24dba1",
"reference": "c072aa8f724c3af64e2c7a96b796a4863d24dba1",
"url": "https://api.github.com/repos/symfony/console/zipball/ea59bb0edfaf9f28d18d8791410ee0355f317669",
"reference": "ea59bb0edfaf9f28d18d8791410ee0355f317669",
"shasum": ""
},
"require": {
@@ -3106,7 +3111,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.4.12"
"source": "https://github.com/symfony/console/tree/v5.4.15"
},
"funding": [
{
@@ -3122,7 +3127,7 @@
"type": "tidelift"
}
],
"time": "2022-08-17T13:18:05+00:00"
"time": "2022-10-26T21:41:52+00:00"
},
{
"name": "symfony/css-selector",
@@ -3192,16 +3197,16 @@
},
{
"name": "symfony/dependency-injection",
"version": "v5.4.11",
"version": "v5.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "a8b9251016e9476db73e25fa836904bc0bf74c62"
"reference": "24cf522668845391c0542bc1de496366072a6d0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a8b9251016e9476db73e25fa836904bc0bf74c62",
"reference": "a8b9251016e9476db73e25fa836904bc0bf74c62",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/24cf522668845391c0542bc1de496366072a6d0e",
"reference": "24cf522668845391c0542bc1de496366072a6d0e",
"shasum": ""
},
"require": {
@@ -3261,7 +3266,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.11"
"source": "https://github.com/symfony/dependency-injection/tree/v5.4.13"
},
"funding": [
{
@@ -3277,7 +3282,7 @@
"type": "tidelift"
}
],
"time": "2022-07-20T13:00:38+00:00"
"time": "2022-08-30T19:10:13+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3586,16 +3591,16 @@
},
{
"name": "symfony/filesystem",
"version": "v5.4.12",
"version": "v5.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447"
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2d67c1f9a1937406a9be3171b4b22250c0a11447",
"reference": "2d67c1f9a1937406a9be3171b4b22250c0a11447",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51",
"reference": "ac09569844a9109a5966b9438fc29113ce77cf51",
"shasum": ""
},
"require": {
@@ -3630,7 +3635,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v5.4.12"
"source": "https://github.com/symfony/filesystem/tree/v5.4.13"
},
"funding": [
{
@@ -3646,20 +3651,20 @@
"type": "tidelift"
}
],
"time": "2022-08-02T13:48:16+00:00"
"time": "2022-09-21T19:53:16+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@@ -3674,7 +3679,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3712,7 +3717,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@@ -3728,20 +3733,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "433d05519ce6990bf3530fba6957499d327395c2"
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
"reference": "433d05519ce6990bf3530fba6957499d327395c2",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@@ -3753,7 +3758,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3793,7 +3798,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@@ -3809,20 +3814,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8"
"reference": "639084e360537a19f9ee352433b84ce831f3d2da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"reference": "59a8d271f00dd0e4c2e518104cc7963f655a1aa8",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
"reference": "639084e360537a19f9ee352433b84ce831f3d2da",
"shasum": ""
},
"require": {
@@ -3836,7 +3841,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3880,7 +3885,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
},
"funding": [
{
@@ -3896,20 +3901,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd"
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
"reference": "219aa369ceff116e673852dce47c3a41794c14bd",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@@ -3921,7 +3926,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3964,7 +3969,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@@ -3980,20 +3985,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@@ -4008,7 +4013,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4047,7 +4052,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@@ -4063,20 +4068,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
"reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": ""
},
"require": {
@@ -4085,7 +4090,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4123,7 +4128,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
},
"funding": [
{
@@ -4139,20 +4144,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85"
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85",
"reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"shasum": ""
},
"require": {
@@ -4161,7 +4166,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4202,7 +4207,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
},
"funding": [
{
@@ -4218,20 +4223,20 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
@@ -4240,7 +4245,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4285,7 +4290,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@@ -4301,20 +4306,20 @@
"type": "tidelift"
}
],
"time": "2022-05-10T07:21:04+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.26.0",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1"
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
"shasum": ""
},
"require": {
@@ -4323,7 +4328,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.26-dev"
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4364,7 +4369,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
},
"funding": [
{
@@ -4380,7 +4385,7 @@
"type": "tidelift"
}
],
"time": "2022-05-24T11:49:31+00:00"
"time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/process",
@@ -4529,16 +4534,16 @@
},
{
"name": "symfony/string",
"version": "v5.4.12",
"version": "v5.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058"
"reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/2fc515e512d721bf31ea76bd02fe23ada4640058",
"reference": "2fc515e512d721bf31ea76bd02fe23ada4640058",
"url": "https://api.github.com/repos/symfony/string/zipball/571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
"reference": "571334ce9f687e3e6af72db4d3b2a9431e4fd9ed",
"shasum": ""
},
"require": {
@@ -4595,7 +4600,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.4.12"
"source": "https://github.com/symfony/string/tree/v5.4.15"
},
"funding": [
{
@@ -4611,20 +4616,20 @@
"type": "tidelift"
}
],
"time": "2022-08-12T17:03:11+00:00"
"time": "2022-10-05T15:16:54+00:00"
},
{
"name": "symfony/translation",
"version": "v5.4.12",
"version": "v5.4.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "42ecc77eb4f229ce2df702a648ec93b8478d76ae"
"reference": "f0ed07675863aa6e3939df8b1bc879450b585cab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/42ecc77eb4f229ce2df702a648ec93b8478d76ae",
"reference": "42ecc77eb4f229ce2df702a648ec93b8478d76ae",
"url": "https://api.github.com/repos/symfony/translation/zipball/f0ed07675863aa6e3939df8b1bc879450b585cab",
"reference": "f0ed07675863aa6e3939df8b1bc879450b585cab",
"shasum": ""
},
"require": {
@@ -4692,7 +4697,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.4.12"
"source": "https://github.com/symfony/translation/tree/v5.4.14"
},
"funding": [
{
@@ -4708,7 +4713,7 @@
"type": "tidelift"
}
],
"time": "2022-08-02T15:52:22+00:00"
"time": "2022-10-07T08:01:20+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -4790,16 +4795,16 @@
},
{
"name": "symfony/yaml",
"version": "v5.4.12",
"version": "v5.4.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c"
"reference": "e83fe9a72011f07c662da46a05603d66deeeb487"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
"reference": "7a3aa21ac8ab1a96cc6de5bbcab4bc9fc943b18c",
"url": "https://api.github.com/repos/symfony/yaml/zipball/e83fe9a72011f07c662da46a05603d66deeeb487",
"reference": "e83fe9a72011f07c662da46a05603d66deeeb487",
"shasum": ""
},
"require": {
@@ -4845,7 +4850,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v5.4.12"
"source": "https://github.com/symfony/yaml/tree/v5.4.14"
},
"funding": [
{
@@ -4861,7 +4866,7 @@
"type": "tidelift"
}
],
"time": "2022-08-02T15:52:22+00:00"
"time": "2022-10-03T15:15:50+00:00"
},
{
"name": "theseer/tokenizer",
+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
+11 -8
View File
@@ -582,11 +582,11 @@ define(
if (action === 'hide' || action === 'show') {
if (action === 'hide') {
sectionElement.addClass('hidden');
setSectionBadge(sectionElement[0], 'hiddenfromstudents', true);
setSectionBadge(sectionElement[0], 'hiddenfromstudents', true, false);
replaceActionItem(actionItem, 'i/show',
'showfromothers', 'format_' + courseformat, 'show');
} else {
setSectionBadge(sectionElement[0], 'hiddenfromstudents', false);
setSectionBadge(sectionElement[0], 'hiddenfromstudents', false, false);
sectionElement.removeClass('hidden');
replaceActionItem(actionItem, 'i/hide',
'hidefromothers', 'format_' + courseformat, 'hide');
@@ -616,13 +616,13 @@ define(
replaceActionItem(actionItem, 'i/marked',
'highlightoff', 'core', 'removemarker');
courseeditor.dispatch('legacySectionAction', action, sectionid);
setSectionBadge(sectionElement[0], 'iscurrent', true);
setSectionBadge(sectionElement[0], 'iscurrent', true, true);
} else if (action === 'removemarker') {
sectionElement.removeClass('current');
replaceActionItem(actionItem, 'i/marker',
'highlight', 'core', 'setmarker');
courseeditor.dispatch('legacySectionAction', action, sectionid);
setSectionBadge(sectionElement[0], 'iscurrent', false);
setSectionBadge(sectionElement[0], 'iscurrent', false, true);
}
};
@@ -733,8 +733,9 @@ define(
* @param {JQuery} sectionElement section element we perform action on
* @param {String} badgetype the type of badge this is for
* @param {bool} add true to add, false to remove
* @param {boolean} removeOther in case of adding a badge, whether to remove all other.
*/
var setSectionBadge = function(sectionElement, badgetype, add) {
var setSectionBadge = function(sectionElement, badgetype, add, removeOther) {
const sectionbadges = sectionElement.querySelector(SELECTOR.SECTIONBADGES);
if (!sectionbadges) {
return;
@@ -744,9 +745,11 @@ define(
return;
}
if (add) {
document.querySelectorAll('[data-type="' + badgetype + '"]').forEach((b) => {
b.classList.add('d-none');
});
if (removeOther) {
document.querySelectorAll('[data-type="' + badgetype + '"]').forEach((b) => {
b.classList.add('d-none');
});
}
badge.classList.remove('d-none');
} else {
badge.classList.add('d-none');
+3 -2
View File
@@ -2640,10 +2640,11 @@ class core_course_category implements renderable, cacheable_object, IteratorAggr
$thislist = array();
foreach ($rs as $record) {
context_helper::preload_from_record($record);
$context = context_coursecat::instance($record->id);
$canview = self::can_view_category($record);
$context = context_coursecat::instance($record->id);
$filtercontext = \context_helper::get_navigation_filter_context($context);
$baselist[$record->id] = array(
'name' => $canview ? format_string($record->name, true, array('context' => $context)) : false,
'name' => $canview ? format_string($record->name, true, array('context' => $filtercontext)) : false,
'path' => $record->path
);
if (!$canview || (!empty($requiredcapability) && !has_all_capabilities($requiredcapability, $context))) {

Some files were not shown because too many files have changed in this diff Show More