Compare commits

..

601 Commits

Author SHA1 Message Date
Jun Pataleta db959720ed Moodle release 4.3.8 2024-10-05 14:46:42 +08:00
AMOS bot 7836fde50f Automatically generated installer lang files 2024-10-05 00:07:43 +00:00
Huong Nguyen 2bf0d3b149 weekly release 4.3.7+ 2024-10-04 20:48:15 +07:00
Huong Nguyen a8f220b2b7 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-10-04 20:48:13 +07:00
AMOS bot 65463981dc Automatically generated installer lang files 2024-10-04 00:07:42 +00:00
Michael Hawkins 5bb490e979 MDL-83352 message: Update usercantbemessaged string 2024-10-03 17:47:06 +07:00
Jun Pataleta c7b2b1c439 Merge branch 'MDL-83238-403-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_403_STABLE 2024-10-03 16:02:17 +08:00
David Mudrák d869697f97 MDL-83238 lang: Fix the changed strings in the tests, too 2024-10-02 22:22:44 +02:00
Helen Foster 9ad5f88019 MDL-83238 lang: Import fixed English strings (en_fix) 2024-10-02 22:09:32 +02:00
Shamim Rezaie 90f82cbe86 Merge branch 'MDL-83332-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-10-03 02:24:36 +10:00
Paul Holden e22816a954 MDL-83180 reportbuilder: correct access check for viewing schedules. 2024-10-02 16:49:46 +08:00
meirzamoodle 23f51d88cf MDL-83332 environment: Reverts the slashargument removal on MDL-62640
We are encountering Behat failures on MacOS and possibly Windows.

This reverts commit 3202109780.
2024-10-02 13:32:28 +07:00
Jun Pataleta 6aa12043d1 Merge branch 'm43-md83163' of https://github.com/danmarsden/moodle into MOODLE_403_STABLE 2024-10-02 12:31:27 +08:00
Dan Marsden 772c763e6b MDL-83310 course: remove hard-coded list of course formats from test. 2024-10-02 08:53:11 +13:00
Paul Holden 9f773c160e MDL-83181 reportbuilder: ensure audience correctness before delete. 2024-10-01 12:44:16 +00:00
Paul Holden d3b930d67c MDL-82386 block_rss_client: user access checks for feed edit/delete. 2024-10-01 12:44:16 +00:00
Huong Nguyen 886f5c8465 weekly release 4.3.7+ 2024-10-01 19:33:04 +07:00
Jun Pataleta 0138b520a4 Merge branch 'MDL-83264-403-1' of https://github.com/mihailges/moodle into MOODLE_403_STABLE 2024-10-01 12:47:18 +08:00
Mihail Geshoski f2f64d40c5 MDL-83264 mod_quiz: Return the correct name for top categories 2024-10-01 09:43:28 +08:00
Shamim Rezaie d56e90c1b7 Merge branch 'MDL-81590-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-09-30 23:01:54 +10:00
Huong Nguyen ab291aa8ed weekly release 4.3.7+ 2024-09-27 18:44:11 +07:00
Huong Nguyen a60f0883cc NOBUG: Fixed SVG browser compatibility 2024-09-27 18:44:10 +07:00
Huong Nguyen 34b45fea59 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-09-27 18:44:09 +07:00
Jun Pataleta 5a24beab3c MDL-81590 core: Build the context path without using DIRECTORY_SEPARATOR 2024-09-27 16:46:16 +08:00
Jun Pataleta 7ba0f509c7 Merge branch 'MDL-80929-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 12:40:23 +08:00
Huong Nguyen fa5eec299a Merge branch 'MDL-83205-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-09-27 11:27:20 +07:00
Huong Nguyen deb427c38f Merge branch 'MDL-82483-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 11:16:08 +07:00
Jun Pataleta caa14d5283 Merge branch 'MDL-82602-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 12:10:53 +08:00
Huong Nguyen f5af008e0f Merge branch 'MDL-80974-MOODLE_403_STABLE' of https://github.com/sh-csg/moodle into MOODLE_403_STABLE 2024-09-27 11:09:02 +07:00
Jun Pataleta 22b6d706bd Merge branch 'MDL-82973-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 12:06:05 +08:00
Jun Pataleta 1f4bca1a2e Merge branch 'MDL-83163-m403' of https://github.com/sammarshallou/moodle into MOODLE_403_STABLE 2024-09-27 11:59:29 +08:00
Andrew Nicols 4b36a967d0 Merge branch 'MDL-83094-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 11:06:14 +08:00
Jun Pataleta 071cc916fd Merge branch 'MDL-81157-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 10:28:31 +08:00
Jun Pataleta d2595b4a4e Merge branch 'MDL-82581-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-27 10:10:55 +08:00
AMOS bot 9c811f8a4c Automatically generated installer lang files 2024-09-27 00:07:42 +00:00
Andrew Nicols 8e40b64f8d Merge branch 'MDL-83268-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-09-26 22:07:15 +08:00
Sara Arjona e600fb2782 MDL-83268 core_h5p: Fix version number 2024-09-26 16:02:47 +02:00
Andrew Nicols fd4f256768 Merge branch 'MDL-83268-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-09-26 21:33:24 +08:00
Sara Arjona 57f527587b MDL-83268 core_h5p: Fix required Moodle version 2024-09-26 15:26:26 +02:00
Andrew Nicols 5e95aa4b3a Merge branch 'MDL-83268-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-09-26 21:08:05 +08:00
Jun Pataleta c36c4e8caf Merge branch 'MDL-79288-403_blockaccessreview_colourcontrastcheck' of https://github.com/brickfield/moodle into MOODLE_403_STABLE 2024-09-26 19:45:06 +08:00
Sara Arjona c217ab2947 MDL-83268 core_h5p: Remove unused font files
In https://h5ptechnology.atlassian.net/browse/HFP-4105, the
fonts/h5p-core-29.svg was merged with some conflicts.
Looking at the patch there, it seems all the h5p-core-29* fonts
can be removed because the ones used by the library are the
h5p-core-30-*.

I haven't added a note in the upgrade because it seems an error
on their release process (so I don't think it's worth adding
a note because it should be fixed in future releases).
2024-09-26 10:32:12 +02:00
Sara Arjona a64e2bc235 MDL-83268 core_h5p: Remove the h5plib_v126 plugin
The h5plib_v126 plugin can be removed because it has been replaced
with h5plib_v127, which is using the latest versions of the
libraries.
2024-09-26 10:32:11 +02:00
Sara Arjona d9f2f7006e MDL-83268 core_h5p: Add editor lib changes after upgrading it 2024-09-26 10:32:11 +02:00
Sara Arjona 5481ef00a1 MDL-83268 core_h5p: Upgrade editor lib to 1.27
This commit is upgrading the joubel/editor library to the one
tagged as moodle-1.27.0 (which also increases the coreApi minorVersion).
2024-09-26 10:32:11 +02:00
Sara Arjona 099f65274c MDL-83268 core_h5p: Add core lib changes after upgrading it 2024-09-26 10:32:10 +02:00
Sara Arjona 15eb08acc2 MDL-83268 core_h5p: Upgrade core lib to 1.27
This commit is upgrading the joubel/core library to the one
tagged as moodle-1.27.0 (which also increases the coreApi minorVersion).
That's why the previous commit was duplicating the existing
h5plib_v126.
2024-09-26 10:32:10 +02:00
Sara Arjona b5b838e16b MDL-83268 h5plib: Create first version of h5plib_v127
AMOS BEGIN
  CPY [editor:a11ytitleshowlabel,h5plib_v126],[editor:a11ytitleshowlabel,h5plib_v127]
  CPY [editor:a11ytitlehidelabel,h5plib_v126],[editor:a11ytitlehidelabel,h5plib_v127]
  CPY [editor:atoz,h5plib_v126],[editor:atoz,h5plib_v127]
  CPY [editor:add,h5plib_v126],[editor:add,h5plib_v127]
  CPY [editor:addauthor,h5plib_v126],[editor:addauthor,h5plib_v127]
  CPY [editor:addentity,h5plib_v126],[editor:addentity,h5plib_v127]
  CPY [editor:addfile,h5plib_v126],[editor:addfile,h5plib_v127]
  CPY [editor:addnewchange,h5plib_v126],[editor:addnewchange,h5plib_v127]
  CPY [editor:addtitle,h5plib_v126],[editor:addtitle,h5plib_v127]
  CPY [editor:addvideodescription,h5plib_v126],[editor:addvideodescription,h5plib_v127]
  CPY [editor:avtablistlabel,h5plib_v126],[editor:avtablistlabel,h5plib_v127]
  CPY [editor:belowmin,h5plib_v126],[editor:belowmin,h5plib_v127]
  CPY [editor:cancel,h5plib_v126],[editor:cancel,h5plib_v127]
  CPY [editor:cancellabel,h5plib_v126],[editor:cancellabel,h5plib_v127]
  CPY [editor:changefile,h5plib_v126],[editor:changefile,h5plib_v127]
  CPY [editor:changelanguage,h5plib_v126],[editor:changelanguage,h5plib_v127]
  CPY [editor:changelibrary,h5plib_v126],[editor:changelibrary,h5plib_v127]
  CPY [editor:changelogdescription,h5plib_v126],[editor:changelogdescription,h5plib_v127]
  CPY [editor:close,h5plib_v126],[editor:close,h5plib_v127]
  CPY [editor:commonfields,h5plib_v126],[editor:commonfields,h5plib_v127]
  CPY [editor:commonfieldsdescription,h5plib_v126],[editor:commonfieldsdescription,h5plib_v127]
  CPY [editor:confirmchangelibrary,h5plib_v126],[editor:confirmchangelibrary,h5plib_v127]
  CPY [editor:confirmdeletechangelog,h5plib_v126],[editor:confirmdeletechangelog,h5plib_v127]
  CPY [editor:confirmimageremoval,h5plib_v126],[editor:confirmimageremoval,h5plib_v127]
  CPY [editor:confirmpastebuttontext,h5plib_v126],[editor:confirmpastebuttontext,h5plib_v127]
  CPY [editor:confirmpastecontent,h5plib_v126],[editor:confirmpastecontent,h5plib_v127]
  CPY [editor:confirmremoval,h5plib_v126],[editor:confirmremoval,h5plib_v127]
  CPY [editor:confirmremoveauthor,h5plib_v126],[editor:confirmremoveauthor,h5plib_v127]
  CPY [editor:contenttypebackbuttonlabel,h5plib_v126],[editor:contenttypebackbuttonlabel,h5plib_v127]
  CPY [editor:contenttypecacheoutdated,h5plib_v126],[editor:contenttypecacheoutdated,h5plib_v127]
  CPY [editor:contenttypecacheoutdateddesc,h5plib_v126],[editor:contenttypecacheoutdateddesc,h5plib_v127]
  CPY [editor:contenttypedemobuttonlabel,h5plib_v126],[editor:contenttypedemobuttonlabel,h5plib_v127]
  CPY [editor:contenttypedetailbuttonlabel,h5plib_v126],[editor:contenttypedetailbuttonlabel,h5plib_v127]
  CPY [editor:contenttypegetbuttonlabel,h5plib_v126],[editor:contenttypegetbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeiconalttext,h5plib_v126],[editor:contenttypeiconalttext,h5plib_v127]
  CPY [editor:contenttypeinstallbuttonlabel,h5plib_v126],[editor:contenttypeinstallbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeinstallerror,h5plib_v126],[editor:contenttypeinstallerror,h5plib_v127]
  CPY [editor:contenttypeinstallsuccess,h5plib_v126],[editor:contenttypeinstallsuccess,h5plib_v127]
  CPY [editor:contenttypeinstallingbuttonlabel,h5plib_v126],[editor:contenttypeinstallingbuttonlabel,h5plib_v127]
  CPY [editor:contenttypelicensepaneltitle,h5plib_v126],[editor:contenttypelicensepaneltitle,h5plib_v127]
  CPY [editor:contenttypenotinstalled,h5plib_v126],[editor:contenttypenotinstalled,h5plib_v127]
  CPY [editor:contenttypenotinstalleddesc,h5plib_v126],[editor:contenttypenotinstalleddesc,h5plib_v127]
  CPY [editor:contenttypeowner,h5plib_v126],[editor:contenttypeowner,h5plib_v127]
  CPY [editor:contenttyperestricted,h5plib_v126],[editor:contenttyperestricted,h5plib_v127]
  CPY [editor:contenttyperestricteddesc,h5plib_v126],[editor:contenttyperestricteddesc,h5plib_v127]
  CPY [editor:contenttypesearchfieldplaceholder,h5plib_v126],[editor:contenttypesearchfieldplaceholder,h5plib_v127]
  CPY [editor:contenttypesectionall,h5plib_v126],[editor:contenttypesectionall,h5plib_v127]
  CPY [editor:contenttypeunsupportedapiversioncontent,h5plib_v126],[editor:contenttypeunsupportedapiversioncontent,h5plib_v127]
  CPY [editor:contenttypeunsupportedapiversiontitle,h5plib_v126],[editor:contenttypeunsupportedapiversiontitle,h5plib_v127]
  CPY [editor:contenttypeupdateavailable,h5plib_v126],[editor:contenttypeupdateavailable,h5plib_v127]
  CPY [editor:contenttypeupdatebuttonlabel,h5plib_v126],[editor:contenttypeupdatebuttonlabel,h5plib_v127]
  CPY [editor:contenttypeupdatesuccess,h5plib_v126],[editor:contenttypeupdatesuccess,h5plib_v127]
  CPY [editor:contenttypeupdatingbuttonlabel,h5plib_v126],[editor:contenttypeupdatingbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeusebuttonlabel,h5plib_v126],[editor:contenttypeusebuttonlabel,h5plib_v127]
  CPY [editor:contributetranslations,h5plib_v126],[editor:contributetranslations,h5plib_v127]
  CPY [editor:copiedbutton,h5plib_v126],[editor:copiedbutton,h5plib_v127]
  CPY [editor:copiedtoclipboard,h5plib_v126],[editor:copiedtoclipboard,h5plib_v127]
  CPY [editor:copybutton,h5plib_v126],[editor:copybutton,h5plib_v127]
  CPY [editor:copytoclipboard,h5plib_v126],[editor:copytoclipboard,h5plib_v127]
  CPY [editor:createcontenttablabel,h5plib_v126],[editor:createcontenttablabel,h5plib_v127]
  CPY [editor:currentmenuselected,h5plib_v126],[editor:currentmenuselected,h5plib_v127]
  CPY [editor:editcopyright,h5plib_v126],[editor:editcopyright,h5plib_v127]
  CPY [editor:editimage,h5plib_v126],[editor:editimage,h5plib_v127]
  CPY [editor:editmode,h5plib_v126],[editor:editmode,h5plib_v127]
  CPY [editor:enteraudiotitle,h5plib_v126],[editor:enteraudiotitle,h5plib_v127]
  CPY [editor:enteraudiourl,h5plib_v126],[editor:enteraudiourl,h5plib_v127]
  CPY [editor:enterfullscreenbuttonlabel,h5plib_v126],[editor:enterfullscreenbuttonlabel,h5plib_v127]
  CPY [editor:entervideotitle,h5plib_v126],[editor:entervideotitle,h5plib_v127]
  CPY [editor:entervideourl,h5plib_v126],[editor:entervideourl,h5plib_v127]
  CPY [editor:errorcalculatingmaxscore,h5plib_v126],[editor:errorcalculatingmaxscore,h5plib_v127]
  CPY [editor:errorcommunicatinghubcontent,h5plib_v126],[editor:errorcommunicatinghubcontent,h5plib_v127]
  CPY [editor:errorcommunicatinghubtitle,h5plib_v126],[editor:errorcommunicatinghubtitle,h5plib_v127]
  CPY [editor:errorheader,h5plib_v126],[editor:errorheader,h5plib_v127]
  CPY [editor:errornotsupported,h5plib_v126],[editor:errornotsupported,h5plib_v127]
  CPY [editor:errorparamsbroken,h5plib_v126],[editor:errorparamsbroken,h5plib_v127]
  CPY [editor:errortoohighversion,h5plib_v126],[editor:errortoohighversion,h5plib_v127]
  CPY [editor:example,h5plib_v126],[editor:example,h5plib_v127]
  CPY [editor:exceedsmax,h5plib_v126],[editor:exceedsmax,h5plib_v127]
  CPY [editor:exitfullscreenbuttonlabel,h5plib_v126],[editor:exitfullscreenbuttonlabel,h5plib_v127]
  CPY [editor:expandcollapse,h5plib_v126],[editor:expandcollapse,h5plib_v127]
  CPY [editor:filetolarge,h5plib_v126],[editor:filetolarge,h5plib_v127]
  CPY [editor:fillinthefieldsbelow,h5plib_v126],[editor:fillinthefieldsbelow,h5plib_v127]
  CPY [editor:gethelp,h5plib_v126],[editor:gethelp,h5plib_v127]
  CPY [editor:h5pfileuploadservererrorcontent,h5plib_v126],[editor:h5pfileuploadservererrorcontent,h5plib_v127]
  CPY [editor:h5pfileuploadservererrortitle,h5plib_v126],[editor:h5pfileuploadservererrortitle,h5plib_v127]
  CPY [editor:h5pfilevalidationfailedcontent,h5plib_v126],[editor:h5pfilevalidationfailedcontent,h5plib_v127]
  CPY [editor:h5pfilevalidationfailedtitle,h5plib_v126],[editor:h5pfilevalidationfailedtitle,h5plib_v127]
  CPY [editor:h5pfilewrongextensioncontent,h5plib_v126],[editor:h5pfilewrongextensioncontent,h5plib_v127]
  CPY [editor:h5pfilewrongextensiontitle,h5plib_v126],[editor:h5pfilewrongextensiontitle,h5plib_v127]
  CPY [editor:height,h5plib_v126],[editor:height,h5plib_v127]
  CPY [editor:hide,h5plib_v126],[editor:hide,h5plib_v127]
  CPY [editor:hideimportantinstructions,h5plib_v126],[editor:hideimportantinstructions,h5plib_v127]
  CPY [editor:hubpanellabel,h5plib_v126],[editor:hubpanellabel,h5plib_v127]
  CPY [editor:illegaldecimalnumber,h5plib_v126],[editor:illegaldecimalnumber,h5plib_v127]
  CPY [editor:imagelightboxprogress,h5plib_v126],[editor:imagelightboxprogress,h5plib_v127]
  CPY [editor:imagelightboxtitle,h5plib_v126],[editor:imagelightboxtitle,h5plib_v127]
  CPY [editor:importantinstructions,h5plib_v126],[editor:importantinstructions,h5plib_v127]
  CPY [editor:insert,h5plib_v126],[editor:insert,h5plib_v127]
  CPY [editor:invalidformat,h5plib_v126],[editor:invalidformat,h5plib_v127]
  CPY [editor:language,h5plib_v126],[editor:language,h5plib_v127]
  CPY [editor:librarymissing,h5plib_v126],[editor:librarymissing,h5plib_v127]
  CPY [editor:licensecandistribute,h5plib_v126],[editor:licensecandistribute,h5plib_v127]
  CPY [editor:licensecanholdliable,h5plib_v126],[editor:licensecanholdliable,h5plib_v127]
  CPY [editor:licensecanmodify,h5plib_v126],[editor:licensecanmodify,h5plib_v127]
  CPY [editor:licensecansublicense,h5plib_v126],[editor:licensecansublicense,h5plib_v127]
  CPY [editor:licensecanusecommercially,h5plib_v126],[editor:licensecanusecommercially,h5plib_v127]
  CPY [editor:licensecannotholdliable,h5plib_v126],[editor:licensecannotholdliable,h5plib_v127]
  CPY [editor:licensedescription,h5plib_v126],[editor:licensedescription,h5plib_v127]
  CPY [editor:licensefetchdetailsfailed,h5plib_v126],[editor:licensefetchdetailsfailed,h5plib_v127]
  CPY [editor:licensemodalsubtitle,h5plib_v126],[editor:licensemodalsubtitle,h5plib_v127]
  CPY [editor:licensemodaltitle,h5plib_v126],[editor:licensemodaltitle,h5plib_v127]
  CPY [editor:licensemustincludecopyright,h5plib_v126],[editor:licensemustincludecopyright,h5plib_v127]
  CPY [editor:licensemustincludelicense,h5plib_v126],[editor:licensemustincludelicense,h5plib_v127]
  CPY [editor:licenseunspecified,h5plib_v126],[editor:licenseunspecified,h5plib_v127]
  CPY [editor:listbelowmin,h5plib_v126],[editor:listbelowmin,h5plib_v127]
  CPY [editor:listexceedsmax,h5plib_v126],[editor:listexceedsmax,h5plib_v127]
  CPY [editor:listlabel,h5plib_v126],[editor:listlabel,h5plib_v127]
  CPY [editor:loading,h5plib_v126],[editor:loading,h5plib_v127]
  CPY [editor:loadingimageeditor,h5plib_v126],[editor:loadingimageeditor,h5plib_v127]
  CPY [editor:logthischange,h5plib_v126],[editor:logthischange,h5plib_v127]
  CPY [editor:loggedchanges,h5plib_v126],[editor:loggedchanges,h5plib_v127]
  CPY [editor:maxscoresemanticsmissing,h5plib_v126],[editor:maxscoresemanticsmissing,h5plib_v127]
  CPY [editor:metadata,h5plib_v126],[editor:metadata,h5plib_v127]
  CPY [editor:metadatasharingandlicensinginfo,h5plib_v126],[editor:metadatasharingandlicensinginfo,h5plib_v127]
  CPY [editor:missingproperty,h5plib_v126],[editor:missingproperty,h5plib_v127]
  CPY [editor:missingtranslation,h5plib_v126],[editor:missingtranslation,h5plib_v127]
  CPY [editor:newchangehasbeenlogged,h5plib_v126],[editor:newchangehasbeenlogged,h5plib_v127]
  CPY [editor:newestfirst,h5plib_v126],[editor:newestfirst,h5plib_v127]
  CPY [editor:nextimage,h5plib_v126],[editor:nextimage,h5plib_v127]
  CPY [editor:nochangeshavebeenlogged,h5plib_v126],[editor:nochangeshavebeenlogged,h5plib_v127]
  CPY [editor:nocontenttypesavailable,h5plib_v126],[editor:nocontenttypesavailable,h5plib_v127]
  CPY [editor:nocontenttypesavailabledesc,h5plib_v126],[editor:nocontenttypesavailabledesc,h5plib_v127]
  CPY [editor:nofollow,h5plib_v126],[editor:nofollow,h5plib_v127]
  CPY [editor:notimageordimensionsfield,h5plib_v126],[editor:notimageordimensionsfield,h5plib_v127]
  CPY [editor:numresults,h5plib_v126],[editor:numresults,h5plib_v127]
  CPY [editor:numberfield,h5plib_v126],[editor:numberfield,h5plib_v127]
  CPY [editor:ok,h5plib_v126],[editor:ok,h5plib_v127]
  CPY [editor:onlynumbers,h5plib_v126],[editor:onlynumbers,h5plib_v127]
  CPY [editor:or,h5plib_v126],[editor:or,h5plib_v127]
  CPY [editor:orderitemdown,h5plib_v126],[editor:orderitemdown,h5plib_v127]
  CPY [editor:orderitemup,h5plib_v126],[editor:orderitemup,h5plib_v127]
  CPY [editor:outofstep,h5plib_v126],[editor:outofstep,h5plib_v127]
  CPY [editor:pasteandreplacebutton,h5plib_v126],[editor:pasteandreplacebutton,h5plib_v127]
  CPY [editor:pasteandreplacefromclipboard,h5plib_v126],[editor:pasteandreplacefromclipboard,h5plib_v127]
  CPY [editor:pastebutton,h5plib_v126],[editor:pastebutton,h5plib_v127]
  CPY [editor:pastecontent,h5plib_v126],[editor:pastecontent,h5plib_v127]
  CPY [editor:pastecontentnotsupported,h5plib_v126],[editor:pastecontentnotsupported,h5plib_v127]
  CPY [editor:pastecontentrestricted,h5plib_v126],[editor:pastecontentrestricted,h5plib_v127]
  CPY [editor:pasteerror,h5plib_v126],[editor:pasteerror,h5plib_v127]
  CPY [editor:pastefromclipboard,h5plib_v126],[editor:pastefromclipboard,h5plib_v127]
  CPY [editor:pastenocontent,h5plib_v126],[editor:pastenocontent,h5plib_v127]
  CPY [editor:pastetoonew,h5plib_v126],[editor:pastetoonew,h5plib_v127]
  CPY [editor:pastetooold,h5plib_v126],[editor:pastetooold,h5plib_v127]
  CPY [editor:popularfirst,h5plib_v126],[editor:popularfirst,h5plib_v127]
  CPY [editor:previousimage,h5plib_v126],[editor:previousimage,h5plib_v127]
  CPY [editor:proceedbuttonlabel,h5plib_v126],[editor:proceedbuttonlabel,h5plib_v127]
  CPY [editor:readless,h5plib_v126],[editor:readless,h5plib_v127]
  CPY [editor:readmore,h5plib_v126],[editor:readmore,h5plib_v127]
  CPY [editor:recentlyusedfirst,h5plib_v126],[editor:recentlyusedfirst,h5plib_v127]
  CPY [editor:reloadbuttonlabel,h5plib_v126],[editor:reloadbuttonlabel,h5plib_v127]
  CPY [editor:removefile,h5plib_v126],[editor:removefile,h5plib_v127]
  CPY [editor:removeimage,h5plib_v126],[editor:removeimage,h5plib_v127]
  CPY [editor:removeitem,h5plib_v126],[editor:removeitem,h5plib_v127]
  CPY [editor:requiredproperty,h5plib_v126],[editor:requiredproperty,h5plib_v127]
  CPY [editor:resettooriginallabel,h5plib_v126],[editor:resettooriginallabel,h5plib_v127]
  CPY [editor:savelabel,h5plib_v126],[editor:savelabel,h5plib_v127]
  CPY [editor:savemetadata,h5plib_v126],[editor:savemetadata,h5plib_v127]
  CPY [editor:screenshots,h5plib_v126],[editor:screenshots,h5plib_v127]
  CPY [editor:scriptmissing,h5plib_v126],[editor:scriptmissing,h5plib_v127]
  CPY [editor:searchresults,h5plib_v126],[editor:searchresults,h5plib_v127]
  CPY [editor:selectfiletoupload,h5plib_v126],[editor:selectfiletoupload,h5plib_v127]
  CPY [editor:selectlibrary,h5plib_v126],[editor:selectlibrary,h5plib_v127]
  CPY [editor:semanticserror,h5plib_v126],[editor:semanticserror,h5plib_v127]
  CPY [editor:show,h5plib_v126],[editor:show,h5plib_v127]
  CPY [editor:showimportantinstructions,h5plib_v126],[editor:showimportantinstructions,h5plib_v127]
  CPY [editor:tabtitlebasicfileupload,h5plib_v126],[editor:tabtitlebasicfileupload,h5plib_v127]
  CPY [editor:tabtitleinputlinkurl,h5plib_v126],[editor:tabtitleinputlinkurl,h5plib_v127]
  CPY [editor:textfield,h5plib_v126],[editor:textfield,h5plib_v127]
  CPY [editor:thecontenttype,h5plib_v126],[editor:thecontenttype,h5plib_v127]
  CPY [editor:thiswillpotentially,h5plib_v126],[editor:thiswillpotentially,h5plib_v127]
  CPY [editor:title,h5plib_v126],[editAMOS END
  or:title,h5plib_v127]
  CPY [editor:toolong,h5plib_v126],[editor:toolong,h5plib_v127]
  CPY [editor:tryagain,h5plib_v126],[editor:tryagain,h5plib_v127]
  CPY [editor:tutorial,h5plib_v126],[editor:tutorial,h5plib_v127]
  CPY [editor:unabletointerpreterror,h5plib_v126],[editor:unabletointerpreterror,h5plib_v127]
  CPY [editor:unabletointerpretsolution,h5plib_v126],[editor:unabletointerpretsolution,h5plib_v127]
  CPY [editor:unknownfieldpath,h5plib_v126],[editor:unknownfieldpath,h5plib_v127]
  CPY [editor:uploadinstructionstitle,h5plib_v126],[editor:uploadinstructionstitle,h5plib_v127]
  CPY [editor:uploadplaceholder,h5plib_v126],[editor:uploadplaceholder,h5plib_v127]
  CPY [editor:uploadsuccess,h5plib_v126],[editor:uploadsuccess,h5plib_v127]
  CPY [editor:uploadtablabel,h5plib_v126],[editor:uploadtablabel,h5plib_v127]
  CPY [editor:uploadvideotitle,h5plib_v126],[editor:uploadvideotitle,h5plib_v127]
  CPY [editor:uploading,h5plib_v126],[editor:uploading,h5plib_v127]
  CPY [editor:uploadingthrobber,h5plib_v126],[editor:uploadingthrobber,h5plib_v127]
  CPY [editor:usedforsearchingreportsandcopyrightinformation,h5plib_v126],[editor:usedforsearchingreportsandcopyrightinformation,h5plib_v127]
  CPY [editor:videoquality,h5plib_v126],[editor:videoquality,h5plib_v127]
  CPY [editor:videoqualitydefaultlabel,h5plib_v126],[editor:videoqualitydefaultlabel,h5plib_v127]
  CPY [editor:videoqualitydescription,h5plib_v126],[editor:videoqualitydescription,h5plib_v127]
  CPY [editor:warningchangebrowsingtoseeresults,h5plib_v126],[editor:warningchangebrowsingtoseeresults,h5plib_v127]
  CPY [editor:warningnocontenttypesinstalled,h5plib_v126],[editor:warningnocontenttypesinstalled,h5plib_v127]
  CPY [editor:warningupdateavailablebody,h5plib_v126],[editor:warningupdateavailablebody,h5plib_v127]
  CPY [editor:warningupdateavailabletitle,h5plib_v126],[editor:warningupdateavailabletitle,h5plib_v127]
  CPY [editor:width,h5plib_v126],[editor:width,h5plib_v127]
AMOS END
2024-09-26 10:32:10 +02:00
Jun Pataleta 31537778b9 Merge branch 'MDL-83263-403' of https://github.com/mihailges/moodle into MOODLE_403_STABLE 2024-09-26 16:28:52 +08:00
Michael Pound 78912de2ab MDL-79288 block_accessreview: Improve heatmap colour contrast. 2024-09-26 08:13:44 +00:00
Huong Nguyen 415195088b Merge branch 'MDL-62640-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-09-26 11:07:35 +07:00
Cameron Ball c90226fc23 MDL-82298 navigation: Update behat tests for theme_classic 2024-09-26 11:15:06 +08:00
Jun Pataleta 372318257c Merge branch 'MDL-83235-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-26 09:25:46 +08:00
Andrew Nicols 8c6c3f0d06 Merge branch 'MDL-82298-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-09-25 22:56:01 +08:00
Andrew Nicols 7a91817a1c MDL-82298 navigation: Update behat tests 2024-09-25 22:38:32 +08:00
Karjun Loong a4290bec3f MDL-82298 navigation: Add behat tests for secondary menu navigation 2024-09-25 22:38:32 +08:00
Jose 1dcf079286 MDL-82298 navigation: Add setting data-disableactive on moremenu items
This setting will avoid conflicts between checkmark and
bfcache. The removed function added as part of the MDL-77732
is no longer required as the behaviour on the menu items (including the
secondary navigation) is not altered anymore by the menuItemHelper function
(menu_navigation file).
2024-09-25 22:38:31 +08:00
Mihail Geshoski fcbe432066 MDL-83263 grade: Handle undefined array key on grade override revert 2024-09-25 17:27:23 +08:00
Huong Nguyen b7852c7225 Merge branch 'MDL-72856-M403' of https://github.com/michael-milette/moodle into MOODLE_403_STABLE 2024-09-25 08:58:34 +07:00
Sara Arjona 4e7e308a77 weekly release 4.3.7+ 2024-09-24 16:52:12 +02:00
Shamim Rezaie a686489653 Merge branch 'MDL-77625_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-09-24 02:54:13 +10:00
Paul Holden 1179e1f534 MDL-83235 qbank_columnsortorder: correct config retrieval ordering.
There is a unique index on plugin/name, so having a trailing order
clause on value would produce no effect. We also cannot order by
CLOB fields on Oracle, lest it complain loudly.
2024-09-23 08:56:45 +01:00
meirzamoodle ee66d8f2bf MDL-62640 environment: Remove the deprecated slash argument check 2024-09-23 13:06:05 +07:00
Sara Arjona 818863cccd Merge branch 'MDL-81612_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-09-23 07:36:26 +02:00
Paul Holden 1a6d6694a2 MDL-82581 mod_label: avoid overflowing length of label name. 2024-09-20 19:26:53 +01:00
Sara Arjona da802580da weekly release 4.3.7+ 2024-09-20 16:36:12 +02:00
Sara Arjona 534f220f21 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-09-20 16:36:07 +02:00
Ilya Tregubov d2e842f7b3 Merge branch 'MDL-82663-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-20 10:17:44 +08:00
Huong Nguyen 4eb7c5a590 Merge branch 'MDL-82740-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-09-20 08:44:34 +07:00
Ilya Tregubov 3b6f8e334f Merge branch 'MDL-74188-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-20 09:39:55 +08:00
Ilya Tregubov 5ba84639dd Merge branch 'MDL-82488-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-20 09:25:33 +08:00
Tim Hunt 7cc4823684 MDL-81612 assign: show current value when editing a student's extension
Also, if there is not currently an extension set, the set extension form
will default to whatever is the latest out of the due date, the cut-off date
and midnight tonight (in the server time-zone).
2024-09-19 16:06:21 +01:00
Tim Hunt 476ae75b70 MDL-81612 assign: test generation of extensions
Also, some other improvements.

* In Behat you can now use either idnumber of name to identify an
  assignment you are generating things for.
* create_submission generator methods now wants the cmid in $data['cmid']
  not the confusingly named 'assignid'. The old name is accepted, but
  generates a debugging warning. (That will fail the test, but in a way
  that explains how to fix it.)
2024-09-19 16:06:20 +01:00
Sara Arjona 2528a52808 Merge branch 'MDL-83050-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-09-19 17:06:11 +02:00
Jun Pataleta 197aac357e MDL-82740 core: Check for monologo icons in theme overrides 2024-09-19 20:49:43 +08:00
Laurent David 26babd2ac0 MDL-83050 core_courseformat: Fix index highlight for collapsed section
* Collapsed sections on course index is not highlighting the correct
element when scrolling over subelements.
2024-09-19 12:01:17 +02:00
Ilya Tregubov e494cab5b9 Merge branch 'MDL-82909-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-19 15:08:51 +08:00
Ilya Tregubov 298a87baf3 Merge branch 'MDL-82494-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-19 14:05:50 +08:00
Andrew Nicols fd18519ea6 MDL-83205 core: Ensure that redis lock expiry is valid
PHP allows the specification of invalid values for `max_execution_time`,
including negative values. These should be normalised the same way that
an empty (unlimited) value is.
2024-09-19 13:37:02 +08:00
Ilya Tregubov 6f3c6fc5eb Merge branch 'MDL-81987_403_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_403_STABLE 2024-09-19 12:50:57 +08:00
Jun Pataleta cf1e58654c MDL-79628 core: Add upgrade notes for the navigation_cache changes 2024-09-19 11:08:48 +08:00
Jun Pataleta f2773ec1cc Merge branch 'MDL-79628-move-navcache-to-muc-feature-MOODLE_403_STABLE' of https://github.com/rajandangi/moodle into MOODLE_403_STABLE 2024-09-19 11:07:36 +08:00
Jun Pataleta 04cf9b4e06 Merge branch 'MDL-80965-403-behat-fix' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-09-19 08:41:50 +08:00
AMOS bot 895acd4aa1 Automatically generated installer lang files 2024-09-19 00:09:29 +00:00
Simey Lameze 1f45291f24 MDL-80965 behat: remove wrong tag from step 2024-09-19 07:49:29 +08:00
Sara Arjona db7296f2f6 Merge branch 'MDL-74917-403-wrong-post-actions-list-in-statslib' of https://github.com/melanietreitinger/moodle into MOODLE_403_STABLE 2024-09-18 17:19:23 +02:00
Huong Nguyen 94a643c0d8 Merge branch 'MDL-81278-403' of https://github.com/mickhawkins/moodle into MOODLE_403_STABLE 2024-09-18 16:09:12 +07:00
Ilya Tregubov f7dd7e096a Merge branch 'MDL-80965-403' of https://github.com/ilyatregubov/moodle into MOODLE_403_STABLE 2024-09-18 15:33:40 +08:00
Ilya Tregubov 674fbe100b MDL-80965 mod_quiz: Code style fixes. 2024-09-18 15:29:54 +08:00
Luca Bösch 93dd090c38 MDL-80965 mod_quiz: Put back random q category on the question page. 2024-09-18 15:29:54 +08:00
AMOS bot 7d229de154 Automatically generated installer lang files 2024-09-18 00:07:40 +00:00
Julien 0457ed850c MDL-77625 question restore: test restoring a quiz into a course twice
The verifies that the previous two commits are doing the right thing.
2024-09-17 16:59:02 +01:00
Tim Hunt 6c325a2b3c MDL-77625 question restore: fix restore of existing questions
Continuing from the last commit, the code to restore question
bank entries, versions and questions, was not taking note of
whether the first stage had indentified questions that did not
need to be restored. This is tricky, but the mapping can only be
worked out for questions, but in the backup file, the questions are
inside the question_bank_entries, and versions, so we encounter
those first.

Now, the code just saves the QBE and QV when it encounters them,
and then does all the processing when it gets to the question,
correctly taking note of whether each question should be restored or not.
In cases where a particular question does not need to be restored,
we still set up the corresponding mappings.
2024-09-17 16:59:02 +01:00
Tim Hunt 31734b11c8 MDL-77625 question restore: fix pre-parsing of questions
Restore of categories and questions happens in several phases.
First, the file is scanned for which questions and categories
it contains, to work out if these are new questions which need
to be restored, or if they already exist in the database in a
place that can be used.

That code had not been updated to cope with the Moodle 4.0
versioning changes, so it is updated here (while still keeping
the code to cope with the old backup format.)
2024-09-17 16:59:01 +01:00
Paul Holden 52746d4c9a MDL-82973 tool_usertours: add missing filelib library require. 2024-09-17 16:49:20 +01:00
Sara Arjona 9a0a83a456 Merge branch 'MDL-82389-403' of https://github.com/ssj365/moodle into MOODLE_403_STABLE 2024-09-17 17:31:52 +02:00
Sara Arjona 3d2052dd89 weekly release 4.3.7+ 2024-09-17 15:09:30 +02:00
sam marshall 84d831318f MDL-83163 core_course: Fresh install fails if dependency on format
If any plugin had dependency on a course format, Moodle fresh install
showed dependency errors (even though course format exists).
2024-09-17 10:40:45 +01:00
Melanie Treitinger 49d74934f1 MDL-74917 core: fix typo in function stats_get_post_actions
Fix phpunit test and apply coding guidelines.
2024-09-16 11:19:22 +02:00
Sara Arjona f01bc02e78 Merge branch 'MDL-82875_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-09-16 09:44:12 +02:00
Michael Hawkins 2ab39f557b MDL-81278 core: Update security.txt expiry 2024-09-16 14:50:43 +08:00
Paul Holden e0933f4f41 MDL-81157 files: consistent repository button styling on small screen. 2024-09-15 11:13:08 +01:00
Paul Holden 7eb8fce830 MDL-82909 theme_boost: ensure we target immediate loading icon only.
Ignoring those used within inplace editable components in the table.
2024-09-15 11:11:50 +01:00
Paul Holden 3c3c7b3268 MDL-82909 javascript: replace custom loading icon with existing module. 2024-09-15 11:11:50 +01:00
Tim Hunt 340e5f9a2c MDL-82875 question export: test for not exporting hidden questions 2024-09-13 16:04:43 +01:00
Vithusha Kethiri 28adbc1374 MDL-82875 qbank_export: Fix removing hidden questions from the export 2024-09-13 16:04:43 +01:00
Sara Arjona 4a5d428cd3 weekly release 4.3.7+ 2024-09-13 13:20:56 +02:00
Sara Arjona abeec88715 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-09-13 13:20:51 +02:00
Paul Holden f16681b267 MDL-83094 customfield: align persistent definitions with DB schema.
Where the field/category tables allow nulls, the definition within
each corresponding persistent should match.
2024-09-12 17:37:04 +01:00
Paul Holden 15b4403980 MDL-82602 webservice: correct config link to enable for mobile. 2024-09-12 08:05:12 +01:00
Huong Nguyen eedb5e5f81 Merge branch 'MDL-82545_403_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_403_STABLE 2024-09-12 10:47:08 +07:00
Huong Nguyen 6b3c54d981 Merge branch 'MDL-82959-MOODLE_403_STABLE' of https://github.com/sh-csg/moodle into MOODLE_403_STABLE 2024-09-12 10:35:28 +07:00
AMOS bot c77d234c19 Automatically generated installer lang files 2024-09-12 00:07:40 +00:00
Shamiso.Jaravaza aa07578b4c MDL-82389 mod_bigbluebuttonbn: Fix disablenotes 2024-09-11 09:32:16 -06:00
Huong Nguyen 9b9965110e Merge branch 'MDL-68676-403' of https://github.com/rhell4/moodle into MOODLE_403_STABLE 2024-09-11 15:50:25 +07:00
Huong Nguyen cd8a797f31 Merge branch 'MDL-75692-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-09-11 15:45:35 +07:00
Jun Pataleta 342f13d5df Merge branch 'MDL-82492-403' of https://github.com/vladaskidanovas/moodle into MOODLE_403_STABLE 2024-09-11 15:36:51 +08:00
Huong Nguyen 8341d84ce5 Merge branch 'MDL-79020-403' of https://github.com/ferranrecio/moodle into MOODLE_403_STABLE 2024-09-11 09:19:36 +07:00
AMOS bot 6dff42d1af Automatically generated installer lang files 2024-09-11 00:07:44 +00:00
Huong Nguyen 7b7e907e66 weekly release 4.3.7+ 2024-09-10 20:03:06 +07:00
Laurent David 0ae1c37e6d MDL-75692 core_h5p: Debounce resize events
* Make sure that we don't call the resize event too often to
avoid infinite loop when content is auto resizing (fonts for example)
2024-09-10 11:31:52 +02:00
Huong Nguyen bdba5a0594 Merge branch 'MDL-83047-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-09-10 10:47:50 +07:00
Jun Pataleta 782d262ef6 MDL-83047 theme_boost: Add upgrade note for theme plugins 2024-09-10 10:33:47 +08:00
Jun Pataleta 91932bf748 MDL-83047 theme_boost: Apply background colour only on select layouts
* Apply the styling of `background-color` for `.page-header-headings`
only in the maintenance and secure layouts.
2024-09-09 17:01:23 +08:00
Huong Nguyen e9f261c0f9 Merge branch 'MDL-82860-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-09-09 14:32:32 +07:00
meirzamoodle 19e92ca42c MDL-82860 atto_link: Set value as default to avoid unexpected behaviour 2024-09-09 08:12:05 +07:00
Jun Pataleta 7f6d05ad04 weekly release 4.3.7+ 2024-09-07 06:45:41 +08:00
Stefan Hanauska f0630a0576 MDL-82959 tool_recyclebin: Avoid null value for forcedsettings 2024-09-06 19:47:42 +02:00
ferranrecio 0fadf1ed19 MDL-79020 core_courseformat: hide completion edit link in bulk edit 2024-09-06 11:10:57 +02:00
Jun Pataleta c9e55faacf Merge branch 'MDL-63399-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-09-06 12:29:25 +08:00
Simey Lameze d76e843d8c MDL-63399 behat: update existing tests to use the better download steps
Co-authored-by: Tim Hunt <T.J.Hunt@open.ac.uk>
2024-09-06 12:15:02 +08:00
Simey Lameze a776b0bf55 MDL-63399 behat: new steps to verify downloads
Co-authored-by: Tim Hunt <T.J.Hunt@open.ac.uk>
2024-09-06 12:09:27 +08:00
Huong Nguyen 24d28bf68e Merge branch 'MDL-82948-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-09-06 11:01:27 +07:00
Huong Nguyen 80e2791f25 Merge branch 'MDL-82677-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-09-06 10:51:10 +07:00
Huong Nguyen 1e53070414 Merge branch 'MDL-80946_MOODLE_403_STABLE' of https://github.com/michaelkotlyar/moodle into MOODLE_403_STABLE 2024-09-05 15:54:14 +07:00
Michael Kotlyar c3d725a3cd MDL-80946 quizaccess_seb: Remove invalidkeys text if not using SEB. 2024-09-05 09:06:52 +01:00
Huong Nguyen ee96ff39cb Merge branch 'MDL-81909-403' of https://github.com/rezaies/moodle into MOODLE_403_STABLE 2024-09-05 14:50:11 +07:00
Shamim Rezaie 98086bf044 MDL-81909 mod_assign: fix test_attempt_reopen_method_untilpass 2024-09-05 03:28:07 +10:00
Michael Milette dd94fb1f8c MDL-72856 lib: Only inject one robots/noindex in head of Additional HTML 2024-09-04 12:34:04 -04:00
Sara Arjona 755dea3652 Merge branch 'MDL-82995_MOODLE_403_STABLE_feedback_broken_audio_video' of https://github.com/mariusros/moodle into MOODLE_403_STABLE 2024-09-04 12:59:21 +02:00
Huong Nguyen cfe13f3b73 Merge branch 'MDL-80225-403' of https://github.com/ssj365/moodle into MOODLE_403_STABLE 2024-09-04 09:30:22 +07:00
Marius Rosenbaum c0ef7bb0e4 MDL-82995 mod_feedback: fixed width of audio or video frames being 0 2024-09-03 17:15:43 +02:00
Paul Holden 16457d9346 MDL-80929 customfield: observe backup/restore settings to include. 2024-09-03 13:56:32 +01:00
Paul Holden b62d3965f6 MDL-80929 restore: consistent settings definition for custom fields. 2024-09-03 13:50:03 +01:00
Jun Pataleta d14f5eaa6c weekly release 4.3.7+ 2024-09-03 20:05:21 +08:00
Jun Pataleta 68ac6e6ef8 Merge branch 'MDL-82957-403' of https://github.com/roland04/moodle into MOODLE_403_STABLE 2024-09-03 11:42:28 +08:00
Jun Pataleta 4e9a865984 Merge branch 'MDL-82804-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-03 10:32:23 +08:00
Jun Pataleta e6a32d87a5 Merge branch 'MDL-82717-403' of https://github.com/liamgm/moodle into MOODLE_403_STABLE 2024-09-03 10:29:29 +08:00
Jun Pataleta 26f41c348d MDL-82255 editor_tiny: No need for extra styles for RTL 2024-09-02 16:56:01 +08:00
Jun Pataleta 01e3740d89 Merge branch 'MDL-82255-403' of https://github.com/raortegar/moodle into MOODLE_403_STABLE 2024-09-02 16:01:55 +08:00
Ilya Tregubov 2a9305dbf5 Merge branch 'MDL-82220-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-09-02 10:10:46 +08:00
Paul Holden c0afa63f6e MDL-82494 user: correct profile field name formatting method.
Add optional `$escape` parameter to allow for unescaped return.
2024-08-30 09:48:13 +01:00
Paul Holden b7c05d2cc4 MDL-82488 customfield: allow for unescaped field formatted names.
Resolves double encoding of the same in Report builder editor.
2024-08-30 09:44:47 +01:00
Mikel Martín 7676cd334f MDL-82957 course: Fix section bulk actions alignment 2024-08-30 10:44:17 +02:00
Huong Nguyen e28403c470 Moodle release 4.3.7 2024-08-30 13:51:08 +07:00
Paul Holden 6554262006 MDL-82804 badges: define no results notice inside report instances.
When doing so from calling code, the property is not persisted when
filtering/paging (or any AJAX interaction); instead, it should be
set from within the report instance itself.
2024-08-29 17:31:34 +01:00
Huong Nguyen 3f94e61e49 weekly release 4.3.6+ 2024-08-29 18:10:02 +07:00
Paul Holden e109b9dd21 MDL-82483 tag: update the max length constant to match schema. 2024-08-29 10:38:06 +01:00
Liam Moran 896fa8b5a0 MDL-82717 enrol_lti: Make contextmembershipsurl property immutable
The contextmembershipsurl property on the nrsp_info object is itself
an object of type moodle_url so its getter should return a copy
of the moodle_url object instead of a reference to the class-internal
object. This commit adds a test for get_context_memberships_url and
updates the getter so the property is immutable.
2024-08-29 03:47:10 -05:00
Jun Pataleta 47deadb259 MDL-82948 theme_boost: Make <blockquote>'s border a bit darker 2024-08-29 16:04:43 +08:00
raortegar ff344e2495 MDL-82255 editor_tiny: Style blockquote in edit view 2024-08-29 09:25:21 +02:00
Paul Holden 3ea261a1c1 MDL-82365 mod_lesson: stricter equality checks of activity password. 2024-08-29 12:13:31 +08:00
Huong Nguyen f4e7f201bc Merge branch 'MDL-82446-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-29 11:05:30 +07:00
Jun Pataleta 0bad70f9c4 Merge branch 'MDL-82651-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-08-29 11:59:40 +08:00
Jun Pataleta c5f8a854b7 Merge branch 'MDL-82802-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-29 11:40:04 +08:00
Huong Nguyen 7945536fde MDL-82790 filter_tidy: Fix coding style 2024-08-29 10:19:51 +07:00
Huong Nguyen 330ecf9203 Merge branch 'MDL-82790-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-29 10:04:14 +07:00
Ilya Tregubov 75af70591b Merge branch 'MDL-82810_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-08-29 10:57:34 +08:00
Huong Nguyen 46f2f2cc29 Merge branch 'MDL-82898-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-08-29 09:50:29 +07:00
Paul Holden 7d2988dfe5 MDL-76962 auth_oauth2: users can only delete their own linked logins. 2024-08-29 10:32:41 +08:00
Stefan Hanauska def0c592a0 MDL-80974 enrol: Set category context for enrol form 2024-08-28 12:33:09 +02:00
Simey Lameze 7669660f9b MDL-82651 behat: remove unnecessary steps 2024-08-28 13:10:35 +08:00
Simey Lameze ed24ab1b04 MDL-82651 behat: wait for button to exist before clicking 2024-08-28 13:10:35 +08:00
Angelia Dela Cruz 3891da010b MDL-82898 enrol_self: Behat to test student enrolment using key 2024-08-28 11:45:59 +08:00
Paul Holden 9e40eb38c0 MDL-82663 user: fix check for current user removing own enrolment.
We only need to remove the current user from selection if they were
ever part of the selection originally.
2024-08-27 16:55:27 +01:00
Marina Glancy 8c875ed525 MDL-82567 core: Add has_capability method
Co-authored-by: David Woloszyn <david.woloszyn@moodle.com>
Co-authored-by: Jun Pataleta <jun@moodle.com>
2024-08-26 04:04:18 +00:00
Huong Nguyen 330d8baf27 MDL-69684 session_redis: Improve upgrade note 2024-08-26 10:59:43 +07:00
Huong Nguyen b1c64a3b25 MDL-69684 session_redis: Improve PHPUnit test 2024-08-26 10:59:36 +07:00
Huong Nguyen 55f37d0dc7 Merge branch 'MDL-69684-M403_its-possible-to-hold-a-redis-session-lock-forever' of https://github.com/ziegenberg/moodle into MOODLE_403_STABLE 2024-08-26 10:58:13 +07:00
rajandangi 1619484716 MDL-79628 navigation: Refactor navigation_cache to use MUC 2024-08-26 09:13:18 +09:30
Shamim Rezaie cd08a0ecee Merge branch 'MDL-82006-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-24 16:21:32 +10:00
Sara Arjona 062791efe1 weekly release 4.3.6+ 2024-08-23 16:04:01 +02:00
Jake Dallimore 6bc54e875d Merge branch 'MDL-82787-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-23 11:51:41 +08:00
Jun Pataleta f308827fa8 Merge branch 'MDL-79215-MOODLE_403_STABLE' of https://github.com/MichaelReyesCatcan/moodle into MOODLE_403_STABLE 2024-08-22 23:57:34 +08:00
KarlReyesCatalyst 37bca6ce6b MDL-79215 lib/graphlib: Typecasting round() function to INT. 2024-08-22 10:28:25 -04:00
Mark Johnson 916bd72fc1 MDL-82545 gradereport_grader: Limit grades per page
This replaces the limit on the number of students per page with a number
of grades per page, to take into account the number of grade items on a
course.
2024-08-22 11:04:57 +01:00
Shamiso.Jaravaza 342b3707b3 MDL-80225 mod_bigbluebuttonbn: Fix missing recordings 2024-08-21 21:00:40 -06:00
Huong Nguyen 19f639210a Merge branch 'MDL-82841-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-08-22 08:43:56 +07:00
Sara Arjona c66b5072e1 Merge branch 'MDL-82695_403_STABLE' of https://github.com/andrewhancox/moodle into MOODLE_403_STABLE 2024-08-21 16:07:52 +02:00
Sara Arjona 377fcdf1bd Merge branch 'MDL-82655-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-08-21 15:54:27 +02:00
Andrew Hancox 2ad2ba2d2c MDL-82695 qtype_multianswer: Fix div by zero in compute_final_grade 2024-08-21 13:44:47 +01:00
Angelia Dela Cruz 56b3532c63 MDL-82841 mod_workshop: Behat for submissions with set # of attachments 2024-08-21 19:01:41 +08:00
Huong Nguyen 71a0ce575f Merge branch 'MDL-82110-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-21 17:43:55 +07:00
Angelia Dela Cruz 1d101c4a52 MDL-82655 mod_workshop: Behat test for manual and random allocation 2024-08-21 17:44:46 +08:00
Jun Pataleta f980061174 Merge branch 'MDL-78785_403_toolbrickfield_rgbcolorcontrasts' of https://github.com/brickfield/moodle into MOODLE_403_STABLE 2024-08-21 11:49:40 +08:00
Andrew Nicols 2af12db84c MDL-82787 behat: Correct stop of webdriver on failure 2024-08-21 08:46:16 +08:00
Sara Arjona 869921831d weekly release 4.3.6+ 2024-08-20 20:16:02 +02:00
Sara Arjona 594795daa6 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-08-20 20:15:59 +02:00
Andrew Nicols 536c0f3e53 MDL-82110 core: Remove debugging for unmigrated hooks in unit tests 2024-08-20 20:28:49 +08:00
Andrew Nicols bff37a3eab MDL-82790 filter_tidy: Disable the tidy filter
This behaves very poorly and for most users has been silently not
working for many years.

When we stopped it from silently failing we discovered a number of
issues that it causes, for example:
- MDL-61117
- MDL-82790
2024-08-20 20:15:23 +08:00
vlad.kidanov c8f98fe85d MDL-82492 gradereport_grader: Grader report HTML output optimization 2024-08-20 10:26:57 +01:00
Sara Arjona 9d7695c5fa Merge branch 'MDL-82455-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-19 16:46:03 +02:00
AMOS bot 027ee0fef8 Automatically generated installer lang files 2024-08-19 00:07:43 +00:00
Karen Holland 2e1aa0c321 MDL-78785 tool_brickfield: Processing rgb & rgba color contrasts
Including rgb() & rgba() processing for colour contrast checking.
  Including review requests :void and @covers for phpunit testing.
2024-08-16 17:32:59 +00:00
Tim Hunt 1ffabb9359 MDL-82810 question bank: stop action menu from getting truncated 2024-08-16 13:38:46 +01:00
Paul Holden 48e0029f0f MDL-74188 notes: consistent formatting of text content.
Each method of adding notes, either via UI or external service (via
course participant actions), defined the format of the content
different from one another. Neither of those formats were correct.
2024-08-16 10:20:08 +01:00
Paul Holden f48077b2ed MDL-82220 group: check valid mapping when restoring custom fields. 2024-08-16 10:09:10 +01:00
Paul Holden b3bdb05db1 MDL-82220 backup: ensure correct group/ing custom fields are included.
We should include only the custom field values that belong to those
groups and/or groupings that are being backed up.
2024-08-16 10:09:10 +01:00
Huong Nguyen 07c3ab9006 weekly release 4.3.6+ 2024-08-16 08:39:21 +07:00
Paul Holden b6887b94ce MDL-82455 badges: link report recipients count to appropriate page. 2024-08-15 22:37:21 +01:00
Paul Holden fcf82fab25 MDL-82006 reportbuilder: move filter Behat scenarios inside component. 2024-08-15 13:17:26 +01:00
Paul Holden 0ac01eea47 MDL-82802 tool_xmldb: allow numeric characters in table names. 2024-08-15 12:00:46 +01:00
Huong Nguyen 765b5e48bd Merge branch 'MDL-82724-MOODLE_403_STABLE' of https://github.com/phmemmel/moodle into MOODLE_403_STABLE 2024-08-15 11:00:01 +07:00
Jun Pataleta 0cda695df0 Merge branch 'MDL-82782-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-15 11:51:50 +08:00
Jun Pataleta 6f950a3ccf Merge branch 'MDL-82747-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-15 11:38:07 +08:00
Andrew Nicols 9c63160dcc MDL-82747 core: Remove erroneously included aws-sdk file import 2024-08-15 11:35:08 +08:00
Jun Pataleta 758503c85d Merge branch 'MDL-82798-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-08-15 11:13:41 +08:00
Huong Nguyen effe286ca8 Merge branch 'MDL-82758-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-08-15 09:38:07 +07:00
Huong Nguyen c3ed25c71c MDL-82798 qtype_ddmarker: Fix Behat failure 2024-08-15 09:17:23 +07:00
Jun Pataleta b0a74d3487 Merge branch 'MDL-82792-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-08-15 10:14:40 +08:00
Jun Pataleta 8e1891c8cb Merge branch 'MDL-82747-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-08-14 23:04:31 +08:00
Daniel Ziegenberg 3460632bf1 MDL-69684 session: Redis session locks set with expiry atomically
Co-Authored-By: Jamie Chapman-Brown <jamie.chapman-brown@agilicus.com>
Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
2024-08-14 17:03:38 +02:00
Andrew Nicols da1163b2b9 MDL-82747 core: Register composer autoload files
Unfortunately PHP does not provide any means to autoload the files that
a functions is located in, even if they are in an namespace.

To work around this, Composer makes use of an `autoload.files` section
in the `composer.json` file. Shortly after the Composer autoloader is
registered with the `spl_autoload_register` call it also includes any
files listed in this section.

Moodle does not do this and really we should be doing so.

This change adds a section to the autoloader registration method which
loads all of the files defined in any third-party library included in
our `lib` directory which contains any `composer.json` file with such a
stanza.
2024-08-14 21:59:52 +08:00
Andrew Nicols 734a5f1e80 MDL-82747 core: Provide a standard way to register the Autoloader 2024-08-14 21:59:52 +08:00
Andrew Nicols 6c4be65b3e MDL-82782 behat: Support runtime scaling of Behat windows 2024-08-14 21:55:32 +08:00
Sara Arjona c49e9f7fc9 MDL-82792 h5p: Fix random behat failures
We've started seeing various failures in Firefox and Classic.
Increasing the default window size fixes them.
2024-08-14 12:18:33 +02:00
Sara Arjona e1daeec17d Merge branch 'MDL-82682-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-08-14 09:13:09 +02:00
Huong Nguyen 092edd5696 MDL-82682 behat: fix window size failures on Chrome 2024-08-14 11:37:14 +08:00
Simey Lameze 4aa8e531a6 MDL-82682 behat: increase window size to avoid fails 2024-08-14 11:37:14 +08:00
Sara Arjona d0302639fa Merge branch 'mdl-82214-m403' of https://github.com/NeillM/moodle into MOODLE_403_STABLE 2024-08-13 16:08:21 +02:00
Sara Arjona 5312f57718 Merge branch 'MDL-82502-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-13 13:15:04 +02:00
Ilya Tregubov e88a87e22e Merge branch 'MDL-64675-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-13 10:44:36 +08:00
Ilya Tregubov fcf23db6be Moodle release 4.3.6 2024-08-10 14:54:55 +08:00
Jun Pataleta 78d0d69cfa MDL-82758 gha: Remove reference to the master branch 2024-08-09 16:16:26 +08:00
Jun Pataleta 6e8dcf515a Merge branch 'MDL-82599-403-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_403_STABLE 2024-08-09 11:18:54 +08:00
Ilya Tregubov e1d320d4bb weekly release 4.3.5+ 2024-08-09 09:34:27 +08:00
Huong Nguyen ce59fcf650 MDL-82745 filter_tex: Improve PHPUnit test 2024-08-08 21:06:01 +08:00
Mark Johnson 019bcd6f18 MDL-81987 redis: Set connection and read timeouts to 10 seconds
This allows the site to continue operating in case of degraded
performance, rather than throwing exceptions.
2024-08-08 13:14:30 +01:00
Michael Hawkins a17934ee11 MDL-82745 filter_tex: Improve filter deny list 2024-08-08 11:40:35 +07:00
Michael Hawkins 07776fe1d5 MDL-82576 qtype_calculated: Improve formula regexes 2024-08-08 11:11:51 +07:00
Ilya Tregubov 8ecbb1bea3 Merge branch 'MDL-82608-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 11:09:39 +08:00
Ilya Tregubov 0194edd6c4 Merge branch 'MDL-82605-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 11:03:45 +08:00
Safat 27c875e461 MDL-82395 tool_xmldb: Table layout update 2024-08-08 10:01:12 +07:00
Jun Pataleta ef4d45b20b Merge branch 'MDL-82560-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-08-08 10:44:48 +08:00
Paul Holden 88f41107c6 MDL-79373 admin: ensure all current password configs are defined.
Ensure the admin preset export tool has an accurate record of each,
to be observed as sensitive settings when creating an export.
2024-08-08 09:22:39 +07:00
Andrew Nicols 4940dc9470 Merge branch 'MDL-80593-403-alt' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-08-08 10:20:00 +08:00
Angelia Dela Cruz 2f9e8dddd2 MDL-82560 mod_forum: Test that students can only start one discussion 2024-08-08 10:18:34 +08:00
Huong Nguyen f9639f1404 Merge branch 'MDL-82177_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-08-08 09:11:17 +07:00
Huong Nguyen c2158534c0 Merge branch 'MDL-82669-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 08:58:57 +07:00
Jun Pataleta 78813b3766 Merge branch 'MDL-77784-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 09:55:32 +08:00
Huong Nguyen cfef0be6c5 Merge branch 'mdl-826620-43' of https://github.com/matthewhilton/moodle into MOODLE_403_STABLE 2024-08-08 08:41:41 +07:00
Ilya Tregubov fa8af811d3 Merge branch 'MDL-82209-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 09:22:32 +08:00
Ilya Tregubov 9c02db4d4d Merge branch 'MDL-82525-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 08:27:34 +08:00
Ilya Tregubov a30b6e8547 Merge branch 'MDL-82208-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-08 08:18:22 +08:00
Paul Holden f83bba28b5 MDL-64675 mod_feedback: better detection of last page break element.
Inform user when a page break item cannot be added.
2024-08-07 16:57:46 +01:00
Philipp Memmel f682ff4097 MDL-82724 editor_tiny: Harden check for quicktoolbar and contextmenu 2024-08-07 11:56:07 +02:00
Jun Pataleta d2a1df8890 Merge branch 'MOODLE_403_MDL-82518' of https://github.com/danielneis/moodle into MOODLE_403_STABLE 2024-08-07 17:12:01 +08:00
Ilya Tregubov 51e55e9fba Merge branch 'MDL-81830-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-07 15:28:21 +08:00
Paul Holden 82243bf8c8 MDL-81394 restore: format backup file metadata details safely. 2024-08-07 14:04:48 +08:00
Ilya Tregubov 2b36e64a26 MDL-79541 gradereport_user: Fix indentation in Behat. 2024-08-07 04:13:54 +00:00
Huong Nguyen 2503e35684 MDL-81718 core_grades: Fix Behat failures 2024-08-07 04:13:54 +00:00
raortegar f4aa615c74 MDL-81718 core: Improve localstorage validation 2024-08-07 04:13:54 +00:00
Paul Holden 6f8db95ccf MDL-82558 h5p: escape template error/exception content. 2024-08-07 04:13:54 +00:00
Paul Holden 0b4100c13e MDL-82392 blocks: consistent cleaning of block instance names. 2024-08-07 04:13:54 +00:00
Paul Holden 01375bdaa0 MDL-82261 mod_feedback: ensure only non-respondents can be messaged. 2024-08-07 04:13:54 +00:00
Paul Holden e360a5dc2e MDL-82390 badges: correct context check when deleting badges. 2024-08-07 04:13:54 +00:00
meirzamoodle 57de85a0a0 MDL-82136 curl: Send credentials to redirect URL if allowed
Curl has the option CURLOPT_UNRESTRICTED_AUTH. If true, curl will send
the credentials to a different host. If false, they will not be sent.

CURLOPT_UNRESTRICTED_AUTH can only work if the CURLOPT_FOLLOWLOCATION
option is true. The filelib forces the CURLOPT_FOLLOWLOCATION option
to be false, because all redirects are emulated at the PHP level. So,
in this case, the CURLOPT_UNRESTRICTED_AUTH option is only being used
in our logic and will not work as you might expect it to.

This patch works almost the same as CURLOPT_UNRESTRICTED_AUTH in ideal
conditions. It will check whether the host is different. If so, the
system will check what value CURLOPT_UNRESTRICTED_AUTH has. If it is
not specified, then by default, it will be false. If false, then
credentials will not be sent.
2024-08-07 04:13:54 +00:00
Paul Holden ee7b35cd2f MDL-82262 mod_feedback: fix broken bulk message sesskey checks. 2024-08-07 04:13:54 +00:00
Paul Holden 2c5f827dcc MDL-64984 mod_glossary: capability check when restoring global type. 2024-08-07 04:13:54 +00:00
David Woloszyn 14feac6458 MDL-81951 communication_matrix: Fix suspended users ignored bug
The implementation of this bug fix is slightly different on 403 branch
compared to later branches due to major changes that were applied
to communication with the addition of hooks and helpers.
2024-08-07 04:13:54 +00:00
David Woloszyn 4e7ee4e0b9 MDL-81951 communication_matrix: New trait for power levels
A more reliable way of obtaining room power levels is now used in the
new trait get_room_power_levels_v3. This makes
get_room_powerlevels_from_sync_v3 less needed, but not necessarily
redundant. The names of the containing methods have been adjusted to
make better sense of which trait they belong to.
2024-08-07 04:13:54 +00:00
Ilya Tregubov 5760639c16 MDL-79541 core_grades: Add missing user info to search services.
Seems just fullname is not enough. So added all name fields.
2024-08-07 04:13:54 +00:00
Ilya Tregubov 299bb8180c MDL-79541 core_grades: Hidden user fields check for search.
If some user profile fields are hidden on some grade reports
users without permission were able to see those.
2024-08-07 04:13:54 +00:00
Huong Nguyen 43ccc81b1b Merge branch 'MDL-82611-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-07 10:25:34 +07:00
Huong Nguyen a4d92e88cf Merge branch 'MDL-82620-403' of https://github.com/ericmerrill/moodle into MOODLE_403_STABLE 2024-08-07 10:20:53 +07:00
Jun Pataleta 0c26411ad5 Merge branch 'MDL-82606_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-08-07 11:12:16 +08:00
Tim Hunt 7323860c03 MDL-82606 filterlib: pass a row limit to recordset for performance
On Postgres, at least, get_recordset_sql performs signficantly worse
if you don't pass a limit. So, we add a limit to the query, but one
that in enormously too large, so it should never have an effect.
(And, there is code to check we never hit the limit, to avoid subtle bugs.)
2024-08-06 10:47:50 +01:00
Jun Pataleta dd9a9980ad Merge branch 'MDL-82344-403' of https://github.com/snake/moodle into MOODLE_403_STABLE 2024-08-06 17:26:52 +08:00
Jun Pataleta 025cb77c93 Merge branch 'MDL-79568-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-08-06 17:20:02 +08:00
Neill Magill 2e975de3ed MDL-82214 admin: Settings should not change when in read only mode
Before this change if some settings were:

* read only
* visible on a settings page
* are set or have values selected

when the settings page was saved the setting would be set tobe empty,
because the hidden input remained on the page, while the other inputs
where not posted to Moodle.
2024-08-06 09:54:18 +01:00
Paul Holden 018f792769 MDL-82446 files: pleasantly style the filepicker modal containers. 2024-08-05 08:41:03 +01:00
Paul Holden 41301da68e MDL-79568 javascript: remove lang parameter from legacy string calls. 2024-08-05 08:33:26 +01:00
Ilya Tregubov d98864859a Merge branch 'MDL-82171-muc-sited-MOODLE_403_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_403_STABLE 2024-08-05 11:19:28 +08:00
Daniel Neis Araujo 6f77e20d2b MDL-82518 core_user: Fix regression introduced by MDL-80271 2024-08-02 14:47:48 -03:00
Paul Holden 69048fc549 MDL-82669 mod_assign: remove Atto reliance workaround for Behat.
See 8fe80e743c for context, and 802ff3e2e3 for additonal comments.
2024-08-02 10:33:43 +01:00
Paul Holden d9a462727b MDL-82669 editor: remove reliance on Atto editor in Behat scenarios. 2024-08-02 10:33:43 +01:00
Jun Pataleta 264c286a63 MDL-82677 theme: Set a background colour for page heading
* Set a background colour for the .page-header-headings class.
* Assign the .page-header-headings class to the maintenance mode
template's page header div.
2024-08-02 17:25:02 +08:00
Paul Holden eadd93065c MDL-82502 courseformat: align module action capability checks.
The "Hide/Show/Duplicate" actions should be considered self-contained,
and not also require "manageactivities" capability (per existing docs)
in addition to the specific capability that controls the action itself.

Also ensure the "Duplicate" capability checks are in the course context.
2024-08-02 10:01:22 +01:00
Paul Holden 8ec33d16c7 MDL-82608 mod_data: null content checks when editing fields. 2024-08-02 09:57:43 +01:00
Paul Holden bc39fac69f MDL-82605 contentbank: pre-load contexts for options list.
Prevents additional DB reads per category/course, which can be
potentially expensive on large sites.
2024-08-02 09:50:24 +01:00
Ilya Tregubov 431f27e7bf weekly release 4.3.5+ 2024-08-02 09:30:53 +08:00
Ilya Tregubov c3097a8084 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-08-02 09:30:49 +08:00
Matthew Hilton 7a325a2824 MDL-82662 login: load library with require_once 2024-08-02 10:52:30 +10:00
David Mudrák c065e8b259 MDL-82599 lang: Use the fixed strings in tests, too 2024-08-01 21:30:50 +02:00
Helen Foster df998bfd47 MDL-82599 lang: Import fixed English strings (en_fix) 2024-08-01 21:16:05 +02:00
Paul Holden 0cd3880ef3 MDL-77784 quiz_grading: editor agnostic Behat scenario steps. 2024-08-01 14:17:23 +01:00
Huong Nguyen 794464cdca Merge branch 'MDL-80064-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-08-01 10:41:53 +07:00
Huong Nguyen 32c6297d21 Merge branch 'MDL-82598-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-08-01 10:27:08 +07:00
Huong Nguyen ab84cbafd1 MDL-80593 core: Make Modal to work with Debug Template Info mode 2024-08-01 10:18:31 +07:00
Huong Nguyen ec8f02fe93 MDL-80017 core_grades: Move upgrade note 2024-08-01 09:17:04 +07:00
Huong Nguyen 1098d89c96 Merge branch 'MDL-80017-403' of https://github.com/jleyva/moodle into MOODLE_403_STABLE 2024-08-01 09:15:51 +07:00
Ilya Tregubov 9316aeadc8 Merge branch 'MDL-81689_MOODLE_403_STABLE' of https://github.com/rzhtwberlin/moodle into MOODLE_403_STABLE 2024-08-01 09:58:57 +08:00
Jun Pataleta 9437d3f3e5 Merge branch 'MDL-82286-403' of https://github.com/daledavies/moodle into MOODLE_403_STABLE 2024-08-01 09:46:37 +08:00
AMOS bot 18b0d6e27b Automatically generated installer lang files 2024-08-01 00:07:32 +00:00
Sara Arjona 3f163bb902 Merge branch 'MDL-72876-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-07-31 17:15:26 +02:00
Sara Arjona bfa3494d6c Merge branch 'MDL-82596-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-31 16:46:12 +02:00
Dale Davies 5302515c40 MDL-82286 quiz_accessrule: Add SEB config test for floating point number
This tests several variations of SEB config files, to ensure Moodle
is able to parse them and generate a config key hash that matches
what SEB expects.

Additional values have been added to the unencrypted_win_233.seb
config file to cover the existence of floating point values,
ensuring they are serialized correctly. The config hash value
has been updated in real_ck_hash_provider to reflect the change.

Also added coverage information to the test case class docblock.
2024-07-31 11:16:45 +01:00
Jun Pataleta c48c1d29ab Merge branch 'MDL-82187-single-button-403' of https://github.com/djarran/moodle into MOODLE_403_STABLE 2024-07-31 17:21:22 +08:00
Paul Holden d78df6e8e4 MDL-82208 block_starredcourses: avoid double encoding course name. 2024-07-31 08:47:29 +01:00
Simey Lameze 105686c55b MDL-82598 behat: improve example submission test 2024-07-31 09:05:20 +08:00
AMOS bot 9364de6276 Automatically generated installer lang files 2024-07-31 00:07:29 +00:00
Tim Hunt 041ed9043b MDL-82177 file upload: default to path '/'when things go wrong
This 'fix' is basically a work-around, but one that is already used in
some places. Now it is used in all similar places.

Exactly what causes the current file path in a file manager to become
unset is still unclear to me, but it seems to be an obscure race
condition that is very hard to reproduce.

However, when it happens, currently we are effectively defaulting to
path '/undefined/'. Using '/' is never worse, and is infinitely better
in the case where the filepicker does not allow folders to be used
(which includes important cases like essay questions in a quiz, which
some people use for exams!). In that case, falling back to non-top-level
path leads to dataloss.

Also, this is all historic JavaScript which will get replaced in the
grand de-YUI-fication, so I think a pragmatic fix is justified here.
2024-07-30 15:07:25 +01:00
Jun Pataleta 17af3c7054 MDL-72876 theme_classic: Enclose welcome message in Bootstrap card 2024-07-30 19:40:32 +08:00
meirzamoodle 7878dda84b MDL-80064 authentication: password can be null
The Open ID Connect plugin uses null for the password,
which makes the internal password update fail to proceed.
Allowing null resolved the problem.

As a note, there is a potential issue if the authentication method has
a false return for the prevent_local_password because it will trigger
the hash_internal_user_password() where  the $password can not be null.
Since this only addresses the oauth2 issue, we should ignore it.
2024-07-29 15:53:08 +07:00
Paul Holden eeb9847c61 MDL-82525 user: correct course parameter for course profile page. 2024-07-29 09:22:07 +01:00
Paul Holden 2e8b0d29ee MDL-81830 calendar: handle clearing of group type course element. 2024-07-29 09:20:56 +01:00
Paul Holden 680fc50218 MDL-82209 calendar: consistent event action icon hovering.
* Apply hover on the icons, rather than the outer container;
* Make hover colour and text decoration appropriate for the icon
2024-07-29 09:19:46 +01:00
Jake Dallimore 5264d41125 MDL-82344 mod_lti: relax content selection validation in instance form
This was added in MDL-78916 in 4.3 but makes configuring a generic
launch to the default tool URL impossible, since a content item must be
selected. This fix:
- Makes this element optional again, which allows teachers to choose
whether a given instance launches into selected content, or launches
the default tool URL.
- Changes the style to btn-secondary, given it's now optional again
2024-07-29 13:07:45 +08:00
Andrew Nicols e79703fa30 Merge branch 'MDL-82250-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-07-29 11:48:32 +08:00
Ilya Tregubov 9247c786e9 Merge branch 'MDL-80345-403' of https://github.com/MartinGauk/moodle into MOODLE_403_STABLE 2024-07-29 11:33:46 +08:00
Paul Holden b3363ff7b7 MDL-82596 behat: switch manual private files upload to generator. 2024-07-28 19:26:49 +01:00
Paul Holden 4870d18dad MDL-82596 behat: tidy up existing usage of private files generator.
Filename is no longer required (since 83db25c330), given it never
did anything so can be removed. Requiring the "Private files" block
also isn't necessary since original switch to generator methods.
2024-07-28 19:13:47 +01:00
Paul Holden 16931c9db2 MDL-82611 mod_assign: capability check before exporting grade link. 2024-07-26 21:20:48 +01:00
Eric Merrill ad0188abae MDL-82620 completion: Make enrol duration comp happen at the right time 2024-07-26 14:11:48 -04:00
Johannes Burk 8f86be0184 MDL-81689 tests: Check task DB record for nextruntime 2024-07-26 10:33:12 +02:00
Johannes Burk c05ead813e MDL-81689 tasks: add unit test to check for the bug 2024-07-26 10:33:12 +02:00
Jun Pataleta e119a01a4f weekly release 4.3.5+ 2024-07-26 13:35:44 +08:00
Jun Pataleta 3548666713 NOBUG: Fixed SVG browser compatibility 2024-07-26 13:35:42 +08:00
Jun Pataleta 4e9d0e5632 Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-07-26 13:35:41 +08:00
Jun Pataleta 9624bc226c Merge branch 'MDL-82373-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-26 13:19:57 +08:00
Andrew Nicols 35e3be3c33 MDL-82373 core_message: Make message drawer router behat-aware
The drawer router was modifying the DOM in a variety of ways and hiding
content, without any pendingJS checks. As a result, there were cases
where a part of the UI was not visible, but had been rendered and was in
the DOM.

This change wraps the router Go method in a pendingJS call that only
resolves when the router transition completes.

Additionally the lazy load manager had a similar issue.
2024-07-26 12:45:30 +08:00
Juan Leyva 5e4e5bf13e MDL-80017 core_grades: Fix return type for itemname 2024-07-25 11:16:45 +02:00
Huong Nguyen 9cb172a65d Merge branch 'MDL-82527-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-25 10:49:18 +07:00
Huong Nguyen 0e14c24d9a Merge branch 'MDL-82328-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-25 10:36:20 +07:00
Jun Pataleta cb247b8c0f Merge branch 'MDL-82373-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-25 11:31:20 +08:00
Huong Nguyen 2548f1ddf5 Merge branch 'MDL-58287-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-25 10:29:59 +07:00
Jun Pataleta 1aa1ffba4e Merge branch 'MDL-77706-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-25 11:02:38 +08:00
Huong Nguyen 9439acba52 Merge branch 'MDL-82553-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-07-25 09:17:47 +07:00
Shamim Rezaie 6ee8b49e95 Merge branch 'MDL-82551-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-07-25 11:53:30 +10:00
Huong Nguyen ad9485bf80 Merge branch 'MDL-82554-MOODLE_403_STABLE' of https://github.com/micaherne/moodle into MOODLE_403_STABLE 2024-07-25 08:51:00 +07:00
Huong Nguyen 977656caaf Merge branch 'MDL-82451-403' of https://github.com/aanabit/moodle into MOODLE_403_STABLE 2024-07-25 08:44:03 +07:00
Huong Nguyen 537b00e8b0 Merge branch 'MDL-82422-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-07-25 08:37:01 +07:00
AMOS bot 9ccfc52146 Automatically generated installer lang files 2024-07-25 00:08:05 +00:00
Amaia Anabitarte 184977d3dc MDL-82451 course: Switch hide/show icons for section action menu 2024-07-24 12:18:35 +02:00
Jun Pataleta c51ea2b1fb Merge branch 'MDL-81803-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-24 16:57:43 +08:00
Jun Pataleta c07afde99f Merge branch 'MDL-82289-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-24 15:05:24 +08:00
Angelia Dela Cruz fab4e5c529 MDL-82422 mod_workshop: Behat for how strict assessment comparison is 2024-07-24 14:01:07 +08:00
Huong Nguyen b906e01ec6 Merge branch 'MDL-82528-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-24 12:01:14 +07:00
Michael Aherne 66ebd9db13 MDL-82554 question: Allow null createdby in question_has_capability_on. 2024-07-23 10:45:09 +01:00
Simey Lameze 117165c346 MDL-82250 core: add web installer test workflow 2024-07-23 13:33:12 +08:00
Jun Pataleta e94157a6dd MDL-82553 behat: Run accessibility tests using WCAG 2.2 success criteria 2024-07-22 14:38:00 +08:00
Jun Pataleta 09ea3a579b MDL-82551 core: Set welcome message heading to level 1 2024-07-22 14:21:14 +08:00
Huong Nguyen 140094cad8 Merge branch 'MDL-82481-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-22 10:40:58 +07:00
Huong Nguyen 3f9b5fa648 Merge branch 'MDL-82193-403' of https://github.com/ericmerrill/moodle into MOODLE_403_STABLE 2024-07-22 09:40:00 +07:00
Ilya Tregubov 587685d0c5 Merge branch 'MDL-82499-MOODLE_403_STABLE' of https://github.com/micaherne/moodle into MOODLE_403_STABLE 2024-07-22 09:43:18 +08:00
djarrancotleanu b2c3857364 MDL-82187 core: Add default type for single button in template 2024-07-22 09:27:36 +10:00
AMOS bot 659af23164 Automatically generated installer lang files 2024-07-21 00:07:39 +00:00
Paul Holden c5451fb629 MDL-58287 courseformat: ensure all format plugins are returned. 2024-07-19 15:23:45 +01:00
Paul Holden 2e4f29999f MDL-82528 courseformat: switch to existing group action icon.
Use a version that already exists in our fontawesome mapping so it
can be consistently styled/overridden.
2024-07-19 12:54:40 +01:00
Sara Arjona ab0045f9a4 Merge branch 'MDL-81119-forced-config-MOODLE_403_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_403_STABLE 2024-07-19 12:37:23 +02:00
Benjamin Walker 36bc92acf0 MDL-81119 tool_recyclebin: Stop overriding unrelated forced config 2024-07-19 14:37:21 +10:00
Ilya Tregubov 8efeae492e weekly release 4.3.5+ 2024-07-19 09:30:31 +08:00
Paul Holden 93f67ab063 MDL-82481 customfield_select: return field options pre-formatted. 2024-07-18 14:03:21 +01:00
Paul Holden a557f745bc MDL-82481 reportbuilder: re-use existing method for field options. 2024-07-18 14:03:21 +01:00
Paul Holden 17f0e4e776 MDL-82527 h5p: improve editor Behat scenarios for embedding content.
* Move the shared drag fixture out of the Atto plugin;
* Switch to using faster generators for populating private files;
* Clarify required fields for private files generator
2024-07-18 09:38:10 +01:00
Jun Pataleta d99a6bbfe4 Merge branch 'MDL-82505-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-18 12:50:36 +08:00
Jun Pataleta 45ec12f24f Merge branch 'MDL-75864-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-07-18 12:47:43 +08:00
Huong Nguyen 5f104acde5 MDL-82505 calendar: more precise matching of calendar day partial
The partial name selector points to the parent element,
but the Javascript code monitors the child element.
We need to make it consistent
2024-07-18 11:37:44 +07:00
Andrew Nicols 661a9ce962 Merge branch 'MDL-82309-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-18 11:59:02 +08:00
Ilya Tregubov 11f0f20e34 Merge branch 'MDL-82445-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-18 11:36:47 +08:00
Andrew Nicols afaf5187e1 Merge branch 'MDL-81932-403' of https://github.com/safatshahin/moodle into MOODLE_403_STABLE 2024-07-18 11:28:31 +08:00
Huong Nguyen ddc90af2da Merge branch 'MDL-82192-403' of https://github.com/ericmerrill/moodle into MOODLE_403_STABLE 2024-07-18 10:27:33 +07:00
Andrew Nicols 8af45284aa Merge branch 'MDL-81272-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-18 11:22:25 +08:00
Andrew Nicols 77104c61cb MDL-82445 filter_tidy: Ensure locale does not change when using Tidy 2024-07-18 11:00:42 +08:00
Andrew Nicols 116e5abbc5 MDL-82445 core: Create locale helper utility 2024-07-18 11:00:42 +08:00
Ilya Tregubov 64796d367e Merge branch 'MDL-82090-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-18 10:40:10 +08:00
Ilya Tregubov 23b8b0fdc6 Merge branch 'MDL-82444-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-18 10:34:04 +08:00
Huong Nguyen ec40091d0a Merge branch 'MDL-82467-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-18 09:20:14 +07:00
Sara Arjona a6a970124a Merge branch 'MDL-82353-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-07-17 17:08:17 +02:00
Andrew Nicols 42fb4adf3e MDL-82373 behat: Disable axe target-size rule
Disable the target-size rule.
This rule was added in Axe 4.7, but changed in 4.8 to allow for spacing
around the element. See https://github.com/dequelabs/axe-core/pull/4117
for more information on this change.

Moodle 4.2 has an earlier version of Axe which does not have this rule.
Moodle 4.4 has a later, unaffected, version of Axe.

The simplest solution here is to simply disable the buggy rule.
2024-07-17 22:51:35 +08:00
Paul Holden 25e9ddf536 MDL-82499 question: test for invalid question in capability check. 2024-07-17 09:58:12 +01:00
Andrew Nicols f08c8b7db7 MDL-82373 contentbank: Pause in Behat before interacting with h5p
It seems that the loading of the h5p content upsets other interactions
with the page in Firefox as it loads. Unfortunately I haven't found a
reliable way to handle this with pendingJS yet.

This is the poor man's fix and we should find a better solution.
2024-07-17 13:29:46 +08:00
Andrew Nicols 66f526f878 MDL-82373 question: Make window larger in behat tests
I would suggest that this is a stop gap to solve some failing tests. We
really need to look at whether we can improve the usability of this
interface on smaller displays as a longer-term fix.
2024-07-17 13:29:46 +08:00
Andrew Nicols 783477d51b MDL-82373 core_grades: Address random failures when editing gradebook 2024-07-17 13:29:45 +08:00
Andrew Nicols 5b665180f1 MDL-82373 behat: Wait for alerts before accepting/dismissing them 2024-07-17 13:29:45 +08:00
Andrew Nicols e3d9453e61 MDL-82373 core: Make CollapsibleRegion more tolerant to behat 2024-07-17 13:29:45 +08:00
Andrew Nicols c8cb3660ac MDL-82373 tool_usertours: Ensure that behat waits for tours to show/hide 2024-07-17 13:29:45 +08:00
Andrew Nicols 3d43a712bc MDL-82373 behat: Stop killing the entire Behat run on driver error
If there's a driver error, for example from a step taking too long, then
this kills the entire Behat run and we have to start from scratch.

This change instead throws away the original connection and starts a new
one to try and continue the test.
2024-07-17 13:29:44 +08:00
Andrew Nicols beb6ab9e4e MDL-82373 behat: Stop calling ensure_node_is_visible before click
W3C WebDriver Element::Click, Element::Clear, and Element::SendKeys all
state that the WebDriver implementation (chromedriver, geckodriver,
edgedriver) should scroll the element into view if it is not already
visible.

It is wrong for us to check if the element is visible or not before
calling these as it may not be but will during the click/clear/type
event.
2024-07-17 13:29:44 +08:00
Andrew Nicols fd6e1984dd MDL-82373 mod_lesson: Fix failing behat tests for Selenium 4
Recent versions of Chrome do not re-render the page but return previous
page state from cache. The page state had the Submit button disabled
before navigating away.

Refreshing the page addresses this.
2024-07-17 13:29:44 +08:00
Ilya Tregubov 034588c559 Merge branch 'MDL-82002-403' of https://github.com/durenadev/moodle into MOODLE_403_STABLE 2024-07-17 11:05:15 +08:00
Michael Aherne 66712ce0d8 MDL-82499 question: Fail if questionid does not exist. 2024-07-16 14:58:53 +01:00
Dale Davies 02d483b628 MDL-82286 core: Set serialize_precision to current PHP default 2024-07-16 10:00:57 +01:00
Angelia Dela Cruz 6c5ba9b786 MDL-82353 gradingform: Behat to verify marking guide can be set to draft 2024-07-16 16:59:57 +08:00
Andrew Nicols 927cfa7e7d MDL-77706 atto_link: Work around Mozilla bug 1906559
This upstream bug prevents creation of an anchor with a hyperlink where
the content has a block-like display.

The workaround is to wrap the content in a span, set the display to
inline, call the `createLink` command on the span, move the content out
of the span, and then remove it.

This is only done for Firefox-based browsers.
2024-07-16 15:37:57 +08:00
Ilya Tregubov c5bca30726 Merge branch 'MDL-82282-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-16 09:26:43 +08:00
Ilya Tregubov 1f9f1afb90 Merge branch 'MDL-73662-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-16 09:16:22 +08:00
Paul Holden 5ec0023392 MDL-82467 completion: simplify field SQL for completion columns.
For columns whose values can be represented purely in SQL, we don't
need to/shouldn't select extra data because it confuses the column
output during aggregation for numeric/boolean columns.
2024-07-15 13:34:50 +01:00
Huong Nguyen e478edc496 MDL-81272 calendar: Improve permission check for separate group mode 2024-07-15 15:47:13 +07:00
Andrew Nicols fc5a993443 MDL-66903 core: Check PHPUNIT_TEST defined before using 2024-07-15 13:43:21 +07:00
Huong Nguyen 5a890734c3 Merge branch 'MDL-66903-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-15 13:22:20 +07:00
Andrew Nicols d4f3368d28 MDL-66903 core: Introduce \core_component::reset to replace hacks
Traditionally we have done this using reflection and it would be better
to do this in a 'proper' fashion in case we ever need to change how it
works.
2024-07-15 12:22:20 +08:00
Andrew Nicols a7f98a4509 MDL-66903 core: Add option to get core in list of components
Note: This change is backported from MDL-81063.
2024-07-15 12:22:20 +08:00
Andrew Nicols 15d78691a8 MDL-66903 core: Add helper to get component name from classname
Note: This change is backported from MDL-81063.
2024-07-15 12:22:19 +08:00
Andrew Nicols dd72df20f2 MDL-66903 testing: Helper to load fixture files 2024-07-15 12:22:17 +08:00
Andrew Nicols b8a075bed6 MDL-66903 testing: Add support for a \tests\ namespace during tests
This commit:
- introduces a \tests\ sub-namespace for use in unit tests only
- the path to this the tests/classes directory of the owning parent
- files here are excluded from unit test runs

This is agreed per policy in MDL-80855.
2024-07-15 12:21:54 +08:00
Andrew Nicols 71e0b0f26b MDL-66903 testing: Fix whitespace 2024-07-15 12:21:06 +08:00
Andrew Nicols 4cee58fa33 MDL-66903 testing: Reset CFG and component after test
This change moves the reset of global test state to the finally section
rather than doing it only if the test passes.

Previously if a test which modifies the `core_component` internals
failed, it would not reset the internal state and impact subsequent
tests.
2024-07-15 12:21:06 +08:00
Eric Merrill 024a1f04d5 MDL-82193 scorm: Don't store header with multiline AICC content 2024-07-12 15:35:42 -04:00
Paul Holden 3abaca02cc MDL-82444 core: skip environment test on optional plugin extensions. 2024-07-12 13:50:01 +01:00
Paul Holden 90fa52089e MDL-82444 filter_tidy: advertise required PHP extension. 2024-07-12 13:34:12 +01:00
Paul Holden 7b03f08342 MDL-73662 mod_quiz: fix initialization arguments to close button.
Co-authored-by: Sergio Rabellino <rabellino@di.unito.it>
2024-07-12 13:18:12 +01:00
Paul Holden e8ecb6156e MDL-81803 tool_dataprivacy: observe disabled expiration time.
A non-positive integer value should indicate "No time limit".
2024-07-12 11:05:05 +01:00
Daniel Ureña 6c0ce5f8a2 MDL-82002 Media: Video embedding from the app is styled properly. 2024-07-12 11:23:31 +02:00
Huong Nguyen 5fe898496b weekly release 4.3.5+ 2024-07-12 08:42:12 +07:00
Andrew Nicols 4a27a1707b Merge branch 'MDL-78936-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-11 12:34:31 +08:00
Jun Pataleta 4bfd122d5c Merge branch 'MDL-81265-403' of https://github.com/junpataleta/moodle into MOODLE_403_STABLE 2024-07-11 12:08:39 +08:00
Jun Pataleta 49abebf564 MDL-81265 mod_workshop: Verify "Setup phase" heading with "should exist" 2024-07-11 11:58:53 +08:00
Laurent David 7c323f7b61 MDL-81265 mod_workshop: Fix accessibility issues
* Page title should be h2
* Contrasts in the table headers (for submission, assessment and grading)
should be 4:1 at least
2024-07-11 11:58:53 +08:00
Andrew Nicols 554ea6e8bd Merge branch 'MDL-82431-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-11 11:46:42 +08:00
Huong Nguyen f771d66f5e Merge branch 'MDL-79717-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-11 09:35:34 +07:00
Huong Nguyen 18fc1b5f5e Merge branch 'MDL-76654-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-07-11 09:19:55 +07:00
Paul Holden 0f0ed01461 MDL-82431 phpunit: correct unit test filename and classname.
Standardise the same test cases, e.g. make final, covers notation,
static data providers, namespaces, etc.

Once the tests run, a couple of them failed. They required changes
to assertions to make them pass.
2024-07-10 19:06:19 +01:00
Jun Pataleta b89e5414b5 Merge branch 'MDL-82417-403' of https://github.com/davewoloszyn/moodle into MOODLE_403_STABLE 2024-07-10 22:16:03 +08:00
Paul Holden aaa03767c8 MDL-79717 phpunit: ensure unique data provider keys in tests.
Duplicate data provider keys were overwriting and/or duplicating
one another, leading to some cases being skipped.

Other "duplicate array key" errors were picked up by `phpcs` in
this dragnet across all tests, which have also been fixed.
2024-07-10 14:08:54 +01:00
Huong Nguyen 9bc5163ef8 Merge branch 'MDL-82308_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-07-10 14:57:43 +07:00
Huong Nguyen c8a0ac0b9d Merge branch 'MDL-68211-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-07-10 09:08:03 +07:00
Huong Nguyen d4438e6011 Merge branch 'MDL-82236-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-07-10 09:04:31 +07:00
Tim Hunt 9e1bb0d779 MDL-82401 quiz: editing modals must be removed on close 2024-07-10 08:58:37 +07:00
Sara Arjona 49b603a177 Merge branch 'MDL-81349-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-09 18:14:50 +02:00
Sara Arjona 0926c469aa Merge branch 'MDL-82360-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-09 15:30:21 +02:00
Sara Arjona c1bcf5867a Merge branch 'MDL-77834-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-09 15:22:18 +02:00
Sara Arjona 978f3d670a Merge branch 'MDL-81991-403-alt' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-09 13:07:52 +02:00
Sara Arjona 1f88a03ab9 Merge branch 'MDL-78388-403' of https://github.com/djarran/moodle into MOODLE_403_STABLE 2024-07-09 11:47:39 +02:00
Sara Arjona bf5569ace8 Merge branch 'MDL-66251-403' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-07-09 10:36:42 +02:00
Paul Holden 90734c4b83 MDL-82309 comment: preserve link text property during AJAX requests.
We really only need to update the count value that follows the link
text content, so do that rather than overwriting the entire thing.
2024-07-09 09:17:23 +01:00
Sara Arjona c71635f492 Merge branch 'MDL-80947-403' of https://github.com/stevandoMoodle/moodle into MOODLE_403_STABLE 2024-07-09 10:03:15 +02:00
Angelia Dela Cruz 71cc856e51 MDL-82236 mod_data: Behat to display DB activity entry rating 2024-07-09 14:59:59 +08:00
Sara Arjona 603c6e3717 Merge branch 'MDL-81296-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-07-09 08:50:42 +02:00
Angelia Dela Cruz 08a8a41f10 MDL-81296 mod_data: Behat test for data activity readonly availability 2024-07-09 12:18:21 +08:00
David Woloszyn 4fa51ddcff MDL-82417 admin: Clarify signoutofotherservices strings 2024-07-09 13:59:14 +10:00
Paul Holden b14cfb6d1b MDL-82328 auth_oauth2: don't load custom profile field data too early.
By prematurely loading custom profile data in the constructor, under
specific circumstances it would happen before the page was fully
initialised which meant that any attempt at applying filters when
formatting profile field data would result in thrown exception.
2024-07-08 08:56:01 +01:00
Simey Lameze 894ab9cf82 MDL-76654 behat: fixes and improvements to self assessment test 2024-07-08 11:22:19 +08:00
Angelia Dela Cruz e82d9489b6 MDL-76654 behat: Coverage for workshop self-assessment 2024-07-08 11:22:19 +08:00
Brendan Heywood 6bdf1b78b2 MDL-82171 core: Rewarm bootstrap.php after a cache purge 2024-07-08 12:53:38 +10:00
meirzamoodle eaf9f48ce8 MDL-66251 form: Hiding and disabling static elements.
Added functionality to locate static text elements within the form,
improving the ability to target and manipulate the static elements for
hiding and disabling purposes.
2024-07-08 09:17:32 +07:00
Stevani Andolo 0548230e7e MDL-80947 communication_customlink: Check before customlink update 2024-07-08 07:26:23 +08:00
Sara Arjona 3b73f08330 MDL-68211 feedback: Export percentage format
The feedback was exporting the percentage in the Analysis file using
a wrong value for the format, so instead of having only 2 decimals,
the number was not formatted.
2024-07-05 10:13:55 +02:00
Ilya Tregubov fd32ceac7c weekly release 4.3.5+ 2024-07-05 09:02:06 +08:00
Paul Holden 4e98ef312b MDL-82289 mod_feedback: correct comparison of current $course. 2024-07-04 10:28:54 +01:00
Sara Arjona 7dec802efd Merge branch 'MDL-80907-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-04 11:19:38 +02:00
Paul Holden e2a7ef37db MDL-82282 question: consider only editable flags in JS module. 2024-07-04 10:19:36 +01:00
Paul Holden f363d21a13 MDL-82090 completion: account for alternate gradepass form fields.
Some modules (e.g. Workshop) have "*gradepass" fields for each grade
item, which should be accounted for when trying to freeze them.
2024-07-04 10:17:41 +01:00
Huong Nguyen c9a86c636d MDL-80907 behat: Fix incorrect column selectors 2024-07-04 15:16:58 +07:00
Safat 923ebdfdef MDL-81932 communication_customlink: Fix behat tests 2024-07-04 16:39:26 +10:00
Safat 4e318cb269 MDL-81932 communication_matrix: Fix behat tests 2024-07-04 16:39:26 +10:00
Safat ca607d2ce0 MDL-81932 core_course: Fix communication provider change issue 2024-07-04 16:39:26 +10:00
Safat 8d000f1883 MDL-81932 core_communication: Fix communication provider change issue 2024-07-04 16:39:26 +10:00
Huong Nguyen 22749997d8 Merge branch 'MDL-80907-403' of https://github.com/marinaglancy/moodle into MOODLE_403_STABLE 2024-07-04 11:14:21 +07:00
Ilya Tregubov e19f7c0357 Merge branch 'MDL-63670-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-07-04 10:58:00 +08:00
Ilya Tregubov 16bad766e7 Merge branch 'MDL-82315-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-04 10:37:51 +08:00
Ilya Tregubov 5bb5629bb3 Merge branch 'MDL-82024-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-07-04 09:51:20 +08:00
Sara Arjona e7dc124935 Merge branch 'MDL-82100-403' of https://github.com/danghieu1407/moodle into MOODLE_403_STABLE 2024-07-03 17:14:22 +02:00
Jun Pataleta c5a33da692 Merge branch 'MDL-31192-M403_colored-box-with-pre-tag-function-generates-a-warning' of https://github.com/ziegenberg/moodle into MOODLE_403_STABLE 2024-07-03 15:13:12 +08:00
Hieu Nguyen Dang 9c41c1e66f MDL-82100 Quiz\report: Show customised question numbers 2024-07-03 13:58:31 +07:00
Sara Arjona 36cd78e14b Merge branch 'MDL-82363-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-07-03 08:23:48 +02:00
lameze bf18f9f12e NOBUG: Increase file size to avoid random failures 2024-07-03 13:40:02 +08:00
Huong Nguyen c16225e5fb MDL-82363 Calendar: Responsiveness improvement for calendar block
Hide the month name if the screen is too small
2024-07-03 11:02:45 +07:00
djarrancotleanu 92564aca0a MDL-78388 course: Copy permissions when duplicating module 2024-07-03 13:50:22 +10:00
Paul Holden 1899587ff8 MDL-82360 courseformat: remove console upload error string debugging. 2024-07-02 15:55:39 +01:00
Paul Holden 6a1277cc52 MDL-77834 mod_feedback: consistent HTML decoding of answer data.
Restores functionality from 72629ee8c0 that went missing along the way.
2024-07-01 16:22:03 +01:00
Sara Arjona 3615bec113 Merge branch 'MDL-81959-403' of https://github.com/lucaboesch/moodle into MOODLE_403_STABLE 2024-07-01 16:15:55 +02:00
Paul Holden c8c9171455 MDL-81349 group: case-sensitive name validation when editing. 2024-07-01 09:41:51 +01:00
Huong Nguyen 0e30f51806 Merge branch 'MDL-79758_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-07-01 14:25:32 +07:00
Huong Nguyen 1dad92a893 Merge branch 'MDL-79971-403' of https://github.com/aanabit/moodle into MOODLE_403_STABLE 2024-07-01 14:16:59 +07:00
Huong Nguyen be28d88b29 Merge branch 'MDL-79796_403' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_403_STABLE 2024-07-01 14:10:23 +07:00
Huong Nguyen 67719360a9 Merge branch 'MDL-73091-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-07-01 14:06:05 +07:00
Amaia Anabitarte 8c5cc0d32f MDL-79971 completion: Don't assume a completed activity is viewed 2024-06-28 10:16:59 +02:00
Luca Bösch 3e6584c714 MDL-81959 qtype_multianswer: Margin between checkboxes and text 2024-06-28 07:58:46 +02:00
Paul Holden 93643512c3 MDL-82315 backup: account for null course section sequence value. 2024-06-27 23:34:55 +01:00
Sara Arjona dc6dda1726 weekly release 4.3.5+ 2024-06-27 16:36:54 +02:00
Sara Arjona 293ad7857a Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-06-27 16:36:51 +02:00
Stephan Robotta c741492c38 MDL-79758 qbank: add filter in pagination links
Contains some minor tweaks by Tim Hunt <T.J.Hunt@open.ac.uk>.
2024-06-27 09:23:06 +01:00
Huong Nguyen b47c6c290d Merge branch 'MDL-62958-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-27 11:05:23 +07:00
Huong Nguyen 05711947e6 Merge branch 'MDL-82008-403' of https://github.com/lucaboesch/moodle into MOODLE_403_STABLE 2024-06-27 10:27:15 +07:00
Jun Pataleta f4a5b5e82d Merge branch 'MDL-79809-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-06-27 11:01:22 +08:00
Andrew Nicols e3743ea066 MDL-63670 core_message: Tests should not use another testcase as base 2024-06-27 09:01:43 +08:00
Tim Hunt 5f01161095 MDL-82308 forms: set a nice default size for multi-selects
This is a backport of MDL-81515.
2024-06-26 13:26:33 +01:00
Sara Arjona 1cdcee4020 Merge branch 'MDL-80625-403' of https://github.com/ssj365/moodle into MOODLE_403_STABLE 2024-06-26 12:15:02 +02:00
Sara Arjona 6ed88f797b Merge branch 'MDL-80344-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-26 12:11:22 +02:00
Huong Nguyen 399e4ead35 MDL-81991 core: Reload accessdata for dirty users in CLI mode 2024-06-26 16:27:59 +07:00
Huong Nguyen be48e8d19b MDL-78936 editor_tiny: Disable quickbars for small target
The quickbars selection toolbar is not displayed correctly
if the target element is too small. We will wait for it
to be fixed in the future before we re-enable it in Moodle
2024-06-26 10:18:19 +07:00
Ilya Tregubov 05081cc0b6 Merge branch 'MDL-82233-403' of https://github.com/sarjona/moodle into MOODLE_403_STABLE 2024-06-26 10:24:21 +08:00
Ilya Tregubov acfb658796 Merge branch 'MDL-82167-403' of https://github.com/ferranrecio/moodle into MOODLE_403_STABLE 2024-06-26 10:20:19 +08:00
Sara Arjona e099ffcf76 Merge branch 'MDL-79231-403' of https://github.com/davewoloszyn/moodle into MOODLE_403_STABLE 2024-06-25 16:13:08 +02:00
ferranrecio 0f405fd48e MDL-82167 core: fix reactive debug panel 2024-06-25 16:00:59 +02:00
Huong Nguyen 71046dbd93 Merge branch 'MDL-82277-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-25 13:54:12 +07:00
Wolfgang Reichert f860bf0a87 MDL-73091 core_badges: Avoid undefined variable notice in review
* Fix review method for award_criteria_courseset when courseset is empty
* Add unit tests for coverage of the award_criteria_courseset class

@co-authored jz-reichert@web.de
2024-06-25 08:47:28 +02:00
Huong Nguyen 41874ea307 Merge branch 'MDL-82200_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-06-25 09:14:01 +07:00
Huong Nguyen fcd49e4377 Merge branch 'MDL-80061-403' of https://github.com/ssj365/moodle into MOODLE_403_STABLE 2024-06-25 09:07:46 +07:00
Paul Holden f70abdc6f3 MDL-82024 format_topics: toggle un/highlight section icon correctly. 2024-06-24 19:48:05 +01:00
Paul Holden df5a0e6447 MDL-82277 mod_h5pactivity: less fragile error Behat step assertion.
Avoids frequent failures related to iframe resizing/timing.
2024-06-24 15:56:07 +01:00
Paul Holden c61ed0b47c MDL-62958 admin: ensure uploaded plugin directory structure present.
Including any empty directories, which would cause validation to
subsequently fail when they were skipped.

Co-authored-by: Leon Stringer <leon.stringer@ntlworld.com>
2024-06-24 12:47:40 +01:00
Huong Nguyen 524779dc8c MDL-79809 environment: Moodle 4.5 requirements 2024-06-24 09:37:24 +07:00
Huong Nguyen 10fbeaa3ed MDL-79809 environment: Add missing Moodle 4.4 requirements 2024-06-24 09:37:24 +07:00
Huong Nguyen bbcc3531e1 MDL-79809 environment: Add recommended custom check
Add support for custom environment checks to have a recommended
option in addition to required an optional.
2024-06-24 09:37:23 +07:00
Rossco Hellmans 8854212b09 MDL-68676 mod_assign: check accessallgroups in can_edit_submission()
In can_edit_submission() when the assign group mode is SEPARATEGROUPS
check if the user has the moodle/site:accessallgroups capability before
checking if they are a shared groupmember. Due to the teamsubmission
setting students might not be in a group but can still submit, which
means they are not returned in get_shared_group_members().
2024-06-22 13:42:34 +10:00
AMOS bot 4cf33f06ba Automatically generated installer lang files 2024-06-22 00:14:06 +00:00
Daniel Ziegenberg 93ca582a25 MDL-31192 core_webservice: do not render div inside span
`<span>` tags only permit "phrasing content" but `<div>` (and also the
`<ins>` tag) are flow content. So, switching to div all along.

Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
2024-06-21 16:33:58 +02:00
Luca Bösch 9eaecc9336 MDL-82008 backup: Format 'Continue' and 'Cancel' button to have a margin 2024-06-21 09:37:06 +02:00
Martin Gauk ebac092c6e MDL-80345 core_lock: deal with hash collisions in postgres_lock_factory 2024-06-20 17:34:00 +02:00
Sara Arjona 91811a4bbc weekly release 4.3.5+ 2024-06-20 16:31:03 +02:00
Sara Arjona aea1811fdb Merge branch 'install_403_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_403_STABLE 2024-06-20 16:31:00 +02:00
David Woloszyn 7962b734aa MDL-79231 core_theme: Fix Tiny menu in fullscreen mode modals 2024-06-20 14:32:44 +10:00
David Woloszyn d4376c28f1 MDL-79231 mod_assign: Fix Tiny menu in fullscreen mode 2024-06-20 14:32:44 +10:00
Huong Nguyen e752a63a54 Merge branch 'MDL-78773-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-20 11:06:43 +07:00
Jun Pataleta 5a2d39ccb3 Merge branch 'MDL-82246-403' of https://github.com/andrewnicols/moodle into MOODLE_403_STABLE 2024-06-20 11:41:41 +08:00
Huong Nguyen eded187633 Merge branch 'MDL-82202-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-20 10:21:42 +07:00
Andrew Nicols 1407ac2079 MDL-82246 tiny_recordrtc: Correct string name for insecure alert title 2024-06-20 10:58:34 +08:00
Huong Nguyen e0836aa36d Merge branch 'MDL-81761-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-20 09:55:06 +07:00
Huong Nguyen 495620cd22 Merge branch 'MDL-82169-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-20 09:20:06 +07:00
Huong Nguyen 73ba9560ea Merge branch 'MDL-77665-403-behat-fix' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-06-20 08:54:52 +07:00
lameze cce376b29b MDL-77665 behat: use different steps to delete user 2024-06-20 09:11:22 +08:00
AMOS bot 5db3e2bae6 Automatically generated installer lang files 2024-06-20 00:16:21 +00:00
Sara Arjona 490dfa0b21 Merge branch 'MDL-81857-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-19 15:53:08 +02:00
Sara Arjona b905dc4e0a Merge branch 'MDL-81730-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-19 13:31:44 +02:00
meirzamoodle b25713d6fe MDL-75864 cache: Change key prefix in cache_cron_task
Currently, the cache_cron_task is set to look for 'sess_' as a key prefix,
which is not used in any code. As a result, sessions that have exceeded the timeout are never deleted.

The proposed patch involves changing the prefix to the LASTACCESS key prefix and
fixing the return value of get_many in the Redis cache so that it can return the required keys.

Co-authored-by: Renaud Lemaire <rlemaire@cblue.be>
2024-06-19 13:43:27 +07:00
Sara Arjona 15de651960 Merge branch 'MDL-77665-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-06-19 07:35:30 +02:00
Huong Nguyen b167c9cc11 Merge branch 'MDL-81249-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-06-19 09:18:50 +07:00
Andrew Nicols b263eac8ca Merge branch 'MDL-81644-403-new' of https://github.com/meirzamoodle/moodle into MOODLE_403_STABLE 2024-06-18 23:26:10 +08:00
Andrew Nicols f7836e1c04 Merge branch 'MDL-81431-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-06-18 22:51:06 +08:00
Andrew Nicols b3716d7a25 Merge branch 'MDL-81739-403' of https://github.com/davewoloszyn/moodle into MOODLE_403_STABLE 2024-06-18 22:39:31 +08:00
Sara Arjona 2056d3d629 MDL-82233 badges: Display awarded users only when it applies
The message with the number of uses who have awarded a badge
were displayed always (even when the badge was disabled).
2024-06-18 16:06:41 +02:00
Angelia Dela Cruz 2bae7d4dc2 MDL-81249 gradingform: Behat test that grades are retained 2024-06-18 18:32:29 +08:00
Angelia Dela Cruz 166de7ade5 MDL-81249 gradingform: Enhance Behat test for deleting marking guide 2024-06-18 17:46:38 +08:00
Huong Nguyen d55c386e8e Merge branch 'MDL-82148_403' of https://github.com/stronk7/moodle into MOODLE_403_STABLE 2024-06-18 16:27:58 +07:00
Shamim Rezaie 59022b4e06 Merge branch 'mdl-78080-403-split' of https://github.com/james-cnz/moodle into MOODLE_403_STABLE 2024-06-18 16:06:34 +10:00
lameze 3aa5d3040b MDL-81431 behat: set grade item checkboxes one at the time 2024-06-18 13:58:29 +08:00
Paul Holden da4e0701ee MDL-82202 course: correct last access report entity column callback.
Ensure it works when being aggregated.
2024-06-17 14:27:15 +01:00
Laurent David dd27138387 MDL-77665 mod_h5pactivity: Improve generator package upload
* Allow the specification of the username in order to set the owner
of the H5P file package when creating a new H5P instance.
2024-06-17 06:31:59 +02:00
Laurent David a843986e1d MDL-77665 core_h5p: Allow deployment if user has been deleted
* If user has been deleted we consider that the content can be deployed
by a user who can deploy other packages
* Add behat test to cover for this use case
* Fix the content bank generator as it was failing to upload the content
as the given user
2024-06-17 06:31:59 +02:00
James C 21c542e3a8 MDL-78080 course: Duplicate section: Duplicate by section id, not num 2024-06-17 12:25:16 +12:00
James C 20e3829749 MDL-78080 course: Duplicate section: No duplicate option for section 0 2024-06-17 12:25:16 +12:00
James C c11eab4121 MDL-78080 course: Duplicate section: Don't copy deleted activities 2024-06-17 12:25:16 +12:00
James C 181f8e7813 MDL-78080 course: Duplicate section: Copy section summary files 2024-06-17 12:24:42 +12:00
James C 1deaaf1964 MDL-78080 course: Duplicate section: Copy custom section options 2024-06-17 12:19:31 +12:00
James C 2e869d5e8b MDL-78080 course: Duplicate section: Fix course_update_section params 2024-06-17 12:19:01 +12:00
Eloy Lafuente (stronk7) e812185a8e MDL-82148 phpunit: Remove all cases of multiple @coversDefaultClass
Only one by class is allowed (to be used as shortcut exclusively).
2024-06-14 16:05:26 +02:00
Tim Hunt eb090d8f10 MDL-82200 inplace editable: fix background of the help text 2024-06-14 13:23:21 +01:00
Anupama Sarjoshi 35f015b33d MDL-79796 quiz: Preview icon should be visible in question bank pop-up 2024-06-14 11:46:56 +01:00
Ilya Tregubov a585bda18f weekly release 4.3.5+ 2024-06-14 08:57:07 +08:00
Eric Merrill 0d0a3381c3 MDL-82192 scorm: Correct field names for AICC ExitAu 2024-06-13 18:38:57 -04:00
Jun Pataleta 3b97ae1814 Merge branch 'MDL-81287-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-13 12:03:13 +08:00
Jun Pataleta 9c6571471f Merge branch 'MDL-82178_403' of https://github.com/timhunt/moodle into MOODLE_403_STABLE 2024-06-13 12:00:43 +08:00
Huong Nguyen cd7f4b6126 Merge branch 'MDL-81577-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-13 10:56:15 +07:00
Huong Nguyen 1da88d59c8 Merge branch 'MDL-82184-dbcollation-comment-403' of https://github.com/leonstr/moodle into MOODLE_403_STABLE 2024-06-13 10:20:05 +07:00
Huong Nguyen 18b872dea6 Merge branch 'MDL-81781-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-13 10:13:19 +07:00
Huong Nguyen cf54f312c7 Merge branch 'MDL-69514-403' of https://github.com/pedrojordao/moodle into MOODLE_403_STABLE 2024-06-13 09:54:32 +07:00
Huong Nguyen 57d3bddedf Merge branch 'MDL-82155-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-13 09:03:36 +07:00
Shamiso.Jaravaza 55b56767d6 MDL-80061 mod_bigbluebuttonbn: Change filter field
* Change dismissed recording time filter from timecreated to timemodified
2024-06-12 13:51:26 -06:00
Leon Stringer 5f9d59a527 MDL-82184 database: Revise dbcollation comment 2024-06-12 18:16:37 +01:00
Tim Hunt fbd10311b3 MDL-82178 quiz graded notification: fix capability check
Also improve the scheduled task logging
2024-06-12 12:41:24 +01:00
Huong Nguyen 1780506eb3 Merge branch 'MDL-81332-403' of https://github.com/andelacruz/moodle into MOODLE_403_STABLE 2024-06-12 13:16:04 +07:00
Jun Pataleta f8f8dee642 Merge branch 'MDL-81355-403' of https://github.com/lameze/moodle into MOODLE_403_STABLE 2024-06-12 10:38:01 +08:00
Michael Aherne 332a467776 MDL-81355 phpdoc: Fix incorrect phpdocs on block_base. 2024-06-12 10:32:51 +08:00
Paul Holden ecb70f2924 MDL-82169 user: remove access to non-existent $options array. 2024-06-11 21:26:07 +01:00
Ilya Tregubov a70030127e Merge branch 'MDL-81510-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-06-11 19:00:02 +08:00
Laurent David 937c1200a3 MDL-81510 core_courseformat: Fix activity highlight in index
* When directly accessing the module with the #module-xxx anchor
we should highlight the module as the current page item.
2024-06-11 12:48:58 +02:00
Huong Nguyen 1ce27d703f MDL-68540 tool_usertours: Remove hideif workaround
We don't need to use the group element to use hideif
for text editor element anymore
2024-06-11 15:33:43 +07:00
Huong Nguyen b21b6214e1 Merge branch 'MDL-68540-403' of https://github.com/davewoloszyn/moodle into MOODLE_403_STABLE 2024-06-11 15:33:17 +07:00
Angelia Dela Cruz 7d94489bcb MDL-81332 core_course: Behat test for grade and activity reports display 2024-06-11 16:30:25 +08:00
Jun Pataleta eb851bbb53 Merge branch 'MDL-81428-403' of https://github.com/HuongNV13/moodle into MOODLE_403_STABLE 2024-06-11 13:41:41 +08:00
David Woloszyn 945ae4127d MDL-68540 form: Correctly target editors in node tree
This fix solves the hideIf and disabledIf form conditions that were not
correctly targetting the editor due to a name attribute mismatch.
2024-06-11 13:06:24 +10:00
Paul Holden 8ff873452f MDL-82155 core: define/correct third party library names. 2024-06-10 19:53:14 +01:00
Shamiso.Jaravaza 83fefe7f72 MDL-80625 mod_bigbluebuttonbn: Fix param name 2024-06-10 10:12:12 -06:00
Sara Arjona 9a47d8f32c Merge branch 'MDL-81949-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-10 16:46:43 +02:00
Sara Arjona 5a52d16d53 Merge branch 'MDL-81678-403' of https://github.com/paulholden/moodle into MOODLE_403_STABLE 2024-06-10 16:39:22 +02:00
Pedro Jordao 1ecaf21c7c MDL-69514 Core: Close popover when modal is closed
Currently in Firefox, if we opened a popover that was inside a modal
and closed the modal by pressing the ESC key, the popover remained on
the screen. With this change, we will ensure that popovers are closed
when the modal is closed.
2024-06-10 10:49:06 -03:00
Sara Arjona ebfcdc6563 Merge branch 'MDL-70972-MOODLE_403_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_403_STABLE 2024-06-10 12:33:32 +02:00
Huong Nguyen 442a0b4edd MDL-81428 theme_boost: Match .disabled opacity with .text-muted 2024-06-10 17:10:18 +07:00
Huong Nguyen 49bab9140b MDL-81428 core: Display the correct status for the contact request 2024-06-10 17:10:18 +07:00
Ilya Tregubov cb6096faca Merge branch 'MDL-81510-403' of https://github.com/laurentdavid/moodle into MOODLE_403_STABLE 2024-06-10 13:32:17 +08:00
Paul Holden e7381b48f2 MDL-81949 tool_replace: prompt user for unrecognised CLI parameters. 2024-06-07 11:41:08 +01:00
Paul Holden ea52af0c77 MDL-81678 enrol: don't escape course name in welcome message. 2024-06-07 11:39:48 +01:00
Paul Holden 612ac0766a MDL-78773 report_stats: improve display of mode selection element.
Make use of existing theme selectors for navigation elements to style.
2024-06-07 11:34:31 +01:00
Paul Holden 2a72cf032d MDL-81781 report_log: escape description selectively on display/export.
Per cd85e090f3 all content was escaped, however we should only do that
when displaying the value in browser or exporting to file format which
supports HTML.
2024-06-07 11:31:02 +01:00
Paul Holden daebafdb2d MDL-81781 dataformat: public helper method to get writer instance. 2024-06-07 11:31:02 +01:00
Laurent David 4ab6a8552f MDL-81510 core_courseformat: Do not reset the scroll position
* Revert the change made in MDL-75762 which would wait and change
  course index selection depending on the actual scroll position
2024-06-07 09:40:21 +02:00
Laurent David c6f9ae9b4f MDL-81510 core_courseformat: Expand course section to show activity
* When a course activity is specified via an anchor in the URL we
should expand the course content containing the activity
* When we point to a specific activity via an anchor in the URL we should
expand the course index (section) surrounding the actitity.
2024-06-07 09:40:21 +02:00
Meirza 27dbdbe702 MDL-81644 calendar: The behaviour of event dates in the block calendar
There is a difference in the behaviour of the calendar block when it is on the calendar page and when it is not.
On the calendar page, when the user clicks on the date or link next/previous month or day name in the calendar block,
it will have the effect of changing the URL, which should not happen.

The patch also includes hiding popover after the user clicks the day number. When the user clicks on the date or
is focused on the date and then presses enter on the keyboard, the popover does not automatically close.
To fix this, I added an event type, "click", to be attached to the hidePopover function and added conditioning to
the target element when there was a "click" event.

An additional step was added to the Behat calendar for the click event to ease the testing process.

For the popover, I set the "animation" to false to avoid the random Behat failure caused by the slow animation.
2024-06-07 14:31:10 +07:00
Paul Holden 7c7ebb074e MDL-81857 user: don't check whether address is an identity field.
It can never be selected as one, so the previous comparison could
never pass.
2024-06-06 08:58:49 +01:00
David Woloszyn 5446cc3dcd MDL-81739 tiny_noautolink: Remove URL checking when preventing auto-link 2024-06-06 15:05:05 +10:00
Paul Holden f537f9c067 MDL-80344 calendar: correct no subscriptions language string use.
Ensure expected parameters are present; avoid string concatenation.
2024-06-05 15:52:23 +01:00
Philipp Memmel 8c7892ceff MDL-70972 format_singleactivity: Apply new behavior to behat test 2024-06-04 06:36:53 +00:00
Philipp Memmel 966f3548ae MDL-70972 format_singleactivity: Show activities when creating course
Co-authored-by: Laurent David <lmedavid@gmail.com>
2024-06-04 06:36:52 +00:00
Paul Holden 9dbfe16744 MDL-81577 mod: correct arguments when formatting text for RSS. 2024-05-30 19:17:32 +01:00
Paul Holden d5be854a11 MDL-81730 assignsubmission_file: deterministic submission file order. 2024-05-20 20:16:24 +01:00
Paul Holden 627fe4cfe8 MDL-81761 gradingform_guide: remove duplicate click of frequent comment. 2024-05-20 17:40:56 +01:00
Paul Holden 88ea564e66 MDL-81287 mod_forum: observe default discussion paging value. 2024-05-15 13:23:23 +01:00
Marina Glancy 09d7b78fee MDL-80907 various: fixes to incorrect column selectors in behat 2024-05-07 19:31:23 +01:00
Marina Glancy 59e774be9a MDL-80907 behat: be more precise in selecting table rows 2024-05-07 19:31:16 +01:00
1316 changed files with 21494 additions and 22006 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ name: Core
on:
push:
branches-ignore:
- master
- main
- MOODLE_[0-9]+_STABLE
tags-ignore:
- v[0-9]+.[0-9]+.[0-9]+*
+23
View File
@@ -0,0 +1,23 @@
name: Web Installer Testing
on:
workflow_dispatch:
jobs:
InstallationTest:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
php: [8.1, 8.3]
steps:
- name: Construct repository URL
run: echo "REPOSITORY_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" >> $GITHUB_ENV
shell: bash
- uses: moodlehq/moodle-webinstaller-test@main
with:
repository: ${{ env.REPOSITORY_URL }}
branch: ${{ github.ref_name }}
php: ${{ matrix.php }}
@@ -500,4 +500,15 @@ abstract class plugin_management_table extends flexible_table implements dynamic
protected function supports_ordering(): bool {
return $this->plugininfoclass::plugintype_supports_ordering();
}
/**
* Check if the user has the capability to access this table.
*
* Default implementation for plugin management tables is to require 'moodle/site:config' capability
*
* @return bool Return true if capability check passed.
*/
public function has_capability(): bool {
return has_capability('moodle/site:config', $this->get_context());
}
}
+3 -7
View File
@@ -177,6 +177,7 @@ $CFG->admin = array_pop($parts);
ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
require_once($CFG->libdir.'/classes/component.php');
require_once($CFG->libdir.'/classes/text.php');
require_once($CFG->libdir.'/classes/string_manager.php');
require_once($CFG->libdir.'/classes/string_manager_install.php');
@@ -192,13 +193,8 @@ require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/componentlib.class.php');
require_once($CFG->dirroot.'/cache/lib.php');
// Register our classloader, in theory somebody might want to replace it to load other hacked core classes.
// Required because the database checks below lead to session interaction which is going to lead us to requiring autoloaded classes.
if (defined('COMPONENT_CLASSLOADER')) {
spl_autoload_register(COMPONENT_CLASSLOADER);
} else {
spl_autoload_register('core_component::classloader');
}
// Register our classloader.
\core_component::register_autoloader();
require($CFG->dirroot.'/version.php');
$CFG->target_release = $release;
+197
View File
@@ -4504,6 +4504,203 @@
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="4.5" requires="4.1.2">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.6.7" />
<VENDOR name="mysql" version="8.0" />
<VENDOR name="postgres" version="13" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="19" />
</DATABASE>
<PHP version="8.1.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
<FEEDBACK>
<ON_ERROR message="sixtyfourbitsrequired" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
<FEEDBACK>
<ON_CHECK message="iscustomadminwarnings" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+7 -4
View File
@@ -874,8 +874,8 @@ class core_admin_renderer extends plugin_renderer_base {
protected function mobile_configuration_warning($mobileconfigured) {
$output = '';
if (!$mobileconfigured) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'mobilesettings']);
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'));
$settingslink = new moodle_url('/admin/search.php', ['query' => 'enablemobilewebservice']);
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'), 'get');
$output .= $this->warning(get_string('mobilenotconfiguredwarning', 'admin') . '&nbsp;' . $configurebutton);
}
@@ -2051,8 +2051,10 @@ class core_admin_renderer extends plugin_renderer_base {
// We are checking installed & enabled things
if ($environment_result->getLevel() == 'required') {
$stringtouse = 'environmentrequirecustomcheck';
} else {
} else if ($environment_result->getLevel() == 'optional') {
$stringtouse = 'environmentrecommendcustomcheck';
} else {
$stringtouse = 'environmentshouldfixcustomcheck';
}
} else if ($environment_result->getPart() == 'php_setting') {
@@ -2083,7 +2085,8 @@ class core_admin_renderer extends plugin_renderer_base {
if ($status) { //Handle ok result (ok)
$status = get_string('statusok');
} else {
if ($environment_result->getLevel() == 'optional') {//Handle check result (warning)
// Handle check result (warning).
if (in_array($environment_result->getLevel(), ['optional', 'recommended'])) {
$status = get_string('check');
$warningline = true;
} else { //Handle error result (error)
+3 -1
View File
@@ -152,7 +152,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$sensiblesettingsdefault .= 'server_password@@search_solr, ssl_keypassword@@search_solr, ';
$sensiblesettingsdefault .= 'alternateserver_password@@search_solr, alternatessl_keypassword@@search_solr, ';
$sensiblesettingsdefault .= 'test_password@@cachestore_redis, password@@mlbackend_python, ';
$sensiblesettingsdefault .= 'badges_badgesalt@@none, calendar_exportsalt@@none';
$sensiblesettingsdefault .= 'badges_badgesalt@@none, calendar_exportsalt@@none, ';
$sensiblesettingsdefault .= 'bigbluebuttonbn_shared_secret@@none, apikey@@tiny_premium, ';
$sensiblesettingsdefault .= 'matrixaccesstoken@@communication_matrix';
$temp->add(new admin_setting_configtextarea('adminpresets/sensiblesettings',
get_string('sensiblesettings', 'core_adminpresets'),
get_string('sensiblesettingstext', 'core_adminpresets'),
@@ -38,6 +38,6 @@
}
}}
<div class="form-checkbox defaultsnext">
<input type="hidden" name="{{name}}" value="{{no}}">
{{^readonly}}<input type="hidden" name="{{name}}" value="{{no}}">{{/readonly}}
<input {{#readonly}}disabled{{/readonly}} type="checkbox" name="{{name}}" value="{{value}}" id="{{id}}" {{#checked}}checked{{/checked}}>
</div>
@@ -35,7 +35,7 @@
}
}}
<div class="form-multicheckbox">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
{{^readonly}}<input type="hidden" name="{{name}}[xxxxx]" value="1">{{/readonly}}
{{#hasoptions}}
<ul>
{{#options}}
@@ -40,7 +40,7 @@
Setting configmultiselect.
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
{{^readonly}}<input type="hidden" name="{{name}}[xxxxx]" value="1">{{/readonly}}
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
@@ -59,7 +59,7 @@
Setting configmultiselect with optgroup support.
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
{{^readonly}}<input type="hidden" name="{{name}}[xxxxx]" value="1">{{/readonly}}
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
+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 / Last name | Email address |
| First 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 / Last name | Email address |
| First name - phonetic | 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 / Last name | Favourite frog | Department |
| First name | Favourite frog | Department |
| User One | Kermit | Attack |
| User Two | Tree | Defence |
And I should not see "Email address" in the "table" "css_element"
-22
View File
@@ -48,25 +48,3 @@ Feature: View task logs report and use its filters
| operator | shouldornotsee |
| Less than | should not see |
| Greater than | should see |
@javascript
Scenario: Reset task log filters
Given I log in as "admin"
And I change window size to "large"
And I navigate to "Server > Tasks > Task logs" in site administration
When I click on "Filters" "button"
And I set the following fields in the "Result" "core_reportbuilder > Filter" to these values:
| Result operator | Is equal to |
| Result value | Fail |
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
Then I should see "Filters applied"
And I should see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
And I should see "Nothing to display"
And I click on "Reset all" "button" in the "[data-region='report-filters']" "css_element"
And I should see "Filters reset"
And I should not see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
And I should see "Filters" in the "#dropdownFiltersButton" "css_element"
And "[data-region='report-filters']" "css_element" should be visible
And the following fields in the "Result" "core_reportbuilder > Filter" match these values:
| Result operator | Is any value |
And I should not see "Nothing to display"
@@ -5,16 +5,18 @@ Feature: I can download a preset
| name |
| Custom preset |
@javascript
Scenario: Custom preset settings can be downloaded
Given I log in as "admin"
And I navigate to "Site admin presets" in site administration
When I open the action menu in "Custom preset" "table_row"
Then following "Download" "link" in the "Custom preset" "table_row" should download between "0" and "5000" bytes
Then following "Download" in the "Custom preset" "table_row" should download a file that:
| Has mimetype | text/xml |
| Contains text in xml element | Custom preset |
@javascript
Scenario: Core preset settings can be downloaded
Given I log in as "admin"
And I navigate to "Site admin presets" in site administration
When I open the action menu in "Starter" "table_row"
Then following "Download" "link" in the "Starter" "table_row" should download between "0" and "5000" bytes
Then following "Download" in the "Starter" "table_row" should download a file that:
| Has mimetype | text/xml |
| Contains text in xml element | Starter |
+1 -1
View File
@@ -25,7 +25,7 @@ Feature: Confirm that we can open multiple browser tabs
And I open a tab named "CourseViewer4" on the "My courses" page
# Switch between all the tabs and confirm their different contents.
Then I should see "You're not enrolled in any course"
Then I should see "You're not enrolled in any courses."
And I switch to "CourseViewer2" tab
And "Course 3" "heading" should exist
And I switch to "CourseViewer1" tab
@@ -245,7 +245,6 @@ class brickfield_accessibility_color_test extends brickfield_accessibility_test
return $luminosity;
}
/**
* Returns the decimal equivalents for a HEX color. Returns null if it cannot be determined.
* @param string $color The hex color value
@@ -268,13 +267,21 @@ class brickfield_accessibility_color_test extends brickfield_accessibility_test
*/
public function convert_color(string $color): string {
$color = trim($color);
if (strpos($color, ' ') !== false) {
$colors = explode(' ', $color);
foreach ($colors as $backgroundpart) {
if (substr(trim($backgroundpart), 0, 1) == '#' ||
in_array(trim($backgroundpart), array_keys($this->colornames)) ||
strtolower(substr(trim($backgroundpart), 0, 3)) == 'rgb') {
$color = $backgroundpart;
// Search for color in rgb format first, as this can potentially contain a space.
if (strpos($color, 'rgb') !== false) {
$colors = explode('rgb', $color, 2); // Getting 2 only in array.
// Getting end point of rgb value, i.e. the end bracket.
$endpos = strpos($colors[1], ')');
$color = 'rgb' . substr($colors[1], 0, ($endpos + 1)); // Recompiling rgb value.
} else {
// Splitting multi-value css background value.
if (strpos($color, ' ') !== false) {
$colors = explode(' ', $color);
foreach ($colors as $backgroundpart) {
if (substr(trim($backgroundpart), 0, 1) == '#' ||
in_array(trim($backgroundpart), array_keys($this->colornames))) {
$color = $backgroundpart;
}
}
}
}
@@ -296,9 +303,20 @@ class brickfield_accessibility_color_test extends brickfield_accessibility_test
}
// RGB values.
if (strtolower(substr($color, 0, 3)) == 'rgb') {
$colors = explode(',', trim(str_replace('rgb(', '', $color), '()'));
if (count($colors) != 3) {
return false;
if (strpos($color, 'rgba') !== false) {
$tmpbg = $this->get_rgb($this->defaultbackground);
$colors = explode(',', trim(str_replace('rgba(', '', $color), '()'));
if (count($colors) != 4) {
return false;
}
$colors[0] = round(((1 - $colors[3]) * $tmpbg['r']) + ($colors[3] * $colors[0]));
$colors[1] = round((1 - $colors[3]) * $tmpbg['g']) + ($colors[3] * $colors[1]);
$colors[2] = round((1 - $colors[3]) * $tmpbg['b']) + ($colors[3] * $colors[2]);
} else {
$colors = explode(',', trim(str_replace('rgb(', '', $color), '()'));
if (count($colors) != 3) {
return false;
}
}
$r = intval($colors[0]);
$g = intval($colors[1]);
@@ -62,9 +62,18 @@ class css_text_has_contrast extends brickfield_accessibility_color_test {
foreach ($entries as $element) {
$style = $this->css->get_style($element);
if (isset($style['background-color']) || isset($style['color'])) {
if (isset($style['background-color']) || isset($style['color']) || isset($style['background'])) {
if (!isset($style['background-color'])) {
$style['background-color'] = $this->defaultbackground;
if (isset($style['background'])) {
// Parsing background-color from CSS background shortcut string.
$style['background-color'] = '#' . $this->convert_color($style['background']);
// If value is empty after hash, then use defaultbackground.
if ($style['background-color'] == '#') {
$style['background-color'] = $this->defaultbackground;
}
} else {
$style['background-color'] = $this->defaultbackground;
}
}
if (!isset($style['color'])) {
@@ -82,11 +91,7 @@ class css_text_has_contrast extends brickfield_accessibility_color_test {
$style['color'] = '#' . $this->convert_color($style['color']);
$style['background-color'] = '#' . $this->convert_color($background);
if (substr($background, 0, 3) == "rgb") {
$background = '#' . $this->convert_color($background);
}
$luminosity = $this->get_luminosity($style['color'], $background);
$luminosity = $this->get_luminosity($style['color'], $style['background-color']);
$fontsize = 0;
$bold = false;
$italic = false;
@@ -30,6 +30,7 @@ require_once('all_checks.php');
/**
* Class test_css_text_has_contrast_test
* @covers \tool_brickfield\local\htmlchecker\brickfield_accessibility
*/
class css_text_has_contrast_test extends all_checks {
/** @var string The check type. */
@@ -229,7 +230,7 @@ EOD;
/**
* Test for the area assign intro
*/
public function test_check() {
public function test_check(): void {
$results = $this->get_checker_results($this->htmlfail1);
$this->assertTrue($results[0]->element->tagName == 'p');
@@ -255,7 +256,7 @@ EOD;
/**
* Test with valid colour names.
*/
public function test_check_for_namedcolours() {
public function test_check_for_namedcolours(): void {
$results = $this->get_checker_results($this->namecolours);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -263,7 +264,7 @@ EOD;
/**
* Test with invalid colour names.
*/
public function test_check_for_invalidcolours() {
public function test_check_for_invalidcolours(): void {
$results = $this->get_checker_results($this->invalidcolours);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -271,7 +272,7 @@ EOD;
/**
* Test with invalid colour numeric values.
*/
public function test_check_for_invalidvalues() {
public function test_check_for_invalidvalues(): void {
$results = $this->get_checker_results($this->invalidvalue);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -279,7 +280,7 @@ EOD;
/**
* Test with empty colour values.
*/
public function test_check_for_emptyvalues() {
public function test_check_for_emptyvalues(): void {
$results = $this->get_checker_results($this->emptyvalue);
$this->assertEmpty($results);
}
@@ -287,7 +288,7 @@ EOD;
/**
* Test for text px18 with insufficient contrast of 4.49.
*/
public function test_check_for_px18_fail() {
public function test_check_for_px18_fail(): void {
$results = $this->get_checker_results($this->px18);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -295,7 +296,7 @@ EOD;
/**
* Test for text px19 bold with sufficient contrast of 4.49.
*/
public function test_check_for_px19bold_pass() {
public function test_check_for_px19bold_pass(): void {
$results = $this->get_checker_results($this->px19bold);
$this->assertEmpty($results);
}
@@ -303,7 +304,7 @@ EOD;
/**
* Test for text px18 with sufficient contrast of 4.81.
*/
public function test_check_for_px18_pass() {
public function test_check_for_px18_pass(): void {
$results = $this->get_checker_results($this->px18pass);
$this->assertEmpty($results);
}
@@ -311,7 +312,7 @@ EOD;
/**
* Test for medium (12pt) text with insufficient contrast of 4.49.
*/
public function test_check_for_medium_fail() {
public function test_check_for_medium_fail(): void {
$results = $this->get_checker_results($this->mediumfail);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -319,7 +320,7 @@ EOD;
/**
* Test for medium (12pt) text with sufficient contrast of 4.81.
*/
public function test_check_for_medium_pass() {
public function test_check_for_medium_pass(): void {
$results = $this->get_checker_results($this->mediumpass);
$this->assertEmpty($results);
}
@@ -327,7 +328,7 @@ EOD;
/**
* Test for larger (14pt) text with insufficient contrast of 2.94.
*/
public function test_check_for_larger_fail() {
public function test_check_for_larger_fail(): void {
$results = $this->get_checker_results($this->largerfail);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -335,7 +336,7 @@ EOD;
/**
* Test for larger (14pt) text with insufficient contrast of 3.02.
*/
public function test_check_for_larger_pass() {
public function test_check_for_larger_pass(): void {
$results = $this->get_checker_results($this->largerpass);
$this->assertTrue($results[0]->element->tagName == 'p');
}
@@ -343,8 +344,118 @@ EOD;
/**
* Test for larger (14pt) bold text with sufficient contrast of 3.02.
*/
public function test_check_for_largerbold_pass() {
public function test_check_for_largerbold_pass(): void {
$results = $this->get_checker_results($this->largerboldpass);
$this->assertEmpty($results);
}
/**
* Test for rgb colors with insufficient contrast.
*/
public function test_bad_rgbcolor(): void {
$html = '<body><p style="color:rgb(255, 255, 255); background-color:rgb(204, 204, 204);">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for rgb colors with sufficient contrast.
*/
public function test_good_rgbcolor(): void {
$html = '<body><p style="color:rgb(255, 255, 255); background-color:rgb(0, 0, 0);">
This is contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
/**
* Test for named colors with insufficient contrast.
*/
public function test_bad_namedcolor2(): void {
$html = '<body><p style="color:lightcyan; background-color:lavender;">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for named colors with sufficient contrast.
*/
public function test_good_namedcolor2(): void {
$html = '<body><p style="color:linen; background-color:darkslategray;">
This is contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
/**
* Test for background value with insufficient contrast.
*/
public function test_bad_backgroundcss(): void {
$html = '<body><p style="color:lightcyan; background:fixed lavender center;">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for background value with sufficient contrast.
*/
public function test_good_backgroundcss(): void {
$html = '<body><p style="color:linen; background:fixed darkslategray center;">
This is contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
/**
* Test for background value with rgb with insufficient contrast.
*/
public function test_bad_backgroundcssrgb(): void {
$html = '<body><p style="color:rgb(255, 255, 255); background:fixed rgb(204, 204, 204) center;">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for background value with rgb with sufficient contrast.
*/
public function test_good_backgroundcssrgb(): void {
$html = '<body><p style="color:rgb(255, 255, 255); background:fixed rgb(0, 0, 0) center;">
This is contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
/**
* Test for text with insufficient contrast of 4.3.
*/
public function test_bad_contrastrounding(): void {
$html = '<body><p style="color:#F50000; background-color:white; font-size: 12px">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for background value with rgba with insufficient contrast.
*/
public function test_bad_backgroundcssrgba(): void {
$html = '<body><p style="color:rgba(255, 255, 255, 0.5); background:fixed rgba(0, 204, 204, 0.5) center;">
This is not contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for background value with rgba with sufficient contrast.
*/
public function test_good_backgroundcssrgba(): void {
$html = '<body><p style="color:rgba(255, 255, 255, 0.75); background:fixed rgba(0, 0, 0, 0.75) center;">
This is contrasty enough.</p></body>';
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
}
@@ -156,9 +156,9 @@ class data_request extends persistent {
case api::DATAREQUEST_STATUS_EXPIRED:
$result = true;
break;
// Complete requests are expired if the expiry time has elapsed.
// Complete requests are expired if the expiry time is a positive value, and has elapsed.
case api::DATAREQUEST_STATUS_DOWNLOAD_READY:
$expiryseconds = get_config('tool_dataprivacy', 'privacyrequestexpiry');
$expiryseconds = (int) get_config('tool_dataprivacy', 'privacyrequestexpiry');
if ($expiryseconds > 0 && time() >= ($request->get('timemodified') + $expiryseconds)) {
$result = true;
}
@@ -179,7 +179,12 @@ class data_request extends persistent {
public static function get_expired_requests($userid = 0) {
global $DB;
$expiryseconds = get_config('tool_dataprivacy', 'privacyrequestexpiry');
// Complete requests are expired if the expiry time is a positive value, and has elapsed.
$expiryseconds = (int) get_config('tool_dataprivacy', 'privacyrequestexpiry');
if ($expiryseconds <= 0) {
return [];
}
$expirytime = strtotime("-{$expiryseconds} second");
$table = self::TABLE;
$sqlwhere = 'type = :export_type AND status = :completestatus AND timemodified <= :expirytime';
@@ -54,6 +54,7 @@ Feature: Data delete from the privacy API
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And I follow "Approve request"
And I wait until "Approve request" "button" exists
And I press "Approve request"
And I should see "Approved" in the "Victim User 1" "table_row"
And I run all adhoc tasks
@@ -80,6 +81,7 @@ Feature: Data delete from the privacy API
And I navigate to "Users > Privacy and policies > Data requests" in site administration
And I open the action menu in "Victim User 1" "table_row"
And I follow "Approve request"
And I wait until "Approve request" "button" exists
And I press "Approve request"
And I log out
@@ -115,6 +117,7 @@ Feature: Data delete from the privacy API
And I navigate to "Users > Privacy and policies > Data requests" in site administration
And I open the action menu in "Victim User 1" "table_row"
And I follow "Approve request"
And I wait until "Approve request" "button" exists
And I press "Approve request"
And I log out
@@ -48,13 +48,15 @@ Feature: Data export from the privacy API
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And I follow "Approve request"
And I wait until "Approve request" "button" exists
And I press "Approve request"
And I should see "Approved" in the "Victim User 1" "table_row"
And I run all adhoc tasks
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
And I wait "1" seconds
@@ -89,7 +91,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Export all of my personal data" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
@@ -115,6 +118,7 @@ Feature: Data export from the privacy API
And I navigate to "Users > Privacy and policies > Data requests" in site administration
And I open the action menu in "Victim User 1" "table_row"
And I follow "Approve request"
And I wait until "Approve request" "button" exists
And I press "Approve request"
And I log out
@@ -126,7 +130,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
@@ -185,7 +190,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "170000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
And I wait "1" seconds
@@ -229,7 +235,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "180000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
@javascript
Scenario: Filter before export data for a user and download it in the view request action
@@ -262,4 +269,5 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "180000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
@@ -26,10 +26,11 @@ require_once('data_privacy_testcase.php');
* Expired data requests tests.
*
* @package tool_dataprivacy
* @covers \tool_dataprivacy\data_request
* @copyright 2018 Michael Hawkins
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class expired_data_requests_test extends data_privacy_testcase {
final class expired_data_requests_test extends data_privacy_testcase {
/**
* Test tearDown.
@@ -107,6 +108,52 @@ class expired_data_requests_test extends data_privacy_testcase {
$this->assertEquals(0, $DB->count_records('files', $fileconditions));
}
/**
* Test that data requests are not expired when expiration is disabled (set to zero)
*/
public function test_data_request_expiry_never(): void {
global $DB;
$this->resetAfterTest();
\core_privacy\local\request\writer::setup_real_writer_instance();
// Disable request expiry.
set_config('privacyrequestexpiry', 0, 'tool_dataprivacy');
// Create and approve data request.
$user = $this->getDataGenerator()->create_user();
$usercontext = \context_user::instance($user->id);
$this->setUser($user->id);
$datarequest = api::create_data_request($user->id, api::DATAREQUEST_TYPE_EXPORT);
$requestid = $datarequest->get('id');
$this->setAdminUser();
api::approve_data_request($requestid);
ob_start();
$this->runAdhocTasks('\tool_dataprivacy\task\process_data_request_task');
ob_end_clean();
// Run expiry deletion - should not affect test export.
$expiredrequests = data_request::get_expired_requests();
$this->assertEmpty($expiredrequests);
data_request::expire($expiredrequests);
// Confirm approved and exported.
$request = new data_request($requestid);
$this->assertEquals(api::DATAREQUEST_STATUS_DOWNLOAD_READY, $request->get('status'));
$fileconditions = [
'userid' => $user->id,
'component' => 'tool_dataprivacy',
'filearea' => 'export',
'itemid' => $requestid,
'contextid' => $usercontext->id,
];
$this->assertEquals(2, $DB->count_records('files', $fileconditions));
}
/**
* Test for \tool_dataprivacy\data_request::is_expired()
* Tests for the expected request status to protect from false positive/negative,
+11 -14
View File
@@ -57,7 +57,7 @@ class locale {
}
// Store current locale.
$currentlocale = $this->set_locale(LC_ALL, 0);
$currentlocale = $this->get_locale();
$locale = get_string_manager()->get_string($stringtofetch, 'langconfig', $a = null, $langpackcode);
@@ -79,19 +79,16 @@ 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') {
if (strlen($locale) <= 255 || PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
// We can set the whole locale all together.
return setlocale($category, $locale);
}
return \core\locale::set_locale($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.
/**
* Get the current locale.
*
* @param int $category
* @return string|false
*/
protected function get_locale(int $category = LC_ALL): string|false {
return \core\locale::get_locale($category);
}
}
+38 -114
View File
@@ -21,39 +21,59 @@ namespace tool_langimport;
*
* @package tool_langimport
* @category test
* @coversDefaultClass \tool_langimport\locale
* @covers \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
*/
class locale_test extends \advanced_testcase {
final class locale_test extends \advanced_testcase {
/** @var string Locale */
protected string $locale;
#[\Override]
public function setUp(): void {
parent::setUp();
$this->locale = \core\locale::get_locale();
}
#[\Override]
public function tearDown(): void {
parent::tearDown();
\core\locale::set_locale(LC_ALL, $this->locale);
}
/**
* Test that \tool_langimport\locale::check_locale_availability() works as expected.
*
* @covers ::check_locale_availability
* @return void
*/
public function test_check_locale_availability() {
// Create a mock of set_locale() method to simulate :
// - first setlocale() call which backup current locale
// - second setlocale() call which try to set new 'es' locale
// - third setlocale() call which restore locale.
public function test_check_locale_availability(): void {
// Create a mock of set_locale() method to simulate:
// - get_locale() call which backup current locale
// - first set_locale() call which try to set new 'es' locale
// - second set_locale() call which restore locale.
$mock = $this->getMockBuilder(locale::class)
->onlyMethods(['set_locale'])
->onlyMethods([
'get_locale',
'set_locale',
])
->getMock();
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', 'es', 'en'));
$mock->method('get_locale')->will($this->onConsecutiveCalls('en'));
$mock->method('set_locale')->will($this->onConsecutiveCalls('es', 'en'));
// Test what happen when locale is available on system.
$result = $mock->check_locale_availability('en');
$this->assertTrue($result);
// Create a mock of set_locale() method to simulate :
// - first setlocale() call which backup current locale
// - second setlocale() call which fail to set new locale
// - third setlocale() call which restore locale.
// Create a mock of set_locale() method to simulate:
// - get_locale() call which backup current locale
// - first set_locale() call which fail to set new locale
// - second set_locale() call which restore locale.
$mock = $this->getMockBuilder(locale::class)
->onlyMethods(['set_locale'])
->onlyMethods([
'get_locale',
'set_locale',
])
->getMock();
$mock->method('set_locale')->will($this->onConsecutiveCalls('en', false, 'en'));
$mock->method('get_locale')->will($this->onConsecutiveCalls('en'));
$mock->method('set_locale')->will($this->onConsecutiveCalls(false, 'en'));
// Test what happen when locale is not available on system.
$result = $mock->check_locale_availability('en');
@@ -64,100 +84,4 @@ class locale_test extends \advanced_testcase {
$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;
}
}
@@ -37,8 +37,8 @@ Feature: Delete custom licenses
| Licence version | ##1 March 2019## |
And I press "Save changes"
And I follow "Private files" in the user menu
And I upload "lib/editor/atto/tests/fixtures/moodle-logo.png" file to "Files" filemanager
And I click on "moodle-logo.png" "link"
And I upload "lib/tests/fixtures/gd-logo.png" file to "Files" filemanager
And I click on "gd-logo.png" "link"
And I set the field "Choose licence" to "Test licence"
And I press "Update"
And I press "Save changes"
@@ -14,6 +14,6 @@ Feature: In a report, admin can see logstore visibility changes
And I click on "Enable" "icon" in the "External database log" "table_row"
And I navigate to "Reports > Config changes" in site administration
Then the following should exist in the "reportbuilder-table" table:
| User | Plugin | Setting | New value | Original value |
| First name | Plugin | Setting | New value | Original value |
| Admin User | logstore_standard | tool_logstore_visibility | 0 | 1 |
| Admin User | logstore_database | tool_logstore_visibility | 1 | 0 |
@@ -170,6 +170,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I wait until "Activate" "button" exists
And I press "Activate"
And I log out
When I log in as "manager"
@@ -260,6 +261,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I wait until "Activate" "button" exists
And I press "Activate"
And I log out
When I log in as "manager"
+10 -6
View File
@@ -117,7 +117,9 @@ class category_bin extends base_bin {
// 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['backup'] = ['backup_auto_storage' => 0, 'backup_auto_files' => 1];
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? [];
$CFG->forced_plugin_settings['backup']['backup_auto_storage'] = 0;
$CFG->forced_plugin_settings['backup']['backup_auto_files'] = 1;
// Backup the course.
$user = get_admin();
@@ -131,9 +133,9 @@ class category_bin extends base_bin {
);
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// We don't need the forced setting anymore, hence restore previous settings.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['backup']);
$CFG->forced_plugin_settings['backup'] = $forcedbackupsettings;
// Grab the result.
$result = $controller->get_results();
@@ -251,7 +253,9 @@ class category_bin extends base_bin {
// 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];
$forcedrestoresettings = $CFG->forced_plugin_settings['restore'] ?? [];
$CFG->forced_plugin_settings['restore']['restore_general_users'] = 1;
$CFG->forced_plugin_settings['restore']['restore_general_groups'] = 1;
// Define the import.
$controller = new \restore_controller(
@@ -287,9 +291,9 @@ class category_bin extends base_bin {
// Run the import.
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// We don't need the forced setting anymore, hence restore previous settings.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['restore']);
$CFG->forced_plugin_settings['restore'] = $forcedrestoresettings;
// Have finished with the controller, let's destroy it, freeing mem and resources.
$controller->destroy();
+10 -6
View File
@@ -121,7 +121,9 @@ class course_bin extends base_bin {
// 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['backup'] = ['backup_auto_storage' => 0, 'backup_auto_files' => 1];
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? [];
$CFG->forced_plugin_settings['backup']['backup_auto_storage'] = 0;
$CFG->forced_plugin_settings['backup']['backup_auto_files'] = 1;
// Backup the activity.
$user = get_admin();
@@ -145,9 +147,9 @@ class course_bin extends base_bin {
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// We don't need the forced setting anymore, hence restore previous settings.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['backup']);
$CFG->forced_plugin_settings['backup'] = $forcedbackupsettings;
// Grab the result.
$result = $controller->get_results();
@@ -252,7 +254,9 @@ class course_bin extends base_bin {
// 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];
$forcedrestoresettings = $CFG->forced_plugin_settings['restore'] ?? null;
$CFG->forced_plugin_settings['restore']['restore_general_users'] = 1;
$CFG->forced_plugin_settings['restore']['restore_general_groups'] = 1;
// Define the import.
$controller = new \restore_controller(
@@ -284,9 +288,9 @@ class course_bin extends base_bin {
// Run the import.
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// We don't need the forced setting anymore, hence restore previous settings.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['restore']);
$CFG->forced_plugin_settings['restore'] = $forcedrestoresettings;
// Have finished with the controller, let's destroy it, freeing mem and resources.
$controller->destroy();
+7 -1
View File
@@ -57,7 +57,13 @@ list($options, $unrecognized) = cli_get_params(
)
);
if ($options['help'] || $options['search'] === null || $options['replace'] === null) {
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// Ensure that user has populated both the search/replace parameters.
if ($options['help'] || !is_string($options['search']) || !is_string($options['replace'])) {
echo $help;
exit(0);
}
@@ -62,8 +62,8 @@ Feature: Manage scheduled tasks
And I press "Save changes"
Then I should see "Changes saved"
And the following should not exist in the "admintable" table:
| Name | Component | Minute | Hour | Day | Day of week | Month |
| Log table cleanup | Standard log | */5 | 1 | 2 | 4 | 3 |
| Name | Minute | Hour | Day | Day of week | Month |
| Log table cleanup | */5 | 1 | 2 | 4 | 3 |
And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
Scenario: Disabled plugin's tasks are labelled as disabled too
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+33 -11
View File
@@ -37,6 +37,7 @@ import {eventTypes} from './events';
import {getString} from 'core/str';
import {prefetchStrings} from 'core/prefetch';
import {notifyFilterContentUpdated} from 'core/event';
import PendingPromise from 'core/pending';
/**
* The minimum spacing for tour step to display.
@@ -486,14 +487,22 @@ const Tour = class {
return this.endTour();
}
const pendingPromise = new PendingPromise(`tool_usertours/tour:_gotoStep-${stepConfig.stepNumber}`);
if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {
stepConfig.delayed = true;
window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);
window.setTimeout(function(stepConfig, direction) {
this._gotoStep(stepConfig, direction);
pendingPromise.resolve();
}, stepConfig.delay, stepConfig, direction);
return this;
} else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {
let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
return this.gotoStep(this[fn](stepConfig.stepNumber), direction);
const fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
this.gotoStep(this[fn](stepConfig.stepNumber), direction);
pendingPromise.resolve();
return this;
}
this.hide();
@@ -504,6 +513,7 @@ const Tour = class {
this.dispatchEvent(eventTypes.stepRendered, {stepConfig});
}
pendingPromise.resolve();
return this;
}
@@ -823,12 +833,14 @@ const Tour = class {
left: 0,
});
const pendingPromise = new PendingPromise(`tool_usertours/tour:addStepToPage-${stepConfig.stepNumber}`);
animationTarget
.animate({
scrollTop: this.calculateScrollTop(stepConfig),
}).promise().then(function() {
this.positionStep(stepConfig);
this.revealStep(stepConfig);
pendingPromise.resolve();
return;
}.bind(this))
.catch(function() {
@@ -900,6 +912,7 @@ const Tour = class {
*/
revealStep(stepConfig) {
// Fade the step in.
const pendingPromise = new PendingPromise(`tool_usertours/tour:revealStep-${stepConfig.stepNumber}`);
this.currentStepNode.fadeIn('', $.proxy(function() {
// Announce via ARIA.
this.announceStep(stepConfig);
@@ -913,6 +926,7 @@ const Tour = class {
if (this.currentStepNode) {
this.currentStepNode.focus();
}
pendingPromise.resolve();
}, this), 100);
}, this));
@@ -1160,6 +1174,7 @@ const Tour = class {
return this;
}
const pendingPromise = new PendingPromise('tool_usertours/tour:hide');
if (this.currentStepNode && this.currentStepNode.length) {
this.currentStepNode.hide();
if (this.currentStepPopper) {
@@ -1194,17 +1209,22 @@ const Tour = class {
this.currentStepConfig = null;
}
let fadeTime = 0;
if (transition) {
fadeTime = 400;
}
// Remove the backdrop features.
$('[data-flexitour="step-background"]').remove();
$('[data-flexitour="step-backdrop"]').removeAttr('data-flexitour');
$('[data-flexitour="backdrop"]').fadeOut(fadeTime, function() {
$(this).remove();
});
const backdrop = $('[data-flexitour="backdrop"]');
if (backdrop.length) {
if (transition) {
const backdropRemovalPromise = new PendingPromise('tool_usertours/tour:hide:backdrop');
backdrop.fadeOut(400, function() {
$(this).remove();
backdropRemovalPromise.resolve();
});
} else {
backdrop.remove();
}
}
// Remove aria-describedby and tabindex attributes.
if (this.currentStepNode && this.currentStepNode.length) {
@@ -1225,6 +1245,8 @@ const Tour = class {
this.currentStepNode = null;
this.currentStepPopper = null;
pendingPromise.resolve();
return this;
}
@@ -116,11 +116,9 @@ class editstep extends \moodleform {
'changeformat' => 1,
'trusttext' => true
];
$objs = $mform->createElement('editor', 'content', get_string('content', 'tool_usertours'), null, $editoroptions);
// TODO: MDL-68540 We need to add the editor to a group element because editor element will not work with hideIf.
$mform->addElement('group', 'contenthtmlgrp', get_string('content', 'tool_usertours'), [$objs], ' ', false);
$mform->addHelpButton('contenthtmlgrp', 'content', 'tool_usertours');
$mform->hideIf('contenthtmlgrp', 'contenttype', 'eq', static::CONTENTTYPE_LANGSTRING);
$mform->addElement('editor', 'content', get_string('content', 'tool_usertours'), null, $editoroptions);
$mform->addHelpButton('content', 'content', 'tool_usertours');
$mform->hideIf('content', 'contenttype', 'eq', static::CONTENTTYPE_LANGSTRING);
// Add the step configuration.
$mform->addElement('header', 'heading_options', get_string('options_heading', 'tool_usertours'));
+5 -1
View File
@@ -572,7 +572,8 @@ class step {
* @return $this
*/
public function persist($force = false) {
global $DB;
global $CFG, $DB;
require_once("{$CFG->libdir}/filelib.php");
if (!$this->dirty && !$force) {
return $this;
@@ -729,6 +730,9 @@ class step {
* @return object
*/
public function prepare_data_for_form() {
global $CFG;
require_once("{$CFG->libdir}/filelib.php");
$data = $this->to_record();
foreach (self::get_config_keys() as $key) {
$data->$key = $this->get_config($key, configuration::get_step_default_value($key));
@@ -27,9 +27,9 @@ Feature: Apply content type to a tour
And the "Content type" select box should contain "Manual"
And I select "Language string ID" from the "Content type" singleselect
And I should see " Language string ID"
And "#fgroup_id_contenthtmlgrp" "css_element" should not be visible
And I should not see "Content" in the "#fitem_id_content" "css_element"
And I select "Manual" from the "Content type" singleselect
And "#fgroup_id_contenthtmlgrp" "css_element" should be visible
And I should see "Content" in the "#fitem_id_content" "css_element"
And I should not see "Language string ID" in the "#fitem_id_contentlangstring" "css_element"
@javascript
@@ -36,6 +36,11 @@ class new_table_from_mysql extends XMLDBAction {
function init() {
parent::init();
global $DB;
if ($DB->get_dbfamily() !== 'mysql') {
throw new moodle_exception('DB family not supported');
}
// Set own custom attributes
// Get needed strings
@@ -55,8 +60,6 @@ class new_table_from_mysql extends XMLDBAction {
function invoke() {
parent::invoke();
$result = true;
// Set own core attributes
$this->does_generate = ACTION_GENERATE_HTML;
@@ -125,11 +128,15 @@ class new_table_from_mysql extends XMLDBAction {
// If table, retrofit information and, if everything works,
// go to the table edit action
} else {
// Get some params (table is mandatory here)
$tableparam = required_param('table', PARAM_CLEAN);
$afterparam = required_param('after', PARAM_CLEAN);
// Get some params (table is mandatory here).
$tableparam = required_param('table', PARAM_ALPHANUMEXT);
$afterparam = required_param('after', PARAM_ALPHANUMEXT);
// Create one new xmldb_table
if (empty($tableparam) || empty($afterparam)) {
throw new moodle_exception('Invalid param value detected.');
}
// Create one new xmldb_table.
$table = new xmldb_table(strtolower(trim($tableparam)));
$table->setComment($table->getName() . ' table retrofitted from MySQL');
// Get fields info from ADODb
@@ -147,7 +154,6 @@ class new_table_from_mysql extends XMLDBAction {
// Get PK, UK and indexes info from ADODb
$dbindexes = $DB->get_indexes($tableparam);
if ($dbindexes) {
$lastkey = NULL; //To temp store the last key processed
foreach ($dbindexes as $indexname => $dbindex) {
// Add the indexname to the array
$dbindex['name'] = $indexname;
@@ -156,9 +162,6 @@ class new_table_from_mysql extends XMLDBAction {
$key = new xmldb_key(strtolower($dbindex['name']));
// Set key with info retrofitted
$key->setFromADOKey($dbindex);
// Set default comment to PKs
if ($key->getType() == XMLDB_KEY_PRIMARY) {
}
// Add key to the table
$table->addKey($key);
@@ -172,18 +175,17 @@ class new_table_from_mysql extends XMLDBAction {
}
}
}
// Finally, add the whole retroffited table to the structure
// in the place specified
// Finally, add the whole retrofitted table to the structure in the place specified.
$structure->addTable($table, $afterparam);
}
// Launch postaction if exists (leave this here!)
if ($this->getPostAction() && $result) {
if ($this->getPostAction()) {
return $this->launch($this->getPostAction());
}
// Return ok if arrived here
return $result;
return true;
}
}
+3 -1
View File
@@ -114,6 +114,7 @@ Feature: Manage analytics models
And I should see "Read actions amount"
And I click on "Select Student 6 for bulk action" "checkbox" in the "Student 6" "table_row"
And I click on "Accept" "button"
And I wait until "Confirm" "button" exists
And I click on "Confirm" "button" in the "Accept" "dialogue"
And I click on "View prediction details" "icon" in the "Student 5" "table_row"
And I click on "Select Student 5 for bulk action" "checkbox" in the "Student 5" "table_row"
@@ -145,7 +146,8 @@ Feature: Manage analytics models
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
And I choose "Export" in the open action menu
And I click on "Actions" "link" in the "Students at risk of not meeting the course completion conditions" "table_row"
And following "Export" should download between "100" and "500" bytes
And following "Export" should download a file that:
| Contains file in zip | model-config.json |
Scenario: Check invalid site elements
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
@@ -14,31 +14,29 @@
// 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 activities completed by classification.
*
* @package core_analytics
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_analytics;
defined('MOODLE_INTERNAL') || die();
use advanced_testcase;
use ReflectionClass;
use ReflectionMethod;
use stdClass;
/**
* Unit tests for activities completed by classification.
*
* @package core_analytics
* @covers \core_analytics\local\indicator\community_of_inquiry_activity
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class community_of_inquiry_activities_completed_by_testcase extends advanced_testcase {
final class community_of_inquiry_activities_completed_by_test extends advanced_testcase {
/**
* availability_levels
*
* @return array
*/
public function availability_levels() {
public static function availability_levels(): array {
return array(
'activity' => array('activity'),
'section' => array('section'),
@@ -148,7 +146,7 @@ class community_of_inquiry_activities_completed_by_testcase extends advanced_tes
$second = $startdate + WEEKSECS;
$third = $startdate + (WEEKSECS * 2);
$forth = $startdate + (WEEKSECS * 3);
$this->assertCount(1, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
$this->assertCount(2, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
$this->assertCount(1, $method->invoke($indicator, $second, $second + WEEKSECS, $stu1));
$this->assertCount(0, $method->invoke($indicator, $third, $third + WEEKSECS, $stu1));
$this->assertCount(2, $method->invoke($indicator, $forth, $forth + WEEKSECS, $stu1));
+9 -4
View File
@@ -345,7 +345,7 @@ class api {
}
/**
* Delete linked login
* Delete a users own linked login
*
* Requires auth/oauth2:managelinkedlogins capability at the user context.
*
@@ -353,14 +353,19 @@ class api {
* @return boolean
*/
public static function delete_linked_login($linkedloginid) {
$login = new linked_login($linkedloginid);
$userid = $login->get('userid');
global $USER;
if (\core\session\manager::is_loggedinas()) {
throw new moodle_exception('notwhileloggedinas', 'auth_oauth2');
}
$context = context_user::instance($userid);
$login = linked_login::get_record([
'id' => $linkedloginid,
'userid' => $USER->id,
'confirmtoken' => '',
], MUST_EXIST);
$context = context_user::instance($login->get('userid'));
require_capability('auth/oauth2:managelinkedlogins', $context);
$login->delete();
+1 -2
View File
@@ -63,7 +63,6 @@ class auth extends \auth_plugin_base {
public function __construct() {
$this->authtype = 'oauth2';
$this->config = get_config('auth_oauth2');
$this->customfields = $this->get_custom_user_profile_fields();
}
/**
@@ -310,7 +309,7 @@ class auth extends \auth_plugin_base {
return $userdata;
}
$allfields = array_merge($this->userfields, $this->customfields);
$allfields = array_merge($this->userfields, $this->get_custom_user_profile_fields());
// Go through each field from the external data.
foreach ($externaldata as $fieldname => $value) {
+25
View File
@@ -137,6 +137,7 @@ class api_test extends \advanced_testcase {
$issuer = \core\oauth2\api::create_standard_issuer('google');
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$info = [];
$info['username'] = 'banana';
@@ -169,6 +170,30 @@ class api_test extends \advanced_testcase {
$this->assertEquals($newuser->id, $match->get('userid'));
}
/**
* Test that we cannot deleted a linked login for another user
*/
public function test_delete_linked_login_other_user(): void {
$this->resetAfterTest();
$this->setAdminUser();
$issuer = \core\oauth2\api::create_standard_issuer('google');
$user = $this->getDataGenerator()->create_user();
api::link_login([
'username' => 'banana',
'email' => 'banana@example.com',
], $issuer, $user->id);
/** @var linked_login $linkedlogin */
$linkedlogin = api::get_linked_logins($user->id)[0];
// We are logged in as a different user, so cannot delete this.
$this->expectException(\dml_missing_record_exception::class);
api::delete_linked_login($linkedlogin->get('id'));
}
/**
* Test that is_enabled correctly identifies when the plugin is enabled.
*/
+1 -1
View File
@@ -52,7 +52,7 @@ abstract class backup_block_task extends backup_task {
}
$this->blockid = $blockid;
$this->blockname = $block->blockname;
$this->blockname = clean_param($block->blockname, PARAM_PLUGIN);
$this->contextid = context_block::instance($this->blockid)->id;
$this->moduleid = $moduleid;
$this->modulename = null;
+37 -14
View File
@@ -552,9 +552,12 @@ class backup_course_structure_step extends backup_structure_step {
FROM {course_format_options}
WHERE courseid = ? AND sectionid = 0', [ backup::VAR_PARENTID ]);
$handler = core_course\customfield\course_handler::create();
$fieldsforbackup = $handler->get_instance_data_for_backup($this->task->get_courseid());
$customfield->set_source_array($fieldsforbackup);
// Custom fields.
if ($this->get_setting_value('customfield')) {
$handler = core_course\customfield\course_handler::create();
$fieldsforbackup = $handler->get_instance_data_for_backup($this->task->get_courseid());
$customfield->set_source_array($fieldsforbackup);
}
// Some annotations
@@ -1403,14 +1406,19 @@ class backup_groups_structure_step extends backup_structure_step {
FROM {groups} g
JOIN {backup_ids_temp} bi ON g.id = bi.itemid
WHERE bi.backupid = ?
AND bi.itemname = 'groupfinal'", array(backup::VAR_BACKUPID));
AND bi.itemname = 'groupfinal'",
[backup_helper::is_sqlparam($this->get_backupid())]
);
$grouping->set_source_sql("
SELECT g.*
FROM {groupings} g
JOIN {backup_ids_temp} bi ON g.id = bi.itemid
WHERE bi.backupid = ?
AND bi.itemname = 'groupingfinal'", array(backup::VAR_BACKUPID));
AND bi.itemname = 'groupingfinal'",
[backup_helper::is_sqlparam($this->get_backupid())]
);
$groupinggroup->set_source_table('groupings_groups', array('groupingid' => backup::VAR_PARENTID));
// This only happens if we are including users.
@@ -1418,9 +1426,20 @@ class backup_groups_structure_step extends backup_structure_step {
$member->set_source_table('groups_members', array('groupid' => backup::VAR_PARENTID));
}
$courseid = $this->task->get_courseid();
$groupcustomfield->set_source_array($this->get_group_custom_fields_for_backup($courseid));
$groupingcustomfield->set_source_array($this->get_grouping_custom_fields_for_backup($courseid));
// Custom fields.
if ($this->get_setting_value('customfield')) {
$groupcustomfieldarray = $this->get_group_custom_fields_for_backup(
$group->get_source_sql(),
[$this->get_backupid()]
);
$groupcustomfield->set_source_array($groupcustomfieldarray);
$groupingcustomfieldarray = $this->get_grouping_custom_fields_for_backup(
$grouping->get_source_sql(),
[$this->get_backupid()]
);
$groupingcustomfield->set_source_array($groupingcustomfieldarray);
}
}
// Define id annotations (as final)
@@ -1439,14 +1458,16 @@ class backup_groups_structure_step extends backup_structure_step {
/**
* Get custom fields array for group
* @param int $courseid
*
* @param string $groupsourcesql
* @param array $groupsourceparams
* @return array
*/
protected function get_group_custom_fields_for_backup(int $courseid): array {
protected function get_group_custom_fields_for_backup(string $groupsourcesql, array $groupsourceparams): array {
global $DB;
$handler = \core_group\customfield\group_handler::create();
$fieldsforbackup = [];
if ($groups = $DB->get_records('groups', ['courseid' => $courseid], '', 'id')) {
if ($groups = $DB->get_records_sql($groupsourcesql, $groupsourceparams)) {
foreach ($groups as $group) {
$fieldsforbackup = array_merge($fieldsforbackup, $handler->get_instance_data_for_backup($group->id));
}
@@ -1456,14 +1477,16 @@ class backup_groups_structure_step extends backup_structure_step {
/**
* Get custom fields array for grouping
* @param int $courseid
*
* @param string $groupingsourcesql
* @param array $groupingsourceparams
* @return array
*/
protected function get_grouping_custom_fields_for_backup(int $courseid): array {
protected function get_grouping_custom_fields_for_backup(string $groupingsourcesql, array $groupingsourceparams): array {
global $DB;
$handler = \core_group\customfield\grouping_handler::create();
$fieldsforbackup = [];
if ($groupings = $DB->get_records('groupings', ['courseid' => $courseid], '', 'id')) {
if ($groupings = $DB->get_records_sql($groupingsourcesql, $groupingsourceparams)) {
foreach ($groupings as $grouping) {
$fieldsforbackup = array_merge($fieldsforbackup, $handler->get_instance_data_for_backup($grouping->id));
}
+9 -1
View File
@@ -300,8 +300,16 @@ class restore_root_task extends restore_task {
$competencies->set_ui(new backup_setting_ui_checkbox($competencies, get_string('rootsettingcompetencies', 'backup')));
$this->add_setting($competencies);
$customfields = new restore_customfield_setting('customfields', base_setting::IS_BOOLEAN, $defaultvalue);
// Custom fields.
$defaultvalue = false;
$changeable = false;
if (isset($rootsettings['customfield']) && $rootsettings['customfield']) { // Only enabled when available.
$defaultvalue = true;
$changeable = true;
}
$customfields = new restore_customfield_setting('customfield', base_setting::IS_BOOLEAN, $defaultvalue);
$customfields->set_ui(new backup_setting_ui_checkbox($customfields, get_string('rootsettingcustomfield', 'backup')));
$customfields->get_ui()->set_changeable($changeable);
$this->add_setting($customfields);
// Define Content bank content.
+121 -115
View File
@@ -1159,11 +1159,15 @@ class restore_groups_structure_step extends restore_structure_step {
$groupinfo = $this->get_setting_value('groups');
if ($groupinfo) {
$paths[] = new restore_path_element('group', '/groups/group');
$paths[] = new restore_path_element('groupcustomfield', '/groups/groupcustomfields/groupcustomfield');
$paths[] = new restore_path_element('grouping', '/groups/groupings/grouping');
$paths[] = new restore_path_element('groupingcustomfield',
'/groups/groupings/groupingcustomfields/groupingcustomfield');
$paths[] = new restore_path_element('grouping_group', '/groups/groupings/grouping/grouping_groups/grouping_group');
// Custom fields.
if ($this->get_setting_value('customfield')) {
$paths[] = new restore_path_element('groupcustomfield', '/groups/groupcustomfields/groupcustomfield');
$paths[] = new restore_path_element('groupingcustomfield',
'/groups/groupings/groupingcustomfields/groupingcustomfield');
}
}
return $paths;
}
@@ -1235,9 +1239,11 @@ class restore_groups_structure_step extends restore_structure_step {
*/
public function process_groupcustomfield($data) {
$newgroup = $this->get_mapping('group', $data['groupid']);
$data['groupid'] = $newgroup->newitemid ?? $data['groupid'];
$handler = \core_group\customfield\group_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
if ($newgroup && $newgroup->newitemid) {
$data['groupid'] = $newgroup->newitemid;
$handler = \core_group\customfield\group_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
}
}
public function process_grouping($data) {
@@ -1291,10 +1297,12 @@ class restore_groups_structure_step extends restore_structure_step {
* @return void
*/
public function process_groupingcustomfield($data) {
$newgroup = $this->get_mapping('grouping', $data['groupingid']);
$data['groupingid'] = $newgroup->newitemid ?? $data['groupingid'];
$handler = \core_group\customfield\grouping_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
$newgrouping = $this->get_mapping('grouping', $data['groupingid']);
if ($newgrouping && $newgrouping->newitemid) {
$data['groupingid'] = $newgrouping->newitemid;
$handler = \core_group\customfield\grouping_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
}
}
public function process_grouping_group($data) {
@@ -1827,12 +1835,19 @@ class restore_course_structure_step extends restore_structure_step {
protected function define_structure() {
$paths = [];
$course = new restore_path_element('course', '/course');
$category = new restore_path_element('category', '/course/category');
$tag = new restore_path_element('tag', '/course/tags/tag');
$customfield = new restore_path_element('customfield', '/course/customfields/customfield');
$courseformatoptions = new restore_path_element('course_format_option', '/course/courseformatoptions/courseformatoption');
$allowedmodule = new restore_path_element('allowed_module', '/course/allowed_modules/module');
$paths[] = $course;
$paths[] = new restore_path_element('category', '/course/category');
$paths[] = new restore_path_element('tag', '/course/tags/tag');
$paths[] = new restore_path_element('course_format_option', '/course/courseformatoptions/courseformatoption');
$paths[] = new restore_path_element('allowed_module', '/course/allowed_modules/module');
// Custom fields.
if ($this->get_setting_value('customfield')) {
$paths[] = new restore_path_element('customfield', '/course/customfields/customfield');
}
// Apply for 'format' plugins optional paths at course level
$this->add_plugin_structure('format', $course);
@@ -1855,7 +1870,7 @@ class restore_course_structure_step extends restore_structure_step {
// Apply for admin tool plugins optional paths at course level.
$this->add_plugin_structure('tool', $course);
return array($course, $category, $tag, $customfield, $allowedmodule, $courseformatoptions);
return $paths;
}
/**
@@ -4912,6 +4927,12 @@ class restore_create_categories_and_questions extends restore_structure_step {
/** @var array $cachedcategory store a question category */
protected $cachedcategory = null;
/** @var stdClass the last question_bank_entry seen during the restore. Processed when we get to a question. */
protected $latestqbe;
/** @var stdClass the last question_version seen during the restore. Processed when we get to a question. */
protected $latestversion;
protected function define_structure() {
// Check if the backup is a pre 4.0 one.
@@ -5037,45 +5058,25 @@ class restore_create_categories_and_questions extends restore_structure_step {
}
/**
* Process pre 4.0 question data where in creates the record for version and entry table.
* Set up date to allow restore of questions from pre-4.0 backups.
*
* @param array $data the data from the XML file.
* @param stdClass $data the data from the XML file.
*/
protected function process_question_legacy_data($data) {
global $DB;
$this->latestqbe = (object) [
'id' => $data->id,
'questioncategoryid' => $data->category,
'ownerid' => $data->createdby,
'idnumber' => $data->idnumber ?? null,
];
$oldid = $data->id;
// Process question bank entry.
$entrydata = new stdClass();
$entrydata->questioncategoryid = $data->category;
$userid = $this->get_mappingid('user', $data->createdby);
if ($userid) {
$entrydata->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$entrydata->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (isset($data->idnumber) && !$DB->record_exists('question_bank_entries',
['idnumber' => $data->idnumber, 'questioncategoryid' => $data->category])) {
$entrydata->idnumber = $data->idnumber;
}
$newentryid = $DB->insert_record('question_bank_entries', $entrydata);
// Process question versions.
$versiondata = new stdClass();
$versiondata->questionbankentryid = $newentryid;
$versiondata->version = 1;
// Question id is updated after inserting the question.
$versiondata->questionid = 0;
$versionstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;
if ((int)$data->hidden === 1) {
$versionstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN;
}
$versiondata->status = $versionstatus;
$newversionid = $DB->insert_record('question_versions', $versiondata);
$this->set_mapping('question_version_created', $oldid, $newversionid);
$this->latestversion = (object) [
'id' => $data->id,
'version' => 1,
'status' => $data->hidden ?
\core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN :
\core_question\local\bank\question_version_status::QUESTION_STATUS_READY,
];
}
/**
@@ -5084,37 +5085,9 @@ class restore_create_categories_and_questions extends restore_structure_step {
* @param array $data the data from the XML file.
*/
protected function process_question_bank_entry($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$questioncreated = $this->get_mappingid('question_category_created', $data->questioncategoryid) ? true : false;
$recordexist = $DB->record_exists('question_bank_entries', ['id' => $data->id,
'questioncategoryid' => $data->questioncategoryid]);
// Check we have category created.
if (!$questioncreated && $recordexist) {
return self::SKIP_ALL_CHILDREN;
}
$data->questioncategoryid = $this->get_new_parentid('question_category');
$userid = $this->get_mappingid('user', $data->ownerid);
if ($userid) {
$data->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$data->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (!empty($data->idnumber) && $DB->record_exists('question_bank_entries',
['idnumber' => $data->idnumber, 'questioncategoryid' => $data->questioncategoryid])) {
unset($data->idnumber);
}
$newitemid = $DB->insert_record('question_bank_entries', $data);
$this->set_mapping('question_bank_entry', $oldid, $newitemid);
// We can only determine the right way to process this once we get to
// process_question and have more information, so for now just store.
$this->latestqbe = (object) $data;
}
/**
@@ -5123,16 +5096,9 @@ class restore_create_categories_and_questions extends restore_structure_step {
* @param array $data the data from the XML file.
*/
protected function process_question_versions($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->questionbankentryid = $this->get_new_parentid('question_bank_entry');
// Question id is updated after inserting the question.
$data->questionid = 0;
$newitemid = $DB->insert_record('question_versions', $data);
$this->set_mapping('question_versions', $oldid, $newitemid);
// We can only determine the right way to process this once we get to
// process_question and have more information, so for now just store.
$this->latestversion = (object) $data;
}
/**
@@ -5143,17 +5109,19 @@ class restore_create_categories_and_questions extends restore_structure_step {
protected function process_question($data) {
global $DB;
$data = (object)$data;
$data = (object) $data;
$oldid = $data->id;
// Check if the backup is a pre 4.0 one.
// Check we have one mapping for this question.
if (!$questionmapping = $this->get_mapping('question', $oldid)) {
// No mapping = this question doesn't need to be created/mapped.
return;
}
// Check if this is a pre 4.0 backup, then there will not be a question bank entry
// or question version in the file. So, we need to set up that data ready to be used below.
$restoretask = $this->get_task();
if ($restoretask->backup_release_compare('4.0', '<') || $restoretask->backup_version_compare(20220202, '<')) {
// Check we have one mapping for this question.
if (!$questionmapping = $this->get_mapping('question', $oldid)) {
return; // No mapping = this question doesn't need to be created/mapped.
}
// Get the mapped category (cannot use get_new_parentid() because not
// all the categories have been created, so it is not always available
// Instead we get the mapping for the question->parentitemid because
@@ -5197,28 +5165,66 @@ class restore_create_categories_and_questions extends restore_structure_step {
}
}
$newitemid = $DB->insert_record('question', $data);
$this->set_mapping('question', $oldid, $newitemid);
// Also annotate them as question_created, we need
// that later when remapping parents (keeping the old categoryid as parentid).
$parentcatid = $this->get_old_parentid('question_category');
$this->set_mapping('question_created', $oldid, $newitemid, false, null, $parentcatid);
// Now update the question_versions table with the new question id. we dont need to do that for random qtypes.
$legacyquestiondata = $this->get_mappingid('question_version_created', $oldid) ? true : false;
if ($legacyquestiondata) {
$parentitemid = $this->get_mappingid('question_version_created', $oldid);
// With newitemid = 0, let's create the question.
if (!$questionmapping->newitemid) {
// Now we know we are inserting a question, we may need to insert the questionbankentry.
if (empty($this->latestqbe->newid)) {
$this->latestqbe->oldid = $this->latestqbe->id;
$this->latestqbe->questioncategoryid = $this->get_new_parentid('question_category');
$userid = $this->get_mappingid('user', $this->latestqbe->ownerid);
if ($userid) {
$this->latestqbe->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$this->latestqbe->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (!empty($this->latestqbe->idnumber) && $DB->record_exists('question_bank_entries',
['idnumber' => $this->latestqbe->idnumber, 'questioncategoryid' => $this->latestqbe->questioncategoryid])) {
unset($this->latestqbe->idnumber);
}
$this->latestqbe->newid = $DB->insert_record('question_bank_entries', $this->latestqbe);
$this->set_mapping('question_bank_entry', $this->latestqbe->oldid, $this->latestqbe->newid);
}
// Now store the question.
$newitemid = $DB->insert_record('question', $data);
$this->set_mapping('question', $oldid, $newitemid);
// Also annotate them as question_created, we need
// that later when remapping parents (keeping the old categoryid as parentid).
$parentcatid = $this->get_old_parentid('question_category');
$this->set_mapping('question_created', $oldid, $newitemid, false, null, $parentcatid);
// Also insert this question_version.
$oldqvid = $this->latestversion->id;
$this->latestversion->questionbankentryid = $this->latestqbe->newid;
$this->latestversion->questionid = $newitemid;
$newqvid = $DB->insert_record('question_versions', $this->latestversion);
$this->set_mapping('question_versions', $oldqvid, $newqvid);
} else {
$parentitemid = $this->get_new_parentid('question_versions');
// By performing this set_mapping() we make get_old/new_parentid() to work for all the
// children elements of the 'question' one (so qtype plugins will know the question they belong to).
$this->set_mapping('question', $oldid, $questionmapping->newitemid);
// Also create the question_bank_entry and version mappings, if required.
$newquestionversion = $DB->get_record('question_versions', ['questionid' => $questionmapping->newitemid]);
$this->set_mapping('question_versions', $this->latestversion->id, $newquestionversion->id);
if (empty($this->latestqbe->newid)) {
$this->latestqbe->oldid = $this->latestqbe->id;
$this->latestqbe->newid = $newquestionversion->questionbankentryid;
$this->set_mapping('question_bank_entry', $this->latestqbe->oldid, $this->latestqbe->newid);
}
}
$version = new stdClass();
$version->id = $parentitemid;
$version->questionid = $newitemid;
$DB->update_record('question_versions', $version);
// Note, we don't restore any question files yet
// as far as the CONTEXT_MODULE categories still
// haven't their contexts to be restored to
// The {@link restore_create_question_files}, executed in the final step
// The {@see restore_create_question_files}, executed in the final
// step will be in charge of restoring all the question files.
}
+1 -2
View File
@@ -36,7 +36,7 @@ require_once($CFG->libdir . '/completionlib.php');
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class moodle2_test extends \advanced_testcase {
final class moodle2_test extends \advanced_testcase {
/**
* Tests the availability field on modules and sections is correctly
@@ -1146,7 +1146,6 @@ class moodle2_test extends \advanced_testcase {
'filearea' => 'package',
'itemid' => 0,
'filepath' => '/',
'filepath' => '/',
'filename' => 'dummy.h5p',
'addxapistate' => true,
];
@@ -77,7 +77,6 @@ abstract class backup_plan_dbops extends backup_dbops {
// Get the course and sequence of the section
$secrec = $DB->get_record('course_sections', array('id' => $sectionid), 'course, sequence');
$courseid = $secrec->course;
$sequence = $secrec->sequence;
// Get the section->sequence contents (it roots the activities order)
// Get all course modules belonging to requested section
@@ -89,7 +88,7 @@ abstract class backup_plan_dbops extends backup_dbops {
WHERE cm.course = ?
AND cm.section = ?
AND cm.deletioninprogress <> 1", array($courseid, $sectionid));
foreach (explode(',', $sequence) as $moduleid) {
foreach (explode(',', (string) $secrec->sequence) as $moduleid) {
if (isset($modules[$moduleid])) {
$module = array('id' => $modules[$moduleid]->id, 'modname' => $modules[$moduleid]->modname);
$modulesarr[] = (object)$module;
+3 -4
View File
@@ -671,8 +671,7 @@ abstract class restore_dbops {
$questions = self::restore_get_questions($restoreid, $category->id);
// Collect all the questions for this category into memory so we only talk to the DB once.
$questioncache = $DB->get_records_sql_menu('SELECT q.id,
q.stamp
$questioncache = $DB->get_records_sql_menu('SELECT q.stamp, q.id
FROM {question} q
JOIN {question_versions} qv
ON qv.questionid = q.id
@@ -683,8 +682,8 @@ abstract class restore_dbops {
WHERE qc.id = ?', array($matchcat->id));
foreach ($questions as $question) {
if (isset($questioncache[$question->stamp." ".$question->version])) {
$matchqid = $questioncache[$question->stamp." ".$question->version];
if (isset($questioncache[$question->stamp])) {
$matchqid = $questioncache[$question->stamp];
} else {
$matchqid = false;
}
@@ -35,22 +35,35 @@ require_once($CFG->dirroot.'/backup/util/xml/parser/processors/grouped_parser_pr
* TODO: Complete phpdocs
*/
class restore_questions_parser_processor extends grouped_parser_processor {
/** @var string XML path in the questions.xml backup file to question categories. */
protected const CATEGORY_PATH = '/question_categories/question_category';
protected $restoreid;
protected $lastcatid;
/** @var string XML path in the questions.xml to question elements within question_category (Moodle 4.0+). */
protected const QUESTION_SUBPATH =
'/question_bank_entries/question_bank_entry/question_version/question_versions/questions/question';
/** @var string XML path in the questions.xml to question elements within question_category (before Moodle 4.0). */
protected const LEGACY_QUESTION_SUBPATH = '/questions/question';
/** @var string identifies the current restore. */
protected string $restoreid;
/** @var int during the restore, this tracks the last category we saw. Any questions we see will be in here. */
protected int $lastcatid;
public function __construct($restoreid) {
$this->restoreid = $restoreid;
$this->lastcatid = 0;
parent::__construct(array());
parent::__construct();
// Set the paths we are interested on
$this->add_path('/question_categories/question_category');
$this->add_path('/question_categories/question_category/questions/question');
$this->add_path(self::CATEGORY_PATH);
$this->add_path(self::CATEGORY_PATH . self::QUESTION_SUBPATH);
$this->add_path(self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH);
}
protected function dispatch_chunk($data) {
// Prepare question_category record
if ($data['path'] == '/question_categories/question_category') {
if ($data['path'] == self::CATEGORY_PATH) {
$info = (object)$data['tags'];
$itemname = 'question_category';
$itemid = $info->id;
@@ -58,7 +71,8 @@ class restore_questions_parser_processor extends grouped_parser_processor {
$this->lastcatid = $itemid;
// Prepare question record
} else if ($data['path'] == '/question_categories/question_category/questions/question') {
} else if ($data['path'] == self::CATEGORY_PATH . self::QUESTION_SUBPATH ||
$data['path'] == self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH) {
$info = (object)$data['tags'];
$itemname = 'question';
$itemid = $info->id;
+11 -11
View File
@@ -134,14 +134,14 @@ class core_backup_renderer extends plugin_renderer_base {
$html .= $this->backup_detail_pair(get_string('backupmode', 'backup'), get_string('backupmode'.$details->mode, 'backup'));
$html .= $this->backup_detail_pair(get_string('backupdate', 'backup'), userdate($details->backup_date));
$html .= $this->backup_detail_pair(get_string('moodleversion', 'backup'),
html_writer::tag('span', $details->moodle_release, array('class' => 'moodle_release')).
html_writer::tag('span', '['.$details->moodle_version.']', array('class' => 'moodle_version sub-detail')));
html_writer::tag('span', s($details->moodle_release), array('class' => 'moodle_release')).
html_writer::tag('span', '[' . s($details->moodle_version) .']', array('class' => 'moodle_version sub-detail')));
$html .= $this->backup_detail_pair(get_string('backupversion', 'backup'),
html_writer::tag('span', $details->backup_release, array('class' => 'moodle_release')).
html_writer::tag('span', '['.$details->backup_version.']', array('class' => 'moodle_version sub-detail')));
html_writer::tag('span', s($details->backup_release), array('class' => 'moodle_release')).
html_writer::tag('span', '[' . s($details->backup_version) . ']', array('class' => 'moodle_version sub-detail')));
$html .= $this->backup_detail_pair(get_string('originalwwwroot', 'backup'),
html_writer::tag('span', $details->original_wwwroot, array('class' => 'originalwwwroot')).
html_writer::tag('span', '['.$details->original_site_identifier_hash.']', array('class' => 'sitehash sub-detail')));
html_writer::tag('span', s($details->original_wwwroot), array('class' => 'originalwwwroot')).
html_writer::tag('span', '[' . s($details->original_site_identifier_hash) . ']', array('class' => 'sitehash sub-detail')));
if (!empty($details->include_file_references_to_external_content)) {
$message = '';
if (backup_general_helper::backup_is_samesite($details)) {
@@ -169,8 +169,8 @@ class core_backup_renderer extends plugin_renderer_base {
$html .= html_writer::start_tag('div', ['class' => 'backup-section',
'role' => 'table', 'aria-labelledby' => 'backupcoursedetailsheader']);
$html .= $this->output->heading(get_string('backupcoursedetails', 'backup'), 2, 'header', 'backupcoursedetailsheader');
$html .= $this->backup_detail_pair(get_string('coursetitle', 'backup'), $details->course->title);
$html .= $this->backup_detail_pair(get_string('courseid', 'backup'), $details->course->courseid);
$html .= $this->backup_detail_pair(get_string('coursetitle', 'backup'), format_string($details->course->title));
$html .= $this->backup_detail_pair(get_string('courseid', 'backup'), clean_param($details->course->courseid, PARAM_INT));
// Warning users about front page backups.
if ($details->original_course_format === 'site') {
@@ -188,7 +188,7 @@ class core_backup_renderer extends plugin_renderer_base {
} else {
continue;
}
$html .= $this->backup_detail_pair(get_string('backupcoursesection', 'backup', $section->title), $value);
$html .= $this->backup_detail_pair(get_string('backupcoursesection', 'backup', format_string($section->title)), $value);
$table = null;
foreach ($details->activities as $activitykey => $activity) {
if ($activity->sectionid != $section->sectionid) {
@@ -206,7 +206,7 @@ class core_backup_renderer extends plugin_renderer_base {
$icon = new image_icon('monologo', '', $activity->modulename, ['class' => 'iconlarge icon-pre']);
$table->data[] = array(
$this->output->render($icon).$name,
$activity->title,
format_string($activity->title),
($activity->settings[$activitykey.'_userinfo']) ? $yestick : $notick,
);
}
@@ -522,7 +522,7 @@ class core_backup_renderer extends plugin_renderer_base {
public function substage_buttons($haserrors) {
$output = html_writer::start_tag('div', array('continuebutton'));
if (!$haserrors) {
$attrs = array('type' => 'submit', 'value' => get_string('continue'), 'class' => 'btn btn-primary');
$attrs = ['type' => 'submit', 'value' => get_string('continue'), 'class' => 'btn btn-primary mr-1'];
$output .= html_writer::empty_tag('input', $attrs);
}
$attrs = array('type' => 'submit', 'name' => 'cancel', 'value' => get_string('cancel'), 'class' => 'btn btn-secondary');
@@ -23,6 +23,7 @@ use core_badges\reportbuilder\local\entities\badge;
use core_reportbuilder\local\helpers\database;
use core_reportbuilder\local\report\{action, column};
use core_reportbuilder\system_report;
use html_writer;
use lang_string;
use moodle_url;
use pix_icon;
@@ -42,6 +43,9 @@ require_once("{$CFG->libdir}/badgeslib.php");
*/
class badges extends system_report {
/** @var int $badgeid The ID of the current badge row */
private int $badgeid;
/**
* Initialise report, we need to set the main table, load our entities and set columns/filters
*/
@@ -73,8 +77,8 @@ class badges extends system_report {
$this->add_filters();
$this->add_actions();
// Set initial sorting by name.
$this->set_initial_sort_column('badge:namewithlink', SORT_ASC);
$this->set_default_no_results_notice(new lang_string('nomatchingbadges', 'core_badges'));
// Set if report can be downloaded.
$this->set_downloadable(false);
@@ -115,7 +119,6 @@ class badges extends system_report {
$this->add_columns_from_entities($columns);
// Issued badges column.
// TODO: Move this column to the entity when MDL-76392 is integrated.
$tempbadgealias = database::generate_alias();
$badgeentityalias = $badgeentity->get_table_alias('badge');
$this->add_column((new column(
@@ -130,7 +133,14 @@ class badges extends system_report {
INNER JOIN {user} u
ON {$tempbadgealias}.userid = u.id
WHERE {$tempbadgealias}.badgeid = {$badgeentityalias}.id AND u.deleted = 0)", 'issued')
->set_is_sortable(true));
->set_is_sortable(true)
->set_callback(function(int $count): string {
if (!has_capability('moodle/badges:viewawarded', $this->get_context())) {
return (string) $count;
}
return html_writer::link(new moodle_url('/badges/recipients.php', ['id' => $this->badgeid]), $count);
}));
// Remove title from image column.
$this->get_column('badge:image')->set_title(null);
@@ -146,11 +156,10 @@ class badges extends system_report {
* unique identifier
*/
protected function add_filters(): void {
$filters = [
$this->add_filters_from_entities([
'badge:name',
'badge:status',
];
$this->add_filters_from_entities($filters);
]);
}
/**
@@ -286,6 +295,15 @@ class badges extends system_report {
}
}
/**
* Store the ID of the badge within each row
*
* @param stdClass $row
*/
public function row_callback(stdClass $row): void {
$this->badgeid = (int) $row->id;
}
/**
* CSS classes to add to the row
*
@@ -197,6 +197,7 @@ class award_criteria_courseset extends award_criteria {
* @return bool Whether criteria is complete
*/
public function review($userid, $filtered = false) {
$overall = false;
foreach ($this->params as $param) {
$course = new stdClass();
$course->id = $param['course'];
+4 -3
View File
@@ -89,11 +89,14 @@ if (!has_any_capability(array(
}
$PAGE->set_title($hdr);
/** @var core_badges_renderer $output */
$output = $PAGE->get_renderer('core', 'badges');
if (($delete || $archive) && has_capability('moodle/badges:deletebadge', $PAGE->context)) {
if ($delete || $archive) {
$badgeid = ($archive != 0) ? $archive : $delete;
$badge = new badge($badgeid);
require_capability('moodle/badges:deletebadge', $badge->get_context());
if (!$confirm) {
echo $output->header();
// Archive this badge?
@@ -158,8 +161,6 @@ if ($msg !== '') {
}
$report = system_report_factory::create(badges::class, $PAGE->context);
$report->set_default_no_results_notice(new lang_string('nobadges', 'badges'));
echo $report->output();
echo $OUTPUT->footer();
+1 -1
View File
@@ -75,7 +75,7 @@ echo $OUTPUT->heading(print_badge_image($badge, $context, 'small') . ' ' . $badg
if ($awards == 'cron') {
echo $OUTPUT->notification(get_string('awardoncron', 'badges'), 'notifysuccess');
} else if ($awards != 0) {
} else if ((int)$awards > 0) {
echo $OUTPUT->notification(get_string('numawardstat', 'badges', $awards), 'notifysuccess');
}
echo $output->print_badge_status_box($badge);
+60
View File
@@ -757,6 +757,66 @@ class badgeslib_test extends advanced_testcase {
$this->assertSame(0, $badge->review_all_criteria()); // Verify award_criteria_cohort->get_completed_criteria_sql().
}
/**
* Test badges observer when user_updated event is fired.
* @covers \award_criteria_courseset
*/
public function test_badges_observer_courseset_criteria_review(): void {
$this->preventResetByRollback(); // Messaging is not compatible with transactions.
$badge = new badge($this->coursebadge);
$this->assertFalse($badge->is_issued($this->user->id));
$additionalcourse = $this->getDataGenerator()->create_course(['enablecompletion' => true]);
$this->getDataGenerator()->enrol_user($this->user->id, $additionalcourse->id);
$criteriaoverall = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id]);
$criteriaoverall->save(['agg' => BADGE_CRITERIA_AGGREGATION_ANY]);
$criteriaoverall1 = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_COURSESET, 'badgeid' => $badge->id]);
$criteriaoverall1->save(['agg' => BADGE_CRITERIA_AGGREGATION_ANY, 'course_' . $this->course->id => $this->course->id,
'course_' . $additionalcourse->id => $additionalcourse->id]);
$ccompletion = new completion_completion(['course' => $this->course->id, 'userid' => $this->user->id]);
$ccompletion2 = new completion_completion(['course' => $additionalcourse->id, 'userid' => $this->user->id]);
// Assert the badge will not be issued to the user as is.
$badge = new badge($this->coursebadge);
$badge->review_all_criteria();
$this->assertFalse($badge->is_issued($this->user->id));
// Mark course as complete.
$sink = $this->redirectMessages();
$ccompletion->mark_complete();
$ccompletion2->mark_complete();
// Thee messages are generated: Two for the course completed and the other one for the badge awarded.
$messages = $sink->get_messages();
$this->assertCount(3, $messages);
$this->assertEquals('badgerecipientnotice', $messages[0]->eventtype);
$this->assertEquals('coursecompleted', $messages[1]->eventtype);
$sink->close();
// Check if badge is awarded.
$this->assertDebuggingCalled('Error baking badge image!');
$this->assertTrue($badge->is_issued($this->user->id));
}
/**
* Test the criteria review method for courseset
* @covers \award_criteria_courseset::review
*/
public function test_badges_courseset_criteria_review_empty_courseset(): void {
$this->preventResetByRollback(); // Messaging is not compatible with transactions.
$badge = new badge($this->coursebadge);
$this->assertFalse($badge->is_issued($this->user->id));
$criteriaoverall = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id]);
$criteriaoverall->save(['agg' => BADGE_CRITERIA_AGGREGATION_ANY]);
$criteriaoverall1 = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_COURSESET, 'badgeid' => $badge->id]);
$criteriaoverall1->save();
// Assert the badge will not be issued to the user as is.
$badge = new badge($this->coursebadge);
$badge->review_all_criteria();
$this->assertFalse($badge->is_issued($this->user->id));
}
/**
* Test badges observer when cohort_member_added event is fired and user required to belong to multiple (all) cohorts.
*
+2 -2
View File
@@ -51,7 +51,7 @@ Feature: Add badges to the system
And I should see "Math"
And I should see "Physics"
And I navigate to "Badges > Manage badges" in site administration
And I should not see "There are currently no badges available for users to earn."
And I should not see "There are no matching badges available for users to earn."
@javascript @_file_upload
Scenario: Add a badge related
@@ -163,7 +163,7 @@ Feature: Add badges to the system
And I should see "Alignments (0)"
And I should not see "Create badge"
And I navigate to "Badges > Manage badges" in site administration
And I should not see "There are currently no badges available for users to earn."
And I should not see "There are no matching badges available for users to earn."
# See buttons from the "Site badges" page.
And I am on homepage
When I click on "Site pages" "list_item" in the "Navigation" "block"
+13 -5
View File
@@ -43,7 +43,7 @@ Feature: Manage badges
And I navigate to "Badges > Manage badges" in site administration
And I press "Delete" action in the "Badge #1" report row
And I press "Delete and remove existing issued badges"
Then I should see "There are currently no badges available for users to earn"
Then I should see "There are no matching badges available for users to earn."
Scenario: Enable and disable access to a badge
Given I log in as "admin"
@@ -68,7 +68,10 @@ Feature: Manage badges
| Badge #1 | Not available |
Scenario: Award a badge
Given I log in as "admin"
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | user1@example.com |
When I log in as "admin"
And I navigate to "Badges > Manage badges" in site administration
And I press "Edit" action in the "Badge #1" report row
And I select "Criteria" from the "jump" singleselect
@@ -79,9 +82,14 @@ Feature: Manage badges
And I press "Enable access" action in the "Badge #1" report row
And I press "Continue"
And I press "Award badge" action in the "Badge #1" report row
And I set the field "potentialrecipients[]" to "Admin User (moodle@example.com)"
And I set the field "potentialrecipients[]" to "Admin User (moodle@example.com),User One (user1@example.com)"
And I press "Award badge"
And I navigate to "Badges > Manage badges" in site administration
Then the following should exist in the "reportbuilder-table" table:
Then the following should exist in the "Badges" table:
| Name | Badge status | Recipients |
| Badge #1 | Available | 1 |
| Badge #1 | Available | 2 |
And I click on "2" "link" in the "Badge #1" "table_row"
And the following should exist in the "generaltable" table:
| -1- |
| Admin User |
| User One |
@@ -4,7 +4,7 @@ Feature: Manage badges is not shown when there are no existing badges.
Scenario: Check navigation at site level with no badges
Given I log in as "admin"
When I navigate to "Badges > Manage badges" in site administration
And I should see "There are currently no badges available for users to earn"
And I should see "There are no matching badges available for users to earn."
Then "Manage badges" "button" should not exist
Scenario: Check navigation at course level with no badges
+7 -7
View File
@@ -1,22 +1,22 @@
.block_accessreview_success,
.block_accessreview.block_accessreview_success.hasinfo {
color: #1e451e;
background: #d7e6d7;
border-color: #c8ddc8;
background: #eff5ef;
box-shadow: 0 0 2px 2px #619a61;
}
.block_accessreview_danger,
.block_accessreview.block_accessreview_danger.hasinfo {
color: #6e211e;
background: #f6d9d8;
border-color: #f3c9c8;
background: #fdf7f7;
box-shadow: 0 0 2px 2px #da6960;
}
.block_accessreview_warning,
.block_accessreview.block_accessreview_warning.hasinfo {
color: #7d5a29;
background: #fcefdc;
border-color: #fbe8cd;
color: #694b21;
background: #fdf2e3;
box-shadow: 0 0 2px 2px #c97a0e;
}
.block_accessreview_table {
@@ -56,6 +56,9 @@ class block_calendar_month extends block_base {
$calendar = \calendar_information::create(time(), $courseid, $categoryid);
list($data, $template) = calendar_get_view($calendar, 'monthblock', isloggedin());
// Add a flag that this is coming from calendar block.
$data->iscalendarblock = true;
$renderer = $this->page->get_renderer('core_calendar');
$this->content->text .= $renderer->render_from_template($template, $data);
@@ -91,3 +91,22 @@ Feature: Enable the calendar block in a course and test it's functionality
Then I should see "Group Event"
And I am on the "Course 1" course page logged in as student2
And I should not see "Group Event"
@javascript
Scenario: Click on today's course event on the calendar view page's calendar block
Given I log in as "admin"
And I create a calendar event with form data:
| id_eventtype | Site |
| id_name | Site Event |
And I am on site homepage
And I turn editing mode on
And I add the "Calendar" block
And I configure the "Calendar" block
And I set the following fields to these values:
| Page contexts | Display throughout the entire site |
And I press "Save changes"
When I am on "Course 1" course homepage
And I follow "Full calendar"
And I click on today in the mini-calendar block to view the detail
Then I should see "Site Event" in the "Calendar" "block"
And ".popover" "css_element" should not exist
+7 -7
View File
@@ -71,7 +71,7 @@ class block_base {
/**
* An object to contain the information to be displayed in the block.
* @var stdClass $content
* @var stdClass|null $content
*/
var $content = NULL;
@@ -88,7 +88,7 @@ class block_base {
public $page = NULL;
/**
* This blocks's context.
* This block's context.
* @var context
*/
public $context = NULL;
@@ -141,7 +141,7 @@ class block_base {
* This should be implemented by the derived class to return
* the content object.
*
* @return stdObject
* @return stdClass
*/
function get_content() {
// This should be implemented by the derived class.
@@ -167,7 +167,7 @@ class block_base {
* Intentionally doesn't check if content_type is set.
* This is already done in {@link _self_test()}
*
* @return string $this->content_type
* @return int $this->content_type
*/
function get_content_type() {
// Intentionally doesn't check if a content_type is set. This is already done in _self_test()
@@ -178,7 +178,7 @@ class block_base {
* Returns true or false, depending on whether this block has any content to display
* and whether the user has permission to view the block
*
* @return boolean
* @return bool
*/
function is_empty() {
if ( !has_capability('moodle/block:view', $this->context) ) {
@@ -194,7 +194,7 @@ class block_base {
* then calls the block's {@link get_content()} function
* to set its value back.
*
* @return stdObject
* @return stdClass
*/
function refresh_content() {
// Nothing special here, depends on content()
@@ -211,7 +211,7 @@ class block_base {
* {@link html_attributes()}, {@link formatted_contents()} or {@link get_content()},
* {@link hide_header()}, {@link (get_edit_controls)}, etc.
*
* @return block_contents a representation of the block, for rendering.
* @return block_contents|null a representation of the block, for rendering.
* @since Moodle 2.0.
*/
public function get_content_for_output($output) {
@@ -88,7 +88,7 @@ $string['sortbylastaccessed'] = 'Sort by last accessed';
$string['sortbyshortname'] = 'Sort by short name';
$string['privacy:request:preference:set'] = 'The value of the setting \'{$a->name}\' was \'{$a->value}\'';
$string['viewquickstart'] = 'View Quickstart guide';
$string['zero_default_title'] = 'You\'re not enrolled in any course';
$string['zero_default_title'] = 'You\'re not enrolled in any courses.';
$string['zero_default_intro'] = 'Once you\'re enrolled in a course, it will appear here.';
$string['zero_request_title'] = 'Request your first course';
$string['zero_request_intro'] = 'Need help getting started? Check out the <a href="{$a->dochref}" title="{$a->doctitle}" target="{$a->doctarget}">Moodle documentation</a> or take your first steps with our <a href="{$a->quickhref}" title="{$a->quicktitle}" target="{$a->quicktarget}">Quickstart guide</a>.';
@@ -35,7 +35,7 @@ Feature: My overview block pagination
Scenario: The pagination controls should be hidden if I am not enrolled in any courses
When I am on the "My courses" page logged in as "student1"
Then I should see "You're not enrolled in any course" in the "Course overview" "block"
Then I should see "You're not enrolled in any courses." in the "Course overview" "block"
And I should not see "Show" in the "Course overview" "block"
And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible
And ".block_myoverview [data-control='next']" "css_element" should not be visible
@@ -40,7 +40,7 @@ Feature: My overview block searching
Scenario: There is no search if I am not enrolled in any course
When I am on the "My courses" page logged in as "student2"
Then I should see "You're not enrolled in any course" in the "Course overview" "block"
Then I should see "You're not enrolled in any courses." in the "Course overview" "block"
And "Search courses" "field" should not exist in the "Course overview" "block"
And I log out
@@ -15,7 +15,7 @@ Feature: Zero state on my overview block
Scenario: Users with no permissions don't see any CTA
Given I am on the "My courses" page logged in as "user"
When I should see "You're not enrolled in any course"
When I should see "You're not enrolled in any courses."
Then I should see "Once you're enrolled in a course, it will appear here."
And I should not see "Create course"
And I should not see "Request a course"
@@ -46,7 +46,7 @@ Feature: Zero state on my overview block
| fullname | Course 1 |
| shortname | C1 |
When I am on the "My courses" page logged in as "manager"
Then I should see "You're not enrolled in any course"
Then I should see "You're not enrolled in any courses."
Then I should see "Once you're enrolled in a course, it will appear here."
And "Manage courses" "button" should exist
And "Create course" "button" should exist
@@ -64,7 +64,7 @@ Feature: Zero state on my overview block
| fullname | Course 1 |
| shortname | C1 |
When I am on the "My courses" page logged in as "manager"
Then I should see "You're not enrolled in any course"
Then I should see "You're not enrolled in any courses."
Then I should not see "To view all courses on this sie, go to Manage courses"
And "Manage courses" "button" should not exist
And "Create course" "button" should exist
+12 -1
View File
@@ -180,7 +180,18 @@ $PAGE->set_pagelayout('admin');
if ($rssid) {
$isadding = false;
$rssrecord = $DB->get_record('block_rss_client', array('id' => $rssid), '*', MUST_EXIST);
if ($managesharedfeeds) {
$select = 'id = :id AND (userid = :userid OR shared = 1)';
} else {
$select = 'id = :id AND userid = :userid';
}
$rssrecord = $DB->get_record_select('block_rss_client', $select, [
'id' => $rssid,
'userid' => $USER->id,
], '*', MUST_EXIST);
} else {
$isadding = true;
$rssrecord = new stdClass;
+16 -16
View File
@@ -22,7 +22,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['addfeed'] = 'Add a news feed URL:';
$string['addfeed'] = 'Add RSS feed URL';
$string['addheadlineblock'] = 'Add RSS headline block';
$string['addnew'] = 'Add new';
$string['addnewfeed'] = 'Add a new feed';
@@ -30,16 +30,16 @@ $string['cannotmakemodification'] = 'You are not allowed to make modifications t
$string['clientchannellink'] = 'Source site...';
$string['clientnumentries'] = 'The default number of entries to show per feed.';
$string['clientshowchannellinklabel'] = 'Should a link to the original site (channel link) be displayed? (Note that if no feed link is supplied in the news feed then no link will be shown) :';
$string['clientshowimagelabel'] = 'Show channel image if available :';
$string['clientshowimagelabel'] = 'Show channel image if available';
$string['configblock'] = 'Configure this block';
$string['couldnotfindfeed'] = 'Could not find feed with id';
$string['couldnotfindfeed'] = 'Could not find feed with ID.';
$string['couldnotfindloadrssfeed'] = 'Could not find or load the RSS feed.';
$string['customtitlelabel'] = 'Custom title (leave blank to use title supplied by feed):';
$string['customtitlelabel'] = 'Custom title (leave blank to use title supplied by feed)';
$string['deletefeedconfirm'] = 'Are you sure you want to delete this feed?';
$string['disabledrssfeeds'] = 'RSS feeds are disabled';
$string['displaydescriptionlabel'] = 'Display each link\'s description?';
$string['editafeed'] = 'Edit a feed';
$string['editfeeds'] = 'Edit, subscribe or unsubscribe from RSS/Atom news feeds';
$string['editfeeds'] = 'Edit, subscribe or unsubscribe from RSS feeds';
$string['editnewsfeeds'] = 'Edit news feeds';
$string['editrssblock'] = 'Edit RSS headline block';
$string['enableautodiscovery'] = 'Enable auto-discovery of feeds?';
@@ -47,21 +47,21 @@ $string['enableautodiscovery_help'] = 'If enabled, feeds on web pages are found
$string['failedfeed'] = 'Feed failed to download - will retry after {$a}';
$string['failedfeeds'] = 'One or more RSS feeds have failed';
$string['feed'] = 'Feed';
$string['feedadded'] = 'News feed added';
$string['feeddeleted'] = 'News feed deleted';
$string['feeds'] = 'News feeds';
$string['feedadded'] = 'RSS feed added';
$string['feeddeleted'] = 'RSS feed deleted';
$string['feeds'] = 'RSS feeds';
$string['feedsaddedit'] = 'Add/edit feeds';
$string['feedsconfigurenewinstance'] = 'Click here to configure this block to display RSS feeds.';
$string['feedsconfigurenewinstance2'] = 'Click the edit icon above to configure this block to display RSS feeds.';
$string['feedupdated'] = 'News feed updated';
$string['feedupdated'] = 'RSS feed updated';
$string['feedurl'] = 'Feed URL';
$string['findmorefeeds'] = 'Find more RSS feeds';
$string['choosefeedlabel'] = 'Choose the feeds which you would like to make available in this block:';
$string['managefeeds'] = 'Manage all my feeds';
$string['managefeeds'] = 'Manage RSS feeds';
$string['nofeeds'] = 'There are no RSS feeds defined for this site.';
$string['numentries'] = 'Entries per feed';
$string['pickfeed'] = 'Pick a news feed';
$string['pluginname'] = 'Remote RSS feeds';
$string['pickfeed'] = 'Pick a RSS feed';
$string['pluginname'] = 'RSS feeds';
$string['privacy:metadata:block_rss_client:description'] = 'The description of the RSS feed.';
$string['privacy:metadata:block_rss_client:preferredtitle'] = 'The preferred (custom) title of the RSS feed.';
$string['privacy:metadata:block_rss_client:shared'] = 'If the RSS feed is available to all courses.';
@@ -71,14 +71,14 @@ $string['privacy:metadata:block_rss_client:tableexplanation'] = 'RSS block infor
$string['privacy:metadata:block_rss_client:title'] = 'The title of the RSS feed.';
$string['privacy:metadata:block_rss_client:url'] = 'The URL of the RSS feed.';
$string['privacy:metadata:block_rss_client:userid'] = 'The ID of the user that added the RSS feed.';
$string['remotenewsfeed'] = 'Remote news feed';
$string['remotenewsfeed'] = 'RSS feed';
$string['refreshfeedstask'] = 'Refresh RSS feeds task';
$string['rss_client:addinstance'] = 'Add a new remote RSS feeds block';
$string['rss_client:addinstance'] = 'Add new RSS feeds block';
$string['rss_client:createprivatefeeds'] = 'Create private RSS feeds';
$string['rss_client:createsharedfeeds'] = 'Create shared RSS feeds';
$string['rss_client:manageanyfeeds'] = 'Manage any RSS feeds';
$string['rss_client:manageownfeeds'] = 'Manage own RSS feeds';
$string['rss_client:myaddinstance'] = 'Add a new Remote RSS feeds block to Dashboard';
$string['rss_client:myaddinstance'] = 'Add new RSS feeds block to Dashboard';
$string['seeallfeeds'] = 'See all feeds';
$string['sharedfeed'] = 'Shared feed';
$string['shownumentrieslabel'] = 'Max number entries to show per block.';
@@ -87,5 +87,5 @@ $string['submitters2'] = 'Submitters';
$string['timeout'] = 'Time in minutes before an RSS feed expires in cache. Note that this time defines the minimum time before expiry; the feed will be refreshed in cache on the next cron execution after expiry. Recommended values are 30 mins or greater.';
$string['timeoutdesc'] = 'Time in minutes for an RSS feed to live in cache.';
$string['timeout2'] = 'Timeout';
$string['updatefeed'] = 'Update a news feed URL:';
$string['updatefeed'] = 'Update RSS feed URL';
$string['viewfeed'] = 'View feed';
+14 -7
View File
@@ -61,20 +61,27 @@ if ($returnurl) {
$baseurl = new moodle_url('/blocks/rss_client/managefeeds.php', $urlparams);
$PAGE->set_url($baseurl);
if ($managesharedfeeds) {
$select = '(userid = :userid OR shared = 1)';
} else {
$select = 'userid = :userid';
}
// Process any actions
if ($deleterssid && confirm_sesskey()) {
$DB->delete_records('block_rss_client', array('id'=>$deleterssid));
$deleterssid = $DB->get_field_select('block_rss_client', 'id', "id = :id AND {$select}", [
'id' => $deleterssid,
'userid' => $USER->id
], MUST_EXIST);
$DB->delete_records('block_rss_client', ['id' => $deleterssid]);
redirect($PAGE->url, get_string('feeddeleted', 'block_rss_client'));
}
// Display the list of feeds.
if ($managesharedfeeds) {
$select = '(userid = ' . $USER->id . ' OR shared = 1)';
} else {
$select = 'userid = ' . $USER->id;
}
$feeds = $DB->get_records_select('block_rss_client', $select, null, $DB->sql_order_by_text('title'));
$feeds = $DB->get_records_select('block_rss_client', $select, ['userid' => $USER->id], $DB->sql_order_by_text('title'));
$strmanage = get_string('managefeeds', 'block_rss_client');
+17 -8
View File
@@ -759,18 +759,27 @@ class cache_helper {
debugging('Cache stores used for session definitions should ideally be searchable.', DEBUG_DEVELOPER);
continue;
}
// Get all of the keys.
$keys = $store->find_by_prefix(cache_session::KEY_PREFIX);
$todelete = array();
// Get all of the last access keys.
$keys = $store->find_by_prefix(cache_session::LASTACCESS);
$todelete = [];
foreach ($store->get_many($keys) as $key => $value) {
if (strpos($key, cache_session::KEY_PREFIX) !== 0 || !is_array($value) || !isset($value['lastaccess'])) {
continue;
$expiresvalue = 0;
if ($value instanceof cache_ttl_wrapper) {
$expiresvalue = $value->data;
} else if ($value instanceof cache_cached_object) {
$expiresvalue = $value->restore_object();
} else {
$expiresvalue = $value;
}
if ((int)$value['lastaccess'] < $purgetime || true) {
$todelete[] = $key;
$expires = (int) $expiresvalue;
if ($expires > 0 && $expires < $purgetime) {
$prefix = substr($key, strlen(cache_session::LASTACCESS));
$foundbyprefix = $store->find_by_prefix($prefix);
$todelete = array_merge($todelete, [$key], $foundbyprefix);
}
}
if (count($todelete)) {
if ($todelete) {
$outcome = (int)$store->delete_many($todelete);
if ($output) {
$strdef = s($definition->get_id());
+14 -3
View File
@@ -63,6 +63,9 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
*/
const TTL_EXPIRE_BATCH = 10000;
/** @var int The number of seconds to wait for a connection or response from the Redis server. */
const CONNECTION_TIMEOUT = 10;
/**
* Name of this store.
*
@@ -241,8 +244,16 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
}
try {
if ($redis->connect($server, $port, 1, null, 100, 1, $opts)) {
$connection = $redis->connect(
$server,
$port,
self::CONNECTION_TIMEOUT, // Timeout.
null,
100, // Retry interval.
self::CONNECTION_TIMEOUT, // Read timeout.
$opts,
);
if ($connection) {
if (!empty($password)) {
$redis->auth($password);
}
@@ -355,7 +366,7 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
* @return array An array of the values of the given keys.
*/
public function get_many($keys) {
$values = $this->redis->hMGet($this->hash, $keys);
$values = $this->redis->hMGet($this->hash, $keys) ?: [];
if ($this->compressor == self::COMPRESSOR_NONE) {
return $values;
+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
+1 -1
View File
@@ -5,6 +5,6 @@
* @copyright 2017 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/calendar_view",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/crud"],(function($,Notification,CalendarSelectors,CalendarEvents,CalendarViewManager,CalendarCrud){return{init:function(root,type){root=$(root),CalendarViewManager.init(root,type),function(root,type){var body=$("body");CalendarCrud.registerRemove(root);var reloadFunction="reloadCurrent"+type.charAt(0).toUpperCase()+type.slice(1);body.on(CalendarEvents.created,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager[reloadFunction](root)})),root.on("change",CalendarSelectors.courseSelector,(function(){var courseId=$(this).val();CalendarViewManager[reloadFunction](root,courseId,null).then((function(){return root.find(CalendarSelectors.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=upcoming&course="+courseId)})).fail(Notification.exception)})),body.on(CalendarEvents.filterChanged,(function(e,data){var daysWithEvent=root.find(CalendarSelectors.eventType[data.type]);1==data.hidden?daysWithEvent.addClass("hidden"):daysWithEvent.removeClass("hidden"),CalendarViewManager.foldDayEvents(root)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root);CalendarCrud.registerEditListeners(root,eventFormPromise)}(root,type)}}}));
define("core_calendar/calendar_view",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/crud"],(function($,Notification,CalendarSelectors,CalendarEvents,CalendarViewManager,CalendarCrud){var registerEventListeners=function(root,type){var body=$("body");CalendarCrud.registerRemove(root);var reloadFunction="reloadCurrent"+type.charAt(0).toUpperCase()+type.slice(1);body.on(CalendarEvents.created,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager[reloadFunction](root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager[reloadFunction](root)})),root.on("change",CalendarSelectors.courseSelector,(function(){var courseId=$(this).val();CalendarViewManager[reloadFunction](root,courseId,null).then((function(){return root.find(CalendarSelectors.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=upcoming&course="+courseId)})).fail(Notification.exception)})),body.on(CalendarEvents.filterChanged,(function(e,data){var daysWithEvent=root.find(CalendarSelectors.eventType[data.type]);1==data.hidden?daysWithEvent.addClass("hidden"):daysWithEvent.removeClass("hidden"),CalendarViewManager.foldDayEvents(root)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root);CalendarCrud.registerEditListeners(root,eventFormPromise)};return{init:function(root,type){let isCalendarBlock=arguments.length>2&&void 0!==arguments[2]&&arguments[2];root=$(root),CalendarViewManager.init(root,type,isCalendarBlock),registerEventListeners(root,type)}}}));
//# sourceMappingURL=calendar_view.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","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)}}}));
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";return{init:function(formId){!function(formElement){var courseGroupSelect=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID),loadGroupSelectOptions=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))}))};courseGroupSelect.on("change",(function(){var courseId=formElement.find(SELECTORS_EVENT_GROUP_COURSE_ID).val();isNaN(courseId)||courseId<=0?loadGroupSelectOptions([]):CalendarRepository.getCourseGroupsData(courseId).then((function(groups){return loadGroupSelectOptions(groups)})).catch(Notification.exception)}))}($("#"+formId))}}}));
//# 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', '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"}
{"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 if (isNaN(courseId) || courseId <= 0) {\n loadGroupSelectOptions([]);\n } else {\n CalendarRepository.getCourseGroupsData(courseId)\n .then(function(groups) {\n return loadGroupSelectOptions(groups);\n })\n .catch(Notification.exception);\n }\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","init","formId","formElement","courseGroupSelect","find","loadGroupSelectOptions","groups","groupSelect","groupSelectOptions","courseGroups","remove","prop","each","id","group","append","attr","text","name","on","courseId","val","isNaN","getCourseGroupsData","then","catch","exception","addCourseGroupSelectListeners"],"mappings":";;;;;;;AAsBAA,kCAAO,CAAC,SAAU,2BAA4B,sBAAsB,SAASC,EAAGC,mBAAoBC,kBAE5FC,gCACuB,yBADvBA,yBAEgB,mBAFhBA,wBAGe,eAqDZ,CACHC,KANO,SAASC,SArCgB,SAASC,iBACrCC,kBAAoBD,YAAYE,KAAKL,iCAErCM,uBAAyB,SAASC,YAC9BC,YAAcL,YAAYE,KAAKL,0BAC/BS,mBAAqBD,YAAYH,KAAKL,yBACtCU,aAAeb,EAAEU,QAGrBE,mBAAmBE,SACnBH,YAAYI,KAAK,YAAY,GAC7BF,aAAaG,MAAK,SAASC,GAAIC,OAC3BlB,EAAEW,aAAaQ,OAAOnB,EAAE,qBAAqBoB,KAAK,QAASF,MAAMD,IAAII,KAAKH,MAAMI,WAKxFf,kBAAkBgB,GAAG,UAAU,eACvBC,SAAWlB,YAAYE,KAAKL,iCAAiCsB,MAC7DC,MAAMF,WAAaA,UAAY,EAC/Bf,uBAAuB,IAEvBR,mBAAmB0B,oBAAoBH,UAClCI,MAAK,SAASlB,eACJD,uBAAuBC,WAEjCmB,MAAM3B,aAAa4B,cAahCC,CADkB/B,EAAE,IAAMK"}
+1 -1
View File
@@ -6,6 +6,6 @@ define("core_calendar/popover",["theme_boost/popover","jquery","core_calendar/se
* @copyright 2021 Huong Nguyen <huongnv13@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj},CalendarSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(CalendarSelectors);const isPopoverConfigured=new Map,showPopover=target=>{const dateContainer=target.closest(CalendarSelectors.elements.dateContainer);if(!isPopoverConfigured.has(dateContainer)){(0,_jquery.default)(target).popover({trigger:"manual",placement:"top",html:!0,title:dateContainer.dataset.title,content:()=>{const source=(0,_jquery.default)(dateContainer).find(CalendarSelectors.elements.dateContent),content=(0,_jquery.default)("<div>");if(source.length){const temptContent=source.find(".hidden").clone(!1);content.html(temptContent.html())}return content.html()}}),isPopoverConfigured.set(dateContainer,!0)}(dateContainer=>"none"===window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display)(dateContainer)&&((0,_jquery.default)(target).popover("show"),target.addEventListener("mouseleave",hidePopover),target.addEventListener("focusout",hidePopover))},hidePopover=e=>{const target=e.target,dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);if(dateContainer&&isPopoverConfigured.has(dateContainer)){const isTargetActive=target.contains(document.activeElement),isTargetHover=target.matches(":hover");isTargetActive||isTargetHover||((0,_jquery.default)(target).popover("hide"),target.removeEventListener("mouseleave",hidePopover),target.removeEventListener("focusout",hidePopover))}};let listenersRegistered=!1;listenersRegistered||((()=>{const showPopoverHandler=e=>{const dayLink=e.target.closest(CalendarSelectors.links.dayLink);dayLink&&(e.preventDefault(),showPopover(dayLink))};document.addEventListener("mouseover",showPopoverHandler),document.addEventListener("focusin",showPopoverHandler)})(),listenersRegistered=!0)}));
*/function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj},CalendarSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(CalendarSelectors);const isPopoverConfigured=new Map,showPopover=target=>{const dateContainer=target.closest(CalendarSelectors.elements.dateContainer);if(!isPopoverConfigured.has(dateContainer)){(0,_jquery.default)(target).popover({trigger:"manual",placement:"top",html:!0,title:dateContainer.dataset.title,content:()=>{const source=(0,_jquery.default)(dateContainer).find(CalendarSelectors.elements.dateContent),content=(0,_jquery.default)("<div>");if(source.length){const temptContent=source.find(".hidden").clone(!1);content.html(temptContent.html())}return content.html()},animation:!1}),isPopoverConfigured.set(dateContainer,!0)}(dateContainer=>"none"===window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display)(dateContainer)&&((0,_jquery.default)(target).popover("show"),target.addEventListener("mouseleave",hidePopover),target.addEventListener("focusout",hidePopover),target.addEventListener("click",hidePopover))},hidePopover=e=>{const target=e.target,dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);if(dateContainer&&isPopoverConfigured.has(dateContainer)){const isTargetActive=target.contains(document.activeElement),isTargetHover=target.matches(":hover"),isTargetClicked=document.activeElement.contains(target);let removeListener=!0;isTargetActive||isTargetHover?isTargetClicked?(0,_jquery.default)(document.activeElement).popover("hide"):removeListener=!1:(0,_jquery.default)(target).popover("hide"),removeListener&&(target.removeEventListener("mouseleave",hidePopover),target.removeEventListener("focusout",hidePopover),target.removeEventListener("click",hidePopover))}};let listenersRegistered=!1;listenersRegistered||((()=>{const showPopoverHandler=e=>{const dayLink=e.target.closest(CalendarSelectors.links.dayLink);dayLink&&(e.preventDefault(),showPopover(dayLink))};document.addEventListener("mouseover",showPopoverHandler),document.addEventListener("focusin",showPopoverHandler)})(),listenersRegistered=!0)}));
//# sourceMappingURL=popover.min.js.map
File diff suppressed because one or more lines are too long
+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/selectors",[],(function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',viewSelector:'div[data-region="view-selector"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]',viewEvent:'[data-action="view-event"]',deleteSubscription:'[data-action="delete-subscription"]'},elements:{courseSelector:'select[name="course"]',dateContainer:".clickable.hasevent",dateContent:'[data-region="day-content"]',monthDetailed:".calendarmonth.calendartable"},today:".today",day:'[data-region="day"]',calendarMain:'[data-region="calendar"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]',links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']",dayLink:"[data-action='view-day-link']"},containers:{loadingIcon:'[data-region="overlay-icon-container"]'},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view"}}));
define("core_calendar/selectors",[],(function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]",other:"[data-eventtype-other]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',viewSelector:'div[data-region="view-selector"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]',viewEvent:'[data-action="view-event"]',deleteSubscription:'[data-action="delete-subscription"]'},elements:{courseSelector:'select[name="course"]',dateContainer:".clickable.hasevent",dateContent:'[data-region="day-content"]',monthDetailed:".calendarmonth.calendartable"},today:".today",day:'[data-region="day"]',calendarMain:'[data-region="calendar"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]',links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']",dayLink:"[data-action='view-day-link']"},containers:{loadingIcon:'[data-region="overlay-icon-container"]'},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view",pageHeaderHeadings:".page-header-headings h1"}}));
//# sourceMappingURL=selectors.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * CSS selectors for the calendar.\n *\n * @module core_calendar/selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n dayLink: \"[data-action='view-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","dayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,gCACbC,QAAS,iCAEbC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB"}
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * CSS selectors for the calendar.\n *\n * @module core_calendar/selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n dayLink: \"[data-action='view-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n pageHeaderHeadings: '.page-header-headings h1',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","dayLink","containers","loadingIcon","mainCalendar","fullCalendarView","pageHeaderHeadings"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,gCACbC,QAAS,iCAEbC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB,qBAClBC,mBAAoB"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+17 -6
View File
@@ -169,8 +169,9 @@ function(
* Register event listeners for the module.
*
* @param {object} root The calendar root element
* @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.
*/
var registerEventListeners = function(root) {
var registerEventListeners = function(root, isCalendarBlock) {
const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);
// Listen the click on the day link to render the day view.
root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {
@@ -183,9 +184,13 @@ function(
const url = '?view=day&time=' + dayLink.data('timestamp');
if (viewingFullCalendar) {
CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,
'core_calendar/calendar_day').then(function() {
'core_calendar/calendar_day', isCalendarBlock).then(function() {
e.preventDefault();
return CalendarViewManager.updateUrl(url);
// Update the URL if it's not calendar block.
if (!isCalendarBlock) {
CalendarViewManager.updateUrl(url);
}
return;
}).catch(Notification.exception);
} else {
window.location.assign(Config.wwwroot + '/calendar/view.php' + url);
@@ -244,10 +249,16 @@ function(
};
return {
init: function(root) {
/**
* Initializes the calendar view manager and registers event listeners.
*
* @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached.
* @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.
*/
init: function(root, isCalendarBlock = false) {
root = $(root);
CalendarViewManager.init(root);
registerEventListeners(root);
CalendarViewManager.init(root, 'month', isCalendarBlock);
registerEventListeners(root, isCalendarBlock);
}
};
});
+3 -3
View File
@@ -83,11 +83,11 @@ function(
};
return {
init: function(root, type) {
init: function(root, type, isCalendarBlock = false) {
root = $(root);
CalendarViewManager.init(root, type);
registerEventListeners(root, type);
CalendarViewManager.init(root, type, isCalendarBlock);
registerEventListeners(root, type, isCalendarBlock);
}
};
});
+9 -5
View File
@@ -55,11 +55,15 @@ define(['jquery', 'core_calendar/repository', 'core/notification'], function($,
// If the user choose a course in the selector do a WS request to get groups.
courseGroupSelect.on('change', function() {
var courseId = formElement.find(SELECTORS.EVENT_GROUP_COURSE_ID).val();
CalendarRepository.getCourseGroupsData(courseId)
.then(function(groups) {
return loadGroupSelectOptions(groups);
})
.catch(Notification.exception);
if (isNaN(courseId) || courseId <= 0) {
loadGroupSelectOptions([]);
} else {
CalendarRepository.getCourseGroupsData(courseId)
.then(function(groups) {
return loadGroupSelectOptions(groups);
})
.catch(Notification.exception);
}
});
};
+17 -1
View File
@@ -54,7 +54,8 @@ const showPopover = target => {
content.html(temptContent.html());
}
return content.html();
}
},
'animation': false,
});
isPopoverConfigured.set(dateContainer, true);
@@ -64,6 +65,8 @@ const showPopover = target => {
jQuery(target).popover('show');
target.addEventListener('mouseleave', hidePopover);
target.addEventListener('focusout', hidePopover);
// Set up the hide function to the click event type.
target.addEventListener('click', hidePopover);
}
};
@@ -76,10 +79,23 @@ const hidePopover = e => {
if (isPopoverConfigured.has(dateContainer)) {
const isTargetActive = target.contains(document.activeElement);
const isTargetHover = target.matches(':hover');
// Checks if a target element is clicked or pressed.
const isTargetClicked = document.activeElement.contains(target);
let removeListener = true;
if (!isTargetActive && !isTargetHover) {
jQuery(target).popover('hide');
} else if (isTargetClicked) {
jQuery(document.activeElement).popover('hide');
} else {
removeListener = false;
}
if (removeListener) {
target.removeEventListener('mouseleave', hidePopover);
target.removeEventListener('focusout', hidePopover);
target.removeEventListener('click', hidePopover);
}
}
};
+1
View File
@@ -73,5 +73,6 @@ define([], function() {
},
mainCalendar: '.maincalendar .heightcontainer',
fullCalendarView: 'page-calendar-view',
pageHeaderHeadings: '.page-header-headings h1',
};
});
+29 -13
View File
@@ -143,8 +143,9 @@ export const registerEventListenersForMonthDetailed = (pendingId) => {
* Register event listeners for the module.
*
* @param {object} root The root element.
* @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.
*/
const registerEventListeners = (root) => {
const registerEventListeners = (root, isCalendarBlock) => {
root = $(root);
// Bind click events to event links.
@@ -190,10 +191,12 @@ const registerEventListeners = (root) => {
const link = e.currentTarget;
if (view === 'month' || view === 'monthblock') {
changeMonth(root, link.href, link.dataset.year, link.dataset.month, courseId, categoryId, link.dataset.day);
changeMonth(root, link.href, link.dataset.year, link.dataset.month,
courseId, categoryId, link.dataset.day, isCalendarBlock);
e.preventDefault();
} else if (view === 'day') {
changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, courseId, categoryId);
changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day,
courseId, categoryId, isCalendarBlock);
e.preventDefault();
}
});
@@ -287,18 +290,19 @@ export const refreshMonthContent = (root, year, month, courseId, categoryId, tar
* @param {number} courseId The id of the course whose events are shown
* @param {number} categoryId The id of the category whose events are shown
* @param {number} day Day (optional)
* @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.
* @return {promise}
*/
export const changeMonth = (root, url, year, month, courseId, categoryId, day = 1) => {
export const changeMonth = (root, url, year, month, courseId, categoryId, day = 1, isCalendarBlock = false) => {
return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day)
.then((...args) => {
if (url.length && url !== '#') {
if (url.length && url !== '#' && !isCalendarBlock) {
updateUrl(url);
}
return args;
})
.then((...args) => {
$('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId]);
$('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId, day, isCalendarBlock]);
return args;
});
};
@@ -338,10 +342,12 @@ export const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => {
* @param {number} categoryId The id of the category whose events are shown
* @param {object} target The element being replaced. If not specified, the calendarwrapper is used.
* @param {string} template The template to be rendered.
* @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.
*
* @return {promise}
*/
export const refreshDayContent = (root, year, month, day, courseId, categoryId, target = null, template = '') => {
export const refreshDayContent = (root, year, month, day, courseId, categoryId,
target = null, template = '', isCalendarBlock = false) => {
startLoading(root);
if (!target || target.length == 0){
@@ -354,6 +360,7 @@ export const refreshDayContent = (root, year, month, day, courseId, categoryId,
.then((context) => {
context.viewingday = true;
context.showviewselector = true;
context.iscalendarblock = isCalendarBlock;
return Templates.render(template, context);
})
.then((html, js) => {
@@ -400,18 +407,19 @@ export const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => {
* @param {Number} day Day
* @param {Number} courseId The id of the course whose events are shown
* @param {Number} categoryId The id of the category whose events are shown
* @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.
* @return {promise}
*/
export const changeDay = (root, url, year, month, day, courseId, categoryId) => {
return refreshDayContent(root, year, month, day, courseId, categoryId)
export const changeDay = (root, url, year, month, day, courseId, categoryId, isCalendarBlock = false) => {
return refreshDayContent(root, year, month, day, courseId, categoryId, null, '', isCalendarBlock)
.then((...args) => {
if (url.length && url !== '#') {
if (url.length && url !== '#' && !isCalendarBlock) {
updateUrl(url);
}
return args;
})
.then((...args) => {
$('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId]);
$('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId, isCalendarBlock]);
return args;
});
};
@@ -557,10 +565,18 @@ const renderEventSummaryModal = (eventId) => {
.catch(Notification.exception);
};
export const init = (root, view) => {
/**
* Initializes the calendar component by prefetching strings, folding day events,
* and registering event listeners.
*
* @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached.
* @param {string} view - A flag indicating whether this is a calendar block.
* @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.
*/
export const init = (root, view, isCalendarBlock) => {
prefetchStrings('calendar', ['moreevents']);
foldDayEvents();
registerEventListeners(root, view);
registerEventListeners(root, isCalendarBlock);
const calendarTable = root.find(CalendarSelectors.elements.monthDetailed);
if (calendarTable.length) {
const pendingId = `month-detailed-${calendarTable.id}-filterChanged`;
+17 -19
View File
@@ -2177,29 +2177,27 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false, s
}
if (!empty($courseeventsfrom) && (calendar_show_event_type(CALENDAR_EVENT_GROUP, $user) || $ignorefilters)) {
if (count($courseeventsfrom) == 1) {
$course = reset($courseeventsfrom);
if (has_any_capability($allgroupscaps, \context_course::instance($course->id))) {
$coursegroups = groups_get_all_groups($course->id, 0, 0, 'g.id');
$group = array_keys($coursegroups);
}
}
if ($group === false) {
if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, \context_system::instance())) {
$group = true;
} else if ($isvaliduser) {
$groupids = array();
foreach ($courseeventsfrom as $courseid => $course) {
if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
// If this course has groups, show events from all of those related to the current user.
if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, \context_system::instance())) {
$group = true;
} else if ($isvaliduser) {
$groupids = [];
foreach ($courseeventsfrom as $courseid => $course) {
if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) {
if (has_all_capabilities($allgroupscaps, \context_course::instance($courseid))) {
// User can access all groups in this course.
// Get all the groups in this course.
$coursegroups = groups_get_all_groups($course->id, 0, 0, 'g.id');
$groupids = array_merge($groupids, array_keys($coursegroups));
} else {
// User can only access their own groups.
// Get the groups the user is in.
$coursegroups = groups_get_user_groups($course->id, $user->id);
$groupids = array_merge($groupids, $coursegroups['0']);
}
}
if (!empty($groupids)) {
$group = $groupids;
}
}
if (!empty($groupids)) {
$group = $groupids;
}
}
}
+4 -4
View File
@@ -351,9 +351,8 @@ class core_calendar_renderer extends plugin_renderer_base {
*/
public function render_no_calendar_subscriptions(): string {
$output = html_writer::start_div('mt-5');
$importlink = html_writer::link((new moodle_url('/calendar/import.php', calendar_get_export_import_link_params()))->out(),
get_string('importcalendarexternal', 'calendar'));
$output .= get_string('nocalendarsubscriptions', 'calendar', $importlink);
$importlink = (new moodle_url('/calendar/import.php', calendar_get_export_import_link_params()))->out();
$output .= get_string('nocalendarsubscriptionsimportexternal', 'core_calendar', $importlink);
$output .= html_writer::end_div();
return $output;
@@ -380,7 +379,8 @@ class core_calendar_renderer extends plugin_renderer_base {
$table->id = 'subscription_details_table';
if (empty($subscriptions)) {
$cell = new html_table_cell(get_string('nocalendarsubscriptions', 'calendar'));
$importlink = (new moodle_url('/calendar/import.php', calendar_get_export_import_link_params()))->out();
$cell = new html_table_cell(get_string('nocalendarsubscriptionsimportexternal', 'core_calendar', $importlink));
$cell->colspan = 5;
$table->data[] = new html_table_row(array($cell));
}
+3 -1
View File
@@ -29,6 +29,7 @@
Example context (json):
{
"iscalendarblock": false
}
}}
<div id="calendar-day-{{uniqid}}" data-template="core_calendar/day_detailed">
@@ -37,6 +38,7 @@
</div>
{{#js}}
require(['jquery', 'core_calendar/calendar_view'], function($, CalendarView) {
CalendarView.init($("#calendar-day-{{uniqid}}"), 'day');
const isCalendarBlock = {{#iscalendarblock}}true{{/iscalendarblock}}{{^iscalendarblock}}false{{/iscalendarblock}};
CalendarView.init($("#calendar-day-{{uniqid}}"), 'day', isCalendarBlock);
});
{{/js}}
+3 -1
View File
@@ -29,6 +29,7 @@
Example context (json):
{
"iscalendarblock": false
}
}}
<div id="calendar-month-{{uniqid}}-{{calendarinstanceid}}" data-template="core_calendar/month_detailed">
@@ -37,6 +38,7 @@
</div>
{{#js}}
require(['jquery', 'core_calendar/calendar', 'core_calendar/popover'], function($, Calendar, calendarPopover) {
Calendar.init($("#calendar-month-{{uniqid}}-{{calendarinstanceid}}"));
const isCalendarBlock = {{#iscalendarblock}}true{{/iscalendarblock}}{{^iscalendarblock}}false{{/iscalendarblock}};
Calendar.init($("#calendar-month-{{uniqid}}-{{calendarinstanceid}}"), isCalendarBlock);
});
{{/js}}
+58
View File
@@ -48,10 +48,19 @@ class behat_calendar extends behat_base {
new behat_component_named_selector('mini calendar block', [".//*[@data-block='calendar_month']"]),
new behat_component_named_selector('full calendar page', [".//*[@id='page-calendar-view']"]),
new behat_component_named_selector('calendar day', [".//*[@data-region='day'][@data-day=%locator%]"]),
new behat_component_named_selector(
'calendar day detail',
[".//*[@data-region='day'][@data-day=%locator%]//a[@data-action='view-day-link']"]
),
new behat_component_named_selector(
'responsive calendar day',
[".//*[@data-region='day'][@data-day=%locator%]/div[contains(@class, 'hidden-desktop')]"]
),
new behat_component_named_selector(
'responsive calendar day detail',
[".//*[@data-region='day'][@data-day=%locator%]" .
"/div[contains(@class, 'hidden-desktop')]//a[@data-action='view-day-link']"]
),
];
}
@@ -132,6 +141,39 @@ class behat_calendar extends behat_base {
);
}
/**
* Click on a specific day in the mini-calendar.
*
* @Given /^I click on day "(?P<dayofmonth>\d+)" of this month in the mini-calendar block(?P<responsive> responsive view|)$/
*
* @param int $day The day of the current month.
* @param string $responsive If not null, find the responsive version of the link.
* @param string $detail If not null, find the detail version of the link.
*/
public function i_click_on_day_of_this_month_in_mini_calendar_block(
int $day,
string $responsive = '',
string $detail = '',
): void {
$selectortype = 'core_calendar >';
if (!empty($responsive)) {
$selectortype .= ' responsive';
}
$selectortype .= ' calendar day';
if (!empty($detail)) {
$selectortype .= ' detail';
}
$this->execute(
contextapi: "behat_general::i_click_on_in_the",
params: [
$day,
$selectortype,
'',
'core_calendar > mini calendar block',
],
);
}
/**
* Hover over today in the mini-calendar.
*
@@ -154,6 +196,22 @@ class behat_calendar extends behat_base {
return $this->i_hover_over_day_of_this_month_in_calendar($todaysday);
}
/**
* Click on today in the mini-calendar.
*
* @Given /^I click on today in the mini-calendar block( responsive view|)( to view the detail|)$/
*
* @param string $responsive If not empty, use the responsive calendar link.
* @param string $detail If not empty, use the detail view calendar link.
*/
public function i_click_on_today_in_mini_calendar_block(string $responsive = '', string $detail = ''): void {
$this->i_click_on_day_of_this_month_in_mini_calendar_block(
day: date('j'),
responsive: $responsive,
detail: $detail,
);
}
/**
* Navigate to a specific month in the calendar.
*
+176
View File
@@ -896,6 +896,182 @@ class lib_test extends \advanced_testcase {
$this->assertEquals($users[1]->id, $userid);
}
/**
* This function tests calendar_set_filters for courses with separate group mode.
*/
public function test_calendar_set_filters_with_separate_group_mode(): void {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
// Create users.
$student1 = $generator->create_user();
$student2 = $generator->create_user();
$teacher1 = $generator->create_user();
$teacher2 = $generator->create_user();
// Create courses.
$course1 = $generator->create_course([
'shortname' => 'C1',
'groupmode' => 1,
'groupmodeforce' => 1,
]);
$course2 = $generator->create_course([
'shortname' => 'C2',
'groupmode' => 1,
'groupmodeforce' => 1,
]);
$course1context = \context_course::instance($course1->id);
$course2context = \context_course::instance($course2->id);
// Create groups.
$group1 = $generator->create_group([
'name' => 'G1-C1',
'courseid' => $course1->id,
]);
$group2 = $generator->create_group([
'name' => 'G1-C2',
'courseid' => $course2->id,
]);
$group3 = $generator->create_group([
'name' => 'G2-C2',
'courseid' => $course2->id,
]);
// Modify the capabilities.
$editingteacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
assign_capability(
'moodle/site:accessallgroups',
CAP_PREVENT,
$editingteacherroleid,
$course1context->id,
true
);
assign_capability(
'moodle/site:accessallgroups',
CAP_PREVENT,
$editingteacherroleid,
$course2context->id,
true
);
// Enrol users.
$generator->enrol_user($student1->id, $course1->id, 'student');
$generator->enrol_user($teacher1->id, $course1->id, 'editingteacher');
$generator->enrol_user($student1->id, $course2->id, 'student');
$generator->enrol_user($student2->id, $course2->id, 'student');
$generator->enrol_user($teacher1->id, $course2->id, 'editingteacher');
$generator->enrol_user($teacher2->id, $course2->id, 'editingteacher');
// Group memberships.
$generator->create_group_member([
'groupid' => $group1->id,
'userid' => $student1->id,
]);
$generator->create_group_member([
'groupid' => $group1->id,
'userid' => $teacher1->id,
]);
$generator->create_group_member([
'groupid' => $group2->id,
'userid' => $student1->id,
]);
$generator->create_group_member([
'groupid' => $group2->id,
'userid' => $teacher1->id,
]);
$generator->create_group_member([
'groupid' => $group3->id,
'userid' => $student2->id,
]);
$generator->create_group_member([
'groupid' => $group3->id,
'userid' => $teacher2->id,
]);
// Test teacher1.
$this->setUser($teacher1);
$defaultcourses = calendar_get_default_courses(
null,
'*',
false,
$teacher1->id
);
[$courseids, $groupids] = calendar_set_filters(
$defaultcourses,
false,
$teacher1
);
// Teacher1 can see SITE, C1, G1-C1, C2, G1-C2.
$this->assertCount(3, $courseids); // SITE, C1, C2.
$this->assertCount(2, $groupids); // G1-C1, G1-C2.
$courseidskey = array_fill_keys($courseids, null);
$this->assertArrayHasKey(SITEID, $courseidskey);
$this->assertArrayHasKey($course1->id, $courseidskey);
$this->assertArrayHasKey($course2->id, $courseidskey);
$groupidskey = array_fill_keys($groupids, null);
$this->assertArrayHasKey($group1->id, $groupidskey);
$this->assertArrayHasKey($group2->id, $groupidskey);
$this->assertArrayNotHasKey($group3->id, $groupidskey);
// Test teacher2.
$this->setUser($teacher2);
$defaultcourses = calendar_get_default_courses(
null,
'*',
false,
$teacher2->id
);
[$courseids, $groupids] = calendar_set_filters(
$defaultcourses,
false,
$teacher2
);
// Teacher2 can see SITE, C2, G2-C2.
$this->assertCount(2, $courseids); // SITE, C2.
$this->assertCount(1, $groupids); // G2-C2.
$courseidskey = array_fill_keys($courseids, null);
$this->assertArrayHasKey(SITEID, $courseidskey);
$this->assertArrayHasKey($course2->id, $courseidskey);
$groupidskey = array_fill_keys($groupids, null);
$this->assertArrayHasKey($group3->id, $groupidskey);
$this->assertArrayNotHasKey($group1->id, $groupidskey);
$this->assertArrayNotHasKey($group2->id, $groupidskey);
// Modify the capabilities.
assign_capability(
'moodle/site:accessallgroups',
CAP_ALLOW,
$editingteacherroleid,
$course2context->id,
true
);
$defaultcourses = calendar_get_default_courses(
null,
'*',
false,
$teacher2->id
);
[$courseids, $groupids] = calendar_set_filters(
$defaultcourses,
false,
$teacher2
);
// Teacher2 can see SITE, C2, G1-C2, G2-C2.
$this->assertCount(2, $courseids); // SITE, C2.
$this->assertCount(2, $groupids); // G1-C2, G2-C2.
$groupidskey = array_fill_keys($groupids, null);
$this->assertArrayHasKey($group2->id, $groupidskey);
$this->assertArrayHasKey($group3->id, $groupidskey);
$this->assertArrayNotHasKey($group1->id, $groupidskey);
}
/**
* Test for calendar_view_event_allowed for course event types.
*/
+9 -9
View File
@@ -100,9 +100,9 @@ M.core_comment = {
var newcomment = Y.Node.create(result.html);
container.appendChild(newcomment);
var ids = result.ids;
var linkText = Y.one('#comment-link-text-' + cid);
if (linkText) {
linkText.set('innerHTML', M.util.get_string('commentscount', 'moodle', obj.count));
var linkTextCount = Y.one('#comment-link-text-' + cid + ' .comment-link-count');
if (linkTextCount) {
linkTextCount.set('innerHTML', obj.count);
}
for(var i in ids) {
var attributes = {
@@ -249,9 +249,9 @@ M.core_comment = {
scope: scope,
params: params,
callback: async function(id, ret, args) {
var linkText = Y.one('#comment-link-text-' + scope.client_id);
if (ret.count && linkText) {
linkText.set('innerHTML', M.util.get_string('commentscount', 'moodle', ret.count));
var linkTextCount = Y.one('#comment-link-text-' + scope.client_id + ' .comment-link-count');
if (linkTextCount) {
linkTextCount.set('innerHTML', ret.count);
}
var container = Y.one('#comment-list-'+scope.client_id);
var pagination = Y.one('#comment-pagination-'+scope.client_id);
@@ -284,10 +284,10 @@ M.core_comment = {
params = {'commentid': id};
function remove_dom(type, anim, cmt) {
cmt.remove();
var linkText = Y.one('#comment-link-text-' + cid),
var linkTextCount = Y.one('#comment-link-text-' + cid + ' .comment-link-count'),
comments = Y.all('#comment-list-' + cid + ' li');
if (linkText && comments) {
linkText.set('innerHTML', M.util.get_string('commentscount', 'moodle', comments.size()));
if (linkTextCount) {
linkTextCount.set('innerHTML', comments.size());
}
}
this.request({
+1 -2
View File
@@ -263,7 +263,6 @@ class comment {
$page->requires->strings_for_js(array(
'addcomment',
'comments',
'commentscount',
'commentsrequirelogin',
'deletecommentbyon'
),
@@ -454,7 +453,7 @@ class comment {
// comments open and closed
$countstring = '';
if ($this->displaytotalcount) {
$countstring = '('.$this->count().')';
$countstring = '(' . html_writer::span($this->count(), 'comment-link-count') . ')';
}
$collapsedimage= 't/collapsed';
if (right_to_left()) {
+1 -1
View File
@@ -17,7 +17,7 @@ Feature: Manage comments made by users
Scenario: View and filter site comments
When I navigate to "Reports > Comments" in site administration
And the following should exist in the "reportbuilder-table" table:
| -0- | Content | Context URL |
| First name | Content | Context URL |
| Admin User | Uno | Course: Course 1 |
| Admin User | Dos | Course: Course 1 |
| Admin User | Tres | Course: Course 1 |

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