Compare commits

..

202 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 0e4c5bfdbe Moodle 1.9.12 release 2011-05-09 15:59:53 +02:00
Eloy Lafuente (stronk7) 9251e27e76 weekly release 1.9.11+ 2011-05-05 00:38:37 +02:00
Eloy Lafuente (stronk7) 9330414966 Merge branch 'MDL-26937' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-05-02 11:37:08 +02:00
Tim Hunt 71ec5d19df MDL-26937 quiz grades report. Work-around MySQL fussiness, like for MDL-26416. 2011-04-29 12:09:05 +01:00
Tim Hunt 551a610ed1 MDL-26981 qtype_random fix restore of attempt data.
Fix worked out by Colin Campbell from colin@umn.edu. Many thanks.
2011-04-28 23:54:59 +01:00
Petr Skoda d14e8ea454 weekly release 1.9.11+ 2011-04-27 12:05:55 +02:00
Eloy Lafuente (stronk7) d58181c60b weekly release 1.9.11+ 2011-04-20 13:37:43 +02:00
Dan Marsden ac9387b049 SCORM MDL-26450 fix undefined pkgtype warning (ONLY REQUIRED IN 1.9 STABLE BRANCH) 2011-04-14 09:58:21 +12:00
Petr Skoda 8be4ad990a weekly release 1.9.11+ 2011-04-13 22:06:49 +02:00
Sam Hemelryk 032be8a19b Merge branch 'MDL-26130' of git://github.com/MaryE/moodle into MOODLE_19_STABLE 2011-04-11 11:31:38 +08:00
Eloy Lafuente (stronk7) bd49223246 Merge branch 'w15_MDL-27069_m19_httpsrequired' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-04-11 01:35:47 +02:00
Petr Skoda 7e58c03d6c MDL-27069 fix notice when inserting images in editor 2011-04-10 21:16:24 +02:00
Mary Evans 5a76642ddf MDL-26130 css fix for orangewhite theme 2011-04-10 01:15:24 +01:00
Tony Levi 697664c813 MDL-27108: Fix invalid SQL syntax in mod/data/field/latlong 2011-04-07 10:05:47 +09:30
Petr Skoda fb8642bce5 weekly release 1.9.11+ 2011-04-06 14:55:11 +02:00
Eloy Lafuente (stronk7) d2cabfdf9b Merge branch 'MDL-20946_19_simplehistory' of git://github.com/andyjdavis/moodle into MOODLE_19_STABLE 2011-04-04 11:39:51 +02:00
Petr Skoda 0c3c77269d weekly release 2011-03-30 13:40:40 +02:00
Andrew Davis (andyjdavis) 6c41ae0a0c gradebook MDL-20946 switched from using IN to using JOIN in the quiries 2011-03-30 13:31:47 +08:00
Eloy Lafuente (stronk7) d6ed445589 Merge branch 'w13_MDL-26966_19_urlparsing' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-03-28 19:12:04 +02:00
Petr Skoda 5a3010310b MDL-26966 improve self URL validation 2011-03-27 12:03:22 +02:00
Petr Skoda dedb3c5121 MDL-26985 new Moodle 2.1 requirements
For now only extra PHP 5.3.2 requirement compared to 2.0.
2011-03-26 22:03:13 +01:00
Petr Skoda 3215955fd0 weekly release 2011-03-23 11:32:35 +01:00
Eloy Lafuente (stronk7) 19f65e6c6b Merge branch 'm19_MDL-25770_hotpotfix' of git://github.com/danmarsden/moodle into MOODLE_19_STABLE 2011-03-21 22:52:16 +01:00
Sam Hemelryk 5b2d591bcb Cherry-picked changes for PULL-460/MDL-26557 into MOODLE_19_STABLE 2011-03-21 17:36:29 +08:00
Tim Hunt 6d276b3254 MDL-20946 fix gradebook SQL to cope with multi-role and deleted users. 2011-03-17 12:30:58 +00:00
Dan Marsden 68d3425577 Hotpot MDL-25770 - missing return - thanks to Tomasz Pawlik for report/fix 2011-03-17 15:30:45 +13:00
Petr Skoda 08bf2b2723 weekly release 2011-03-16 09:34:19 +01:00
Petr Skoda 5dce59a4cf Merge branch 'MDL-4633-m19' of git://github.com/rwijaya/moodle into MOODLE_19_STABLE 2011-03-14 17:58:46 +01:00
Eloy Lafuente (stronk7) 72250eed86 Merge branch 'w11_MDL-26634_19_ldapset' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-03-14 16:29:02 +01:00
Eloy Lafuente (stronk7) 49e0d5d5e3 Merge branch 'MDL-19555_m19' of git://github.com/rwijaya/moodle into MOODLE_19_STABLE 2011-03-14 01:41:32 +01:00
Eloy Lafuente (stronk7) fd602f4620 MDL-9376 fix minor global use 2011-03-14 01:37:28 +01:00
Eloy Lafuente (stronk7) fb7abd481b Merge branch 's7_MDL-9376_qaforum_m19' of git://github.com/dongsheng/moodle into MOODLE_19_STABLE 2011-03-14 01:35:57 +01:00
Eloy Lafuente (stronk7) 7e06e9ff4a Merge branch 'MDL-21446_19' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-03-14 01:32:18 +01:00
Petr Skoda 416ea17252 MDL-26634 LDAP NTLM SSO Multiple subnet separator is not specified and people use a wrong one
Credit goes to Inaki Arenaza.
2011-03-13 10:18:02 +01:00
Aparup Banerjee f8fb37424e MDL-26757 fixed regression in glossary recent activity block url 2011-03-11 13:27:45 +08:00
Dongsheng Cai a6df2c2e5f MDL-9376, disallow student to see the other users posts in max editing time, credits to Vlas Voloshin and Charles Fulton MOODLE_19_STABLE 2011-03-11 12:25:46 +08:00
Rossiani Wijaya 04b4210605 MDL-19555: add NULL string test to format_test(). Credit goes to Matej Vela. Thanks 2011-03-11 12:14:29 +08:00
Rossiani Wijaya e1bde19170 MDL-4633: remove 'required' rule for user's profile description 2011-03-10 15:56:20 +08:00
Tim Hunt 5cf3a84aee MDL-21446 truncate >31 char worksheet names that otherwise break Excel export. 2011-03-09 14:48:24 +00:00
Petr Skoda 1c712d947a weekly release 2011-03-09 09:05:15 +01:00
Eloy Lafuente (stronk7) 1b607c2266 Merge branch 'm19_MDL-26672_aiccfix' of git://github.com/danmarsden/moodle into MOODLE_19_STABLE 2011-03-07 02:38:48 +01:00
Eloy Lafuente (stronk7) cddf3e1679 Merge branch 'MDL-26324_19' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-03-07 01:25:53 +01:00
Dan Marsden eb2dc3ab87 AICC MDL-26672 fix for AICC Value=0 - thanks to Matteo for fix/report 2011-03-07 10:03:04 +13:00
Petr Skoda f483e32922 MDL-26605 fix problematic mediaplugin regex matching 2011-03-05 10:04:26 +01:00
Tim Hunt 83f22aae0e MDL-26324 overall feedback problem when quiz changed to being graded out of 0 2011-03-04 17:45:03 +00:00
Petr Skoda 0e33a45653 weekly release 2011-03-03 18:25:05 +01:00
Daren Chandisingh 18174ef082 MDL-26534 allow iframes in course category descriptions 2011-02-28 09:27:11 +01:00
Eloy Lafuente (stronk7) 6720f29ccf weekly release 2011-02-23 20:04:29 +01:00
Eloy Lafuente (stronk7) 9044a8edb3 Merge branch 'MDL-26528_restore_forum_read' of git://github.com/stronk7/moodle into MOODLE_19_STABLE 2011-02-22 16:15:24 +01:00
Eloy Lafuente (stronk7) 86a8740b67 Merge branch 'MDL-26502_symbian' of git://github.com/stronk7/moodle into MOODLE_19_STABLE 2011-02-22 15:21:01 +01:00
Eloy Lafuente (stronk7) 49a1b113ad Merge branch 'MDL-25122_19' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-02-22 12:45:37 +01:00
Eloy Lafuente (stronk7) f733078c91 MDL-26502 check browser - fix for Symbian (backported) 2011-02-22 11:51:26 +01:00
Eloy Lafuente (stronk7) eeff6a0839 Merge branch 'MDL-26505_19' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-02-22 10:56:28 +01:00
Eloy Lafuente (stronk7) 9170eb5aab MDL-26528 restore - ignore wrong forum_read records 2011-02-21 16:00:41 +01:00
Martin Dougiamas 783cca4ee3 Moodle 1.9.11 release 2011-02-21 13:19:01 +01:00
Tim Hunt 49b2521492 MDL-26505 rounding problem in quiz_save_best_grade.
Note I cheated and slipped in a fix for another instance of MDL-21811 too, since I noticed it at the same time.
2011-02-18 19:34:31 +00:00
Petr Skoda 3075ec4341 emergency release 2011-02-18 19:59:18 +01:00
Petr Skoda b408c5f485 Merge branch 'MDL-21811' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-02-18 19:31:20 +01:00
Tim Hunt 12e4ff0d19 MDL-21811 also need to fix the rounding on the review page. 2011-02-18 18:25:28 +00:00
Tim Hunt 8d5eaee1c9 MDL-25122 Quiz review page does not check and enforce separate groups mode. 2011-02-18 17:23:41 +00:00
Petr Skoda 0c9bd492a0 Merge branch 'MDL-21811' of git://github.com/timhunt/moodle into MOODLE_19_STABLE 2011-02-18 18:00:19 +01:00
Tim Hunt db99a96d1e MDL-21811 use the un-rounded grade to display the overall feedback in the quiz reports. 2011-02-17 09:43:32 +00:00
Petr Skoda c737ead6f4 weekly release 2011-02-17 01:18:34 +01:00
Aparup Banerjee 7cc4ceae64 MDL-22970 glossary - backporting recent activity fix from 2.0.x 2011-02-15 00:48:08 +01:00
Petr Skoda af497cf64c Merge branch 'm19_MDL-26216_windowoptions' of github.com:danmarsden/moodle into MOODLE_19_STABLE 2011-02-14 21:40:23 +01:00
Petr Skoda 05d38f44cc Merge branch 'MDL-26371_distinct_text_m19' of git://github.com/stronk7/moodle into MOODLE_19_STABLE 2011-02-14 21:23:15 +01:00
Dan Marsden 776ecc8b9d SCORM MDL-26216 - prevent auto update from resetting window options 2011-02-14 17:34:44 +13:00
Eloy Lafuente (stronk7) d7ef29dcbd Merge branch 'w07_MDL-26030_19_mediafilter' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-02-14 01:14:40 +01:00
Eloy Lafuente (stronk7) 185f71c40d MDL-26371 sql - avoid distinct + text in lesson essay and report 2011-02-13 01:45:18 +01:00
Eloy Lafuente (stronk7) 6d12bf2020 MDL-26371 sql - avoid distinct + text in security report 2011-02-13 01:30:20 +01:00
Petr Skoda 8f81bfd412 MDL-26030 fix js and attribute quoting 2011-02-12 13:29:38 +01:00
Rossiani Wijaya eabab3de5a MDL-26030_m19: fix regex in media filter and removing addslashes to non-js code 2011-02-12 13:16:30 +01:00
Petr Skoda 782d74e053 MDL-26322 always allow https in login local redirection test
This fixes problems for sites that use loginhtts where the redirection after login did not work for pages that require https such as the forgotten passowrds page.
2011-02-11 11:31:20 +01:00
Petr Skoda e7d43de4ed weekly release 2011-02-09 12:25:53 +01:00
Eloy Lafuente (stronk7) 21cec9df42 MDL-26052 data - fix various transitions that were not working ok 2011-02-04 20:06:26 +01:00
Petr Skoda 35f730f16b weekly release 2011-02-02 14:07:51 +01:00
Eloy Lafuente (stronk7) b178d86aab Merge branch 'MDL-17201_index_19' of git://github.com/andyjdavis/moodle into MOODLE_19_STABLE 2011-01-31 15:49:13 +01:00
Eloy Lafuente (stronk7) d9fe1c6aa1 Merge branch 'w05_MDL-26189_19_imse' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-01-31 11:59:31 +01:00
Sam Hemelryk 490a186269 Merge branch 'm19_MDL-25320' of git://github.com/danmarsden/moodle into MOODLE_19_STABLE 2011-01-31 13:14:52 +08:00
Petr Skoda 886c6635e2 MDL-26189 protect imsenterprise enrol file 2011-01-30 13:57:37 +01:00
Dan Marsden c504285645 SCORM MDL-25320 removes spaces from children patterns - thanks to Ian Wright for report 2011-01-28 23:09:48 +13:00
Petr Skoda 251d6f3e6d weekly release 2011-01-25 19:37:59 +01:00
andyjdavis 73c07a1f72 profiles MDL-17201 added an index to user_info_data table 2011-01-25 15:06:32 +08:00
Petr Skoda c7bb198fe2 weekly release 2011-01-19 14:10:18 +01:00
Sam Hemelryk 093f30a3fe Merge branch 'MDL-18839_19_wip' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-01-18 13:52:23 +08:00
Sam Hemelryk e7682e584a Merge branch 'MDL-25754_19_wip' of git://github.com/skodak/moodle into MOODLE_19_STABLE 2011-01-18 13:38:05 +08:00
Rossiani Wijaya 12e3dc19a6 MDL-25646: fixed html_writer class, get string param, remove url addslashed from regular context (only use addslashes_js if it prints for javascript. Add new string to mediaplugin file. 2011-01-14 12:02:17 +08:00
Petr Skoda fd29b2ad1c MDL-25754 improved tag sanitisation and fixed tag autocomplete 2011-01-13 22:55:52 +01:00
Petr Skoda 8f031d5431 MDL-18839 sesskey protection for RSS feed actions 2011-01-12 22:21:48 +01:00
Petr Skoda 8b085f23ca weekly release 2011-01-12 10:51:14 +01:00
Petr Skoda 6226c65506 MDL-24561 fixed missing u. prefix 2011-01-11 09:51:57 +01:00
Eloy Lafuente (stronk7) 344817fa8a Merge branch 'MDL-24561_forum_subscribe_sesskey_m19' of git://github.com/mudrd8mz/moodle into MOODLE_19_STABLE 2011-01-10 21:45:08 +01:00
Petr Skoda bffe6c274e Merge branch 'MDL-20607' of git://github.com/arborrow/moodle into MOODLE_19_STABLE 2011-01-10 14:28:55 +01:00
Dan Marsden af778921f0 SCORM MDL-25891 typo causing general exception for some SCORM objects - thanks to Hais Deakin for report/fix 2011-01-10 14:24:39 +01:00
Anthony Borrow eddf533b0a MDL-20607 - adding firstname as secondary sort criteria 2011-01-05 09:30:20 -06:00
David Mudrak be7c8bb2c2 MDL-24561 forum: require sesskey for the course-wide subscriptions - backported from 2.0
mod/forum/index.php allows to subscribe to and unsubscribe from all
forums in the course. However, sesskey was not checked here.
2011-01-05 15:58:41 +01:00
David Mudrak 0b393d6716 MDL-24561 forum subscription checks sesskey - backported from 2.0
The only case when sesskey is not available is when we came to
subscribe.php from a link in email. In that case, we display a
confirmation page that redirects back providing the sesskey.
All other links to subscribe.php are fixed now so they provide sesskey
as a parameter.
2011-01-05 15:52:25 +01:00
Petr Skoda 44ddbc657b weekly release 2011-01-05 11:53:45 +01:00
Petr Skoda d04350adeb weekly release version updated 2010-12-29 17:51:23 +01:00
Petr Skoda d1dd5f0a08 Merge branch 'MDL-25186_m19' into MOODLE_19_STABLE 2010-12-27 12:18:53 +01:00
Petr Skoda 1150662ecc MDL-25186 fixed whitespace 2010-12-27 12:18:31 +01:00
Petr Skoda 76035b1339 Merge branch 'MDL-25713_recordset' of git://github.com/andyjdavis/moodle into MOODLE_19_STABLE 2010-12-27 12:09:58 +01:00
Petr Skoda 535037f521 Merge branch 'm19-MDL-16858-fixed' of git://github.com/mouneyrac/moodle into MOODLE_19_STABLE 2010-12-27 11:50:17 +01:00
sam marshall 010758adb2 accessibility MDL-24613 Update previous change to fix back to 'top' for RTL languages 2010-12-27 11:45:53 +01:00
Petr Skoda 53c8f1056f Merge branch 'MOODLE_19_STABLE' of github.com:danmarsden/moodle into MOODLE_19_STABLE 2010-12-27 11:33:00 +01:00
Rossiani Wijaya 059518944a MDL-25186: add environmental check to recommend PHP 5.3.3 2010-12-23 11:32:36 +08:00
Eloy Lafuente (stronk7) 93b89cae76 MDL-25755 enrol ldap - avoid reserved keyword. (k) goes to Chris Myers 2010-12-23 00:23:18 +01:00
Petr Skoda 0300e588d5 Updated the 19 build version 2010-12-22 08:32:34 +01:00
Penny Leach 612d671fbc mnet MDL-16858 xmlrpc client signature verification code 2010-12-21 10:30:41 +08:00
David Mudrak 603cc5c6e6 MDLSITE-1162 .gitignore file for Moodle git mirror 2010-12-20 20:48:24 +01:00
Dongsheng Cai 009fca2bb4 category editing MDL-21671 MOODLE_19_STABLE check capability when parent category changed 2010-12-20 19:23:46 +01:00
Dongsheng Cai 5b6519cb42 MDL-21671, MOODLE_19_STABLE site level categroy manage capability when edit category, credits to Vadim Dvorovenko 2010-12-20 19:23:45 +01:00
Petr Skoda dc92d40c44 Merge branch 'mssql_database_activity' of git://github.com/stronk7/moodle into MOODLE_19_STABLE 2010-12-20 19:09:04 +01:00
Sam Hemelryk 2e490b8b29 mod-lesson MDL-22349 Fixed bug with matching lesson type and empty correct response. Kudos to Michael Lipp for the patch 2010-12-20 18:59:39 +01:00
andyjdavis 635f4f2c64 gradebook MDL-20617 replaced the missing range column on the user report 2010-12-20 16:39:30 +01:00
Petr Skoda 1d7908e7f7 MDL-25725 escape query parameter in enrol/database setup_enrolments() 2010-12-20 14:58:55 +01:00
Dongsheng Cai 42d9cf7dff MDL-14934 fixed excel time in MOODLE_19_STABLE credits to Jonathon Fowler 2010-12-20 12:30:22 +01:00
Dan Marsden cb1e1bc1ca SCORM MDL-25739 check var set before using - Thanks to Howard for report - This only affects 1.9stable, fix already in head 2010-12-20 22:29:46 +13:00
andyjdavis 49436db62a gradebook MDL-25713 switched grade_object fetch_all_helper over to use a recordset 2010-12-20 16:15:35 +08:00
Eloy Lafuente (stronk7) 7911272ea2 MDL-25692 fix sortings and edit->single navigation 2010-12-16 01:21:48 +01:00
Eloy Lafuente (stronk7) 3751c84008 MDL-25692 search working for mssql + oracle 2010-12-16 01:07:16 +01:00
Eloy Lafuente (stronk7) 5dd05d5a21 MDL-25692 make search template to work for mssql + oracle 2010-12-16 00:09:47 +01:00
Moodle Robot 3703965f09 Updated the 19 build version to 20101214 2010-12-14 00:53:48 +00:00
Moodle Robot f332f25f95 Updated the 19 build version to 20101213 2010-12-13 00:51:19 +00:00
Moodle Robot 9cfc7cce93 Updated the 19 build version to 20101212 2010-12-12 00:51:18 +00:00
Moodle Robot ba3d4c3449 Updated the 19 build version to 20101211 2010-12-11 00:51:14 +00:00
Moodle Robot da5abcf6ba Updated the 19 build version to 20101210 2010-12-10 00:52:18 +00:00
David Mudrak 4a7b983bbf MDL-21554 MNet: fixed SQL usage to check a record existence
The solution backported from 2.0 and independently suggested by Penny,
too.
2010-12-09 09:33:32 +00:00
Moodle Robot 5fa5c2ed74 Updated the 19 build version to 20101209 2010-12-09 00:52:05 +00:00
Moodle Robot 3090cf62fe Updated the 19 build version to 20101208 2010-12-08 00:51:52 +00:00
Petr Skoda 7111a5c1a9 MDL-25591 disable ajax and htmleditor in ios devices
The problem appeared after changes from MDL-16336 because ios devices were detected as Safari. This is an ugly hack, hopefully it will not create visual or JS regressions elsewhere.
2010-12-07 17:56:04 +00:00
Moodle Robot 5a5e4020fa Updated the 19 build version to 20101207 2010-12-07 00:51:57 +00:00
Moodle Robot f480eefc6b Updated the 19 build version to 20101206 2010-12-06 00:56:11 +00:00
Moodle Robot 269fe00559 Updated the 19 build version to 20101205 2010-12-05 00:53:52 +00:00
Helen Foster 4014622ee9 MDL-25550 bom removal 2010-12-04 14:51:17 +00:00
Moodle Robot 6644a83d10 Updated the 19 build version to 20101204 2010-12-04 00:55:36 +00:00
Moodle Robot 409bd4de70 Updated the 19 build version to 20101203 2010-12-03 00:51:41 +00:00
Moodle Robot dae5d69789 Updated the 19 build version to 20101202 2010-12-02 00:52:15 +00:00
Moodle Robot 56043dc26b Updated the 19 build version to 20101201 2010-12-01 00:51:14 +00:00
Moodle Robot c186da462f Updated the 19 build version to 20101130 2010-11-30 00:54:20 +00:00
Moodle Robot a4a7b67871 Updated the 19 build version to 20101129 2010-11-29 00:53:31 +00:00
Moodle Robot 3e117f45c3 Updated the 19 build version to 20101128 2010-11-28 00:52:06 +00:00
Moodle Robot 50fde5927d Updated the 19 build version to 20101127 2010-11-27 00:53:15 +00:00
Moodle Robot 2b94ab066d Updated the 19 build version to 20101126 2010-11-26 00:53:31 +00:00
Dan Marsden a2aa8324a4 SCORM MDL-25298 escape html vars correctly - thanks to Xavier Paz for report/fix merged from HEAD 2010-11-25 01:47:48 +00:00
Moodle Robot 14a4e75ccd Updated the 19 build version to 20101125 2010-11-25 00:52:18 +00:00
Petr Skoda 7eef630957 MDL-24699 minimalistic fix for the missing mnet host id when updating local user records, thanks 2010-11-24 04:03:18 +00:00
Moodle Robot 1929455fba Updated the 19 build version to 20101124 2010-11-24 00:52:46 +00:00
Moodle Robot f39ae19ef3 Updated the 19 build version to 20101123 2010-11-23 00:51:42 +00:00
Moodle Robot e9cef979c1 Updated the 19 build version to 20101122 2010-11-22 00:54:41 +00:00
Moodle Robot 9c850a8942 Updated the 19 build version to 20101121 2010-11-21 00:54:17 +00:00
Moodle Robot eb04d38327 Updated the 19 build version to 20101120 2010-11-20 01:01:34 +00:00
Moodle Robot 96eeb9812c Updated the 19 build version to 20101119 2010-11-19 00:55:45 +00:00
Rossiani Wijaya cd1f8ac253 MDL-20044: add test to prevent javascript error due to null data. 2010-11-18 09:30:33 +00:00
Rossiani Wijaya c476a2ecfc MDL-16336: add Chrome to browser identification to display HMTL editor. 2010-11-18 08:49:26 +00:00
Inaki 064f325bce auth/cas: MDL-25062 CAS authentication plugin does not validate the CAS server certificate
If we enable the server validation but don't specify a certificate file path
flag the error and don't let the user save the settings.
2010-11-18 00:58:21 +00:00
Moodle Robot b7b35426b9 Updated the 19 build version to 20101118 2010-11-18 00:50:07 +00:00
Inaki c07fcc1383 auth/cas: MDL-25062 CAS authentication plugin does not validate the CAS server certificate
The CAS protocol security model requires that you verify the cas server
certificate before you trust the answer (valid authentication and username
etc.).

Credit goes to Joachim Fritschi for reporting it and providing a patch.
2010-11-18 00:09:02 +00:00
Moodle Robot 70ec102175 Updated the 19 build version to 20101117 2010-11-17 00:50:23 +00:00
Andrew Davis 5cb39510c0 gradebook MDL-25171 made it possible to deselect all grade items when exporting grades 2010-11-16 05:37:51 +00:00
Moodle Robot 5f19bece4c Updated the 19 build version to 20101116 2010-11-16 00:51:27 +00:00
Moodle Robot 594b0a31ab Updated the 19 build version to 20101115 2010-11-15 00:50:35 +00:00
Moodle Robot e072f9a1e5 Updated the 19 build version to 20101114 2010-11-14 00:49:45 +00:00
Moodle Robot 114cda373e Updated the 19 build version to 20101113 2010-11-13 00:49:42 +00:00
Petr Skoda fd5a71b0cb MDL-21907 reverting latest change in groups api, we definitely can not make changes like this in stable and right before the release 2010-11-12 10:03:10 +00:00
Andrew Davis bdc05176e9 gradebook MDL-21907 grader report group view was being limited to groups in the course's default grouping 2010-11-12 04:04:01 +00:00
Moodle Robot 628344cb79 Updated the 19 build version to 20101112 2010-11-12 00:51:06 +00:00
Moodle Robot fcf01f3d30 Updated the 19 build version to 20101111 2010-11-11 00:51:44 +00:00
Dan Marsden eef2618dc8 MDL-25147 tidy up readme wording related to cron 2010-11-11 00:25:36 +00:00
Dan Marsden 67e13a8014 SCORM MDL-24217 correct handling of suspend icon and fix SCORM 2004 usage of cmi.core.exit - thanks to Valerian for report/fix 2010-11-10 22:22:46 +00:00
Dan Marsden ab34dd9ca9 SCORM MDL-24579 remove badly formatted debugging code - thanks to Peter Chamberlain for report. 2010-11-10 21:53:35 +00:00
Dan Marsden 89d793478f SCORM MDL-24579 fix CMILongIdentifier regex (SCORM 2004) - thanks to Peter Chamberlain for report/fix merged from HEAD 2010-11-10 21:38:18 +00:00
Dan Marsden 57512f8b54 SCORM MDL-25085 fix typo in $usertracks array - thanks to Valerian for report/fix 2010-11-10 21:08:33 +00:00
Moodle Robot e548b53474 Updated the 19 build version to 20101110 2010-11-10 00:49:03 +00:00
Aparup Banerjee 990ec2171c assignment MDL-25109 added missing sesskey check for file upload 2010-11-09 02:39:18 +00:00
Moodle Robot 1b1834e8be Updated the 19 build version to 20101109 2010-11-09 00:52:02 +00:00
Tim Hunt 54c489cb73 question bank MDL-24312 problem when deleting a course with orphaned categories.
When there was a question category whose parent had somehow been deleted from the question bank, while the child category was still there, then that gave an error because a DB query was still referring to the question_categories.courese coloumn, that was changed to contextid in moodle 1.9.

Backported to from HEAD. Fix thanks to Mahmoud Kassaei.
2010-11-08 16:00:29 +00:00
Petr Skoda 15a18acddc MDL-25053 invalid SQL syntax
postgresql requires AS when defining column aliases, credit goes to Alan Peter Carter and Brett Wilkins
2010-11-08 01:26:10 +00:00
Moodle Robot 87bf65cbb6 Updated the 19 build version to 20101108 2010-11-08 00:52:12 +00:00
Patrick Malley fbda4556a8 MDL-20757 2010-11-07 19:19:34 +00:00
Moodle Robot 81fb0527dc Updated the 19 build version to 20101107 2010-11-07 00:51:09 +00:00
Moodle Robot 193173bf1f Updated the 19 build version to 20101106 2010-11-06 00:49:55 +00:00
Moodle Robot 974d440d73 Updated the 19 build version to 20101105 2010-11-05 00:49:21 +00:00
Moodle Robot 251aa8e3b1 Updated the 19 build version to 20101104 2010-11-04 00:50:54 +00:00
Moodle Robot c536d23cd5 Updated the 19 build version to 20101103 2010-11-03 00:50:29 +00:00
Tim Hunt 9e8badd3a0 html_to_text MDL-25018 fix regression caused by be previous comment.
Thanks Eloy for spotting this.
I was worried about this happening, so I checked the diff before committing, to make sure something like this did not happen, and still Eclipse+CVS screwed it up for me. Sorry.
2010-11-02 21:50:20 +00:00
Tim Hunt 36a40748e1 MDL-25018 stop html_to_text from breaking utf-8 multibyte characters. 2010-11-02 20:03:50 +00:00
Moodle Robot 52f29243e1 Updated the 19 build version to 20101102 2010-11-02 00:50:59 +00:00
Inaki b59d5522d6 grade/report: MDL-21001 Gradebook shows ranges always
We unconditionnally set them to visible, ignoring configured settings.
Fix it.
2010-11-01 10:22:06 +00:00
Moodle Robot e239bb1734 Updated the 19 build version to 20101101 2010-11-01 00:49:34 +00:00
Moodle Robot fb94121fbc Updated the 19 build version to 20101031 2010-10-31 00:54:23 +00:00
Moodle Robot 60546676cf Updated the 19 build version to 20101030 2010-10-30 00:52:25 +00:00
Andrew Davis 7755bba3f0 gradebook MDL-24791 fixing grader report column highlighting 2010-10-29 07:06:46 +00:00
Moodle Robot 6cfe146bf7 Updated the 19 build version to 20101029 2010-10-29 00:55:16 +00:00
Rossiani Wijaya bb8c661c9d MDL-22528: fixed AJAX Course editing in Chrome and Safari. 2010-10-28 07:41:28 +00:00
Moodle Robot f7dad24fbc Updated the 19 build version to 20101028 2010-10-28 00:51:07 +00:00
Martin Dougiamas dd8a49c15e Bumping version post-release 2010-10-27 06:35:51 +00:00
Moodle Robot 75a917faee Updated the 19 build version to 20101027 2010-10-27 00:51:22 +00:00
Moodle Robot 1946377765 Updated the 19 build version to 20101026 2010-10-26 00:54:47 +00:00
Sam Marshall b085489d88 files MDL-24841 Changed require to require_once in files/index.php so it doesn't break if libraries are required elsewhere 2010-10-25 11:22:31 +00:00
Eloy Lafuente a83fefb70c MDL-24836 data - I'm idiot! Sorry! 2010-10-25 09:31:10 +00:00
Eloy Lafuente c3303a2517 MDL-24836 data - fix causing DBs with new file fields to boom updating records. Merged from 18_STABLE 2010-10-25 08:23:16 +00:00
99 changed files with 1130 additions and 602 deletions
+27
View File
@@ -0,0 +1,27 @@
# This file specifies intentionally untracked files that all Moodle git
# repositories should ignore. It is recommended not to modify this file in your
# local clone. Instead, use .git/info/exclude and add new records there as
# needed.
#
# Example: if you deploy a contributed plugin mod/foobar into your site, put
# the following line into .git/info/exclude file in your Moodle clone:
# /mod/foobar/
#
# See gitignore(5) man page for more details
#
/config.php
/lib/editor/tinymce/extra/tools/temp/
*~
*.swp
/tags
/TAGS
/cscope.*
/.patches/
/.idea/
/nbproject/
CVS
.DS_Store
/.settings/
/.project
/.buildpath
/.cache
+119
View File
@@ -321,6 +321,125 @@
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/customcheckslib.php" function="php_check_php533" level="optional">
<FEEDBACK>
<ON_CHECK message="php533warning" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="2.1" requires="1.9">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mysql" version="5.0.25">
<FEEDBACK>
<ON_ERROR message="mysql416required" />
</FEEDBACK>
</VENDOR>
<VENDOR name="postgres" version="8.3" />
<VENDOR name="mssql" version="9.0" />
<VENDOR name="odbc_mssql" version="9.0" />
<VENDOR name="mssql_n" version="9.0" />
<VENDOR name="oracle" version="10.2" />
<VENDOR name="sqlite" version="2.0" />
</DATABASE>
<PHP version="5.3.2" level="required">
</PHP>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_CHECK message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="optional">
<FEEDBACK>
<ON_CHECK message="mbstringrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_CHECK message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="optional">
<FEEDBACK>
<ON_CHECK message="opensslrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</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="gd" level="optional">
<FEEDBACK>
<ON_CHECK message="gdrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_CHECK message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_CHECK 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="intl" level="optional">
<FEEDBACK>
<ON_CHECK message="intlrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="40M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="safe_mode" value="0" level="optional">
<FEEDBACK>
<ON_CHECK message="settingsafemode" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+4 -4
View File
@@ -1050,8 +1050,7 @@ function report_security_check_riskadmin($detailed=false) {
AND (sc.path = c.path OR sc.path LIKE ".sql_concat('c.path', "'/%'")." OR c.path LIKE ".sql_concat('sc.path', "'/%'").")
AND u.id = ra.userid AND u.deleted = 0
AND ra.contextid = sc.id AND ra.roleid = rc.roleid AND ra.contextid <> ".SYSCONTEXTID."
GROUP BY u.id, u.firstname, u.lastname, u.picture, u.imagealt, u.email, ra.contextid, ra.roleid
ORDER BY u.lastname, u.firstname";
GROUP BY u.id, u.firstname, u.lastname, u.picture, u.imagealt, u.email, ra.contextid, ra.roleid";
$unsupcount = count_records_sql("SELECT COUNT('x') FROM ($sqlunsup) unsup");
@@ -1077,6 +1076,7 @@ function report_security_check_riskadmin($detailed=false) {
$result->info = get_string('check_riskadmin_warning', 'report_security', $a);
if ($detailed) {
$sqlunsup .= " ORDER BY u.lastname, u.firstname";
$rs = get_recordset_sql($sqlunsup);
$users = array();
while ($user = rs_fetch_next_record($rs)) {
@@ -1113,13 +1113,13 @@ function report_security_check_riskbackup($detailed=false) {
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$systemroles = get_records_sql(
"SELECT DISTINCT r.*
"SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder
FROM {$CFG->prefix}role r
JOIN {$CFG->prefix}role_capabilities rc ON rc.roleid = r.id
WHERE rc.capability = 'moodle/backup:userinfo' AND rc.contextid = $syscontext->id AND rc.permission = ".CAP_ALLOW."");
$overriddenroles = get_records_sql(
"SELECT DISTINCT r.*, rc.contextid
"SELECT DISTINCT r.id, r.name, r.shortname, r.sortorder, rc.contextid
FROM {$CFG->prefix}role r
JOIN {$CFG->prefix}role_capabilities rc ON rc.roleid = r.id
WHERE rc.capability = 'moodle/backup:userinfo' AND rc.contextid <> $syscontext->id AND rc.permission = ".CAP_ALLOW."");
+23
View File
@@ -114,8 +114,12 @@ class auth_plugin_cas extends auth_plugin_base {
// Connection to CAS server
$this->connectCAS();
if($this->config->certificate_check && $this->config->certificate_path){
phpCAS::setCasServerCACert($this->config->certificate_path);
}else{
// Don't try to validate the server SSL credentials
phpCAS::setNoCasServerValidation();
}
// Gestion de la connection CAS si accs direct d'un ent ou autre
if (phpCAS::checkAuthentication()) {
@@ -202,6 +206,19 @@ if ( !is_object($PHPCAS_CLIENT) ) {
function config_form($config, $err, $user_fields) {
include 'config.html';
}
/**
* A chance to validate form data, and last chance to
* do stuff before it is inserted in config_plugin
* @param object object with submitted configuration settings (without system magic quotes)
* @param array $err array of error messages
*/
function validate_form(&$form, &$err) {
$certificate_path = trim($form->certificate_path);
if ($form->certificate_check && empty($certificate_path)) {
$err['certificate_path'] = get_string('auth_cas_certificate_path_empty', 'auth');
}
}
/**
* Returns the URL for changing the user's pw, or empty if the default can
* be used.
@@ -248,6 +265,10 @@ if ( !is_object($PHPCAS_CLIENT) ) {
$config->logoutcas = '';
if (!isset ($config->multiauth))
$config->multiauth = '';
if (!isset ($config->certificate_check))
$config->certificate_check = '';
if (!isset ($config->certificate_path))
$config->certificate_path = '';
// LDAP settings
if (!isset($config->host_url))
{ $config->host_url = ''; }
@@ -290,6 +311,8 @@ if ( !is_object($PHPCAS_CLIENT) ) {
set_config('proxycas', $config->proxycas, 'auth/cas');
set_config('logoutcas', $config->logoutcas, 'auth/cas');
set_config('multiauth', $config->multiauth, 'auth/cas');
set_config('certificate_check', $config->certificate_check, 'auth/cas');
set_config('certificate_path', $config->certificate_path, 'auth/cas');
// save LDAP settings
set_config('host_url', $config->host_url, 'auth/cas');
set_config('ldapencoding', $config->ldapencoding, 'auth/cas');
+46
View File
@@ -48,6 +48,14 @@
$config->multiauth = '';
if (!isset ($config->certificate_check))
$config->certificate_check = '';
if (!isset ($config->certificate_path))
$config->certificate_path = '';
// set to defaults if undefined (LDAP)
if (!isset($config->host_url))
@@ -364,6 +372,44 @@ if (!function_exists('ldap_connect')) { // Is php4-ldap really there?
<tr valign="top" class="required">
<td align="right"><?php print_string('auth_cas_certificate_check_key', 'auth') ?>:</td>
<td>
<?php choose_from_menu ($yesno, 'certificate_check', $config->certificate_check, ''); ?>
</td>
<td><?php print_string('auth_cas_certificate_check', 'auth') ?></td>
</tr>
<tr valign="top" class="required">
<td align="right"><?php print_string('auth_cas_certificate_path_key', 'auth') ?>:</td>
<td>
<input name="certificate_path" type="text" size="30" value="<?php echo $config->certificate_path ?>" />
<?php if (isset($err['certificate_path'])) formerr($err['certificate_path']); ?>
</td>
<td>
<?php print_string('auth_cas_certificate_path', 'auth') ?>
</td>
</tr>
<tr>
<td colspan="2">
@@ -101,6 +101,7 @@ if (isset($rss_record)) {
if ($act == 'updfeed') {
require_sesskey();
if (!$managefeeds) {
error(get_string('noguestpost', 'forum').
@@ -153,6 +154,7 @@ if ($act == 'updfeed') {
redirect($referrer, $message);
} else if ($act == 'addfeed' ) {
require_sesskey();
$canaddprivfeeds = has_capability('block/rss_client:createprivatefeeds', $context);
$canaddsharedfeeds = has_capability('block/rss_client:createsharedfeeds', $context);
@@ -225,6 +227,7 @@ if ($act == 'updfeed') {
rss_print_form($act, $url, $rssid, $preferredtitle, $shared, $id, $context);
} else if ($act == 'delfeed') {
require_sesskey();
if (!$managefeeds) {
error(get_string('noguestpost', 'forum').
+5 -2
View File
@@ -57,7 +57,7 @@
if ($resort and confirm_sesskey()) {
if ($courses = get_courses($category->id, "fullname ASC", 'c.id,c.fullname,c.sortorder')) {
// move it off the range
$sortorderresult = get_record_sql('SELECT MIN(sortorder) AS min, 1
FROM ' . $CFG->prefix . 'course WHERE category=' . $category->id);
$sortordermin = $sortorderresult->min;
@@ -131,7 +131,10 @@
/// Print current category description
if (!$editingon && $category->description) {
print_box_start();
echo format_text($category->description); // for multilang filter
$options = new stdClass();
$options->noclean = true;
$options->para = false;
echo format_text($category->description, FORMAT_MOODLE, $options); // for multilang filter
print_box_end();
}
+2
View File
@@ -61,6 +61,8 @@ if ($mform->is_cancelled()) {
// Update an existing category.
$newcategory->id = $category->id;
if ($newcategory->parent != $category->parent) {
// check category manage capability if parent changed
require_capability('moodle/category:manage', get_category_or_system_context((int)$newcategory->parent));
$parent_cat = get_record('course_categories', 'id', $newcategory->parent);
move_category($newcategory, $parent_cat);
}
+7 -1
View File
@@ -9,11 +9,17 @@ class editcategory_form extends moodleform {
$category = $this->_customdata;
// get list of categories to use as parents, with site as the first one
$options = array(get_string('top'));
$options = array();
if (has_capability('moodle/category:manage', get_system_context()) || $category->parent == 0) {
$options[0] = get_string('top');
}
$parents = array();
if ($category->id) {
// Editing an existing category.
make_categories_list($options, $parents, 'moodle/category:manage', $category->id);
if (empty($options[$category->parent])) {
$options[$category->parent] = get_field('course_categories', 'name', 'id', $category->parent);
}
$strsubmit = get_string('savechanges');
} else {
// Making a new category
+1 -1
View File
@@ -5,6 +5,6 @@
$CFG->ajaxcapable = true;
$CFG->ajaxtestedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111);
$CFG->ajaxtestedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari'=>531, 'Chrome'=>6.0);
?>
+2 -2
View File
@@ -221,11 +221,11 @@
echo '<td class="right side">';
if ($displaysection == $section) { // Show the zoom boxes
echo '<a href="view.php?id='.$course->id.'&amp;topic=0#section-'.$section.'" title="'.$strshowalltopics.'">'.
'<img src="'.$CFG->pixpath.'/i/all.gif" alt="'.$strshowalltopics.'" /></a><br />';
'<img src="'.$CFG->pixpath.'/i/all.gif" class="icon topicall" alt="'.$strshowalltopics.'" /></a><br />';
} else {
$strshowonlytopic = get_string('showonlytopic', '', $section);
echo '<a href="view.php?id='.$course->id.'&amp;topic='.$section.'" title="'.$strshowonlytopic.'">'.
'<img src="'.$CFG->pixpath.'/i/one.gif" alt="'.$strshowonlytopic.'" /></a><br />';
'<img src="'.$CFG->pixpath.'/i/one.gif" class="icon topicone" alt="'.$strshowonlytopic.'" /></a><br />';
}
if (isediting($course->id) && has_capability('moodle/course:update', get_context_instance(CONTEXT_COURSE, $course->id))) {
+1 -1
View File
@@ -5,6 +5,6 @@
$CFG->ajaxcapable = true;
$CFG->ajaxtestedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111);
$CFG->ajaxtestedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari'=>531, 'Chrome'=>6.0);
?>
+1 -1
View File
@@ -186,7 +186,7 @@
FROM (SELECT * FROM {$CFG->prefix}role_assignments WHERE contextid $relatedcontexts AND roleid = $roleid ) ra
JOIN {$CFG->prefix}user u ON u.id = ra.userid
LEFT JOIN (
SELECT userid, COUNT(action) actioncount FROM {$CFG->prefix}log WHERE cmid = $instanceid AND time > $timefrom AND $actionsql GROUP BY userid
SELECT userid, COUNT(action) AS actioncount FROM {$CFG->prefix}log WHERE cmid = $instanceid AND time > $timefrom AND $actionsql GROUP BY userid
) l ON (l.userid = ra.userid)";
+1 -1
View File
@@ -87,7 +87,7 @@ Cron
====
If your class offers a cron() method, it will be invoked by
the standard Moodle cron every 5 minutes. Note that if the
the standard Moodle cron every time it is called. Note that if the
tasks are not lightweight you must control how frequently they
execute, perhaps offering a config option.
+1 -1
View File
@@ -93,7 +93,7 @@ function setup_enrolments(&$user) {
//error_log('[ENROL_DB] Found '.count($existing).' existing roles and '.$count.' in external database');
foreach ($courselist as $coursefield) { /// Check the list of courses against existing
$course = get_record('course', $CFG->enrol_localcoursefield, $coursefield);
$course = get_record('course', $CFG->enrol_localcoursefield, addslashes($coursefield));
if (!is_object($course)) {
if (empty($CFG->enrol_db_autocreate)) { // autocreation not allowed
if (debugging('',DEBUG_ALL)) {
+89 -89
View File
@@ -4,8 +4,8 @@ require_once("$CFG->dirroot/enrol/enrol.class.php");
class enrolment_plugin_ldap {
var $log;
var $log;
var $enrol_localcoursefield = 'idnumber';
/**
@@ -23,7 +23,7 @@ function setup_enrolments(&$user) {
notify("[ENROL_LDAP] LDAP-module cannot connect to server: {$CFG->enrol_ldap_host_url}");
return false;
}
// we are connected OK, continue...
// Get all the possible roles
@@ -37,7 +37,7 @@ function setup_enrolments(&$user) {
if (!$roleassignments) {
$roleassignments = array();
}
// Get the ones that came from LDAP
$ldap_assignments = array_filter($roleassignments, create_function('$x', 'return $x->enrol == \'ldap\';'));
@@ -46,20 +46,20 @@ function setup_enrolments(&$user) {
// Get enrolments for each type of role from LDAP.
foreach($roles as $role) {
$enrolments = $this->find_ext_enrolments(
$ldap_connection,
$user->idnumber ,
$ldap_connection,
$user->idnumber ,
$role);
//error_log('[ENROL_LDAP] LDAP reports ' . count($enrolments) . ' enrolments of type ' . $role->shortname . '.');
foreach ($enrolments as $enrol){
$course_ext_id = $enrol[$CFG->enrol_ldap_course_idnumber][0];
if(empty($course_ext_id)){
error_log("[ENROL_LDAP] The course external id is invalid!\n");
continue; // next; skip this one!
}
// create the course ir required
$course_obj = get_record( 'course',
$this->enrol_localcoursefield,
@@ -74,18 +74,18 @@ function setup_enrolments(&$user) {
error_log("[ENROL_LDAP] User $user->username enrolled to a nonexistant course $course_ext_id \n");
}
}
// deal with enrolment in the moodle db
if (!empty($course_obj)) { // does course exist now?
if (!empty($course_obj)) { // does course exist now?
$context = get_context_instance(CONTEXT_COURSE, $course_obj->id);
//$courseroles = get_user_roles($context, $user->id);
if (!get_record('role_assignments', 'roleid', $role->id, 'userid', $user->id, 'contextid', $context->id)) {
//error_log("[ENROL_LDAP] Assigning role '{$role->name}' to {$user->id} ({$user->username}) in course {$course_obj->id} ({$course_obj->shortname})");
if (!role_assign($role->id, $user->id, 0, $context->id, 0, 0, 0, 'ldap')){
error_log("[ENROL_LDAP] Failed to assign role '{$role->name}' to $user->id ($user->username) into course $course_obj->id ($course_obj->shortname)");
}
}
} else {
//error_log("[ENROL_LDAP] Role '{$role->name}' already assigned to {$user->id} ({$user->username}) in course {$course_obj->id} ({$course_obj->shortname})");
}
@@ -115,7 +115,7 @@ function setup_enrolments(&$user) {
@ldap_close($ldap_connection);
//error_log('[ENROL_LDAP] finished with setup_enrolments');
return true;
}
@@ -137,7 +137,7 @@ function sync_enrolments($type, $enrol = false) {
notify("LDAP-module cannot connect to server: $CFG->ldap_host_url");
return false;
}
// we are connected OK, continue...
$this->enrol_ldap_bind($ldap_connection);
@@ -145,7 +145,7 @@ function sync_enrolments($type, $enrol = false) {
$ldap_contexts = explode(";",$CFG->{'enrol_ldap_contexts_role'.$role->id});
// get all the fields we will want for the potential course creation
// as they are light. don't get membership -- potentially a lot of data.
// as they are light. don't get membership -- potentially a lot of data.
$ldap_fields_wanted = array( 'dn', $CFG->enrol_ldap_course_idnumber);
if (!empty($CFG->enrol_ldap_course_fullname)){
array_push($ldap_fields_wanted, $CFG->enrol_ldap_course_fullname);
@@ -161,11 +161,11 @@ function sync_enrolments($type, $enrol = false) {
}
// define the search pattern
if (!empty($CFG->enrol_ldap_objectclass)){
if (!empty($CFG->enrol_ldap_objectclass)){
$ldap_search_pattern='(objectclass='.$CFG->enrol_ldap_objectclass.')';
} else {
$ldap_search_pattern="(objectclass=*)";
}
// first, pack the sortorder...
@@ -176,19 +176,19 @@ function sync_enrolments($type, $enrol = false) {
$context = trim($context);
if ($CFG->enrol_ldap_search_sub){
//use ldap_search to find first user from subtree
$ldap_result = @ldap_search($ldap_connection,
$context,
$ldap_result = @ldap_search($ldap_connection,
$context,
$ldap_search_pattern,
$ldap_fields_wanted);
} else {
//search only in this context
$ldap_result = @ldap_list($ldap_connection,
$context,
$ldap_result = @ldap_list($ldap_connection,
$context,
$ldap_search_pattern,
$ldap_fields_wanted,0,0);
}
// check and push results
$records = $ldap_result
? ldap_get_entries($ldap_connection,$ldap_result)
@@ -197,9 +197,9 @@ function sync_enrolments($type, $enrol = false) {
// ldap libraries return an odd array, really. fix it:
$flat_records=array();
for ($c=0;$c<$records['count'];$c++) {
array_push($flat_records, $records["$c"]);
array_push($flat_records, $records["$c"]);
}
// free mem -- is there a leak?
// free mem -- is there a leak?
$records=0; $ldap_result=0;
if (count($flat_records)) {
@@ -208,7 +208,7 @@ function sync_enrolments($type, $enrol = false) {
foreach($flat_records as $course){
$idnumber = $course{$CFG->enrol_ldap_course_idnumber}[0];
print "== Synching $idnumber\n";
// does the course exist in moodle already?
// does the course exist in moodle already?
$course_obj = false;
$course_obj = get_record( 'course',
$this->enrol_localcoursefield,
@@ -237,22 +237,22 @@ function sync_enrolments($type, $enrol = false) {
$context = get_context_instance(CONTEXT_COURSE, $course_obj->id);
// pull the ldap membership into a nice array
// this is an odd array -- mix of hash and array --
// this is an odd array -- mix of hash and array --
$ldapmembers=array();
if(array_key_exists('enrol_ldap_memberattribute_role'.$role->id, $CFG)
&& !empty($CFG->{'enrol_ldap_memberattribute_role'.$role->id})
&& !empty($course[strtolower($CFG->{'enrol_ldap_memberattribute_role'.$role->id} ) ])){ // may have no membership!
$ldapmembers = $course[strtolower($CFG->{'enrol_ldap_memberattribute_role'.$role->id} )];
$ldapmembers = $course[strtolower($CFG->{'enrol_ldap_memberattribute_role'.$role->id} )];
unset($ldapmembers['count']); // remove oddity ;)
$ldapmembers = addslashes_recursive($ldapmembers);
}
// prune old ldap enrolments
// hopefully they'll fit in the max buffer size for the RDBMS
$sql = '
SELECT enr.userid AS user, 1
SELECT enr.userid
FROM '.$CFG->prefix.'role_assignments enr
JOIN '.$CFG->prefix.'user usr ON usr.id=enr.userid
WHERE enr.roleid = '.$role->id.'
@@ -266,7 +266,7 @@ function sync_enrolments($type, $enrol = false) {
$todelete = get_records_sql($sql);
if(!empty($todelete)){
foreach ($todelete as $member) {
$member = $member->user;
$member = $member->userid;
if (role_unassign($role->id, $member, 0, $context->id, 'ldap')) {
print "Unassigned $type from $member for course $course_obj->id ($course_obj->shortname)\n";
@@ -275,21 +275,21 @@ function sync_enrolments($type, $enrol = false) {
}
}
}
// insert current enrolments
// insert current enrolments
// bad we can't do INSERT IGNORE with postgres...
foreach ($ldapmembers as $ldapmember) {
$sql = 'SELECT id,1 FROM '.$CFG->prefix.'user '
." WHERE idnumber='$ldapmember'";
$member = get_record_sql($sql);
// print "sql: $sql \nidnumber = ".stripslashes($ldapmember)." \n".var_dump($member);
$member = get_record_sql($sql);
// print "sql: $sql \nidnumber = ".stripslashes($ldapmember)." \n".var_dump($member);
if(empty($member) || empty($member->id)){
print "Could not find user ".stripslashes($ldapmember).", skipping\n";
continue;
}
$member = $member->id;
if (!get_record('role_assignments', 'roleid', $role->id,
'contextid', $context->id,
if (!get_record('role_assignments', 'roleid', $role->id,
'contextid', $context->id,
'userid', $member, 'enrol', 'ldap')){
if (role_assign($role->id, $member, 0, $context->id, 0, 0, 0, 'ldap')){
print "Assigned role $type to $member (".stripslashes($ldapmember).") for course $course_obj->id ($course_obj->shortname)\n";
@@ -302,10 +302,10 @@ function sync_enrolments($type, $enrol = false) {
}
}
}
// we are done now, a bit of housekeeping
fix_course_sortorder();
@ldap_close($ldap_connection);
return true;
}
@@ -321,7 +321,7 @@ function config_form($frm) {
global $CFG;
$this->check_legacy_config();
include("$CFG->dirroot/enrol/ldap/config.html");
}
@@ -339,7 +339,7 @@ function process_config($config) {
$config->enrol_ldap_version = '';
}
set_config('enrol_ldap_version', $config->enrol_ldap_version);
if (!isset ($config->enrol_ldap_bind_dn)) {
$config->enrol_ldap_bind_dn = '';
}
@@ -348,58 +348,58 @@ function process_config($config) {
if (!isset ($config->enrol_ldap_bind_pw)) {
$config->enrol_ldap_bind_pw = '';
}
set_config('enrol_ldap_bind_pw', $config->enrol_ldap_bind_pw);
set_config('enrol_ldap_bind_pw', $config->enrol_ldap_bind_pw);
if (!isset ($config->enrol_ldap_objectclass)) {
$config->enrol_ldap_objectclass = '';
}
set_config('enrol_ldap_objectclass', $config->enrol_ldap_objectclass);
set_config('enrol_ldap_objectclass', $config->enrol_ldap_objectclass);
if (!isset ($config->enrol_ldap_category)) {
$config->enrol_ldap_category = '';
}
set_config('enrol_ldap_category', $config->enrol_ldap_category);
set_config('enrol_ldap_category', $config->enrol_ldap_category);
if (!isset ($config->enrol_ldap_template)) {
$config->enrol_ldap_template = '';
}
set_config('enrol_ldap_template', $config->enrol_ldap_template);
set_config('enrol_ldap_template', $config->enrol_ldap_template);
if (!isset ($config->enrol_ldap_course_fullname)) {
$config->enrol_ldap_course_fullname = '';
}
set_config('enrol_ldap_course_fullname', $config->enrol_ldap_course_fullname);
set_config('enrol_ldap_course_fullname', $config->enrol_ldap_course_fullname);
if (!isset ($config->enrol_ldap_course_shortname)) {
$config->enrol_ldap_course_shortname = '';
}
set_config('enrol_ldap_course_shortname', $config->enrol_ldap_course_shortname);
set_config('enrol_ldap_course_shortname', $config->enrol_ldap_course_shortname);
if (!isset ($config->enrol_ldap_course_summary)) {
$config->enrol_ldap_course_summary = '';
}
set_config('enrol_ldap_course_summary', $config->enrol_ldap_course_summary);
set_config('enrol_ldap_course_summary', $config->enrol_ldap_course_summary);
if (!isset ($config->enrol_ldap_course_idnumber)) {
$config->enrol_ldap_course_idnumber = '';
}
set_config('enrol_ldap_course_idnumber', $config->enrol_ldap_course_idnumber);
set_config('enrol_ldap_course_idnumber', $config->enrol_ldap_course_idnumber);
if (!isset ($config->enrol_localcoursefield)) {
$config->enrol_localcoursefield = '';
}
set_config('enrol_localcoursefield', $config->enrol_localcoursefield);
if (!isset ($config->enrol_ldap_user_memberfield)) {
$config->enrol_ldap_user_memberfield = '';
}
set_config('enrol_ldap_user_memberfield', $config->enrol_ldap_user_memberfield);
set_config('enrol_ldap_user_memberfield', $config->enrol_ldap_user_memberfield);
if (!isset ($config->enrol_ldap_search_sub)) {
$config->enrol_ldap_search_sub = '0';
}
set_config('enrol_ldap_search_sub', $config->enrol_ldap_search_sub);
set_config('enrol_ldap_search_sub', $config->enrol_ldap_search_sub);
if (!isset ($config->enrol_ldap_autocreate)) {
$config->enrol_ldap_autocreate = '0';
}
@@ -410,11 +410,11 @@ function process_config($config) {
if (!isset($config->{'enrol_ldap_contexts_role'.$role->id})) {
$config->{'enrol_ldap_contexts_role'.$role->id} = '';
}
if (!isset($config->{'enrol_ldap_memberattribute_role'.$role->id})) {
$config->{'enrol_ldap_memberattribute_role'.$role->id} = '';
}
set_config('enrol_ldap_contexts_role'.$role->id, $config->{'enrol_ldap_contexts_role'.$role->id});
set_config('enrol_ldap_memberattribute_role'.$role->id, $config->{'enrol_ldap_memberattribute_role'.$role->id});
}
@@ -435,7 +435,7 @@ function enrol_ldap_connect(){
if (!empty($CFG->enrol_ldap_bind_dn)) {
$bind = ldap_bind( $result,
$CFG->enrol_ldap_bind_dn,
$CFG->enrol_ldap_bind_dn,
$CFG->enrol_ldap_bind_pw );
if (!$bind) {
notify("Error in binding to LDAP server");
@@ -464,11 +464,11 @@ function enrol_ldap_bind($ldap_connection){
}
} else {
//bind anonymously
//bind anonymously
if ( !ldap_bind($ldap_connection)){
notify("Error: could not bind ldap anonymously");
return false;
}
}
}
return true;
@@ -477,13 +477,13 @@ function enrol_ldap_bind($ldap_connection){
function find_ext_enrolments ($ldap_connection, $memberuid, $role){
/// role is a record from the mdl_role table
/// return multidimentional array array with of courses (at least dn and idnumber)
///
///
global $CFG;
if(empty($memberuid)) { // No "idnumber" stored for this user, so no LDAP enrolments
return array();
}
}
//default return value
$courses = array();
@@ -493,7 +493,7 @@ function find_ext_enrolments ($ldap_connection, $memberuid, $role){
$ldap_contexts = explode(";",$CFG->{'enrol_ldap_contexts_role'.$role->id});
// get all the fields we will want for the potential course creation
// as they are light. don't get membership -- potentially a lot of data.
// as they are light. don't get membership -- potentially a lot of data.
$ldap_fields_wanted = array( 'dn', $CFG->enrol_ldap_course_idnumber);
if (!empty($CFG->enrol_ldap_course_fullname)){
array_push($ldap_fields_wanted, $CFG->enrol_ldap_course_fullname);
@@ -507,7 +507,7 @@ function find_ext_enrolments ($ldap_connection, $memberuid, $role){
// define the search pattern
$ldap_search_pattern = "(".$CFG->{'enrol_ldap_memberattribute_role'.$role->id}."=".$this->filter_addslashes($memberuid).")";
if (!empty($CFG->enrol_ldap_objectclass)){
if (!empty($CFG->enrol_ldap_objectclass)){
$ldap_search_pattern='(&(objectclass='.$CFG->enrol_ldap_objectclass.')'.$ldap_search_pattern.')';
}
@@ -516,31 +516,31 @@ function find_ext_enrolments ($ldap_connection, $memberuid, $role){
if (empty($context)) {
continue; // next;
}
if ($CFG->enrol_ldap_search_sub){
//use ldap_search to find first user from subtree
$ldap_result = ldap_search($ldap_connection,
$context,
$ldap_result = ldap_search($ldap_connection,
$context,
$ldap_search_pattern,
$ldap_fields_wanted);
} else {
//search only in this context
$ldap_result = ldap_list($ldap_connection,
$context,
$ldap_result = ldap_list($ldap_connection,
$context,
$ldap_search_pattern,
$ldap_fields_wanted);
}
// check and push results
$records = ldap_get_entries($ldap_connection,$ldap_result);
$records = ldap_get_entries($ldap_connection,$ldap_result);
// ldap libraries return an odd array, really. fix it:
$flat_records=array();
for ($c=0;$c<$records['count'];$c++) {
array_push($flat_records, $records["$c"]);
array_push($flat_records, $records["$c"]);
}
if (count($flat_records)) {
$courses = array_merge($courses, $flat_records);
}
@@ -551,7 +551,7 @@ function find_ext_enrolments ($ldap_connection, $memberuid, $role){
// will create the moodle course from the template
// course_ext is an array as obtained from ldap -- flattened somewhat
// NOTE: if you pass true for $skip_fix_course_sortorder
// NOTE: if you pass true for $skip_fix_course_sortorder
// you will want to call fix_course_sortorder() after your are done
// with course creation
function create_course ($course_ext,$skip_fix_course_sortorder=0){
@@ -578,7 +578,7 @@ function create_course ($course_ext,$skip_fix_course_sortorder=0){
$course->shortname = $course_ext[$CFG->enrol_ldap_course_shortname][0];
if ( empty($course->idnumber)
|| empty($course->fullname)
|| empty($course->shortname) ) {
|| empty($course->shortname) ) {
// we are in trouble!
error_log("Cannot create course: missing required data from the LDAP record!");
error_log(var_export($course, true));
@@ -588,10 +588,10 @@ function create_course ($course_ext,$skip_fix_course_sortorder=0){
$course->summary = empty($CFG->enrol_ldap_course_summary) || empty($course_ext[$CFG->enrol_ldap_course_summary][0])
? ''
: $course_ext[$CFG->enrol_ldap_course_summary][0];
if(!empty($CFG->enrol_ldap_category)){ // optional ... but ensure it is set!
$course->category = $CFG->enrol_ldap_category;
}
}
if ($course->category == 0){ // must be avoided as it'll break moodle
$course->category = 1; // the misc 'catch-all' category
}
@@ -600,13 +600,13 @@ function create_course ($course_ext,$skip_fix_course_sortorder=0){
$sort = get_record_sql('SELECT MAX(sortorder) AS max, 1 FROM ' . $CFG->prefix . 'course WHERE category=' . $course->category);
$sort = $sort->max;
$sort++;
$course->sortorder = $sort;
$course->sortorder = $sort;
// override with local data
$course->startdate = time();
$course->timecreated = time();
$course->visible = 1;
$course = addslashes_recursive($course);
// store it and log
@@ -619,8 +619,8 @@ function create_course ($course_ext,$skip_fix_course_sortorder=0){
blocks_repopulate_page($page); // Return value no
if(!$skip_fix_course_sortorder){
fix_course_sortorder();
if(!$skip_fix_course_sortorder){
fix_course_sortorder();
}
add_to_log($newcourseid, "course", "new", "view.php?id=$newcourseid", "enrol/ldap auto-creation");
} else {
@@ -628,7 +628,7 @@ function create_course ($course_ext,$skip_fix_course_sortorder=0){
notify("Serious Error! Could not create the new course!");
return false;
}
return $newcourseid;
}
@@ -665,7 +665,7 @@ function check_legacy_config () {
unset_config('enrol_ldap_teacher_contexts');
}
if (isset($CFG->enrol_ldap_teacher_memberattribute)) {
if (isset($teacher_role)
or $teacher_role = get_record('role', 'shortname', 'teacher')) {
+15 -7
View File
@@ -13,7 +13,7 @@
//TODO: Blog attachments do not have access control implemented - anybody can read them!
// It might be better to move the code to separate file because the access
// control is quite complex - see bolg/index.php
// control is quite complex - see bolg/index.php
require_once('config.php');
require_once('lib/filelib.php');
@@ -29,7 +29,7 @@
$relativepath = get_file_argument('file.php');
$forcedownload = optional_param('forcedownload', 0, PARAM_BOOL);
// relative path must start with '/', because of backup/restore!!!
if (!$relativepath) {
error('No valid arguments supplied or incorrect server configuration');
@@ -39,12 +39,20 @@
$pathname = $CFG->dataroot.$relativepath;
// protect imsenterprise plugin data
if (strtolower("$CFG->dataroot/1/imsenterprise-enrol.xml") === strtolower(realpath($pathname))
or (!empty($CFG->enrol_imsfilelocation) and strtolower($CFG->enrol_imsfilelocation) === strtolower(realpath($pathname)))) {
require_login();
require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
$forcedownload = 1;
}
// extract relative path components
$args = explode('/', trim($relativepath, '/'));
if (count($args) == 0) { // always at least courseid, may search for index.html in course root
error('No valid arguments supplied');
}
// security: limit access to existing course subdirectories
if (($args[0]!='blog') and (!$course = get_record_sql("SELECT * FROM {$CFG->prefix}course WHERE id='".(int)$args[0]."'"))) {
error('Invalid course ID');
@@ -84,7 +92,7 @@
if (!has_capability('moodle/site:backup', get_context_instance(CONTEXT_COURSE, $course->id))) {
error('Access not allowed');
} else {
$lifetime = 0; //disable browser caching for backups
$lifetime = 0; //disable browser caching for backups
}
}
@@ -120,7 +128,7 @@
if (!has_capability('mod/assignment:grade', get_context_instance(CONTEXT_MODULE, $cm->id))) {
error('Access not allowed');
}
}
}
}
// security: force download of all attachments submitted by students
@@ -144,11 +152,11 @@
}
if ($args[0] == 'blog') {
$forcedownload = 1; // force download of all attachments
}
}
// security: some protection of hidden resource files
// warning: it may break backwards compatibility
if ((!empty($CFG->preventaccesstohiddenfiles))
if ((!empty($CFG->preventaccesstohiddenfiles))
and (count($args) >= 2)
and (!(strtolower($args[1]) == 'moddata' and strtolower($args[2]) != 'resource')) // do not block files from other modules!
and (!has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_COURSE, $course->id)))) {
+2 -2
View File
@@ -8,8 +8,8 @@
// USER is a persistent variable using sessions
require('../config.php');
require($CFG->libdir.'/filelib.php');
require($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir . '/filelib.php');
require_once($CFG->libdir . '/adminlib.php');
$id = required_param('id', PARAM_INT);
$file = optional_param('file', '', PARAM_PATH);
+65 -48
View File
@@ -36,80 +36,80 @@ function mediaplugin_filter($courseid, $text) {
$newtext = $text; // fullclone is slow and not needed here
if ($CFG->filter_mediaplugin_enable_mp3) {
$search = '/<a.*?href="([^<]+\.mp3)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.mp3)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_mp3_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_ogg) {
$search = '/<a[^>]*?href="([^<]+\.ogg)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.ogg)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'filter_mediaplugin_ogg_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_ogv) {
$search = '/<a[^>]*?href="([^<]+\.ogv)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.ogv)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'filter_mediaplugin_ogv_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_swf) {
$search = '/<a.*?href="([^<]+\.swf)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.swf)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_swf_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_flv) {
$search = '/<a.*?href="([^<]+\.flv)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.flv)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_flv_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_mov) {
$search = '/<a.*?href="([^<]+\.mov)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.mov)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_qt_callback', $newtext);
// MDL-18658
$search = '/<a.*?href="([^<]+\.mp4)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.mp4)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_qt_callback', $newtext);
$search = '/<a.*?href="([^<]+\.m4v)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.m4v)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_qt_callback', $newtext);
$search = '/<a.*?href="([^<]+\.m4a)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^<]+\.m4a)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_qt_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_wmv) {
$search = '/<a.*?href="([^<]+\.wmv)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.wmv)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_wmp_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_mpg) {
$search = '/<a.*?href="([^<]+\.mpe?g)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.mpe?g)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_qt_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_avi) {
$search = '/<a.*?href="([^<]+\.avi)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.avi)(\?d=([\d]{1,4}%?)x([\d]{1,4}%?))?"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_wmp_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_ram) {
$search = '/<a.*?href="([^<]+\.ram)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.ram)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_real_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_rpm) {
$search = '/<a.*?href="([^<]+\.rpm)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.rpm)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_real_callback', $newtext);
}
if ($CFG->filter_mediaplugin_enable_rm) {
$search = '/<a.*?href="([^<]+\.rm)"[^>]*>.*?<\/a>/is';
$search = '/<a\s[^>]*href="([^"]+\.rm)"[^>]*>.*?<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_real_callback', $newtext);
}
if (!empty($CFG->filter_mediaplugin_enable_youtube)) {
$search = '/<a[^>]*?href="([^<]*)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
$search = '/<a\s[^>]*href="([^"]*)youtube.com\/watch\?v=([^"]*)"[^>]*>(.*?)<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_youtube_callback', $newtext);
$search = '/<a[^>]*?href="([^<]*)youtube.com\/v\/([^"]*)"[^>]*>(.*?)<\/a>/is';
$search = '/<a\s[^>]*href="([^"]*)youtube.com\/v\/([^"]*)"[^>]*>(.*?)<\/a>/is';
$newtext = preg_replace_callback($search, 'mediaplugin_filter_youtube_callback', $newtext);
}
@@ -143,14 +143,15 @@ function mediaplugin_filter_mp3_callback($link) {
static $count = 0;
$count++;
$id = 'filter_mp3_'.time().$count; //we need something unique because it might be stored in text cache
$url = $link[1];
$jsurl = addslashes_js($link[1]);
$url = addslashes_js($link[1]);
return $link[0].
$printlink = '<a href="'.$url.'">'.get_string('mp3audio', 'mediaplugin').'</a>';
return $printlink.
'<span class="mediaplugin mediaplugin_mp3" id="'.$id.'">('.get_string('mp3audio', 'mediaplugin').')</span>
<script type="text/javascript">
//<![CDATA[
var FO = { movie:"'.$CFG->wwwroot.'/filter/mediaplugin/mp3player.swf?src='.$url.'",
var FO = { movie:"'.$CFG->wwwroot.'/filter/mediaplugin/mp3player.swf?src='.$jsurl.'",
width:"90", height:"15", majorversion:"6", build:"40", flashvars:"'.$c.'", quality: "high" };
UFO.create(FO, "'.$id.'");
//]]>
@@ -158,38 +159,44 @@ function mediaplugin_filter_mp3_callback($link) {
}
function filter_mediaplugin_ogg_callback($link) {
global $CFG, $OUTPUT, $PAGE;
global $CFG;
static $count = 0;
$count++;
$id = 'filter_ogg_'.time().$count; //we need something unique because it might be stored in text cache
$url = addslashes_js($link[1]);
$printlink = html_writer::link($url, get_string('oggaudio', 'filter_mediaplugin'));
$unsupportedplugins = get_string('unsupportedplugins', 'filter_mediaplugin', $printlink);
$url = $link[1];
$printlink = '<a href="'.$url.'">'.get_string('oggaudio', 'mediaplugin').'</a>';
$unsupportedplugins = get_string('unsupportedplugins', 'mediaplugin', $printlink);
$output = <<<OET
<span class="mediaplugin mediaplugin_ogg" id="$id">
<audio id="$id" src="$url" controls="true" width="100">
$unsupportedplugins
</audio>
</span>
OET;
return $output;
}
function filter_mediaplugin_ogv_callback($link) {
global $CFG, $OUTPUT, $PAGE;
global $CFG;
static $count = 0;
$count++;
$id = 'filter_ogv_'.time().$count; //we need something unique because it might be stored in text cache
$url = addslashes_js($link[1]);
$printlink = html_writer::link($url, get_string('ogvvideo', 'filter_mediaplugin'));
$unsupportedplugins = get_string('unsupportedplugins', 'filter_mediaplugin', $printlink);
$url = $link[1];
$printlink = '<a href="'.$url.'">'.get_string('ogvvideo', 'mediaplugin').'</a>';
$unsupportedplugins = get_string('unsupportedplugins', 'mediaplugin', $printlink);
$output = <<<OET
<span class="mediaplugin mediaplugin_ogv" id="$id">
<video id="$id" src="$url" controls="true" width="600" >
$unsupportedplugins
</video>
</span>
OET;
return $output;
@@ -202,13 +209,15 @@ function mediaplugin_filter_swf_callback($link) {
$width = empty($link[3]) ? '400' : $link[3];
$height = empty($link[4]) ? '300' : $link[4];
$url = addslashes_js($link[1]);
$url = $link[1];
$jsurl = addslashes_js($link[1]);
$printlink = '<a href="'.$url.'">'.get_string('flashvideo', 'mediaplugin').'</a>';
return $link[0].
return $printlink.
'<span class="mediaplugin mediaplugin_swf" id="'.$id.'">('.get_string('flashanimation', 'mediaplugin').')</span>
<script type="text/javascript">
//<![CDATA[
var FO = { movie:"'.$url.'", width:"'.$width.'", height:"'.$height.'", majorversion:"6", build:"40",
var FO = { movie:"'.$jsurl.'", width:"'.$width.'", height:"'.$height.'", majorversion:"6", build:"40",
allowscriptaccess:"never", quality: "high" };
UFO.create(FO, "'.$id.'");
//]]>
@@ -224,13 +233,15 @@ function mediaplugin_filter_flv_callback($link) {
$width = empty($link[3]) ? '480' : $link[3];
$height = empty($link[4]) ? '360' : $link[4];
$url = addslashes_js($link[1]);
$url = $link[1];
$jsurl = addslashes_js($link[1]);
$printlink = '<a href="'.$url.'">'.get_string('flashvideo', 'mediaplugin').'</a>';
return $link[0].
return $printlink.
'<span class="mediaplugin mediaplugin_flv" id="'.$id.'">('.get_string('flashvideo', 'mediaplugin').')</span>
<script type="text/javascript">
//<![CDATA[
var FO = { movie:"'.$CFG->wwwroot.'/filter/mediaplugin/flvplayer.swf?file='.$url.'",
var FO = { movie:"'.$CFG->wwwroot.'/filter/mediaplugin/flvplayer.swf?file='.$jsurl.'",
width:"'.$width.'", height:"'.$height.'", majorversion:"6", build:"40",
allowscriptaccess:"never", quality: "high", allowfullscreen: "true" };
UFO.create(FO, "'.$id.'");
@@ -239,29 +250,31 @@ function mediaplugin_filter_flv_callback($link) {
}
function mediaplugin_filter_real_callback($link, $autostart=false) {
$url = addslashes_js($link[1]);
$url = $link[1];
$jsurl = addslashes_js($link[1]);
$mimetype = mimeinfo('type', $url);
$autostart = $autostart ? 'true' : 'false';
$printlink = '<a href="'.$url.'">'.get_string('realaudio', 'mediaplugin').'</a>';
// embed kept for now see MDL-8674
return $link[0].
return $printlink.
'<span class="mediaplugin mediaplugin_real">
<script type="text/javascript">
//<![CDATA[
document.write(\'<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="180">\\
<param name="src" value="'.$url.'" />\\
<param name="src" value="'.$jsurl.'" />\\
<param name="autostart" value="'.$autostart.'" />\\
<param name="controls" value="imagewindow" />\\
<param name="console" value="video" />\\
<param name="loop" value="true" />\\
<embed src="'.$url.'" width="240" height="180" loop="true" type="'.$mimetype.'" controls="imagewindow" console="video" autostart="'.$autostart.'" />\\
<embed src="'.$jsurl.'" width="240" height="180" loop="true" type="'.$mimetype.'" controls="imagewindow" console="video" autostart="'.$autostart.'" />\\
</object><br />\\
<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="240" height="30">\\
<param name="src" value="'.$url.'" />\\
<param name="src" value="'.$jsurl.'" />\\
<param name="autostart" value="'.$autostart.'" />\\
<param name="controls" value="ControlPanel" />\\
<param name="console" value="video" />\\
<embed src="'.$url.'" width="240" height="30" controls="ControlPanel" type="'.$mimetype.'" console="video" autostart="'.$autostart.'" />\\
<embed src="'.$jsurl.'" width="240" height="30" controls="ControlPanel" type="'.$mimetype.'" console="video" autostart="'.$autostart.'" />\\
</object>\');
//]]>
</script></span>';
@@ -272,18 +285,20 @@ document.write(\'<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" wi
*/
function mediaplugin_filter_youtube_callback($link, $autostart=false) {
$site = addslashes_js($link[1]);
$url = addslashes_js($link[2]);
$info = addslashes_js($link[3]);
$site = s($link[1]);
$url = $link[2];
$info = s($link[3]);
return '<object title="'.$info.'"
return '<span class="mediaplugin mediaplugin_youtube">'.
'<object title="'.$info.'"
class="mediaplugin mediaplugin_youtube" type="application/x-shockwave-flash"
data="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" width="425" height="344">'.
'<param name="movie" value="'.$site.'youtube.com/v/'.$url.'&amp;fs=1&amp;rel=0" />'.
'<param name="FlashVars" value="playerMode=embedded" />'.
'<param name="wmode" value="transparent" />'.
'<param name="allowFullScreen" value="true" />'.
'</object>';
'</object>'.
'</span>';
}
/**
@@ -302,8 +317,9 @@ function mediaplugin_filter_wmp_callback($link, $autostart=false) {
}
$mimetype = mimeinfo('type', $url);
$autostart = $autostart ? 'true' : 'false';
$printlink = '<a href="'.$url.'">'.get_string('wmpvideo', 'mediaplugin').'</a>';
return $link[0].
return $printlink.
'<span class="mediaplugin mediaplugin_wmp">
<object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" '.$mpsize.'
standby="Loading Microsoft(R) Windows(R) Media Player components..."
@@ -341,8 +357,9 @@ function mediaplugin_filter_qt_callback($link, $autostart=false) {
}
$mimetype = mimeinfo('type', $url);
$autostart = $autostart ? 'true' : 'false';
$printlink = '<a href="'.$url.'">'.get_string('quicktime', 'mediaplugin').'</a>';
return $link[0].
return $printlink.
'<span class="mediaplugin mediaplugin_qt">
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
codebase="http://www.apple.com/qtactivex/qtplugin.cab" '.$size.'>
+24 -9
View File
@@ -54,13 +54,20 @@ class grade_export {
$this->groupid = $groupid;
$this->grade_items = grade_item::fetch_all(array('courseid'=>$this->course->id));
//Populating the columns here is required by /grade/export/(whatever)/export.php
//however index.php, when the form is submitted, will construct the collection here
//with an empty $itemlist then reconstruct it in process_form() using $formdata
$this->columns = array();
if (!empty($itemlist)) {
$itemids = explode(',', $itemlist);
// remove items that are not requested
foreach ($itemids as $itemid) {
if (array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
if ($itemlist=='-1') {
//user deselected all items
} else {
$itemids = explode(',', $itemlist);
// remove items that are not requested
foreach ($itemids as $itemid) {
if (array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
}
} else {
@@ -87,9 +94,13 @@ class grade_export {
$this->columns = array();
if (!empty($formdata->itemids)) {
foreach ($formdata->itemids as $itemid=>$selected) {
if ($selected and array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
if ($formdata->itemids=='-1') {
//user deselected all items
} else {
foreach ($formdata->itemids as $itemid=>$selected) {
if ($selected and array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
}
} else {
@@ -267,10 +278,14 @@ class grade_export {
*/
function get_export_params() {
$itemids = array_keys($this->columns);
$itemidsparam = implode(',', $itemids);
if (empty($itemidsparam)) {
$itemidsparam = '-1';
}
$params = array('id' =>$this->course->id,
'groupid' =>$this->groupid,
'itemids' =>implode(',', $itemids),
'itemids' =>$itemidsparam,
'export_letters' =>$this->export_letters,
'export_feedback' =>$this->export_feedback,
'updatedgradesonly' =>$this->updatedgradesonly,
+17 -9
View File
@@ -108,10 +108,14 @@ class graded_users_iterator {
$users_sql = "SELECT u.* $ofields
FROM {$CFG->prefix}user u
INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
$groupsql
WHERE ra.roleid $gradebookroles
AND ra.contextid $relatedcontexts
JOIN (
SELECT DISTINCT ra.userid
FROM {$CFG->prefix}role_assignments ra
WHERE ra.roleid $gradebookroles
AND ra.contextid $relatedcontexts
) rainner ON rainner.userid = u.id
WHERE u.deleted = 0
$groupwheresql
ORDER BY $order";
@@ -123,13 +127,17 @@ class graded_users_iterator {
$grades_sql = "SELECT g.* $ofields
FROM {$CFG->prefix}grade_grades g
INNER JOIN {$CFG->prefix}user u ON g.userid = u.id
INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
JOIN {$CFG->prefix}user u ON g.userid = u.id
$groupsql
WHERE ra.roleid $gradebookroles
AND ra.contextid $relatedcontexts
AND g.itemid IN ($itemids)
$groupwheresql
JOIN (
SELECT DISTINCT ra.userid
FROM {$CFG->prefix}role_assignments ra
WHERE ra.roleid $gradebookroles
AND ra.contextid $relatedcontexts
) rainner ON rainner.userid = u.id
WHERE u.deleted = 0
AND g.itemid IN ($itemids)
$groupwheresql
ORDER BY $order, g.itemid ASC";
$this->grades_rs = get_recordset_sql($grades_sql);
} else {
+4 -4
View File
@@ -14,15 +14,15 @@ function set_row(idx) {
}
/** highlight/unset the column of a table **/
function set_col(col,gradecelloffset) {
function set_col(col,gradecelloffset,lastheaderrow) {
var table = document.getElementById('user-grades');
//highlight the column header
flip_vmarked(table,2,col);
flip_vmarked(table,lastheaderrow,col);
//add any grade cell offset (due to colspans) then iterate down the table
col += gradecelloffset;
for (var row = 3; row < table.rows.length; row++) {
for (var row = lastheaderrow + 1; row < table.rows.length; row++) {
flip_vmarked(table,row,col);
}
}
@@ -35,4 +35,4 @@ function flip_vmarked(table,row,col) {
table.rows[row].cells[col].className += ' vmarked';
}
}
}
}
+55 -47
View File
@@ -78,6 +78,10 @@ class grade_report_grader extends grade_report {
* */
var $canviewhidden;
/** @var boolean, whether the current user is allowed to see the user report.
* This affects the table layout. */
var $canviewuserreport;
var $preferences_page=false;
/**
@@ -93,6 +97,7 @@ class grade_report_grader extends grade_report {
parent::grade_report($courseid, $gpr, $context, $page);
$this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->course->id));
$this->canviewuserreport = has_capability('gradereport/'.$CFG->grade_profilereport.':view', $this->context);
// load collapsed settings for this report
if ($collapsed = get_user_preferences('grade_report_grader_collapsed_categories')) {
@@ -322,41 +327,38 @@ class grade_report_grader extends grade_report {
global $CFG;
if (is_numeric($this->sortitemid)) {
// the MAX() magic is required in order to please PG
$sort = "MAX(g.finalgrade) $this->sortorder";
$sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
FROM {$CFG->prefix}user u
JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id
$this->groupsql
LEFT JOIN {$CFG->prefix}grade_grades g ON (g.userid = u.id AND g.itemid = $this->sortitemid)
WHERE ra.roleid in ($this->gradebookroles) AND u.deleted = 0
$this->groupwheresql
AND ra.contextid ".get_related_contexts_string($this->context)."
GROUP BY u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
ORDER BY $sort";
$sortjoin = "LEFT JOIN {$CFG->prefix}grade_grades g ON " .
"g.userid = u.id AND g.itemid = $this->sortitemid";
$sort = "g.finalgrade $this->sortorder";
} else {
$sortjoin = '';
switch($this->sortitemid) {
case 'lastname':
$sort = "u.lastname $this->sortorder, u.firstname $this->sortorder"; break;
$sort = "u.lastname $this->sortorder, u.firstname $this->sortorder";
break;
case 'firstname':
$sort = "u.firstname $this->sortorder, u.lastname $this->sortorder"; break;
$sort = "u.firstname $this->sortorder, u.lastname $this->sortorder";
break;
case 'idnumber':
default:
$sort = "u.idnumber $this->sortorder"; break;
$sort = "u.idnumber $this->sortorder";
break;
}
$sql = "SELECT DISTINCT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
FROM {$CFG->prefix}user u
JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
$this->groupsql
WHERE ra.roleid in ($this->gradebookroles)
$this->groupwheresql
AND ra.contextid ".get_related_contexts_string($this->context)."
ORDER BY $sort";
}
$sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
FROM {$CFG->prefix}user u
$this->groupsql
$sortjoin
JOIN (
SELECT DISTINCT ra.userid
FROM {$CFG->prefix}role_assignments ra
WHERE ra.roleid IN ($this->gradebookroles)
AND ra.contextid " . get_related_contexts_string($this->context) . "
) rainner ON rainner.userid = u.id
WHERE u.deleted = 0
$this->groupwheresql
ORDER BY $sort";
$this->users = get_records_sql($sql, $this->get_pref('studentsperpage') * $this->page,
$this->get_pref('studentsperpage'));
@@ -662,14 +664,15 @@ class grade_report_grader extends grade_report {
//The width of the table varies depending on fixedstudents.
// $fixedstudents == 0, students and grades display in the same table.
// $fixedstudents == 1, students and grades are display in separate table.
if ($fixedstudents) {
if ($fixedstudents || !$this->canviewuserreport) {
$incrementcellindex = '0';
} else {
$incrementcellindex = '1';
}
//MDL-21088 - IE 7 ignores nowraps on tds or ths so we this in a span with a nowrap on it.
$headerhtml .= '<th class=" '.$columnclass.' '.$type.$catlevel.$hidden.'" scope="col" onclick="set_col(this.cellIndex,' . $incrementcellindex . ')"><span>'
.shorten_text($headerlink) . $arrow;
$headerhtml .= '<th class=" '.$columnclass.' '.$type.$catlevel.$hidden.
'" scope="col" onclick="set_col(this.cellIndex,' . $incrementcellindex . ',' . (count($this->gtree->levels) - 1) .
')"><span>' . shorten_text($headerlink) . $arrow;
$headerhtml .= '</span></th>';
}
@@ -745,7 +748,7 @@ class grade_report_grader extends grade_report {
//we're either going to add a th or a colspan to keep things aligned
$userreportcell = '';
$userreportcellcolspan = '';
if (has_capability('gradereport/'.$CFG->grade_profilereport.':view', $this->context)) {
if ($this->canviewuserreport) {
$a->user = fullname($user, $canviewfullname);
$strgradesforuser = get_string('gradesforuser', 'grades', $a);
$userreportcell = '<th class="header userreport"><a href="'.$CFG->wwwroot.'/grade/report/'.$CFG->grade_profilereport.'/index.php?id='.$this->courseid.'&amp;userid='.$user->id.'">'
@@ -1032,7 +1035,7 @@ class grade_report_grader extends grade_report {
//either add a th or a colspan to keep things aligned
$userreportcell = '';
$userreportcellcolspan = '';
if (has_capability('gradereport/'.$CFG->grade_profilereport.':view', $this->context)) {
if ($this->canviewuserreport) {
$a->user = fullname($user, $canviewfullname);
$strgradesforuser = get_string('gradesforuser', 'grades', $a);
$userreportcell = '<th class="userreport"><a href="'.$CFG->wwwroot.'/grade/report/'.$CFG->grade_profilereport.'/index.php?id='.$this->courseid.'&amp;userid='.$user->id.'">'
@@ -1146,20 +1149,24 @@ class grade_report_grader extends grade_report {
if ($showaverages) {
// find sums of all grade items in course
$SQL = "SELECT g.itemid, SUM(g.finalgrade) AS sum
$sql = "SELECT g.itemid, SUM(g.finalgrade) AS sum
FROM {$CFG->prefix}grade_items gi
JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
JOIN {$CFG->prefix}user u ON u.id = g.userid
JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id
JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
JOIN {$CFG->prefix}user u ON u.id = g.userid
$groupsql
WHERE gi.courseid = $this->courseid
AND ra.roleid in ($this->gradebookroles)
AND ra.contextid ".get_related_contexts_string($this->context)."
AND g.finalgrade IS NOT NULL
$groupwheresql
JOIN (
SELECT DISTINCT ra.userid
FROM {$CFG->prefix}role_assignments ra
WHERE ra.roleid IN ($this->gradebookroles)
AND ra.contextid " . get_related_contexts_string($this->context) . "
) rainner ON rainner.userid = u.id
WHERE gi.courseid = $this->courseid
AND u.deleted = 0
AND g.finalgrade IS NOT NULL
$groupwheresql
GROUP BY g.itemid";
$sum_array = array();
if ($sums = get_records_sql($SQL)) {
if ($sums = get_records_sql($sql)) {
foreach ($sums as $itemid => $csum) {
$sum_array[$itemid] = $csum->sum;
}
@@ -1171,20 +1178,21 @@ class grade_report_grader extends grade_report {
// MDL-10875 Empty grades must be evaluated as grademin, NOT always 0
// This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
$SQL = "SELECT gi.id, COUNT(u.id) AS count
$sql = "SELECT gi.id, COUNT(DISTINCT u.id) AS count
FROM {$CFG->prefix}grade_items gi
CROSS JOIN {$CFG->prefix}user u
JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id
LEFT OUTER JOIN {$CFG->prefix}grade_grades g ON (g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL)
JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id
LEFT OUTER JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL
$groupsql
WHERE gi.courseid = $this->courseid
AND ra.roleid in ($this->gradebookroles)
AND ra.contextid ".get_related_contexts_string($this->context)."
AND ra.roleid IN ($this->gradebookroles)
AND u.deleted = 0
AND ra.contextid " . get_related_contexts_string($this->context) . "
AND g.id IS NULL
$groupwheresql
GROUP BY gi.id";
$ungraded_counts = get_records_sql($SQL);
$ungraded_counts = get_records_sql($sql);
$fixedstudents = $this->is_fixed_students();
if (!$fixedstudents) {
+2 -1
View File
@@ -100,7 +100,8 @@ class grade_report_user extends grade_report {
$this->showpercentage = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage);
$this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
$this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
//comment this out to hide the range column on the user report. Control of this via a setting was added to 2.0 (MDL-20617)
$this->showrange = true;
$this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
+1 -1
View File
@@ -208,7 +208,7 @@
$subtext = get_string('subscribe', 'forum');
}
print_heading_block($newsforum->name);
echo '<div class="subscribelink"><a href="mod/forum/subscribe.php?id='.$newsforum->id.'">'.$subtext.'</a></div>';
echo '<div class="subscribelink"><a href="mod/forum/subscribe.php?id='.$newsforum->id.'&amp;sesskey='.sesskey().'">'.$subtext.'</a></div>';
} else {
print_heading_block($newsforum->name);
}
+1
View File
@@ -588,6 +588,7 @@ $string['performance'] = 'Performance';
$string['pgcluster'] = 'PostgreSQL Cluster';
$string['pgclusterdescription'] = 'PostgreSQL version/cluster parameter for command line operations. If you only have one postgresql on your system or you are not sure what this is, leave this blank.';
$string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please upgrade to 5.1.x or downgrade to 4.3.x or 4.4.x';
$string['php533warning'] = 'PHP 5.3.3 and upwards is recommended';
$string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - $a';
$string['pleaseregister'] = 'Please register your site to remove this button';
$string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on $a';
+9 -4
View File
@@ -36,9 +36,14 @@ $string['auth_nologintitle'] = 'No login';
$string['auth_cas_proxycas_key'] = "Proxy mode";
$string['auth_cas_logoutcas_key'] = "Logout CAS";
$string['auth_cas_multiauth_key'] = "Multi-authentication";
$string['auth_cas_proxycas'] = "Turn this to 'yes'' if you use CASin proxy-mode";
$string['auth_cas_logoutcas'] = "Turn this to 'yes'' if tou want to logout from CAS when you deconnect from Moodle";
$string['auth_cas_multiauth'] = "Turn this to 'yes'' if you want to have multi-authentication (CAS + other authentication)";
$string['auth_cas_certificate_check_key'] = "Server validation";
$string['auth_cas_certificate_path_key'] = "Certificate path";
$string['auth_cas_proxycas'] = "Turn this to ''yes'' if you use CASin proxy-mode";
$string['auth_cas_logoutcas'] = "Turn this to ''yes'' if tou want to logout from CAS when you deconnect from Moodle";
$string['auth_cas_multiauth'] = "Turn this to ''yes'' if you want to have multi-authentication (CAS + other authentication)";
$string['auth_cas_certificate_check'] = "Turn this to ''yes'' if you want to validate the server certificate";
$string['auth_cas_certificate_path'] = "Path of the CA chain file (PEM Format) to validate the server certificate";
$string['auth_cas_certificate_path_empty'] = "If you turn on Server validation, you need to specify a certificate path";
$string['accesCAS'] = "CAS users";
$string['accesNOCAS'] = "other users";
$string['CASform'] = "Authentication choice";
@@ -255,7 +260,7 @@ $string['auth_ntlmsso_enabled'] = 'Set to yes to attempt Single Sign On with the
$string['auth_ntlmsso_ie_fastpath'] = 'Set to yes to enable the NTLM SSO fast path (bypasses certain steps and only works if the client\'s browser is MS Internet Explorer).';
$string['auth_ntlmsso_ie_fastpath_key'] = 'MS IE fast path?';
$string['auth_ntlmsso_subnet_key'] = 'Subnet';
$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask';
$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask. Separate multiple subnets with \',\' (comma).';
$string['ntlmsso_attempting'] = 'Attempting Single Sign On via NTLM...';
$string['ntlmsso_failed'] = 'Auto-login failed, try the normal login page...';
$string['ntlmsso_isdisabled'] = 'NTLM SSO is disabled.';
+3 -1
View File
@@ -47,6 +47,8 @@ $string['configreplytouser'] = 'When a forum post is mailed out, should it conta
$string['configshortpost'] = 'Any post under this length (in characters not including HTML) is considered short (see below).';
$string['configtrackreadposts'] = 'Set to \'yes\' if you want to track read/unread for each user.';
$string['configusermarksread'] = 'If \'yes\', the user must manually mark a post as read. If \'no\', when the post is viewed it is marked as read.';
$string['confirmsubscribe'] = 'Do you really want to subscribe to forum \'{$a}\'?';
$string['confirmunsubscribe'] = 'Do you really want to unsubscribe from forum \'{$a}\'?';
$string['couldnotadd'] = 'Could not add your post due to an unknown error';
$string['couldnotdeleteratings'] = 'Sorry, that cannot be deleted as people have already rated it';
$string['couldnotdeletereplies'] = 'Sorry, that cannot be deleted as people have already responded to it';
@@ -92,7 +94,7 @@ $string['forum'] = 'Forum';
$string['forum:addnews'] = 'Add news';
$string['forumauthorhidden'] = 'Author (hidden)';
$string['forumblockingalmosttoomanyposts'] = 'You are approaching the posting threshold. You have posted $a->numposts times in the last $a->blockperiod and the limit is $a->blockafter posts.';
$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion yet.';
$string['forumbodyhidden'] = 'This post cannot be viewed by you, probably because you have not posted in the discussion or the maximum editing time hasn\'t passed yet.';
$string['forum:createattachment'] = 'Create attachments';
$string['forum:deleteanypost'] = 'Delete any posts (anytime)';
$string['forum:deleteownpost'] = 'Delete own posts (within deadline)';
+1
View File
@@ -12,6 +12,7 @@ $string['allowcomments'] = 'Allow comments on entries';
$string['allowduplicatedentries'] = 'Duplicated entries allowed';
$string['allowprintview'] = 'Allow print view';
$string['allowratings'] = 'Allow entries to be rated?';
$string['andmorenewentries'] = 'and {$a} more new entries.';
$string['answer'] = 'Answer';
$string['approve'] = 'Approve';
$string['areyousuredelete'] = 'Are you sure you want to delete this entry?';
+3
View File
@@ -9,5 +9,8 @@ $string['flashvideo'] = 'Flash video';
$string['mp3audio'] = 'MP3 audio';
$string['oggaudio'] = 'OGG audio';
$string['ogvvideo'] = 'OGV video';
$string['quicktime'] = 'Quicktime';
$string['realaudio'] = 'Real audio';
$string['wmpvideo'] = 'WMP video';
$string['unsupportedplugins'] = '(The browser does not support this type of file. {$a})';
?>
+1 -1
View File
@@ -5011,7 +5011,7 @@ function sort_by_roleassignment_authority($users, $context, $roles=array(), $sor
* @param bool gethidden - whether to fetch hidden enrolments too
* @return array()
*/
function get_role_users($roleid, $context, $parent=false, $fields='', $sort='u.lastname ASC', $gethidden=true, $group='', $limitfrom='', $limitnum='') {
function get_role_users($roleid, $context, $parent=false, $fields='', $sort='u.lastname ASC, u.firstname ASC', $gethidden=true, $group='', $limitfrom='', $limitnum='') {
global $CFG;
if (empty($fields)) {
+2 -2
View File
@@ -1,4 +1,4 @@
<?php
<?php
/*
Bulgarian language, v1.0, 25.03.2004, encoding by UTF-8 charset
contributed by Valentin Sheiretsky <valio#valio.eu.org>
@@ -34,4 +34,4 @@ $ADODB_LANG_ARRAY = array (
DB_ERROR_NOSUCHDB => 'несъществуваща база данни',
DB_ERROR_ACCESS_VIOLATION => 'нямате достатъчно права'
);
?>
?>
+9 -7
View File
@@ -94,8 +94,8 @@ section_class.prototype.init_buttons = function() {
commandContainer.appendChild(highlightbutton);
this.highlightButton = highlightbutton;
}
if (this.sectionId > 0 ) {
if (this.sectionId > 0 ) {
var viewbutton = main.mk_button('div', '/i/hide.gif', main.getString('hidesection', this.sectionId), [['title', main.portal.strings['hide'] ]]);
YAHOO.util.Event.addListener(viewbutton, 'click', this.toggle_hide, this,true);
commandContainer.appendChild(viewbutton);
@@ -141,12 +141,12 @@ section_class.prototype.process_section = function() {
// Find/edit resources
this.resources_ul = this.content_td.getElementsByTagName('ul')[0];
var i=0;
while (this.resources_ul && this.resources_ul.className != 'section img-text') {
var i=0;
while (this.resources_ul && this.resources_ul.className != 'section img-text') {
this.resources_ul = this.content_td.getElementsByTagName('ul')[i];
i++;
}
if (!this.resources_ul) {
this.resources_ul = document.createElement('ul');
this.resources_ul.className='section';
@@ -158,10 +158,12 @@ section_class.prototype.process_section = function() {
var resource = this.resources_ul.getElementsByTagName('li')[i];
this.resources[this.resources.length] = new resource_class(resource.id, 'resources', null, this);
}
this.summary = YAHOO.util.Dom.getElementsByClassName('summary', null, this.getEl())[0].firstChild.data || '';
var summarysection = YAHOO.util.Dom.getElementsByClassName('summary', null, this.getEl())[0].firstChild;
if (summarysection != null) {
this.summary = summarysection.data || '';
}
}
section_class.prototype.startDrag = function(x, y) {
//operates in point mode
YAHOO.util.DDM.mode = YAHOO.util.DDM.POINT;
+8
View File
@@ -54,4 +54,12 @@ function php_check_register_globals($result) {
return $result;
}
function php_check_php533($result) {
if (version_compare(phpversion(), '5.3.3') < 0) {
$result->status = false;
} else {
$result = null;
}
return $result;
}
?>
+3
View File
@@ -933,6 +933,9 @@
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="userfieldidx" UNIQUE="false" FIELDS="userid, fieldid"/>
</INDEXES>
</TABLE>
<TABLE NAME="mnet_enrol_course" COMMENT="Information about courses on remote hosts" PREVIOUS="user_info_data" NEXT="mnet_enrol_assignments">
<FIELDS>
+17
View File
@@ -3351,6 +3351,23 @@ function xmldb_main_upgrade($oldversion=0) {
set_config('filter_mediaplugin_enable_ogg', 1);
upgrade_main_savepoint($result, 2007101590.01);
}
if ($result && $oldversion < 2007101591.01) {
/// Define index userfieldidx (not unique) to be added to user_info_data
$table = new XMLDBTable('user_info_data');
$index = new XMLDBIndex('userfieldidx');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('userid', 'fieldid'));
/// Launch add index userfieldidx
if (!index_exists($table, $index)) {
$result = $result && add_index($table, $index);
}
/// Main savepoint reached
upgrade_main_savepoint($result, 2007101591.01);
}
return $result;
}
+4
View File
@@ -2371,6 +2371,7 @@ HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
HTMLArea.is_gecko = (navigator.product == "Gecko");
HTMLArea.is_safari = (HTMLArea.agt.indexOf("safari") != -1);
HTMLArea.is_webkit = (HTMLArea.agt.indexOf("applewebkit") != -1); // eg: chrome
// variable used to pass the object to the popup editor window.
HTMLArea._object = null;
@@ -2398,6 +2399,9 @@ HTMLArea.cloneObject = function(obj) {
// FIXME!!! this should return false for IE < 5.5
HTMLArea.checkSupportedBrowser = function() {
if (HTMLArea.is_webkit) {
return true;
}
if (HTMLArea.is_gecko) {
if (navigator.productSub < 20021201) {
alert("You need at least Mozilla-1.3 Alpha.\n" +
@@ -3,6 +3,7 @@
require("../../../../config.php");
$id = optional_param('id', SITEID, PARAM_INT);
$httpsrequired = optional_param('httpsrequired', 0, PARAM_BOOL);
require_login($id);
require_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $id));
@@ -2,8 +2,10 @@
require("../../../../config.php");
$id = optional_param('id', SITEID, PARAM_INT);
$httpsrequired = optional_param('httpsrequired', 0, PARAM_BOOL);
require_course_login($id);
@header('Content-Type: text/html; charset=utf-8');
if ($httpsrequired or (!empty($_SERVER['HTTPS']) and $_SERVER['HTTPS'] != 'off')) {
+17 -2
View File
@@ -122,7 +122,16 @@ class MoodleExcelWorksheet {
*/
function MoodleExcelWorksheet($name, &$workbook, $latin_output=false) {
/// Internally, add one sheet to the workbook
if (strlen($name) > 31) {
// Excel does not seem able to cope with sheet names > 31 chars.
// With $latin_output = false, it does not cope at all.
// With $latin_output = true it is supposed to work, but in our experience,
// it doesn't. Therefore, truncate in all circumstances.
$textlib = textlib_get_instance();
$name = $textlib->substr($name, 0, 31);
}
/// Internally, add one sheet to the workbook
$this->pear_excel_worksheet =& $workbook->addWorksheet($name);
$this->latin_output = $latin_output;
/// Set encoding to UTF-16LE
@@ -196,7 +205,13 @@ class MoodleExcelWorksheet {
$format = $this->MoodleExcelFormat2PearExcelFormat($format);
/// Convert the date to Excel format
$timezone = get_user_timezone_offset();
$value = ((usertime($date) + (int)($timezone * HOURSECS * 2)) / 86400) + 25569;
if ($timezone == 99) {
// system timezone offset in seconds
$offset = (int)date('Z');
} else {
$offset = (int)($timezone * HOURSECS * 2);
}
$value = ((usertime($date) + $offset) / 86400) + 25569;
/// Add the date safely to the PEAR Worksheet
$this->pear_excel_worksheet->writeNumber($row, $col, $value, $format);
}
+4 -2
View File
@@ -656,12 +656,14 @@ class moodleform {
/**
* Adds a link/button that controls the checked state of a group of checkboxes.
* @param int $groupid The id of the group of advcheckboxes this element controls
* @param string $text The text of the link. Defaults to "select all/none"
* @param string $text The text of the link. Defaults to selectallornone ("select all/none")
* @param array $attributes associative array of HTML attributes
* @param int $originalValue The original general state of the checkboxes before the user first clicks this element
*/
function add_checkbox_controller($groupid, $buttontext, $attributes, $originalValue = 0) {
function add_checkbox_controller($groupid, $text = null, $attributes = null, $originalValue = 0) {
global $CFG;
// Set the default text if none was specified
if (empty($text)) {
$text = get_string('selectallornone', 'form');
}
+3 -2
View File
@@ -173,13 +173,14 @@ class grade_object {
$wheresql = implode("AND", $wheresql);
}
if ($datas = get_records_select($table, $wheresql, 'id')) {
if ($rs = get_recordset_select($table, $wheresql, 'id')) {
$result = array();
foreach($datas as $data) {
while ($data = rs_fetch_next_record($rs)) {
$instance = new $classname();
grade_object::set_properties($instance, $data);
$result[$instance->id] = $instance;
}
rs_close($rs);
return $result;
} else {
+1 -1
View File
@@ -157,7 +157,7 @@ function groups_get_user_groups($courseid, $userid=0) {
$result = array();
$allgroups = array();
while ($group = rs_fetch_next_record($rs)) {
$allgroups[$group->id] = $group->id;
if (is_null($group->groupingid)) {
+2 -4
View File
@@ -589,10 +589,8 @@ class html2text
*/
function _strtoupper($str)
{
if (function_exists('mb_strtoupper'))
return mb_strtoupper($str);
else
return strtoupper($str);
$tl = textlib_get_instance();
return $tl->strtoupper($str);
}
}
+22 -1
View File
@@ -60,4 +60,25 @@ index b7e3e3e..96ef508 100644
}
}
-- Tim Hunt 2010-08-04
-- Tim Hunt 2010-08-04
3- Use textlib, not crappy functions that break UTF-8, in the _strtoupper method.
Index: lib/html2text.php
--- lib/html2text.php 2 Sep 2010 12:49:29 -0000 1.16
+++ lib/html2text.php 2 Nov 2010 19:57:09 -0000
@@ -580,9 +580,7 @@
*/
function _strtoupper($str)
{
- if (function_exists('mb_strtoupper'))
- return mb_strtoupper($str);
- else
- return strtoupper($str);
+ $tl = textlib_get_instance();
+ return $tl->strtoupper($str);
}
}
-- Tim Hunt 2010-11-02
+30 -11
View File
@@ -567,8 +567,12 @@ function clean_param($param, $type) {
}
case PARAM_TAG:
// Please note it is not safe to use the tag name directly anywhere,
// it must be processed with s(), urlencode() before embedding anywhere.
// remove some nasties
$param = preg_replace('~[[:cntrl:]]|[<>`]~u', '', $param);
//as long as magic_quotes_gpc is used, a backslash will be a
//problem, so remove *all* backslash.
//problem, so remove *all* backslash - BUT watch out for SQL injections caused by this sloppy design (skodak)
$param = str_replace('\\', '', $param);
//convert many whitespace chars into one
$param = preg_replace('/\s+/', ' ', $param);
@@ -576,7 +580,6 @@ function clean_param($param, $type) {
$param = $textlib->substr(trim($param), 0, TAG_MAX_LENGTH);
return $param;
case PARAM_TAGLIST:
$tags = explode(',', $param);
$result = array();
@@ -2978,7 +2981,7 @@ function create_user_record($username, $password, $auth='manual') {
$newuser->mnethostid = $CFG->mnet_localhost_id;
if (insert_record('user', $newuser)) {
$user = get_complete_user_data('username', $newuser->username);
$user = get_complete_user_data('username', $newuser->username, $CFG->mnet_localhost_id);
if(!empty($CFG->{'auth_'.$newuser->auth.'_forcechangepassword'})){
set_user_preference('auth_forcepasswordchange', 1, $user->id);
}
@@ -2995,17 +2998,19 @@ function create_user_record($username, $password, $auth='manual') {
* @param string $username New user's username to add to record
* @return user A {@link $USER} object
*/
function update_user_record($username, $authplugin) {
function update_user_record($username, $unused) {
global $CFG;
$username = trim(moodle_strtolower($username)); /// just in case check text case
$oldinfo = get_record('user', 'username', $username, '','','','', 'username, auth');
$oldinfo = get_record('user', 'username', $username, 'mnethostid', $CFG->mnet_localhost_id, '','', 'id, username, auth');
$userauth = get_auth_plugin($oldinfo->auth);
if ($newinfo = $userauth->get_userinfo($username)) {
$newinfo = truncate_userinfo($newinfo);
foreach ($newinfo as $key => $value){
if ($key === 'username') {
// 'username' is not a mapped updateable/lockable field, so skip it.
if ($key === 'username' or $key === 'id' or $key === 'auth' or $key === 'mnethostid' or $key === 'deleted') {
// these fields must not be changed
continue;
}
$confval = $userauth->config->{'field_updatelocal_' . $key};
@@ -3022,14 +3027,14 @@ function update_user_record($username, $authplugin) {
// nothing_ for this field. Thus it makes sense to let this value
// stand in until LDAP is giving a value for this field.
if (!(empty($value) && $lockval === 'unlockedifempty')) {
set_field('user', $key, $value, 'username', $username)
set_field('user', $key, $value, 'id', $oldinfo->id)
|| error_log("Error updating $key for $username");
}
}
}
}
return get_complete_user_data('username', $username);
return get_complete_user_data('username', $username, $CFG->mnet_localhost_id);
}
function truncate_userinfo($info) {
@@ -6417,13 +6422,25 @@ function check_php_version($version='4.1.0') {
}
break;
case 'Chrome':
if (preg_match("/Chrome\/(.*)[ ]+/i", $agent, $match)) {
if (version_compare($match[1], $version) >= 0) {
return true;
}
}
break;
case 'Safari': /// Safari
// Look for AppleWebKit, excluding strings with OmniWeb, Shiira and SimbianOS
// Look for AppleWebKit, excluding strings with OmniWeb, Shiira and SymbianOS
if (strpos($agent, 'OmniWeb')) { // Reject OmniWeb
return false;
} elseif (strpos($agent, 'Shiira')) { // Reject Shiira
return false;
} elseif (strpos($agent, 'SimbianOS')) { // Reject SimbianOS
} elseif (strpos($agent, 'SymbianOS')) { // Reject SymbianOS
return false;
}
if (strpos($agent, 'iPhone') or strpos($agent, 'iPad') or strpos($agent, 'iPod')) {
// No Apple mobile devices here - editor does not work, course ajax is not touch compatible, etc.
return false;
}
@@ -6520,6 +6537,8 @@ function can_use_html_editor() {
return 'MSIE';
} else if (check_browser_version('Gecko', 20030516)) {
return 'Gecko';
} else if (check_browser_version('Safari', 531)) {
return 'AppleWebKit';
}
}
return false;
+3 -3
View File
@@ -517,7 +517,7 @@ function question_delete_course($course, $feedback=true) {
//Cache some strings
$strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
$categoriescourse = get_records('question_categories', 'contextid', $coursecontext->id, 'parent', 'id, parent, name');
$categoriescourse = get_records('question_categories', 'contextid', $coursecontext->id, 'parent', 'id, parent, name, contextid');
if ($categoriescourse) {
@@ -676,7 +676,7 @@ function question_delete_activity($cm, $feedback=true) {
//Cache some strings
$strcatdeleted = get_string('unusedcategorydeleted', 'quiz');
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
if ($categoriesmods = get_records('question_categories', 'contextid', $modcontext->id, 'parent', 'id, parent, name')){
if ($categoriesmods = get_records('question_categories', 'contextid', $modcontext->id, 'parent', 'id, parent, name, contextid')){
//Sort categories following their tree (parent-child) relationships
//this will make the feedback more readable
$categoriesmods = sort_categories_by_tree($categoriesmods);
@@ -1796,7 +1796,7 @@ function sort_categories_by_tree(&$categories, $id = 0, $level = 1) {
if ($level == 1) {
foreach ($keys as $key) {
//If not processed and it's a good candidate to start (because its parent doesn't exist in the course)
if (!isset($categories[$key]->processed) && !record_exists('question_categories', 'course', $categories[$key]->course, 'id', $categories[$key]->parent)) {
if (!isset($categories[$key]->processed) && !record_exists('question_categories', 'contextid', $categories[$key]->contextid, 'id', $categories[$key]->parent)) {
$children[$key] = $categories[$key];
$categories[$key]->processed = true;
$children = $children + sort_categories_by_tree($categories, $children[$key]->id, $level+1);
+6 -5
View File
@@ -177,7 +177,7 @@ function rss_standard_header($title = NULL, $link = NULL, $description = NULL) {
//write image info
$rsspix = $CFG->pixpath."/i/rsssitelogo.gif";
//write the info
//write the info
$result .= rss_start_tag('image', 2, true);
$result .= rss_full_tag('url', 3, false, $rsspix);
$result .= rss_full_tag('title', 3, false, 'moodle');
@@ -226,10 +226,10 @@ function rss_add_items($items) {
$result .= rss_full_tag('link',3,false,$item->link);
$result .= rss_add_enclosures($item);
$result .= rss_full_tag('pubDate',3,false,gmdate('D, d M Y H:i:s',$item->pubdate).' GMT'); # MDL-12563
//Include the author if exists
//Include the author if exists
if (isset($item->author)) {
//$result .= rss_full_tag('author',3,false,$item->author);
//We put it in the description instead because it's more important
//We put it in the description instead because it's more important
//for moodle than most other feeds, and most rss software seems to ignore
//the author field ...
$item->description = get_string('byname','',$item->author).'. &nbsp;<p>'.$item->description.'</p>';
@@ -415,7 +415,7 @@ function rss_display_feeds($courseid, $userid, $rssid='', $context) {
$feedicons = '<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=rssedit&amp;rssid='. $feed->id .'&amp;shared='.$feed->shared.'&amp;blogid='. $blogid .'">'.
'<img src="'. $CFG->pixpath .'/t/edit.gif" alt="'. get_string('edit').'" title="'. get_string('edit') .'" /></a>&nbsp;'.
'<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=delfeed&amp;rssid='. $feed->id.'&amp;shared='.$feed->shared.'blogid='. $blogid .'"
'<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=delfeed&amp;sesskey='.sesskey().'&amp;rssid='. $feed->id.'&amp;shared='.$feed->shared.'blogid='. $blogid .'"
onclick="return confirm(\''. get_string('deletefeedconfirm', 'block_rss_client') .'\');">'.
'<img src="'. $CFG->pixpath .'/t/delete.gif" alt="'. get_string('delete').'" title="'. get_string('delete') .'" /></a>';
}
@@ -519,6 +519,7 @@ function rss_get_form($act='none', $url='', $rssid='', $preferredtitle='', $shar
$returnstring .= '<input type="hidden" name="id" value="'. $courseid .'" />'."\n";
$returnstring .= '<input type="hidden" name="blogid" value="'. $blogid .'" />'."\n";
$returnstring .= '<input type="hidden" name="user" value="'. $USER->id .'" />'."\n";
$returnstring .= '<input type="hidden" name="sesskey" value="'. sesskey() .'" />'."\n";
$returnstring .= '<br /><input type="submit" value="';
$validatestring = "<a href=\"#\" onclick=\"window.open('http://feedvalidator.org/check.cgi?url='+getElementById('block_rss').elements['url'].value,'validate','width=640,height=480,scrollbars=yes,status=yes,resizable=yes');return true;\">". get_string('validatefeed', 'block_rss_client')."</a>";
@@ -530,7 +531,7 @@ function rss_get_form($act='none', $url='', $rssid='', $preferredtitle='', $shar
$returnstring .= '" />&nbsp;'. $validatestring ."\n";
$returnstring .= '</div></form>'."\n";
return $returnstring;
}
+4
View File
@@ -251,5 +251,9 @@ END;
$long = "Here is a long string, more than 75 characters long, since by default html_to_text wraps text at 75 chars.";
$this->assertEqual($long, html_to_text($long, 0));
}
public function test_html_to_text_dont_screw_up_utf8() {
$this->assertEqual("\n\nAll the WORLDS a stage.", html_to_text('<p>All the <strong>worlds</strong> a stage.</p>'));
}
}
?>
+20 -12
View File
@@ -216,33 +216,41 @@ function get_referer($stripquery=true) {
*
* @return string
*/
function me() {
function me() {
if (!empty($_SERVER['REQUEST_URI'])) {
return $_SERVER['REQUEST_URI'];
$return = $_SERVER['REQUEST_URI'];
} else if (!empty($_SERVER['PHP_SELF'])) {
if (!empty($_SERVER['QUERY_STRING'])) {
return $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING'];
$return = $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING'];
} else {
$return = $_SERVER['PHP_SELF'];
}
return $_SERVER['PHP_SELF'];
} else if (!empty($_SERVER['SCRIPT_NAME'])) {
if (!empty($_SERVER['QUERY_STRING'])) {
return $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING'];
$return = $_SERVER['SCRIPT_NAME'] .'?'. $_SERVER['QUERY_STRING'];
} else {
$return = $_SERVER['SCRIPT_NAME'];
}
return $_SERVER['SCRIPT_NAME'];
} else if (!empty($_SERVER['URL'])) { // May help IIS (not well tested)
if (!empty($_SERVER['QUERY_STRING'])) {
return $_SERVER['URL'] .'?'. $_SERVER['QUERY_STRING'];
$return = $_SERVER['URL'] .'?'. $_SERVER['QUERY_STRING'];
} else {
$return = $_SERVER['URL'];
}
return $_SERVER['URL'];
} else {
notify('Warning: Could not find any of these web server variables: $REQUEST_URI, $PHP_SELF, $SCRIPT_NAME or $URL');
return false;
}
// sanitize the url a bit more, the encoding style may be different in vars above
$return = str_replace('"', '%22', $return);
$return = str_replace('\'', '%27', $return);
return $return;
}
/**
@@ -1502,7 +1510,7 @@ function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL
static $croncache = array();
if ($text === '') {
if ($text === '' || is_null($text)) {
return ''; // no need to do any filters and cleaning
}
@@ -2757,9 +2765,9 @@ function print_header ($title='', $heading='', $navigation='', $focus='',
$pageclass .= ' dir-'.get_string('thisdirection');
$pageclass .= ' lang-'.$currentlanguage;
$pageclass .= ' lang-'.s($currentlanguage);
$bodytags .= ' class="'.$pageclass.'" id="'.$pageid.'"';
$bodytags .= ' class="'.s($pageclass).'" id="'.s($pageid).'"';
ob_start();
include($CFG->header);
+1 -1
View File
@@ -179,7 +179,7 @@ httpsrequired();
$urltogo = $CFG->wwwroot.'/user/edit.php';
// We don't delete $SESSION->wantsurl yet, so we get there later
} else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0)) {
} else if (isset($SESSION->wantsurl) and (strpos($SESSION->wantsurl, $CFG->wwwroot) === 0 or strpos($SESSION->wantsurl, str_replace('http://', 'https://', $CFG->wwwroot)) === 0)) {
$urltogo = $SESSION->wantsurl; /// Because it's an address in this site
unset($SESSION->wantsurl);
+10 -3
View File
@@ -149,7 +149,7 @@ class mnet_xmlrpc_client {
// Find methods that we subscribe to on this host
$sql = "
SELECT
*
r.id
FROM
{$CFG->prefix}mnet_rpc r,
{$CFG->prefix}mnet_service2rpc s2r,
@@ -161,8 +161,7 @@ class mnet_xmlrpc_client {
h2s.subscribe = '1' AND
h2s.hostid in ({$id_list})";
$permission = get_record_sql($sql);
if ($permission == false) {
if (!record_exists_sql($sql)) {
global $USER;
$this->error[] = '7:User with ID '. $USER->id .
' attempted to call unauthorised method '.
@@ -333,6 +332,14 @@ class mnet_xmlrpc_client {
$this->error[] = $this->response['faultCode'] . " : " . $this->response['faultString'];
}
}
// ok, it's signed, but is it signed with the right certificate ?
// do this *after* we check for an out of date key
if (!openssl_verify($this->xmlrpcresponse, base64_decode($sig_parser->signature),
$mnet_peer->public_key)) {
$this->error[] = 'Invalid signature';
}
return empty($this->error);
}
}
@@ -591,7 +591,7 @@ class assignment_upload extends assignment_base {
require_once($CFG->dirroot.'/lib/uploadlib.php');
$um = new upload_manager('newfile',false,true,$this->course,false,$this->assignment->maxbytes,true);
if ($um->process_file_uploads($dir)) {
if ($um->process_file_uploads($dir) and confirm_sesskey()) {
$submission = $this->get_submission($USER->id, true); //create new submission if needed
$updated = new object();
$updated->id = $submission->id;
+3 -3
View File
@@ -113,17 +113,18 @@ class data_field_checkbox extends data_field_base {
}
return array('checked'=>$selected, 'allrequired'=>$allrequired);
}
function generate_sql($tablealias, $value) {
$allrequired = $value['allrequired'];
$selected = $value['checked'];
$varcharcontent = sql_compare_text("{$tablealias}.content", 255);
if ($selected) {
$conditions = array();
foreach ($selected as $sel) {
$likesel = str_replace('%', '\%', $sel);
$likeselsel = str_replace('_', '\_', $likesel);
$conditions[] = "({$tablealias}.fieldid = {$this->field->id} AND ({$tablealias}.content = '$sel'
$conditions[] = "({$tablealias}.fieldid = {$this->field->id} AND ($varcharcontent = '$sel'
OR {$tablealias}.content LIKE '$likesel##%'
OR {$tablealias}.content LIKE '%##$likesel'
OR {$tablealias}.content LIKE '%##$likesel##%'))";
@@ -138,7 +139,6 @@ class data_field_checkbox extends data_field_base {
}
}
function update_content($recordid, $value, $name='') {
$content = new object();
$content->fieldid = $this->field->id;
+1 -1
View File
@@ -111,7 +111,7 @@ class data_field_file extends data_field_base {
$oldcontent = new object;
$oldcontent->fieldid = $this->field->id;
$oldcontent->recordid = $recordid;
if ($oldcontent->id = insert_record('data_content', $oldcontent)) {
if (!$oldcontent->id = insert_record('data_content', $oldcontent)) {
error('Could not make an empty record!');
}
}
+14 -10
View File
@@ -70,17 +70,19 @@ class data_field_latlong extends data_field_base {
function display_search_field($value = '') {
global $CFG;
$lats = get_records_sql_menu('SELECT id, content from '.$CFG->prefix.'data_content WHERE fieldid='.$this->field->id.' GROUP BY content ORDER BY content');
$longs = get_records_sql_menu('SELECT id, content1 from '.$CFG->prefix.'data_content WHERE fieldid='.$this->field->id.' GROUP BY content ORDER BY content');
$varcharlat = sql_compare_text('content');
$varcharlong= sql_compare_text('content1');
$latlongsrs = get_recordset_sql(
"SELECT DISTINCT $varcharlat AS la, $varcharlong AS lo
FROM {$CFG->prefix}data_content
WHERE fieldid = {$this->field->id}
ORDER BY $varcharlat, $varcharlong");
$options = array();
if(!empty($lats) && !empty($longs)) {
$options[''] = '';
// Make first index blank.
foreach($lats as $key => $temp) {
$options[$temp.','.$longs[$key]] = $temp.','.$longs[$key];
}
while ($latlong = rs_fetch_next_record($latlongsrs)) {
$options[$latlong->la . ',' . $latlong->lo] = $latlong->la . ',' . $latlong->lo;
}
return choose_from_menu($options, 'f_'.$this->field->id, $value, 'choose', '', 0, true);
rs_close($latlongsrs);
return choose_from_menu($options, 'f_'.$this->field->id, $value, 'choose', '', 0, true);
}
function parse_search_field() {
@@ -91,7 +93,9 @@ class data_field_latlong extends data_field_base {
$latlong[0] = '';
$latlong[1] = '';
$latlong = explode (',', $value, 2);
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content = '$latlong[0]' AND {$tablealias}.content1 = '$latlong[1]') ";
$varcharlat = sql_compare_text("{$tablealias}.content");
$varcharlong= sql_compare_text("{$tablealias}.content1");
return " ({$tablealias}.fieldid = {$this->field->id} AND $varcharlat = '$latlong[0]' AND $varcharlong = '$latlong[1]') ";
}
function display_browse_field($recordid, $template) {
+1 -1
View File
@@ -29,7 +29,7 @@
<option value="-2"<?php if($this->field->param2==-2) echo ' selected="selected"' ?>><?php echo get_string('latitude', 'data').'/'.get_string('longitude', 'data') ?></option>
<?php
// Fetch all "suitable" other fields that exist for this database
$textfields = get_records_select('data_fields', 'dataid='.$this->data->id.' AND type="text"');
$textfields = get_records_select('data_fields', 'dataid='.$this->data->id." AND type='text'");
echo '<optgroup label="'.get_string('latlongotherfields', 'data').':">';
if(sizeof($textfields)>0) {
foreach($textfields as $textfield) {
+8 -5
View File
@@ -56,14 +56,16 @@ class data_field_menu extends data_field_base {
return $str;
}
function display_search_field($content = '') {
global $CFG;
$usedoptions = array();
$sql = "SELECT DISTINCT content
$varcharcontent = sql_compare_text('content', 255);
$sql = "SELECT DISTINCT $varcharcontent AS content
FROM {$CFG->prefix}data_content
WHERE fieldid={$this->field->id} AND content IS NOT NULL";
$usedoptions = array();
if ($used = get_records_sql($sql)) {
foreach ($used as $data) {
$value = $data->content;
@@ -87,7 +89,7 @@ class data_field_menu extends data_field_base {
return '';
}
return choose_from_menu($options, 'f_'.$this->field->id, stripslashes($content), '&nbsp;', '', 0, true);
return choose_from_menu($options, 'f_'.$this->field->id, stripslashes($content), 'choose', '', 0, true);
}
function parse_search_field() {
@@ -95,7 +97,8 @@ class data_field_menu extends data_field_base {
}
function generate_sql($tablealias, $value) {
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content = '$value') ";
$varcharcontent = sql_compare_text("{$tablealias}.content", 255);
return " ({$tablealias}.fieldid = {$this->field->id} AND $varcharcontent = '$value') ";
}
}
+6 -3
View File
@@ -78,10 +78,12 @@ class data_field_multimenu extends data_field_base {
$str = '<select name="f_'.$this->field->id.'[]" multiple="multiple">';
// display only used options
$usedoptions = array();
$sql = "SELECT DISTINCT content
$varcharcontent = sql_compare_text('content', 255);
$sql = "SELECT DISTINCT $varcharcontent AS content
FROM {$CFG->prefix}data_content
WHERE fieldid={$this->field->id} AND content IS NOT NULL";
$usedoptions = array();
if ($used = get_records_sql($sql)) {
foreach ($used as $data) {
$valuestr = $data->content;
@@ -138,13 +140,14 @@ class data_field_multimenu extends data_field_base {
function generate_sql($tablealias, $value) {
$allrequired = $value['allrequired'];
$selected = $value['selected'];
$varcharcontent = sql_compare_text("{$tablealias}.content", 255);
if ($selected) {
$conditions = array();
foreach ($selected as $sel) {
$likesel = str_replace('%', '\%', $sel);
$likeselsel = str_replace('_', '\_', $likesel);
$conditions[] = "({$tablealias}.fieldid = {$this->field->id} AND ({$tablealias}.content = '$sel'
$conditions[] = "({$tablealias}.fieldid = {$this->field->id} AND ($varcharcontent = '$sel'
OR {$tablealias}.content LIKE '$likesel##%'
OR {$tablealias}.content LIKE '%##$likesel'
OR {$tablealias}.content LIKE '%##$likesel##%'))";
+3 -3
View File
@@ -76,10 +76,10 @@ class data_field_number extends data_field_base {
function parse_search_field() {
return optional_param('f_'.$this->field->id, '', PARAM_NOTAGS);
}
// need to cast?
function generate_sql($tablealias, $value) {
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content = '$value') ";
$varcharcontent = sql_compare_text("{$tablealias}.content");
return " ({$tablealias}.fieldid = {$this->field->id} AND $varcharcontent = '$value') ";
}
function get_sort_sql($fieldname) {
+15 -8
View File
@@ -66,15 +66,21 @@ class data_field_radiobutton extends data_field_base {
$str .= '</div>';
return $str;
}
function display_search_field($value = '') {
global $CFG;
$temp = get_records_sql_menu('SELECT id, content from '.$CFG->prefix.'data_content WHERE fieldid='.$this->field->id.' GROUP BY content ORDER BY content');
$varcharcontent = sql_compare_text('content', 255);
$used = get_records_sql(
"SELECT DISTINCT $varcharcontent AS content
FROM {$CFG->prefix}data_content
WHERE fieldid={$this->field->id}
ORDER BY $varcharcontent");
$options = array();
if(!empty($temp)) {
$options[''] = ''; //Make first index blank.
foreach ($temp as $key) {
$options[$key] = $key; //Build following indicies from the sql.
if(!empty($used)) {
foreach ($used as $rec) {
$options[$rec->content] = $rec->content; //Build following indicies from the sql.
}
}
return choose_from_menu($options, 'f_'.$this->field->id, $value, 'choose', '', 0, true);
@@ -83,9 +89,10 @@ class data_field_radiobutton extends data_field_base {
function parse_search_field() {
return optional_param('f_'.$this->field->id, '', PARAM_NOTAGS);
}
function generate_sql($tablealias, $value) {
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content = '$value') ";
$varcharcontent = sql_compare_text("{$tablealias}.content", 255);
return " ({$tablealias}.fieldid = {$this->field->id} AND $varcharcontent = '$value') ";
}
}
+6 -6
View File
@@ -29,19 +29,19 @@ class data_field_text extends data_field_base {
function data_field_text($field=0, $data=0) {
parent::data_field_base($field, $data);
}
function display_search_field($value = '') {
return '<input type="text" size="16" name="f_'.$this->field->id.'" value="'.$value.'" />';
return '<input type="text" size="16" name="f_'.$this->field->id.'" value="'.$value.'" />';
}
function parse_search_field() {
return optional_param('f_'.$this->field->id, '', PARAM_NOTAGS);
}
function generate_sql($tablealias, $value) {
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content LIKE '%{$value}%') ";
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content LIKE '%{$value}%') ";
}
}
?>
+7 -7
View File
@@ -68,20 +68,20 @@ class data_field_textarea extends data_field_base {
$str .= '</div>';
return $str;
}
function display_search_field($value = '') {
return '<input type="text" size="16" name="f_'.$this->field->id.'" value="'.$value.'" />';
return '<input type="text" size="16" name="f_'.$this->field->id.'" value="'.$value.'" />';
}
function parse_search_field() {
return optional_param('f_'.$this->field->id, '', PARAM_NOTAGS);
}
function generate_sql($tablealias, $value) {
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content LIKE '%{$value}%') ";
return " ({$tablealias}.fieldid = {$this->field->id} AND {$tablealias}.content LIKE '%{$value}%') ";
}
function gen_textarea($usehtmleditor, $text='') {
// MDL-16018: Don't print htmlarea with < 7 lines height, causes visualization problem
$text = clean_text($text);
+5 -6
View File
@@ -504,10 +504,10 @@
} else {
$sortcontent = $sortfield->get_sort_field();
$sortcontentfull = $sortfield->get_sort_sql('c.'.$sortcontent);
$sortcontent = sql_compare_text('c.' . $sortfield->get_sort_field());
$sortcontentfull = $sortfield->get_sort_sql($sortcontent);
$what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, '.sql_compare_text($sortcontentfull).' AS _order ';
$what = ' DISTINCT r.id, r.approved, r.timecreated, r.timemodified, r.userid, u.firstname, u.lastname, '.$sortcontentfull.' AS _order ';
$count = ' COUNT(DISTINCT c.recordid) ';
$tables = $CFG->prefix.'data_content c,'.$CFG->prefix.'data_records r,'.$CFG->prefix.'data_content cs, '.$CFG->prefix.'user u ';
$where = 'WHERE c.recordid = r.id
@@ -545,7 +545,6 @@
$fromsql = "FROM $tables $advtables $where $advwhere $groupselect $approveselect $searchselect $advsearchselect";
$sqlselect = "SELECT $what $fromsql $sortorder";
$sqlcount = "SELECT $count $fromsql"; // Total number of records when searching
$sqlrids = "SELECT tmp.id FROM ($sqlselect) tmp";
$sqlmax = "SELECT $count FROM $tables $where $groupselect $approveselect"; // number of all recoirds user may see
/// Work out the paging numbers and counts
@@ -562,8 +561,8 @@
$mode = 'single';
$page = 0;
if ($allrecordids = get_records_sql($sqlrids)) {
$allrecordids = array_keys($allrecordids);
// TODO: Improve this because we are executing $sqlselect twice (here and some lines below)!
if ($allrecordids = get_fieldset_sql($sqlselect)) {
$page = (int)array_search($record->id, $allrecordids);
unset($allrecordids);
}
+3 -2
View File
@@ -119,6 +119,7 @@
/// Do course wide subscribe/unsubscribe
if (!is_null($subscribe) and !isguestuser() and !isguest()) {
require_sesskey();
foreach ($modinfo->instances['forum'] as $forumid=>$cm) {
$forum = $forums[$forumid];
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
@@ -387,9 +388,9 @@
if (!isguest()) {
print_box_start('subscription');
echo '<span class="helplink">';
echo '<a href="index.php?id='.$course->id.'&amp;subscribe=1">'.get_string('allsubscribe', 'forum').'</a>';
echo '<a href="index.php?id='.$course->id.'&amp;subscribe=1&amp;sesskey='.sesskey().'">'.get_string('allsubscribe', 'forum').'</a>';
echo '</span><br /><span class="helplink">';
echo '<a href="index.php?id='.$course->id.'&amp;subscribe=0">'.get_string('allunsubscribe', 'forum').'</a>';
echo '<a href="index.php?id='.$course->id.'&amp;subscribe=0&amp;sesskey='.sesskey().'">'.get_string('allunsubscribe', 'forum').'</a>';
echo '</span>';
print_box_end();
print_box('&nbsp;', 'clearer');
+31 -5
View File
@@ -380,6 +380,12 @@ function forum_cron() {
continue;
}
// Don't send email if the forum is Q&A and the user has not posted
if ($forum->type == 'qanda' && !forum_get_user_posted_time($discussion->id, $userto->id)) {
mtrace('Did not email '.$userto->id.' because user has not posted in discussion');
continue;
}
// Get info about the sending user
if (array_key_exists($post->userid, $users)) { // we might know him/her already
$userfrom = $users[$post->userid];
@@ -4299,6 +4305,7 @@ function forum_get_subscribe_link($forum, $context, $messages = array(), $cantac
$backtoindexlink = '';
}
$link = '';
$sesskeylink = '&amp;sesskey='.sesskey();
if ($fakelink) {
$link .= <<<EOD
@@ -4306,14 +4313,15 @@ function forum_get_subscribe_link($forum, $context, $messages = array(), $cantac
//<![CDATA[
var subs_link = document.getElementById("subscriptionlink");
if(subs_link){
subs_link.innerHTML = "<a title=\"$linktitle\" href='$CFG->wwwroot/mod/forum/subscribe.php?id={$forum->id}{$backtoindexlink}'>$linktext<\/a>";
subs_link.innerHTML = "<a title=\"$linktitle\" href='$CFG->wwwroot/mod/forum/subscribe.php?id={$forum->id}{$backtoindexlink}{$sesskeylink}'>$linktext<\/a>";
}
//]]>
</script>
<noscript>
EOD;
}
$options ['id'] = $forum->id;
$options['id'] = $forum->id;
$options['sesskey'] = sesskey();
$link .= print_single_button($CFG->wwwroot . '/mod/forum/subscribe.php',
$options, $linktext, 'post', '_self', true, $linktitle);
if ($fakelink) {
@@ -4634,7 +4642,7 @@ function forum_user_can_see_discussion($forum, $discussion, $context, $user=NULL
*
*/
function forum_user_can_see_post($forum, $discussion, $post, $user=NULL, $cm=NULL) {
global $USER;
global $CFG, $USER;
// retrieve objects (yuk)
if (is_numeric($forum)) {
@@ -4695,9 +4703,10 @@ function forum_user_can_see_post($forum, $discussion, $post, $user=NULL, $cm=NUL
if ($forum->type == 'qanda') {
$firstpost = forum_get_firstpost_from_discussion($discussion->id);
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
$userfirstpost = forum_get_user_posted_time($discussion->id, $user->id);
return (forum_user_has_posted($forum->id,$discussion->id,$user->id) ||
$firstpost->id == $post->id ||
return (($userfirstpost !== false && (time() - $userfirstpost >= $CFG->maxeditingtime)) ||
$firstpost->id == $post->id || $post->userid == $user->id || $firstpost->userid == $user->id ||
has_capability('mod/forum:viewqandawithoutposting', $modcontext, $user->id, false));
}
return true;
@@ -6935,4 +6944,21 @@ function forum_get_extra_capabilities() {
return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames', 'moodle/site:trustcontent');
}
/**
* Returns creation time of the first user's post in given discussion
* @global object $DB
* @param int $did Discussion id
* @param int $userid User id
* @return int|bool post creation time stamp or return false
*/
function forum_get_user_posted_time($did, $userid) {
global $CFG;
$posttime = get_field('forum_posts', 'MIN(created)', 'userid', $userid, 'discussion', $did);
if (empty($posttime)) {
return false;
}
return $posttime;
}
?>
+5 -10
View File
@@ -385,15 +385,12 @@
$read->firstread = backup_todb($rea_info['#']['FIRSTREAD']['0']['#']);
$read->lastread = backup_todb($rea_info['#']['LASTREAD']['0']['#']);
//Some recoding and check are performed now
$toinsert = true;
//We have to recode the userid field
$user = backup_getid($restore->backup_unique_code,"user",$read->userid);
if ($user) {
$read->userid = $user->new_id;
} else {
$toinsert = false;
continue; // Skip this forum_read record
}
//We have to recode the discussionid field
@@ -401,7 +398,7 @@
if ($discussion) {
$read->discussionid = $discussion->new_id;
} else {
$toinsert = false;
continue; // Skip this forum_read record
}
//We have to recode the postid field
@@ -409,14 +406,12 @@
if ($post) {
$read->postid = $post->new_id;
} else {
$toinsert = false;
continue; // Skip this forum_read record
}
//The structure is equal to the db, so insert the forum_read
// Arrived here, the structure is equal to the db, so insert the forum_read
$newid = 0;
if ($toinsert) {
$newid = insert_record ("forum_read",$read);
}
$newid = insert_record ("forum_read",$read);
//Do some output
if (($i+1) % 50 == 0) {
+24 -1
View File
@@ -1,4 +1,4 @@
<?php // $Id$
<?php
// Subscribe to or unsubscribe from a forum.
@@ -8,6 +8,7 @@
$id = required_param('id',PARAM_INT); // The forum to subscribe or unsubscribe to
$force = optional_param('force','',PARAM_ALPHA); // Force everyone to be subscribed to this forum?
$user = optional_param('user',0,PARAM_INT);
$sesskey = optional_param('sesskey', null, PARAM_RAW);
if (! $forum = get_record("forum", "id", $id)) {
error("Forum ID was incorrect");
@@ -25,6 +26,7 @@
}
if ($user) {
require_sesskey();
if (!has_capability('mod/forum:managesubscriptions', $context)) {
error('You do not have the permission to subscribe/unsubscribe other people!');
}
@@ -65,6 +67,7 @@
: "view.php?f=$id";
if ($force and has_capability('mod/forum:managesubscriptions', $context)) {
require_sesskey();
if (forum_is_forcesubscribed($forum)) {
forum_forcesubscribe($forum->id, 0);
redirect($returnto, get_string("everyonecannowchoose", "forum"), 1);
@@ -81,7 +84,20 @@
$info->name = fullname($user);
$info->forum = format_string($forum->name);
if ($user->id == $USER->id) {
$selflink = 'subscribe.php?id='.$id.'&amp;sesskey='.sesskey();
} else {
$selflink = 'subscribe.php?id='.$id.'&amp;user='.$user->id.'&amp;sesskey='.sesskey();
}
if (forum_is_subscribed($user->id, $forum->id)) {
if (is_null($sesskey)) { // we came here via link in email
$navigation = build_navigation('', $cm);
print_header($course->shortname, $course->fullname, $navigation, '', '', true, '', navmenu($course, $cm));
notice_yesno(get_string('confirmunsubscribe', 'forum', format_string($forum->name)), $selflink, $returnto);
print_footer($course);
exit;
}
if (forum_unsubscribe($user->id, $forum->id)) {
add_to_log($course->id, "forum", "unsubscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
redirect($returnto, get_string("nownotsubscribed", "forum", $info), 1);
@@ -97,6 +113,13 @@
if (!has_capability('mod/forum:viewdiscussion', $context)) {
error("Could not subscribe you to that forum", $_SERVER["HTTP_REFERER"]);
}
if (is_null($sesskey)) { // we came here via link in email
$navigation = build_navigation('', $cm);
print_header($course->shortname, $course->fullname, $navigation, '', '', true, '', navmenu($course, $cm));
notice_yesno(get_string('confirmsubscribe', 'forum', format_string($forum->name)), $selflink, $returnto);
print_footer($course);
exit;
}
if (forum_subscribe($user->id, $forum->id) ) {
add_to_log($course->id, "forum", "subscribe", "view.php?f=$forum->id", $forum->id, $cm->id);
redirect($returnto, get_string("nowsubscribed", "forum", $info), 1);
+1 -1
View File
@@ -120,7 +120,7 @@
}
/// Get all the potential subscribers excluding users already subscribed
$users = forum_get_potential_subscribers($context, $currentgroup, 'id,email,firstname,lastname', 'firstname ASC, lastname ASC');
$users = forum_get_potential_subscribers($context, $currentgroup, 'u.id,u.email,u.firstname,u.lastname', 'u.firstname ASC, u.lastname ASC');
if (!$users) {
$users = array();
}
+2 -2
View File
@@ -131,7 +131,7 @@
helpbutton("subscription", $strallowchoice, "forum");
echo '&nbsp;<span class="helplink">';
if (has_capability('mod/forum:managesubscriptions', $context)) {
echo "<a title=\"$strallowchoice\" href=\"subscribe.php?id=$forum->id&amp;force=no\">$strallowchoice</a>";
echo "<a title=\"$strallowchoice\" href=\"subscribe.php?id=$forum->id&amp;force=no&amp;sesskey=".sesskey()."\">$strallowchoice</a>";
} else {
echo $streveryoneisnowsubscribed;
}
@@ -150,7 +150,7 @@
echo '&nbsp;';
if (has_capability('mod/forum:managesubscriptions', $context)) {
echo "<span class=\"helplink\"><a title=\"$strforcesubscribe\" href=\"subscribe.php?id=$forum->id&amp;force=yes\">$strforcesubscribe</a></span>";
echo "<span class=\"helplink\"><a title=\"$strforcesubscribe\" href=\"subscribe.php?id=$forum->id&amp;force=yes&amp;sesskey=".sesskey()."\">$strforcesubscribe</a></span>";
} else {
echo '<span class="helplink">'.$streveryonecannowchoose.'</span>';
}
+47 -36
View File
@@ -242,11 +242,14 @@ function glossary_print_recent_activity($course, $viewfullnames, $timestart) {
/// Return true if there was output, or false is there was none.
global $CFG, $USER;
//TODO: use timestamp in approved field instead of changing timemodified when approving in 2.0
if (!defined('GLOSSARY_RECENT_ACTIVITY_LIMIT')) {
define('GLOSSARY_RECENT_ACTIVITY_LIMIT', 50);
}
$modinfo = get_fast_modinfo($course);
$ids = array();
foreach ($modinfo->cms as $cm) {
if ($cm->modname != 'glossary') {
continue;
@@ -254,58 +257,66 @@ function glossary_print_recent_activity($course, $viewfullnames, $timestart) {
if (!$cm->uservisible) {
continue;
}
$ids[$cm->instance] = $cm->instance;
$ids[$cm->instance] = $cm->id;
}
if (!$ids) {
return false;
}
$glist = implode(',', $ids); // there should not be hundreds of glossaries in one course, right?
if (!$entries = get_records_sql("SELECT ge.id, ge.concept, ge.approved, ge.timemodified, ge.glossaryid,
ge.userid, u.firstname, u.lastname, u.email, u.picture
FROM {$CFG->prefix}glossary_entries ge
JOIN {$CFG->prefix}user u ON u.id = ge.userid
WHERE ge.glossaryid IN ($glist) AND ge.timemodified > $timestart
ORDER BY ge.timemodified ASC")) {
return false;
}
$editor = array();
foreach ($entries as $entryid=>$entry) {
if ($entry->approved) {
continue;
}
if (!isset($editor[$entry->glossaryid])) {
$editor[$entry->glossaryid] = has_capability('mod/glossary:approve', get_context_instance(CONTEXT_MODULE, $modinfo->instances['glossary'][$entry->glossaryid]->id));
}
if (!$editor[$entry->glossaryid]) {
unset($entries[$entryid]);
// generate list of approval capabilities for all glossaries in the course.
$approvals = array();
foreach ($ids as $glinstanceid => $glcmid) {
$context = get_context_instance(CONTEXT_MODULE, $glcmid);
// get records glossary entries that are approved if user has no capability to approve entries.
if (has_capability('mod/glossary:approve', $context)) {
$approvals[] = ' ge.glossaryid = '.$glinstanceid.' ';
} else {
$approvals[] = ' (ge.approved = 1 AND ge.glossaryid = '.$glinstanceid.') ';
}
}
if (!$entries) {
$selectsql = "SELECT ge.id, ge.concept, ge.approved, ge.timemodified, ge.glossaryid,
ge.userid, u.firstname, u.lastname, u.email, u.picture ";
$countsql = "SELECT COUNT(*)";
$joins = array(" FROM {$CFG->prefix}glossary_entries ge ");
$joins[] = "JOIN {$CFG->prefix}user u ON u.id = ge.userid ";
$fromsql = implode($joins, "\n");
$clausesql = ' WHERE ge.timemodified > '.$timestart.' AND (';
$approvalsql = implode($approvals, ' OR ');
$ordersql = ') ORDER BY ge.timemodified ASC';
$entries = get_records_sql($selectsql.$fromsql.$clausesql.$approvalsql.$ordersql, 0, (GLOSSARY_RECENT_ACTIVITY_LIMIT+1));
$fromsql = implode($joins, "\n");
if (empty($entries)) {
return false;
}
print_headline(get_string('newentries', 'glossary').':');
$strftimerecent = get_string('strftimerecent');
$entrycount = 0;
foreach ($entries as $entry) {
$link = $CFG->wwwroot.'/mod/glossary/view.php?g='.$entry->glossaryid.'&amp;mode=entry&amp;hook='.$entry->id;
if ($entry->approved) {
$dimmed = '';
if ($entrycount < GLOSSARY_RECENT_ACTIVITY_LIMIT) {
if ($entry->approved) {
$dimmed = '';
$link = $CFG->wwwroot.'/mod/glossary/view.php?g='.$entry->glossaryid.'&amp;mode=entry&amp;hook='.$entry->id;
} else {
$dimmed = ' dimmed_text';
$link = $CFG->wwwroot.'/mod/glossary/view.php?id='.$ids[$entry->glossaryid].'&amp;mode=approval&amp;hook='.format_text($entry->concept, true);
}
echo '<div class="head'.$dimmed.'">';
echo '<div class="date">'.userdate($entry->timemodified, $strftimerecent).'</div>';
echo '<div class="name">'.fullname($entry, $viewfullnames).'</div>';
echo '</div>';
echo '<div class="info"><a href="'.$link.'">'.format_text($entry->concept, true).'</a></div>';
$entrycount += 1;
} else {
$dimmed = ' dimmed_text';
$numnewentries = count_records_sql($countsql.$joins[0].$clausesql.$approvalsql.')');
echo '<div class="head"><div class="activityhead">'.get_string('andmorenewentries', 'glossary', $numnewentries - GLOSSARY_RECENT_ACTIVITY_LIMIT).'</div></div>';
break;
}
echo '<div class="head'.$dimmed.'">';
echo '<div class="date">'.userdate($entry->timemodified, $strftimerecent).'</div>';
echo '<div class="name">'.fullname($entry, $viewfullnames).'</div>';
echo '</div>';
echo '<div class="info"><a href="'.$link.'">'.format_text($entry->concept, true).'</a></div>';
}
return true;
+3 -3
View File
@@ -1089,13 +1089,13 @@ class hotpot_xml_quiz_template extends hotpot_xml_template_default {
// JCross quiztype
function v6_expand_CluesAcrossLabel() {
$this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',clues-across');
return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',clues-across');
}
function v6_expand_CluesDownLabel() {
$this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',clues-down');
return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',clues-down');
}
function v6_expand_EnterCaption() {
$this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',enter-caption');
return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',enter-caption');
}
function v6_expand_ShowHideClueList() {
$value = $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clue-list');
+3 -16
View File
@@ -415,12 +415,7 @@
$response = '';
if ($ncorrect == count($answers)-2) { // dont count correct/wrong responses in the total.
foreach ($answers as $answer) {
if ($answer->response == NULL && $answer->answer != NULL) {
$response = $answer->answer;
break;
}
}
$response = reset($answers)->answer;
if (isset($correctpageid)) {
$newpageid = $correctpageid;
}
@@ -429,16 +424,8 @@
}
$correctanswer = true;
} else {
$t = 0;
foreach ($answers as $answer) {
if ($answer->response == NULL && $answer->answer != NULL) {
if ($t == 1) {
$response = $answer->answer;
break;
}
$t++;
}
}
reset($answers);
$response = next($answers)->answer;
$newpageid = $wrongpageid;
$answerid = $wronganswerid;
}
+10 -7
View File
@@ -31,12 +31,15 @@
if ($essayattempts = get_records_select('lesson_attempts', 'pageid IN('.implode(',', array_keys($pages)).')')) {
// Get all the users who have taken this lesson, order by their last name
if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) {
$sql = "SELECT DISTINCT u.*
FROM {$CFG->prefix}lesson_attempts a
INNER JOIN {$CFG->prefix}user u ON u.id = a.userid
INNER JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id
INNER JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = {$cm->groupingid}
WHERE a.lessonid = '$lesson->id'
$sql = "SELECT u.*
FROM {$CFG->prefix}user u
JOIN (
SELECT DISTINCT u.id
FROM {$CFG->prefix}lesson_attempts a
JOIN {$CFG->prefix}user u ON u.id = a.userid
JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id
JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = {$cm->groupingid}
WHERE a.lessonid = '$lesson->id') ui ON u.id = ui.id
ORDER BY u.lastname";
} else {
$sql = "SELECT u.*
@@ -367,4 +370,4 @@
}
print_footer($course);
?>
?>
+10 -7
View File
@@ -17,14 +17,17 @@
$nothingtodisplay = false;
list($cm, $course, $lesson) = lesson_get_basics($id);
if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) {
$sql = "SELECT DISTINCT u.*
FROM {$CFG->prefix}lesson_attempts a
INNER JOIN {$CFG->prefix}user u ON u.id = a.userid
INNER JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id
INNER JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = {$cm->groupingid}
WHERE a.lessonid = '$lesson->id'
$sql = "SELECT u.*
FROM {$CFG->prefix}user u
JOIN (
SELECT DISTINCT u.id
FROM {$CFG->prefix}lesson_attempts a
JOIN {$CFG->prefix}user u ON u.id = a.userid
JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id
JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = {$cm->groupingid}
WHERE a.lessonid = '$lesson->id') ui ON u.id = ui.id
ORDER BY u.lastname";
} else {
$sql = "SELECT u.*
+1 -1
View File
@@ -147,7 +147,7 @@
$feedback = '';
if ($quiz->grade && !is_null($bestgrade)) {
if ($alloptions->scores) {
$grade = "$bestgrade / $quiz->grade";
$grade = round($bestgrade, $quiz->decimalpoints) . ' / ' . $quiz->grade;
}
if ($alloptions->overallfeedback) {
$feedback = quiz_feedback_for_grade($bestgrade, $quiz->id);
+1 -1
View File
@@ -186,7 +186,7 @@ function quiz_get_best_grade($quiz, $userid) {
// Need to detect errors/no result, without catching 0 scores.
if (is_numeric($grade)) {
return round($grade, $quiz->decimalpoints);
return $grade + 0;
} else {
return NULL;
}
+1 -1
View File
@@ -429,7 +429,7 @@ function quiz_save_best_grade($quiz, $userid = null) {
// Calculate the best grade
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
$bestgrade = quiz_rescale_grade($bestgrade, $quiz);
$bestgrade = quiz_rescale_grade($bestgrade, $quiz, false);
// Save the best grade in the database
if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid', $userid)) {
+8
View File
@@ -282,6 +282,14 @@ class mod_quiz_mod_form extends moodleform_mod {
$key = 0;
foreach ($this->_feedbacks as $feedback){
$default_values['feedbacktext['.$key.']'] = $feedback->feedbacktext;
if ($default_values['grade'] == 0) {
// When a quiz is un-graded, there can only be one lot of
// feedback. If the quiz previously had a maximum grade and
// several lots of feedback, we must now avoid putting text
// into input boxes that are disabled, but which the
// validation will insist are blank.
break;
}
if ($feedback->mingrade > 0) {
$default_values['feedbackboundaries['.$key.']'] = (100.0 * $feedback->mingrade / $default_values['grade']) . '%';
}
+17 -4
View File
@@ -348,9 +348,22 @@ class quiz_report extends quiz_default_report {
"END) AS gradedattempt, ";
}
$select .= 'qa.uniqueid AS attemptuniqueid, qa.id AS attempt, ' .
'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, ' .
'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration ';
$select .= '
qa.uniqueid AS attemptuniqueid,
qa.id AS attempt,
u.id AS userid,
u.idnumber,
u.firstname,
u.lastname,
u.picture,
u.imagealt,
u.email,
qa.sumgrades,
qa.timefinish,
qa.timestart,
CASE WHEN qa.timefinish = 0 THEN null
WHEN qa.timefinish > qa.timestart THEN qa.timefinish - qa.timestart
ELSE 0 END AS duration ';
// This part is the same for all cases - join users and quiz_attempts tables
$from = 'FROM '.$CFG->prefix.'user u ';
@@ -559,7 +572,7 @@ class quiz_report extends quiz_default_report {
// Feedback column.
if ($hasfeedback) {
if ($attempt->timefinish) {
$row[] = quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $quiz), $quiz->id);
$row[] = quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $quiz, false), $quiz->id);
} else {
$row[] = '-';
}
+12 -1
View File
@@ -78,6 +78,16 @@
redirect('view.php?q=' . $quiz->id, $message);
}
}
} else if (!has_capability('moodle/site:accessallgroups', $context) &&
groups_get_activity_groupmode($cm) == SEPARATEGROUPS) {
// Check the users have at least one group in common.
$teachersgroups = groups_get_activity_allowed_groups($cm);
$studentsgroups = groups_get_all_groups($cm->course, $attempt->userid, $cm->groupingid);
if (!($teachersgroups && $studentsgroups &&
array_intersect(array_keys($teachersgroups), array_keys($studentsgroups)))) {
print_error('noreview', 'quiz', 'view.php?q=' . $quiz->id);
}
}
/// Bits needed to print a good URL for this page.
@@ -255,7 +265,8 @@
}
/// Feedback if there is any, and the user is allowed to see it now.
$feedback = quiz_feedback_for_grade($grade, $attempt->quiz);
$feedback = quiz_feedback_for_grade(quiz_rescale_grade(
$attempt->sumgrades, $quiz, false), $attempt->quiz);
if ($options->overallfeedback && $feedback) {
$rows[] = '<tr><th scope="row" class="cell">' . get_string('feedback', 'quiz') .
'</th><td class="cell">' . $feedback . '</td></tr>';
+10
View File
@@ -80,6 +80,16 @@
if ($attempt->userid != $USER->id) {
error('This is not your attempt!');
}
} else if (!has_capability('moodle/site:accessallgroups', $context) &&
groups_get_activity_groupmode($cm) == SEPARATEGROUPS) {
// Check the users have at least one group in common.
$teachersgroups = groups_get_activity_allowed_groups($cm);
$studentsgroups = groups_get_all_groups($cm->course, $attempt->userid, $cm->groupingid);
if (!($teachersgroups && $studentsgroups &&
array_intersect(array_keys($teachersgroups), array_keys($studentsgroups)))) {
print_error('noreview', 'quiz', 'view.php?q=' . $quiz->id);
}
}
//add_to_log($course->id, 'quiz', 'review', "review.php?id=$cm->id&amp;attempt=$attempt->id", "$quiz->id", "$cm->id");
+3 -3
View File
@@ -267,11 +267,11 @@
}
// Ouside the if because we may be showing feedback but not grades.
$attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz);
$attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz, false);
if ($gradecolumn) {
if ($attemptoptions->scores && $attempt->timefinish > 0) {
$formattedgrade = $attemptgrade;
$formattedgrade = round($attemptgrade, $quiz->decimalpoints);
// highlight the highest grade if appropriate
if ($overallstats && $numattempts > 1 && !is_null($mygrade) && $attemptgrade == $mygrade && $quiz->grademethod == QUIZ_GRADEHIGHEST) {
$table->rowclass[$attempt->attempt] = 'bestrow';
@@ -313,7 +313,7 @@
if ($available && $moreattempts) {
$a = new stdClass;
$a->method = quiz_get_grading_option_name($quiz->grademethod);
$a->mygrade = $mygrade;
$a->mygrade = round($mygrade, $quiz->decimalpoints);
$a->quizgrade = $quiz->grade;
$resultinfo .= print_heading(get_string('gradesofar', 'quiz', $a), '', 2, 'main', true);
} else {
+6 -7
View File
@@ -77,7 +77,7 @@
if ($sco = scorm_get_sco($scoid)) {
$userdata->course_id = $sco->identifier;
$userdata->datafromlms = isset($sco->datafromlms)?$sco->datafromlms:'';
$userdata->mastery_score = isset($sco->mastery_score)?$sco->mastery_score:'';
$userdata->mastery_score = isset($sco->mastery_score) && is_numeric($sco->mastery_score)?trim($sco->mastery_score):'';
$userdata->max_time_allowed = isset($sco->max_time_allowed)?$sco->max_time_allowed:'';
$userdata->time_limit_action = isset($sco->time_limit_action)?$sco->time_limit_action:'';
echo "error=0\r\nerror_text=Successful\r\naicc_data=";
@@ -135,7 +135,7 @@
echo "[Core_Vendor]\r\n".$userdata->datafromlms."\r\n";
echo "[Evaluation]\r\nCourse_ID = {".$userdata->course_id."}\r\n";
echo "[Student_Data]\r\n";
echo 'Mastery_Score='.$userdata->mastery_score."\r\n";
echo 'Mastery_Score='.$userdata->mastery_score."\r\n";
echo 'Max_Time_Allowed='.$userdata->max_time_allowed."\r\n";
echo 'Time_Limit_Action='.$userdata->time_limit_action."\r\n";
} else {
@@ -250,7 +250,7 @@
$value .= $datarow."\r\n";
next($datarows);
}
$value = rawurlencode(stripslashes($value));
$value = rawurlencode(stripslashes($value));
$id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
}
}
@@ -260,11 +260,10 @@
$id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, 'cmi.core.lesson_status', 'browsed');
}
if ($mode == 'normal') {
if ($sco = scorm_get_sco($scoid)) {
if (!empty($sco->mastery_score)) {
if (!empty($score)) {
if ($score >= $sco->mastery_score) {
if (isset($sco->mastery_score) && is_numeric($sco->mastery_score)) {
if ($score != '') { // $score is correctly initialized w/ an empty string, see above
if ($score >= trim($sco->mastery_score)) {
$lessonstatus = 'passed';
} else {
$lessonstatus = 'failed';
+1 -1
View File
@@ -448,7 +448,7 @@ function scorm_get_toc($user,$scorm,$liststyle,$currentorg='',$scoid='',$mode='n
$score = '('.get_string('score','scorm').':&nbsp;'.$usertrack->score_raw.')';
}
$strsuspended = get_string('suspended','scorm');
if (isset($usertrack->{'cmi.core.exit'}) && ($usertrack->{'cmi.core.exit'} == 'suspend')) {
if ($incomplete && isset($usertrack->{'cmi.core.exit'}) && ($usertrack->{'cmi.core.exit'} == 'suspend')) {
$statusicon = '<img src="'.$scormpixdir.'/suspend.gif" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />';
}
} else {
+9 -9
View File
@@ -36,15 +36,15 @@ function SCORMapi1_2() {
CMIResult = '^correct$|^wrong$|^unanticipated$|^neutral$|^([0-9]{0,3})?(\.[0-9]{1,2})?$';
NAVEvent = '^previous$|^continue$';
// Children lists
cmi_children = 'core, suspend_data, launch_data, comments, objectives, student_data, student_preference, interactions';
core_children = 'student_id, student_name, lesson_location, credit, lesson_status, entry, score, total_time, lesson_mode, exit, session_time';
score_children = 'raw, min, max';
comments_children = 'content, location, time';
objectives_children = 'id, score, status';
cmi_children = 'core,suspend_data,launch_data,comments,objectives,student_data,student_preference,interactions';
core_children = 'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,lesson_mode,exit,session_time';
score_children = 'raw,min,max';
comments_children = 'content,location,time';
objectives_children = 'id,score,status';
correct_responses_children = 'pattern';
student_data_children = 'mastery_score, max_time_allowed, time_limit_action';
student_preference_children = 'audio, language, speed, text';
interactions_children = 'id, objectives, time, type, correct_responses, weighting, student_response, result, latency';
student_data_children = 'mastery_score,max_time_allowed,time_limit_action';
student_preference_children = 'audio,language,speed,text';
interactions_children = 'id,objectives,time,type,correct_responses,weighting,student_response,result,latency';
// Data ranges
score_range = '0#100';
audio_range = '-1#100';
@@ -421,7 +421,7 @@ function SCORMapi1_2() {
}
?>
result = ('true' == result) ? 'true' : 'false';
errorCode = (result ==' true')? '0' : '101';
errorCode = (result =='true')? '0' : '101';
<?php
if (debugging('',DEBUG_DEVELOPER)) {
//echo 'alert("Finished SCORM 1.2");';
+3 -5
View File
@@ -59,7 +59,7 @@ function scorm_eval_prerequisites($prerequisites, $usertracks) {
$count = 0;
foreach ($set as $setelement) {
if (isset($usertracks[$setelement]) &&
($usertracks[$setelement]->status == 'completed' || $usertracks[$element]->status == 'passed')) {
($usertracks[$setelement]->status == 'completed' || $usertracks[$setelement]->status == 'passed')) {
$count++;
}
}
@@ -247,10 +247,8 @@ function scorm_get_toc($user,$scorm,$liststyle,$currentorg='',$scoid='',$mode='n
$score = '('.get_string('score','scorm').':&nbsp;'.$usertrack->score_raw.')';
}
$strsuspended = get_string('suspended','scorm');
if (isset($usertrack->{'cmi.core.exit'}) && ($usertrack->{'cmi.core.exit'} == 'suspend')) {
if($usertrack->status !='completed') {
$statusicon = '<img src="'.$scormpixdir.'/suspend.gif" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />';
}
if ($incomplete && isset($usertrack->{'cmi.core.exit'}) && ($usertrack->{'cmi.core.exit'} == 'suspend')) {
$statusicon = '<img src="'.$scormpixdir.'/suspend.gif" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />';
}
} else {
if ($play && empty($scoid)) {
+9 -12
View File
@@ -74,7 +74,7 @@ function SCORMapi1_3() {
var CMIDecimal = '^-?([0-9]{1,5})(\\.[0-9]{1,18})?$';
var CMIIdentifier = '^\\S{0,250}[a-zA-Z0-9]$';
var CMIShortIdentifier = '^[\\w\.]{1,250}$';
var CMILongIdentifier = '^\\S{0,4000}[a-zA-Z0-9]$';
var CMILongIdentifier = '^\\S{0,4000}$';
var CMIFeedback = '^.*$'; // This must be redefined
var CMIIndex = '[._](\\d+).';
var CMIIndexStore = '.N(\\d+).';
@@ -88,14 +88,14 @@ function SCORMapi1_3() {
var NAVBoolean = '^unknown$|^true$|^false$';
var NAVTarget = '^previous$|^continue$|^choice.{target=\\S{0,200}[a-zA-Z0-9]}$'
// Children lists
var cmi_children = '_version, comments_from_learner, comments_from_lms, completion_status, credit, entry, exit, interactions, launch_data, learner_id, learner_name, learner_preference, location, max_time_allowed, mode, objectives, progress_measure, scaled_passing_score, score, session_time, success_status, suspend_data, time_limit_action, total_time';
var comments_children = 'comment, timestamp, location';
var score_children = 'max, raw, scaled, min';
var objectives_children = 'progress_measure, completion_status, success_status, description, score, id';
var cmi_children = '_version,comments_from_learner,comments_from_lms,completion_status,credit,entry,exit,interactions,launch_data,learner_id,learner_name,learner_preference,location,max_time_allowed,mode,objectives,progress_measure,scaled_passing_score,score,session_time,success_status,suspend_data,time_limit_action,total_time';
var comments_children = 'comment,timestamp,location';
var score_children = 'max,raw,scaled,min';
var objectives_children = 'progress_measure,completion_status,success_status,description,score,id';
var correct_responses_children = 'pattern';
var student_data_children = 'mastery_score, max_time_allowed, time_limit_action';
var student_preference_children = 'audio_level, audio_captioning, delivery_speed, language';
var interactions_children = 'id, type, objectives, timestamp, correct_responses, weighting, learner_response, result, latency, description';
var student_data_children = 'mastery_score,max_time_allowed,time_limit_action';
var student_preference_children = 'audio_level,audio_captioning,delivery_speed,language';
var interactions_children = 'id,type,objectives,timestamp,correct_responses,weighting,learner_response,result,latency,description';
// Data ranges
var scaled_range = '-1#1';
var audio_range = '0#*';
@@ -578,9 +578,6 @@ function SCORMapi1_3() {
} else {
nodes[0] = value;
}
if (interactiontype == 'choice' && nodes.length == 1) {
alert('not enough choices: ' + element);
}
if ((nodes.length > 0) && (nodes.length <= correct_responses[interactiontype].max)) {
errorCode = CRcheckValueNodes (element, interactiontype, nodes, value, errorCode);
} else if (nodes.length > correct_responses[interactiontype].max) {
@@ -1270,4 +1267,4 @@ if (debugging('',DEBUG_DEVELOPER)) {
include_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
echo 'AppendToLog("Moodle SCORM 1.3 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);';
}
?>
?>
+1 -3
View File
@@ -139,10 +139,8 @@ function scorm_get_toc($user,$scorm,$liststyle,$currentorg='',$scoid='',$mode='n
$score = '('.get_string('score','scorm').':&nbsp;'.$usertrack->score_raw.')';
}
$strsuspended = get_string('suspended','scorm');
if (isset($usertrack->{'cmi.core.exit'}) && ($usertrack->{'cmi.core.exit'} == 'suspend')) {
if($usertrack->status !='completed') {
if ($incomplete && isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} == 'suspend')) {
$statusicon = '<img src="'.$scormpixdir.'/suspend.gif" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />';
}
}
} else {
if ($play && empty($scoid)) {
+4 -2
View File
@@ -100,7 +100,9 @@ function scorm_update_instance($scorm) {
$scorm->timemodified = time();
$scorm->id = $scorm->instance;
$scorm = scorm_option2text($scorm);
if (empty($scorm->options)) {
$scorm = scorm_option2text($scorm);
}
$scorm->width = str_replace('%','',$scorm->width);
$scorm->height = str_replace('%','',$scorm->height);
@@ -343,7 +345,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
$report .= "\t\t\t<li><ul class='$liststyle'>\n";
foreach($usertrack as $element => $value) {
if (substr($element,0,3) == 'cmi') {
$report .= '<li>'.$element.' => '.$value.'</li>';
$report .= '<li>'.$element.' => '.s($value).'</li>';
}
}
$report .= "\t\t\t</ul></li>\n";
+6 -1
View File
@@ -445,7 +445,7 @@ function scorm_grade_user_attempt($scorm, $userid, $attempt=1, $time=false) {
if (($userdata->status == 'completed') || ($userdata->status == 'passed')) {
$attemptscore->scoes++;
}
if (!empty($userdata->score_raw) || ($scorm->type=='sco' && isset($userdata->score_raw))) {
if (!empty($userdata->score_raw) || (isset($scorm->type) && $scorm->type=='sco' && isset($userdata->score_raw))) {
$attemptscore->values++;
$attemptscore->sum += $userdata->score_raw;
$attemptscore->max = ($userdata->score_raw > $attemptscore->max)?$userdata->score_raw:$attemptscore->max;
@@ -730,6 +730,11 @@ function scorm_simple_play($scorm,$user, $context) {
$result = false;
if ($scorm->updatefreq == UPDATE_EVERYTIME) {
if (strpos($scorm->version, 'AICC') !== false) {
$scorm->pkgtype = 'AICC';
} else {
$scorm->pkgtype = 'SCORM';
}
scorm_parse($scorm);
}
if (has_capability('mod/scorm:viewreport', $context)) { //if this user can view reports, don't skipview so they can see links to reports.
+1 -1
View File
@@ -373,7 +373,7 @@ class random_qtype extends default_questiontype {
echo 'Could not get qtype while recoding question random-'.$answerregs[1].'<br />';
return($answer_field);
}
$newstate = $state;
$newstate = clone($state);
$newstate->question = $wrapped->new_id;
$newstate->answer = $answerregs[2];
$answer_field = 'random'.$wrapped->new_id.'-';
+9 -9
View File
@@ -4,7 +4,7 @@ require_once('../config.php');
require_once('lib.php');
require_once('edit_form.php');
require_js(array('yui_dom-event', 'yui_connection', 'yui_animation', 'yui_autocomplete'));
require_js(array('yui_dom-event', 'yui_connection', 'yui_animation', 'yui_datasource', 'yui_autocomplete'));
require_login();
@@ -92,21 +92,21 @@ if ($tagnew = $tagform->get_data()) {
error('Error updating tag record');
}
}
//log tag changes activity
//if tag name exist from form, renaming is allow. record log action as rename
//otherwise, record log action as update
//otherwise, record log action as update
if (isset($tagnew->name) && ($tag->name != $tagnew->name)){
add_to_log($COURSE->id, 'tag', 'update', 'index.php?id='. $tag->id, $tag->name . '->'. $tagnew->name);
} elseif ($tag->description != $tagnew->description) {
} elseif ($tag->description != $tagnew->description) {
add_to_log($COURSE->id, 'tag', 'update', 'index.php?id='. $tag->id, $tag->name);
}
//updated related tags
tag_set('tag', $tagnew->id, explode(',', trim($tagnew->relatedtags)));
//print_object($tagnew); die();
redirect($CFG->wwwroot.'/tag/index.php?tag='.rawurlencode($tag->name)); // must use $tag here, as the name isn't in the edit form
}
}
@@ -133,9 +133,9 @@ if (ajaxenabled()) {
<script type="text/javascript">
// An XHR DataSource
var myServer = "./tag_autocomplete.php";
var myDataSource = new YAHOO.widget.DS_XHR(myServer, ["\n", "\t"]);
myDataSource.responseType = YAHOO.widget.DS_XHR.TYPE_FLAT;
var myDataSource = new YAHOO.util.XHRDataSource("./tag_autocomplete.php");
myDataSource.responseType = YAHOO.util.XHRDataSource.TYPE_TEXT;
myDataSource.responseSchema = {recordDelim: "\n", fieldDelim: "\t"};
myDataSource.maxCacheEntries = 60;
myDataSource.queryMatchSubset = true;
+100 -97
View File
@@ -3,24 +3,24 @@
/**
* Moodle tag library
*
* Tag strings : you can use any character in tags, except the comma (which is
* the separator) and the '\' (backslash). Note that many spaces (or other
* blank characters) will get "compressed" into one. A tag string is always a
* Tag strings : you can use any character in tags, except the comma (which is
* the separator) and the '\' (backslash). Note that many spaces (or other
* blank characters) will get "compressed" into one. A tag string is always a
* rawurlencode'd string. This is the same behavior as http://del.icio.us.
*
* A "record" is a php array (note that an object will work too) that contains
* the following variables :
* A "record" is a php array (note that an object will work too) that contains
* the following variables :
* - type: the table containing the record that we are tagging (eg: for a
* blog, this is table 'post', and for a user it is 'user')
* - id: the id of the record
* - id: the id of the record
*
* TODO: turn this into a full-fledged categorization system. This could start
* by modifying (removing, probably) the 'tag type' to use another table
* describing the relationship between tags (parents, sibling, etc.), which
* TODO: turn this into a full-fledged categorization system. This could start
* by modifying (removing, probably) the 'tag type' to use another table
* describing the relationship between tags (parents, sibling, etc.), which
* could then be merged with the 'course categorization' system...
*
* BASIC INSTRUCTIONS :
* - to "tag a blog post" (for example):
* BASIC INSTRUCTIONS :
* - to "tag a blog post" (for example):
* tag_set('post', $blog_post->id, $array_of_tags);
*
* - to "remove all the tags on a blog post":
@@ -56,16 +56,16 @@ require_once($CFG->dirroot .'/tag/locallib.php');
/**
* Set the tags assigned to a record. This overwrites the current tags.
*
* This function is meant to be fed the string coming up from the user
*
* This function is meant to be fed the string coming up from the user
* interface, which contains all tags assigned to a record.
*
* @param string $record_type the type of record to tag ('post' for blogs,
* @param string $record_type the type of record to tag ('post' for blogs,
* 'user' for users, 'tag' for tags, etc.
* @param int $record_id the id of the record to tag
* @param array $tags the array of tags to set on the record. If
* @param array $tags the array of tags to set on the record. If
* given an empty array, all tags will be removed.
* @return void
* @return void
*/
function tag_set($record_type, $record_id, $tags) {
@@ -79,7 +79,7 @@ function tag_set($record_type, $record_id, $tags) {
//echo 'tags-in-tag_set'; var_dump($tags); var_dump($tags_ids); var_dump($cleaned_tags);
$current_ids = tag_get_tags_ids($record_type, $record_id);
//var_dump($current_ids);
//var_dump($current_ids);
// for data coherence reasons, it's better to remove deleted tags
// before adding new data: ordering could be duplicated.
@@ -87,7 +87,7 @@ function tag_set($record_type, $record_id, $tags) {
if (!in_array($current_id, $tags_ids)) {
tag_delete_instance($record_type, $record_id, $current_id);
if ( $record_type == 'tag' && !$in_recursion_semaphore) {
// if we are removing a tag-on-a-tag (manually related tag),
// if we are removing a tag-on-a-tag (manually related tag),
// we need to remove the opposite relationship as well.
tag_delete_instance('tag', $current_id, $record_id);
}
@@ -102,7 +102,7 @@ function tag_set($record_type, $record_id, $tags) {
$clean_tag = $cleaned_tags[$tag];
$tag_current_id = $tags_ids[$clean_tag];
if ( is_null($tag_current_id) ) {
// create new tags
//echo "call to add tag $tag\n";
@@ -124,8 +124,8 @@ function tag_set($record_type, $record_id, $tags) {
/**
* Adds a tag to a record, without overwriting the current tags.
*
* @param string $record_type the type of record to tag ('post' for blogs,
*
* @param string $record_type the type of record to tag ('post' for blogs,
* 'user' for users, etc.
* @param int $record_id the id of the record to tag
* @param string $tag the tag to add
@@ -138,14 +138,14 @@ function tag_set_add($record_type, $record_id, $tag) {
$new_tags[] = $current_tag->rawname;
}
$new_tags[] = $tag;
return tag_set($record_type, $record_id, $new_tags);
}
/**
* Removes a tag from a record, without overwriting other current tags.
*
* @param string $record_type the type of record to tag ('post' for blogs,
*
* @param string $record_type the type of record to tag ('post' for blogs,
* 'user' for users, etc.
* @param int $record_id the id of the record to tag
* @param string $tag the tag to delete
@@ -182,13 +182,13 @@ function tag_type_set($tagid, $type) {
}
/**
/**
* Set the description of a tag
*
*
* @param int $tagid the id of the tag
* @param string $description the description
* @param int $descriptionformat the moodle text format of the description
* @return true on success, false otherwise
* @return true on success, false otherwise
*/
function tag_description_set($tagid, $description, $descriptionformat) {
if ($tag = get_record('tag', 'id', $tagid, '', '', '', '', 'id')) {
@@ -225,17 +225,17 @@ function tag_get($field, $value, $returnfields='id, name, rawname') {
/**
* Get the array of db record of tags associated to a record (instances). Use
* Get the array of db record of tags associated to a record (instances). Use
* tag_get_tags_csv to get the same information in a comma-separated string.
*
* @param string $record_type the record type for which we want to get the tags
* @param int $record_id the record id for which we want to get the tags
* @param string $record_type the record type for which we want to get the tags
* @param int $record_id the record id for which we want to get the tags
* @param string $type the tag type (either 'default' or 'official'). By default,
* all tags are returned.
* @return array the array of tags
*/
function tag_get_tags($record_type, $record_id, $type=null) {
global $CFG;
if ($type) {
@@ -247,16 +247,16 @@ function tag_get_tags($record_type, $record_id, $type=null) {
"FROM {$CFG->prefix}tag_instance ti INNER JOIN {$CFG->prefix}tag tg ON tg.id = ti.tagid ".
"WHERE ti.itemtype = '{$record_type}' AND ti.itemid = '{$record_id}' {$type} ".
"ORDER BY ti.ordering ASC");
// This version of the query, reversing the ON clause, "correctly" returns
// a row with NULL values for instances that are still in the DB even though
// the tag has been deleted. This shouldn't happen, but if it did, using
// This version of the query, reversing the ON clause, "correctly" returns
// a row with NULL values for instances that are still in the DB even though
// the tag has been deleted. This shouldn't happen, but if it did, using
// this query could help "clean it up". This causes bugs at this time.
//$tags = get_records_sql("SELECT ti.tagid, tg.tagtype, tg.name, tg.rawname, tg.flag, ti.ordering ".
// "FROM {$CFG->prefix}tag_instance ti LEFT JOIN {$CFG->prefix}tag tg ON ti.tagid = tg.id ".
// "WHERE ti.itemtype = '{$record_type}' AND ti.itemid = '{$record_id}' {$type} ".
// "ORDER BY ti.ordering ASC");
if (!$tags) {
if (!$tags) {
return array();
} else {
return $tags;
@@ -265,7 +265,7 @@ function tag_get_tags($record_type, $record_id, $type=null) {
/**
* Get the array of tags display names, indexed by id.
*
*
* @param string $record_type the record type for which we want to get the tags
* @param int $record_id the record id for which we want to get the tags
* @param string $type the tag type (either 'default' or 'official'). By default,
@@ -314,7 +314,7 @@ function tag_get_tags_csv($record_type, $record_id, $html=TAG_RETURN_HTML, $type
* @return array of tag ids, indexed and sorted by 'ordering'
*/
function tag_get_tags_ids($record_type, $record_id) {
$tag_ids = array();
foreach (tag_get_tags($record_type, $record_id) as $tag) {
if ( array_key_exists($tag->ordering, $tag_ids) ) {
@@ -329,16 +329,16 @@ function tag_get_tags_ids($record_type, $record_id) {
return $tag_ids;
}
/**
/**
* Returns the database ID of a set of tags.
*
*
* @param mixed $tags one tag, or array of tags, to look for.
* @param bool $return_value specify the type of the returned value. Either
* TAG_RETURN_OBJECT, or TAG_RETURN_ARRAY (default). If TAG_RETURN_ARRAY
* is specified, an array will be returned even if only one tag was
* @param bool $return_value specify the type of the returned value. Either
* TAG_RETURN_OBJECT, or TAG_RETURN_ARRAY (default). If TAG_RETURN_ARRAY
* is specified, an array will be returned even if only one tag was
* passed in $tags.
* @return mixed tag-indexed array of ids (or objects, if second parameter is
* TAG_RETURN_OBJECT), or only an int, if only one tag is given *and* the
* @return mixed tag-indexed array of ids (or objects, if second parameter is
* TAG_RETURN_OBJECT), or only an int, if only one tag is given *and* the
* second parameter is null. No value for a key means the tag wasn't found.
*/
function tag_get_id($tags, $return_value=null) {
@@ -348,13 +348,13 @@ function tag_get_id($tags, $return_value=null) {
$return_an_int = false;
if (!is_array($tags)) {
if(is_null($return_value) || $return_value == TAG_RETURN_OBJECT) {
$return_an_int = true;
$return_an_int = true;
}
$tags = array($tags);
}
$result = array();
//TODO: test this and see if it helps performance without breaking anything
//foreach($tags as $key => $tag) {
// $clean_tag = moodle_strtolower($tag);
@@ -366,7 +366,7 @@ function tag_get_id($tags, $return_value=null) {
$tags = array_values(tag_normalize($tags));
foreach($tags as $key => $tag) {
$tags[$key] = addslashes(moodle_strtolower($tag));
$tags[$key] = addslashes(moodle_strtolower($tag));
$result[moodle_strtolower($tag)] = null; // key must exists : no value for a key means the tag wasn't found.
}
$tag_string = "'". implode("', '", $tags) ."'";
@@ -396,12 +396,12 @@ function tag_get_id($tags, $return_value=null) {
* - manually added related tags, which are tag_instance entries for that tag
* - correlated tags, which are a calculated
*
* @param string $tag_name_or_id is a single **normalized** tag name or the id
* @param string $tag_name_or_id is a single **normalized** tag name or the id
* of a tag
* @param int $type the function will return either manually
* (TAG_RELATED_MANUAL) related tags or correlated (TAG_RELATED_CORRELATED)
* @param int $type the function will return either manually
* (TAG_RELATED_MANUAL) related tags or correlated (TAG_RELATED_CORRELATED)
* tags. Default is TAG_RELATED_ALL, which returns everything.
* @param int $limitnum return a subset comprising this many records (optional,
* @param int $limitnum return a subset comprising this many records (optional,
* default is 10)
* @return array an array of tag objects
*/
@@ -425,7 +425,7 @@ function tag_get_related_tags($tagid, $type=TAG_RELATED_ALL, $limitnum=10) {
return array_slice(object_array_unique($related_tags), 0 , $limitnum);
}
/**
/**
* Get a comma-separated list of tags related to another tag.
*
* @param array $related_tags the array returned by tag_get_related_tags
@@ -468,13 +468,13 @@ function tag_rename($tagid, $newrawname) {
// Prevent the rename if a tag with that name already exists
if ($existing = tag_get('name', $newname_clean, 'id, name, rawname')) {
if ($existing->id != $tagid) { // Another tag already exists with this name
return false;
return false;
}
}
if ($tag = tag_get('id', $tagid, 'id, name, rawname')) {
$tag->rawname = addslashes($newrawname_clean);
$tag->name = addslashes($newname_clean);
$tag->rawname = addslashes($newrawname_clean);
$tag->name = addslashes($newname_clean);
$tag->timemodified = time();
return update_record('tag', $tag);
}
@@ -484,9 +484,9 @@ function tag_rename($tagid, $newrawname) {
/**
* Delete one or more tag, and all their instances if there are any left.
*
*
* @param mixed $tagids one tagid (int), or one array of tagids to delete
* @return bool true on success, false otherwise
* @return bool true on success, false otherwise
*/
function tag_delete($tagids) {
@@ -499,8 +499,8 @@ function tag_delete($tagids) {
if (is_null($tagid)) { // can happen if tag doesn't exists
continue;
}
// only delete the main entry if there were no problems deleting all the
// instances - that (and the fact we won't often delete lots of tags)
// only delete the main entry if there were no problems deleting all the
// instances - that (and the fact we won't often delete lots of tags)
// is the reason for not using delete_records_select()
if ( delete_records('tag_instance', 'tagid', $tagid) ) {
$success &= (bool) delete_records('tag', 'id', $tagid);
@@ -526,9 +526,9 @@ function tag_delete_instance($record_type, $record_id, $tagid) {
if ( !record_exists_sql("SELECT tg.id ".
"FROM {$CFG->prefix}tag tg ".
"WHERE tg.id = $tagid AND ( tg.tagtype = 'official' OR ".
"EXISTS (SELECT 1
FROM {$CFG->prefix}tag_instance ti
WHERE ti.tagid=$tagid) )") ) {
"EXISTS (SELECT 1
FROM {$CFG->prefix}tag_instance ti
WHERE ti.tagid=$tagid) )") ) {
return tag_delete($tagid);
}
} else {
@@ -550,7 +550,7 @@ function tag_display_name($tagobject, $html=TAG_RETURN_HTML) {
global $CFG;
if(!isset($tagobject->name)) {
if (!isset($tagobject->name)) {
return '';
}
@@ -563,11 +563,14 @@ function tag_display_name($tagobject, $html=TAG_RETURN_HTML) {
$tagname = $tagobject->rawname;
}
// clean up a bit just in case the rules change again
$tagname = clean_param($tagname, PARAM_TAG);
if ($html == TAG_RETURN_TEXT) {
return $tagname;
} else { // TAG_RETURN_HTML
return htmlspecialchars($tagname);
}
}
}
/**
@@ -581,7 +584,7 @@ function tag_display_name($tagobject, $html=TAG_RETURN_HTML) {
* @return array of matching objects, indexed by record id, from the table containing the type requested
*/
function tag_find_records($tag, $type, $limitfrom='', $limitnum='') {
global $CFG;
if (!$tag || !$type) {
@@ -593,8 +596,8 @@ function tag_find_records($tag, $type, $limitfrom='', $limitnum='') {
$query = "SELECT it.* ".
"FROM {$CFG->prefix}{$type} it INNER JOIN {$CFG->prefix}tag_instance tt ON it.id = tt.itemid ".
"WHERE tt.itemtype = '{$type}' AND tt.tagid = '{$tagid}'";
return get_records_sql($query, $limitfrom, $limitnum);
return get_records_sql($query, $limitfrom, $limitnum);
}
@@ -604,20 +607,20 @@ function tag_find_records($tag, $type, $limitfrom='', $limitnum='') {
/////////////////// PRIVATE TAG API ///////////////////
/**
* Adds one or more tag in the database. This function should not be called
* Adds one or more tag in the database. This function should not be called
* directly : you should use tag_set.
*
* @param mixed $tags one tag, or an array of tags, to be created
* @param string $type type of tag to be created ("default" is the default
* @param string $type type of tag to be created ("default" is the default
* value and "official" is the only other supported value at this time). An
* official tag is kept even if there are no records tagged with it.
* @return an array of tags ids, indexed by their lowercase normalized names.
* @return an array of tags ids, indexed by their lowercase normalized names.
* Any boolean false in the array indicates an error while adding the tag.
*/
function tag_add($tags, $type="default") {
global $USER;
require_capability('moodle/tag:create', get_context_instance(CONTEXT_SYSTEM));
require_capability('moodle/tag:create', get_context_instance(CONTEXT_SYSTEM));
if (!is_array($tags)) {
$tags = array($tags);
@@ -636,9 +639,9 @@ function tag_add($tags, $type="default") {
if (!$tag) {
$tags_ids[$tag] = false;
} else {
// note that the difference between rawname and name is only
// capitalization : the rawname is NOT the same at the rawtag.
$tag_object->rawname = addslashes($tag);
// note that the difference between rawname and name is only
// capitalization : the rawname is NOT the same at the rawtag.
$tag_object->rawname = addslashes($tag);
$tag_name_lc = moodle_strtolower($tag);
$tag_object->name = addslashes($tag_name_lc);
//var_dump($tag_object);
@@ -652,10 +655,10 @@ function tag_add($tags, $type="default") {
/**
* Assigns a tag to a record: if the record already exists, the time and
* ordering will be updated.
*
*
* @param string $record_type the type of the record that will be tagged
* @param int $record_id the id of the record that will be tagged
* @param string $tagid the tag id to set on the record.
* @param string $tagid the tag id to set on the record.
* @param int $ordering the order of the instance for this record
* @return bool true on success, false otherwise
*/
@@ -667,7 +670,7 @@ function tag_assign($record_type, $record_id, $tagid, $ordering) {
$tag_instance_object->ordering = $ordering;
$tag_instance_object->timemodified = time();
return update_record('tag_instance', $tag_instance_object);
} else {
} else {
$tag_instance_object = new StdClass;
$tag_instance_object->tagid = $tagid;
$tag_instance_object->itemid = $record_id;
@@ -689,12 +692,12 @@ function tag_autocomplete($text) {
return get_records_sql("SELECT tg.id, tg.name, tg.rawname FROM {$CFG->prefix}tag tg WHERE tg.name LIKE '". moodle_strtolower($text) ."%'");
}
/**
/**
* Clean up the tag tables, making sure all tagged object still exists.
*
* This should normally not be necessary, but in case related tags are not deleted
* when the tagged record is removed, this should be done once in a while, perhaps on
* an occasional cron run. On a site with lots of tags, this could become an expensive
* an occasional cron run. On a site with lots of tags, this could become an expensive
* function to call: don't run at peak time.
*/
function tag_cleanup() {
@@ -705,7 +708,7 @@ function tag_cleanup() {
// cleanup tag instances
while ($instance = rs_fetch_next_record($instances)) {
$delete = false;
if (!record_exists('tag', 'id', $instance->tagid)) {
// if the tag has been removed, instance should be deleted.
$delete = true;
@@ -775,11 +778,11 @@ function tag_compute_correlations($min_correlation=2) {
"WHERE ta.tagid = {$tag->id} AND tb.tagid != {$tag->id} ".
"GROUP BY tb.tagid ".
"HAVING COUNT(*) > $min_correlation ".
"ORDER BY COUNT(*) DESC";
"ORDER BY COUNT(*) DESC";
$correlated = array();
// Correlated tags happen when they appear together in more occasions
// Correlated tags happen when they appear together in more occasions
// than $min_correlation.
if ($tag_correlations = get_records_sql($query)) {
foreach($tag_correlations as $correlation) {
@@ -847,9 +850,9 @@ function tag_find_tags($text, $ordered=true, $limitfrom='', $limitnum='') {
return get_records_sql($query, $limitfrom , $limitnum);
}
/**
/**
* Get the name of a tag
*
*
* @param mixed $tagids the id of the tag, or an array of ids
* @return mixed string name of one tag, or id-indexed array of strings
*/
@@ -862,7 +865,7 @@ function tag_get_name($tagids) {
}
$tag_names = array();
foreach(get_records_list('tag', 'id', implode(',', $tagids)) as $tag) {
foreach(get_records_list('tag', 'id', implode(',', $tagids)) as $tag) {
$tag_names[$tag->id] = $tag->name;
}
@@ -875,7 +878,7 @@ function tag_get_name($tagids) {
/**
* Returns the correlated tags of a tag, retrieved from the tag_correlation
* table. Make sure cron runs, otherwise the table will be empty and this
* table. Make sure cron runs, otherwise the table will be empty and this
* function won't return anything.
*
* @param int $tag_id is a single tag id
@@ -889,14 +892,14 @@ function tag_get_correlated($tag_id, $limitnum=null) {
if (!$tag_correlation || empty($tag_correlation->correlatedtags)) {
return array();
}
// this is (and has to) return the same fields as the query in tag_get_tags
if ( !$result = get_records_sql("SELECT tg.id, tg.tagtype, tg.name, tg.rawname, tg.flag, ti.ordering ".
"FROM {$CFG->prefix}tag tg INNER JOIN {$CFG->prefix}tag_instance ti ON tg.id = ti.tagid ".
"WHERE tg.id IN ({$tag_correlation->correlatedtags})") ) {
return array();
}
return $result;
}
@@ -904,9 +907,9 @@ function tag_get_correlated($tag_id, $limitnum=null) {
* Function that normalizes a list of tag names.
*
* @param mixed $tags array of tags, or a single tag.
* @param int $case case to use for returned value (default: lower case).
* @param int $case case to use for returned value (default: lower case).
* Either TAG_CASE_LOWER (default) or TAG_CASE_ORIGINAL
* @return array of lowercased normalized tags, indexed by the normalized tag,
* @return array of lowercased normalized tags, indexed by the normalized tag,
* in the same order as the original array. (Eg: 'Banana' => 'banana').
*/
function tag_normalize($rawtags, $case = TAG_CASE_LOWER) {
@@ -929,13 +932,13 @@ function tag_normalize($rawtags, $case = TAG_CASE_LOWER) {
$cleaned_tags_lc[$rawtag] = moodle_strtolower( clean_param($rawtag, PARAM_TAG) );
$cleaned_tags_mc[$rawtag] = clean_param($rawtag, PARAM_TAG);
}
if ( $case == TAG_CASE_LOWER ) {
if ( $case == TAG_CASE_LOWER ) {
$result[$rawtag] = $cleaned_tags_lc[$rawtag];
} else { // TAG_CASE_ORIGINAL
$result[$rawtag] = $cleaned_tags_mc[$rawtag];
}
}
return $result;
}
@@ -951,7 +954,7 @@ function tag_record_count($record_type, $tagid) {
}
/**
* Determine if a record is tagged with a specific tag
* Determine if a record is tagged with a specific tag
*
* @param string $record_type the record type to look for
* @param int $record_id the record id to look for
@@ -968,7 +971,7 @@ function tag_record_tagged_with($record_type, $record_id, $tag) {
/**
* Flag a tag as inapropriate
*
*
* @param mixed $tagids one (int) tagid, or an array of tagids
* @return void
*/
@@ -984,9 +987,9 @@ function tag_set_flag($tagids) {
}
}
/**
/**
* Remove the inapropriate flag on a tag
*
*
* @param mixed $tagids one (int) tagid, or an array of tagids
* @return bool true if function succeeds, false otherwise
*/
+11 -2
View File
@@ -9,11 +9,20 @@ if (empty($CFG->usetags)) {
print_error('tagsaredisabled', 'tag');
}
$query = addslashes(optional_param('query', '', PARAM_RAW));
/// Headers to make it not cacheable and json
@header('Content-type: application/json; charset=utf-8');
@header('Cache-Control: no-store, no-cache, must-revalidate');
@header('Cache-Control: post-check=0, pre-check=0', false);
@header('Pragma: no-cache');
@header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
@header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
@header('Accept-Ranges: none');
$query = optional_param('query', '', PARAM_RAW);
if ($similar_tags = tag_autocomplete($query)) {
foreach ($similar_tags as $tag) {
echo $tag->name . "\t" . tag_display_name($tag) . "\n";
echo clean_param($tag->name, PARAM_TAG) . "\t" . tag_display_name($tag) . "\n";
}
}
+1 -1
View File
@@ -308,7 +308,7 @@ form.mform div.textarea textarea {
width:30px
}
#course-view .section .left a {
display:none
/* display:none */
}
#course-view .section .spacer {
height:2em
+1 -1
View File
@@ -486,7 +486,7 @@ img.iconkbhelp {
font-size:1em;
}
.dir-rtl .accesshide {
right:-10000px;
top:-30000px;
left:auto;
}
-1
View File
@@ -27,7 +27,6 @@ class user_edit_form extends moodleform {
useredit_shared_definition($mform);
/// extra settigs
$mform->addRule('description', $strrequired, 'required', null, 'client');
if (!empty($CFG->gdversion) and !empty($CFG->disableuserimages)) {
$mform->removeElement('deletepicture');
$mform->removeElement('imagefile');
+2 -2
View File
@@ -6,10 +6,10 @@
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
$version = 2007101591.00; // YYYYMMDD = date of the 1.9 branch (don't change)
$version = 2007101591.03; // YYYYMMDD = date of the 1.9 branch (don't change)
// X = release number 1.9.[0,1,2,3,4,5...]
// Y.YY = micro-increments between releases
$release = '1.9.10 (Build: 20101025)'; // Human-friendly version name
$release = '1.9.12 (Build: 20110510)'; // Human-friendly version name
?>