Merge branch 'w12_MDL-29894_m23_objectparams' of git://github.com/skodak/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 20 Mar 2012 08:40:28 +0000 (16:40 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 20 Mar 2012 08:40:28 +0000 (16:40 +0800)
275 files changed:
admin/cron.php
admin/index.php
admin/mnet/peer_forms.php
admin/roles/override.php
admin/settings/security.php
admin/tool/unittest/dbtest.php
admin/tool/unittest/index.php
admin/tool/xmldb/actions/XMLDBAction.class.php
auth/cas/auth.php
auth/cas/config.html
auth/db/config.html
auth/email/auth.php
auth/email/config.html
auth/fc/config.html
auth/imap/config.html
auth/ldap/config.html
auth/manual/config.html
auth/mnet/config.html
auth/nntp/config.html
auth/none/config.html
auth/pam/config.html
auth/pop3/config.html
auth/shibboleth/config.html
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
blocks/quiz_results/block_quiz_results.php
calendar/lib.php
calendar/renderer.php
course/category.php
course/edit.php
course/edit_form.php
course/editcategory.php
course/index.php
course/lib.php
course/modedit.php
course/recent.php
course/reset_form.php
course/view.php
enrol/database/lib.php
grade/edit/tree/lib.php
grade/export/grade_export_form.php
grade/import/grade_import_form.php
grade/report/grader/index.php
grade/report/grader/lib.php
group/group.php
group/members.php
lang/en/admin.php
lang/en/blog.php
lang/en/message.php
lang/en/moodle.php
lib/authlib.php
lib/blocklib.php
lib/cronlib.php
lib/csslib.php
lib/csvlib.class.php
lib/db/install.xml
lib/db/upgrade.php
lib/enrollib.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/form/duration.php
lib/form/editor.php
lib/form/header.php
lib/form/tags.php
lib/formslib.php
lib/grade/grade_category.php
lib/grade/grade_grade.php
lib/grade/grade_scale.php
lib/javascript.php
lib/minify/README.txt [deleted file]
lib/minify/builder/_index.js [deleted file]
lib/minify/builder/bm.js [deleted file]
lib/minify/builder/index.php [deleted file]
lib/minify/builder/ocCheck.php [deleted file]
lib/minify/builder/rewriteTest.js [deleted file]
lib/minify/config.php
lib/minify/groupsConfig.php
lib/minify/lib/FirePHP.php
lib/minify/lib/HTTP/ConditionalGet.php
lib/minify/lib/HTTP/Encoder.php
lib/minify/lib/JSMin.php
lib/minify/lib/JSMinPlus.php
lib/minify/lib/Minify.php
lib/minify/lib/Minify/CSS.php
lib/minify/lib/Minify/CSS/Compressor.php
lib/minify/lib/Minify/CSS/UriRewriter.php
lib/minify/lib/Minify/Cache/APC.php
lib/minify/lib/Minify/Cache/File.php
lib/minify/lib/Minify/Cache/Memcache.php
lib/minify/lib/Minify/Cache/ZendPlatform.php [new file with mode: 0644]
lib/minify/lib/Minify/CommentPreserver.php
lib/minify/lib/Minify/Controller/Base.php
lib/minify/lib/Minify/Controller/Groups.php
lib/minify/lib/Minify/Controller/MinApp.php
lib/minify/lib/Minify/Controller/Page.php
lib/minify/lib/Minify/Controller/Version1.php
lib/minify/lib/Minify/DebugDetector.php [new file with mode: 0644]
lib/minify/lib/Minify/HTML.php
lib/minify/lib/Minify/HTML/Helper.php [new file with mode: 0644]
lib/minify/lib/Minify/ImportProcessor.php
lib/minify/lib/Minify/JS/ClosureCompiler.php [new file with mode: 0644]
lib/minify/lib/Minify/Lines.php
lib/minify/lib/Minify/Logger.php
lib/minify/lib/Minify/YUI/CssCompressor.java [new file with mode: 0644]
lib/minify/lib/Minify/YUI/CssCompressor.php [new file with mode: 0644]
lib/minify/lib/Minify/YUICompressor.php
lib/minify/lib/MrClay/Cli.php [new file with mode: 0644]
lib/minify/lib/MrClay/Cli/Arg.php [new file with mode: 0644]
lib/minify/lib/Solar/Dir.php [deleted file]
lib/minify/readme_moodle.txt
lib/minify/utils.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputlib.php
lib/pear/HTML/QuickForm.php
lib/pear/HTML/QuickForm/RuleRegistry.php
lib/pear/HTML/QuickForm/advcheckbox.php
lib/pear/HTML/QuickForm/header.php
lib/pear/HTML/QuickForm/hidden.php
lib/pear/HTML/QuickForm/hiddenselect.php
lib/pear/HTML/QuickForm/html.php
lib/portfolio/forms.php
lib/searchlib.php
lib/setuplib.php
lib/thirdpartylibs.xml
lib/upgradelib.php
message/edit.php
message/lib.php
mod/assignment/db/access.php
mod/assignment/lang/en/assignment.php
mod/assignment/lib.php
mod/assignment/type/offline/assignment.class.php
mod/assignment/type/online/assignment.class.php
mod/assignment/type/upload/assignment.class.php
mod/assignment/type/uploadsingle/assignment.class.php
mod/assignment/version.php
mod/chat/db/access.php
mod/chat/lang/en/chat.php
mod/chat/lib.php
mod/chat/version.php
mod/choice/db/access.php
mod/choice/lang/en/choice.php
mod/choice/mod_form.php
mod/choice/version.php
mod/data/db/access.php
mod/data/export_form.php
mod/data/lang/en/data.php
mod/data/version.php
mod/feedback/db/access.php
mod/feedback/lang/en/feedback.php
mod/feedback/lib.php
mod/feedback/version.php
mod/folder/db/access.php
mod/folder/edit.php
mod/folder/lang/en/folder.php
mod/folder/version.php
mod/forum/db/access.php
mod/forum/index.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/version.php
mod/glossary/db/access.php
mod/glossary/lang/en/glossary.php
mod/glossary/lib.php
mod/glossary/version.php
mod/imscp/db/access.php
mod/imscp/lang/en/imscp.php
mod/imscp/version.php
mod/label/db/access.php [new file with mode: 0644]
mod/label/lang/en/label.php
mod/label/version.php
mod/lesson/db/access.php
mod/lesson/lang/en/lesson.php
mod/lesson/locallib.php
mod/lesson/pagetypes/branchtable.php
mod/lesson/pagetypes/endofbranch.php
mod/lesson/pagetypes/endofcluster.php
mod/lesson/pagetypes/essay.php
mod/lesson/pagetypes/matching.php
mod/lesson/pagetypes/truefalse.php
mod/lesson/version.php
mod/lti/db/access.php
mod/lti/lang/en/lti.php
mod/lti/version.php
mod/page/db/access.php
mod/page/lang/en/page.php
mod/page/version.php
mod/quiz/attempt.php
mod/quiz/attemptlib.php
mod/quiz/backup/moodle2/backup_quiz_stepslib.php
mod/quiz/db/access.php
mod/quiz/db/install.xml
mod/quiz/db/upgrade.php
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/mod_form.php
mod/quiz/module.js
mod/quiz/renderer.php
mod/quiz/settings.php
mod/quiz/styles.css
mod/quiz/version.php
mod/resource/db/access.php
mod/resource/lang/en/resource.php
mod/resource/version.php
mod/scorm/db/access.php
mod/scorm/lang/en/scorm.php
mod/scorm/version.php
mod/survey/db/access.php
mod/survey/lang/en/survey.php
mod/survey/version.php
mod/upgrade.txt
mod/url/db/access.php
mod/url/lang/en/url.php
mod/url/version.php
mod/wiki/admin.php
mod/wiki/comments.php
mod/wiki/create.php
mod/wiki/db/access.php
mod/wiki/diff.php
mod/wiki/edit.php
mod/wiki/history.php
mod/wiki/index.php
mod/wiki/instancecomments.php
mod/wiki/lang/en/wiki.php
mod/wiki/lib.php
mod/wiki/lock.php
mod/wiki/map.php
mod/wiki/overridelocks.php
mod/wiki/pagelib.php
mod/wiki/prettyview.php
mod/wiki/restoreversion.php
mod/wiki/version.php
mod/wiki/view.php
mod/wiki/viewversion.php
mod/workshop/db/access.php
mod/workshop/lang/en/workshop.php
mod/workshop/lib.php
mod/workshop/version.php
question/behaviour/deferredcbm/behaviour.php
question/behaviour/immediatecbm/behaviour.php
question/category_class.php
question/editlib.php
question/engine/bank.php
question/engine/questionattempt.php
question/engine/simpletest/testquestionattempt.php
question/format/aiken/format.php
question/format/blackboard/format.php
question/format/blackboard_six/format.php
question/format/examview/format.php
question/format/learnwise/format.php
question/format/multianswer/format.php
question/format/webct/format.php
question/format/xml/format.php
question/qbank.js
question/type/calculated/edit_calculated_form.php
question/type/calculatedmulti/edit_calculatedmulti_form.php
question/type/multianswer/questiontype.php
question/type/numerical/edit_numerical_form.php
repository/coursefiles/lib.php
repository/filepicker.js
repository/lib.php
repository/local/lib.php
repository/merlot/lib.php
repository/recent/lib.php
repository/repository_ajax.php
repository/s3/lib.php
repository/upload/lib.php
repository/user/lib.php
rss/file.php
theme/base/style/course.css
theme/fusion/layout/frontpage.php
theme/fusion/settings.php
user/filters/checkbox.php
version.php
webservice/xmlrpc/lib.php

index 5b473a3..cce8ae3 100644 (file)
@@ -81,6 +81,9 @@ if (check_browser_version('MSIE')) {
     @header('Content-Type: text/plain; charset=utf-8');
 }
 
+// we do not want html markup in emulated CLI
+@ini_set('html_errors', 'off');
+
 // execute the cron
 cron_run();
 
index 70dcafa..5baad8c 100644 (file)
@@ -307,7 +307,8 @@ if (during_initial_install()) {
     }
 
     // at this stage there can be only one admin unless more were added by install - users may change username, so do not rely on that
-    $adminuser = get_complete_user_data('id', reset(explode(',', $CFG->siteadmins)));
+    $adminids = explode(',', $CFG->siteadmins);
+    $adminuser = get_complete_user_data('id', reset($adminids));
 
     if ($adminuser->password === 'adminsetuppending') {
         // prevent installation hijacking
index 4c5243b..4725e1f 100644 (file)
@@ -141,10 +141,10 @@ class mnet_review_host_form extends moodleform {
 
         if ($mnet_peer && !empty($mnet_peer->deleted)) {
             $radioarray = array();
-            $radioarray[] = MoodleQuickForm::createElement('static', 'deletedinfo', '',
+            $radioarray[] = $mform->createElement('static', 'deletedinfo', '',
                 $OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'deletedhostinfo'));
-            $radioarray[] = MoodleQuickForm::createElement('radio', 'deleted', '', get_string('yes'), 1);
-            $radioarray[] = MoodleQuickForm::createElement('radio', 'deleted', '', get_string('no'), 0);
+            $radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('yes'), 1);
+            $radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('no'), 0);
             $mform->addGroup($radioarray, 'radioar', get_string('deleted'), array(' ', ' '), false);
         } else {
             $mform->addElement('hidden', 'deleted');
index 9cd3ce5..ff6848d 100644 (file)
@@ -50,8 +50,10 @@ if ($course) {
 
 // security first
 require_login($course, false, $cm);
+$safeoverridesonly = false;
 if (!has_capability('moodle/role:override', $context)) {
     require_capability('moodle/role:safeoverride', $context);
+    $safeoverridesonly = true;
 }
 $PAGE->set_url($url);
 $PAGE->set_context($context);
@@ -119,7 +121,7 @@ if (empty($overridableroles[$roleid])) {
 }
 
 // If we are actually overriding a role, create the table object, and save changes if appropriate.
-$overridestable = new override_permissions_table_advanced($context, $roleid, false);
+$overridestable = new override_permissions_table_advanced($context, $roleid, $safeoverridesonly);
 $overridestable->read_submitted_permissions();
 
 if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
index 6e499ac..189bf87 100644 (file)
@@ -86,19 +86,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $ADMIN->add('security', $temp);
 
 
-    // "modulesecurity" settingpage
-    $temp = new admin_settingpage('modulesecurity', new lang_string('modulesecurity', 'admin'));
-    $temp->add(new admin_setting_configselect('restrictmodulesfor', new lang_string('restrictmodulesfor', 'admin'), new lang_string('configrestrictmodulesfor', 'admin'), 'none', array('none' => new lang_string('nocourses'),
-                                                                                                                                                                              'all' => new lang_string('fulllistofcourses'),
-                                                                                                                                                                              'requested' => new lang_string('requestedcourses'))));
-    $temp->add(new admin_setting_configcheckbox('restrictbydefault', new lang_string('restrictbydefault', 'admin'), new lang_string('configrestrictbydefault', 'admin'), 0));
-    $temp->add(new admin_setting_configmultiselect_modules('defaultallowedmodules',
-            new lang_string('defaultallowedmodules', 'admin'),
-            new lang_string('configdefaultallowedmodules', 'admin')));
-    $ADMIN->add('security', $temp);
-
-
-
     // "notifications" settingpage
     $temp = new admin_settingpage('notifications', new lang_string('notifications', 'admin'));
     $temp->add(new admin_setting_configselect('displayloginfailures', new lang_string('displayloginfailures', 'admin'), new lang_string('configdisplayloginfailures', 'admin'), '', array('' => new lang_string('nobody'),
index 8a0a60c..e5e2eb1 100644 (file)
@@ -27,6 +27,11 @@ define('NO_OUTPUT_BUFFERING', true);
 
 require(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir.'/adminlib.php');
+
+// unfortunately outdated SimpleTest is not E_STRICT compatible
+$CFG->debug = ($CFG->debug & ~E_STRICT);
+error_reporting($CFG->debug);
+
 require_once('simpletestlib.php');
 require_once('simpletestcoveragelib.php');
 require_once('ex_simple_test.php');
index 4deef62..62a60a7 100644 (file)
@@ -28,16 +28,18 @@ define('NO_OUTPUT_BUFFERING', true);
 
 require(dirname(__FILE__) . '/../../../config.php');
 require_once($CFG->libdir.'/adminlib.php');
-require_once('simpletestlib.php');
-require_once('simpletestcoveragelib.php');
-require_once('ex_simple_test.php');
-require_once('ex_reporter.php');
 
 // Always run the unit tests in developer debug mode.
-$CFG->debug = DEBUG_DEVELOPER;
+// unfortunately outdated SimpleTest is not E_STRICT compatible
+$CFG->debug = (DEBUG_DEVELOPER & ~E_STRICT);
 error_reporting($CFG->debug);
 raise_memory_limit(MEMORY_EXTRA);
 
+require_once('simpletestlib.php');
+require_once('simpletestcoveragelib.php');
+require_once('ex_simple_test.php');
+require_once('ex_reporter.php');
+
 // page parameters
 $path         = optional_param('path', null, PARAM_PATH);
 $showpasses   = optional_param('showpasses', false, PARAM_BOOL);
index b853a7e..d984894 100644 (file)
@@ -54,18 +54,11 @@ class XMLDBAction {
 
     var $sesskey_protected; // Actions must be protected by sesskey mechanism
 
-    /**
-     * Constructor
-     */
-    function XMLDBAction() {
-        $this->init();
-    }
-
     /**
      * Constructor to keep PHP5 happy
      */
     function __construct() {
-        $this->XMLDBAction();
+        $this->init();
     }
 
     /**
index fa6fb0f..d8c9523 100644 (file)
@@ -215,7 +215,7 @@ class auth_plugin_cas extends auth_plugin_ldap {
      * @param object object with submitted configuration settings (without system magic quotes)
      * @param array $err array of error messages
      */
-    function validate_form(&$form, &$err) {
+    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_cas');
index 81894ea..4781cb9 100644 (file)
@@ -437,6 +437,6 @@ $help .= get_string('auth_updateremote_expl', 'auth');
 $help .= '<hr />';
 $help .= get_string('auth_updateremote_ldap', 'auth');
 
-print_auth_lock_options('cas', $user_fields, $help, true, true);
+print_auth_lock_options($this->authtype, $user_fields, $help, true, true);
 ?>
 </table>
index 63d014c..94d981b 100644 (file)
 
 <?php
 
-print_auth_lock_options('db', $user_fields, get_string('auth_dbextrafields', 'auth_db'), true, true);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_dbextrafields', 'auth_db'), true, true);
 
 ?>
 </table>
index 4436097..0051aaf 100644 (file)
@@ -127,7 +127,7 @@ class auth_plugin_email extends auth_plugin_base {
             if ($user->confirmed) {
                 return AUTH_CONFIRM_ALREADY;
 
-            } else if ($user->auth != 'email') {
+            } else if ($user->auth != $this->authtype) {
                 return AUTH_CONFIRM_ERROR;
 
             } else if ($user->secret == $confirmsecret) {   // They have provided the secret key to get in
index 095171e..1b26e3f 100644 (file)
@@ -25,7 +25,7 @@
 </tr>
 <?php
 
-print_auth_lock_options('email', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index 9f44af1..91dd8c8 100644 (file)
@@ -97,7 +97,7 @@
 
 <?php
 
-print_auth_lock_options('fc', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index d604b47..d88ad3a 100644 (file)
@@ -87,7 +87,7 @@ if (!isset($config->changepasswordurl)) {
 
 <?php
 
-print_auth_lock_options('imap', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index 25c6786..72519c7 100644 (file)
@@ -547,6 +547,6 @@ $help .= get_string('auth_updateremote_expl', 'auth');
 $help .= '<hr />';
 $help .= get_string('auth_updateremote_ldap', 'auth');
 
-print_auth_lock_options('ldap', $user_fields, $help, true, true);
+print_auth_lock_options($this->authtype, $user_fields, $help, true, true);
 ?>
 </table>
index 9caa591..8c03ce0 100644 (file)
@@ -1,5 +1,5 @@
 <table cellspacing="0" cellpadding="5" border="0">
 <?php
-print_auth_lock_options('manual', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 ?>
 </table>
index 5fc988b..2dbba3f 100644 (file)
@@ -88,7 +88,7 @@ foreach($service_providers as $host) {
 <?php
 }
 
-// print_auth_lock_options('mnet', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+// print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index 5d50324..179efdd 100644 (file)
@@ -68,7 +68,7 @@ if (!isset($config->changepasswordurl)) {
 
 <?php
 
-print_auth_lock_options('nntp', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index abeada0..0068836 100644 (file)
@@ -4,7 +4,7 @@
 <table cellspacing="0" cellpadding="5" border="0">
 <?php
 
-print_auth_lock_options('none', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index f2f6f1a..0068836 100644 (file)
@@ -4,7 +4,7 @@
 <table cellspacing="0" cellpadding="5" border="0">
 <?php
 
-print_auth_lock_options('pam', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index 8726b28..e2d7e7a 100644 (file)
@@ -105,7 +105,7 @@ if (!isset($config->changepasswordurl)) {
 
 <?php
 
-print_auth_lock_options('pop3', $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
+print_auth_lock_options($this->authtype, $user_fields, get_string('auth_fieldlocks_help', 'auth'), false, false);
 
 ?>
 </table>
index b15b17a..8eff5f2 100644 (file)
@@ -138,7 +138,7 @@ urn:mace:organization2:providerID, Example Organization 2, /Shibboleth.sso/WAYF/
 
 <?php
 
-print_auth_lock_options('shibboleth', $user_fields, '<!-- empty help -->', true, false);
+print_auth_lock_options($this->authtype, $user_fields, '<!-- empty help -->', true, false);
 
 ?>
 </table>
index 78d2721..e22ff35 100644 (file)
@@ -403,7 +403,7 @@ class backup_course_structure_step extends backup_structure_step {
             'visible', 'hiddensections', 'groupmode', 'groupmodeforce',
             'defaultgroupingid', 'lang', 'theme',
             'timecreated', 'timemodified',
-            'requested', 'restrictmodules',
+            'requested',
             'enablecompletion', 'completionstartonenrol', 'completionnotify'));
 
         $category = new backup_nested_element('category', array('id'), array(
@@ -414,10 +414,6 @@ class backup_course_structure_step extends backup_structure_step {
         $tag = new backup_nested_element('tag', array('id'), array(
             'name', 'rawname'));
 
-        $allowedmodules = new backup_nested_element('allowed_modules');
-
-        $module = new backup_nested_element('module', array(), array('modulename'));
-
         // attach format plugin structure to $course element, only one allowed
         $this->add_plugin_structure('format', $course, false);
 
@@ -444,9 +440,6 @@ class backup_course_structure_step extends backup_structure_step {
         $course->add_child($tags);
         $tags->add_child($tag);
 
-        $course->add_child($allowedmodules);
-        $allowedmodules->add_child($module);
-
         // Set the sources
 
         $courserec = $DB->get_record('course', array('id' => $this->task->get_courseid()));
@@ -466,11 +459,6 @@ class backup_course_structure_step extends backup_structure_step {
                                      backup_helper::is_sqlparam('course'),
                                      backup::VAR_PARENTID));
 
-        $module->set_source_sql('SELECT m.name AS modulename
-                                   FROM {modules} m
-                                   JOIN {course_allowed_modules} cam ON m.id = cam.module
-                                  WHERE course = ?', array(backup::VAR_COURSEID));
-
         // Some annotations
 
         $course->annotate_ids('grouping', 'defaultgroupingid');
index 58048ec..6dd757e 100644 (file)
@@ -1069,6 +1069,21 @@ class restore_section_structure_step extends restore_structure_step {
  * the course record (never inserting)
  */
 class restore_course_structure_step extends restore_structure_step {
+    /**
+     * @var bool this gets set to true by {@link process_course()} if we are
+     * restoring an old coures that used the legacy 'module security' feature.
+     * If so, we have to do more work in {@link after_execute()}.
+     */
+    protected $legacyrestrictmodules = false;
+
+    /**
+     * @var array Used when {@link $legacyrestrictmodules} is true. This is an
+     * array with array keys the module names ('forum', 'quiz', etc.). These are
+     * the modules that are allowed according to the data in the backup file.
+     * In {@link after_execute()} we then have to prevent adding of all the other
+     * types of activity.
+     */
+    protected $legacyallowedmodules = array();
 
     protected function define_structure() {
 
@@ -1131,8 +1146,9 @@ class restore_course_structure_step extends restore_structure_step {
             $data->hiddensections = 0;
         }
 
-        // Only restrict modules if original course was and target site too for new courses
-        $data->restrictmodules = $data->restrictmodules && !empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all';
+        // Set legacyrestrictmodules to true if the course was resticting modules. If so
+        // then we will need to process restricted modules after execution.
+        $this->legacyrestrictmodules = !empty($data->restrictmodules);
 
         $data->startdate= $this->apply_date_offset($data->startdate);
         if ($data->defaultgroupingid) {
@@ -1187,31 +1203,44 @@ class restore_course_structure_step extends restore_structure_step {
     }
 
     public function process_allowed_module($data) {
-        global $CFG, $DB;
-
         $data = (object)$data;
 
-        // only if enabled by admin setting
-        if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all') {
-            $available = get_plugin_list('mod');
-            $mname = $data->modulename;
-            if (array_key_exists($mname, $available)) {
-                if ($module = $DB->get_record('modules', array('name' => $mname, 'visible' => 1))) {
-                    $rec = new stdclass();
-                    $rec->course = $this->get_courseid();
-                    $rec->module = $module->id;
-                    if (!$DB->record_exists('course_allowed_modules', (array)$rec)) {
-                        $DB->insert_record('course_allowed_modules', $rec);
-                    }
-                }
-            }
+        // Backwards compatiblity support for the data that used to be in the
+        // course_allowed_modules table.
+        if ($this->legacyrestrictmodules) {
+            $this->legacyallowedmodules[$data->modulename] = 1;
         }
     }
 
     protected function after_execute() {
+        global $DB;
+
         // Add course related files, without itemid to match
         $this->add_related_files('course', 'summary', null);
         $this->add_related_files('course', 'legacy', null);
+
+        // Deal with legacy allowed modules.
+        if ($this->legacyrestrictmodules) {
+            $context = context_course::instance($this->get_courseid());
+
+            list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
+            list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
+            foreach ($managerroleids as $roleid) {
+                unset($roleids[$roleid]);
+            }
+
+            foreach (get_plugin_list('mod') as $modname => $notused) {
+                if (isset($this->legacyallowedmodules[$modname])) {
+                    // Module is allowed, no worries.
+                    continue;
+                }
+
+                $capability = 'mod/' . $modname . ':addinstance';
+                foreach ($roleids as $roleid) {
+                    assign_capability($capability, CAP_PREVENT, $roleid, $context);
+                }
+            }
+        }
     }
 }
 
index a8d24e5..7ea73f0 100644 (file)
@@ -76,7 +76,7 @@ class block_quiz_results extends block_base {
         return $cm->instance;
     }
 
-    function instance_config_save($data) {
+    function instance_config_save($data, $nolongerused = false) {
         if (empty($data->quizid)) {
             $data->quizid = $this->get_owning_quiz();
         }
index 645ae18..7280f14 100644 (file)
@@ -497,7 +497,7 @@ function calendar_get_upcoming($courses, $groups, $users, $daysinfuture, $maxeve
 
     if ($events !== false) {
 
-        $modinfo =& get_fast_modinfo($COURSE);
+        $modinfo = get_fast_modinfo($COURSE);
 
         foreach($events as $event) {
 
index 312c572..ade2f63 100644 (file)
@@ -413,6 +413,8 @@ class core_calendar_renderer extends plugin_renderer_base {
 
         $table = new html_table();
         $table->attributes = array('class'=>'calendarmonth calendartable');
+        $time = make_timestamp($calendar->year, $calendar->month);
+        $table->summary = get_string('calendarheading', 'calendar', userdate($time, get_string('strftimemonthyear')));
         $table->data = array();
 
         $header = new html_table_row();
index 27f4653..64ebaaa 100644 (file)
 <?php
-      // Displays the top level category or all courses
-      // In editing mode, allows the admin to edit a category,
-      // and rearrange courses
-
-    require_once("../config.php");
-    require_once("lib.php");
-
-    $id = required_param('id', PARAM_INT); // Category id
-    $page = optional_param('page', 0, PARAM_INT); // which page to show
-    $perpage = optional_param('perpage', $CFG->coursesperpage, PARAM_INT); // how many per page
-    $categoryedit = optional_param('categoryedit', -1, PARAM_BOOL);
-    $hide = optional_param('hide', 0, PARAM_INT);
-    $show = optional_param('show', 0, PARAM_INT);
-    $moveup = optional_param('moveup', 0, PARAM_INT);
-    $movedown = optional_param('movedown', 0, PARAM_INT);
-    $moveto = optional_param('moveto', 0, PARAM_INT);
-    $resort = optional_param('resort', 0, PARAM_BOOL);
-
-    $site = get_site();
-
-    if (empty($id)) {
-        print_error("unknowcategory");
-    }
-
-    $PAGE->set_category_by_id($id);
-    $urlparams = array('id' => $id);
-    if ($page) {
-        $urlparams['page'] = $page;
-    }
-    if ($perpage) {
-        $urlparams['perpage'] = $perpage;
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Displays the top level category or all courses
+ * In editing mode, allows the admin to edit a category,
+ * and rearrange courses
+ *
+ * @package    core
+ * @subpackage course
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("../config.php");
+require_once($CFG->dirroot.'/course/lib.php');
+
+$id = required_param('id', PARAM_INT); // Category id
+$page = optional_param('page', 0, PARAM_INT); // which page to show
+$perpage = optional_param('perpage', $CFG->coursesperpage, PARAM_INT); // how many per page
+$categoryedit = optional_param('categoryedit', -1, PARAM_BOOL);
+$hide = optional_param('hide', 0, PARAM_INT);
+$show = optional_param('show', 0, PARAM_INT);
+$moveup = optional_param('moveup', 0, PARAM_INT);
+$movedown = optional_param('movedown', 0, PARAM_INT);
+$moveto = optional_param('moveto', 0, PARAM_INT);
+$resort = optional_param('resort', 0, PARAM_BOOL);
+$sesskey = optional_param('sesskey', '', PARAM_RAW);
+
+if (empty($id)) {
+    print_error("unknowcategory");
+}
+
+$PAGE->set_category_by_id($id);
+$PAGE->set_url(new moodle_url('/course/category.php', array('id' => $id)));
+// This is sure to be the category context
+$context = $PAGE->context;
+// And the object has been loaded for us no need for another DB call
+$category = $PAGE->category;
+
+$canedit = can_edit_in_category($category->id);
+if ($canedit) {
+    if ($categoryedit !== -1) {
+        $USER->editing = $categoryedit;
     }
-    $PAGE->set_url(new moodle_url('/course/category.php', array('id' => $id)));
-    navigation_node::override_active_url($PAGE->url);
-    $context = $PAGE->context;
-    $category = $PAGE->category;
-
-    $canedit = can_edit_in_category($category->id);
-    if ($canedit) {
-        if ($categoryedit !== -1) {
-            $USER->editing = $categoryedit;
-        }
+    require_login();
+    $editingon = $PAGE->user_is_editing();
+} else {
+    if ($CFG->forcelogin) {
         require_login();
-        $editingon = $PAGE->user_is_editing();
-    } else {
-        if ($CFG->forcelogin) {
-            require_login();
+    }
+    $editingon = false;
+}
+
+if (!$category->visible) {
+    require_capability('moodle/category:viewhiddencategories', $context);
+}
+
+$canmanage = has_capability('moodle/category:manage', $context);
+$sesskeyprovided = !empty($sesskey) && confirm_sesskey($sesskey);
+
+// Process any category actions.
+if ($canmanage && $resort && $sesskeyprovided) {
+    // Resort the category if requested
+    if ($courses = get_courses($category->id, "fullname ASC", 'c.id,c.fullname,c.sortorder')) {
+        $i = 1;
+        foreach ($courses as $course) {
+            $DB->set_field('course', 'sortorder', $category->sortorder+$i, array('id'=>$course->id));
+            $i++;
         }
-        $editingon = false;
+        fix_course_sortorder(); // should not be needed
     }
+}
 
-    if (!$category->visible) {
-        require_capability('moodle/category:viewhiddencategories', $context);
-    }
+// Process any course actions.
+if ($editingon && $sesskeyprovided) {
 
-    // Process any category actions.
-    if (has_capability('moodle/category:manage', $context)) {
-        /// Resort the category if requested
-        if ($resort and confirm_sesskey()) {
-            if ($courses = get_courses($category->id, "fullname ASC", 'c.id,c.fullname,c.sortorder')) {
-                $i = 1;
-                foreach ($courses as $course) {
-                    $DB->set_field('course', 'sortorder', $category->sortorder+$i, array('id'=>$course->id));
-                    $i++;
-                }
-                fix_course_sortorder(); // should not be needed
-            }
+    // Move a specified course to a new category
+    if (!empty($moveto) and $data = data_submitted()) {
+        // Some courses are being moved
+        // user must have category update in both cats to perform this
+        require_capability('moodle/category:manage', $context);
+        require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $moveto));
+
+        if (!$destcategory = $DB->get_record('course_categories', array('id' => $data->moveto))) {
+            print_error('cannotfindcategory', '', '', $data->moveto);
         }
-    }
 
-    // Process any course actions.
-    if ($editingon) {
-    /// Move a specified course to a new category
-        if (!empty($moveto) and $data = data_submitted() and confirm_sesskey()) {   // Some courses are being moved
-            // user must have category update in both cats to perform this
-            require_capability('moodle/category:manage', $context);
-            require_capability('moodle/category:manage', get_context_instance(CONTEXT_COURSECAT, $moveto));
-
-            if (!$destcategory = $DB->get_record('course_categories', array('id' => $data->moveto))) {
-                print_error('cannotfindcategory', '', '', $data->moveto);
-            }
+        $courses = array();
+        foreach ($data as $key => $value) {
+            if (preg_match('/^c\d+$/', $key)) {
+                $courseid = substr($key, 1);
+                array_push($courses, $courseid);
 
-            $courses = array();
-            foreach ($data as $key => $value) {
-                if (preg_match('/^c\d+$/', $key)) {
-                    $courseid = substr($key, 1);
-                    array_push($courses, $courseid);
-
-                    // check this course's category
-                    if ($movingcourse = $DB->get_record('course', array('id'=>$courseid))) {
-                        if ($movingcourse->category != $id ) {
-                            print_error('coursedoesnotbelongtocategory');
-                        }
-                    } else {
-                        print_error('cannotfindcourse');
+                // check this course's category
+                if ($movingcourse = $DB->get_record('course', array('id'=>$courseid))) {
+                    if ($movingcourse->category != $id ) {
+                        print_error('coursedoesnotbelongtocategory');
                     }
+                } else {
+                    print_error('cannotfindcourse');
                 }
             }
-            move_courses($courses, $data->moveto);
         }
+        move_courses($courses, $data->moveto);
+    }
 
-    /// Hide or show a course
-        if ((!empty($hide) or !empty($show)) and confirm_sesskey()) {
-            if (!empty($hide)) {
-                $course = $DB->get_record('course', array('id' => $hide));
-                $visible = 0;
-            } else {
-                $course = $DB->get_record('course', array('id' => $show));
-                $visible = 1;
-            }
+    // Hide or show a course
+    if (!empty($hide) or !empty($show)) {
+        if (!empty($hide)) {
+            $course = $DB->get_record('course', array('id' => $hide));
+            $visible = 0;
+        } else {
+            $course = $DB->get_record('course', array('id' => $show));
+            $visible = 1;
+        }
 
-            if ($course) {
-                $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
-                require_capability('moodle/course:visibility', $coursecontext);
-                $DB->set_field('course', 'visible', $visible, array('id' => $course->id));
-                $DB->set_field('course', 'visibleold', $visible, array('id' => $course->id)); // we set the old flag when user manually changes visibility of course
-            }
+        if ($course) {
+            $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
+            require_capability('moodle/course:visibility', $coursecontext);
+            // Set the visibility of the course
+            $DB->set_field('course', 'visible', $visible, array('id' => $course->id));
+            // we set the old flag when user manually changes visibility of course
+            $DB->set_field('course', 'visibleold', $visible, array('id' => $course->id));
         }
+    }
 
 
-    /// Move a course up or down
-        if ((!empty($moveup) or !empty($movedown)) and confirm_sesskey()) {
-            require_capability('moodle/category:manage', $context);
+    // Move a course up or down
+    if (!empty($moveup) or !empty($movedown)) {
+        require_capability('moodle/category:manage', $context);
 
-            // Ensure the course order has continuous ordering
-            fix_course_sortorder();
-            $swapcourse = NULL;
+        // Ensure the course order has continuous ordering
+        fix_course_sortorder();
+        $swapcourse = NULL;
 
-            if (!empty($moveup)) {
-                if ($movecourse = $DB->get_record('course', array('id' => $moveup))) {
-                    $swapcourse = $DB->get_record('course', array('sortorder' => $movecourse->sortorder - 1));
-                }
-            } else {
-                if ($movecourse = $DB->get_record('course', array('id' => $movedown))) {
-                    $swapcourse = $DB->get_record('course', array('sortorder' => $movecourse->sortorder + 1));
-                }
+        if (!empty($moveup)) {
+            if ($movecourse = $DB->get_record('course', array('id' => $moveup))) {
+                $swapcourse = $DB->get_record('course', array('sortorder' => $movecourse->sortorder - 1));
             }
-            if ($swapcourse and $movecourse) {
-                // check course's category
-                if ($movecourse->category != $id) {
-                    print_error('coursedoesnotbelongtocategory');
-                }
-                $DB->set_field('course', 'sortorder', $swapcourse->sortorder, array('id' => $movecourse->id));
-                $DB->set_field('course', 'sortorder', $movecourse->sortorder, array('id' => $swapcourse->id));
+        } else {
+            if ($movecourse = $DB->get_record('course', array('id' => $movedown))) {
+                $swapcourse = $DB->get_record('course', array('sortorder' => $movecourse->sortorder + 1));
             }
         }
-
-    } // End of editing stuff
-
-    // Print headings
-    $numcategories = $DB->count_records('course_categories');
-
-    $stradministration = get_string('administration');
-    $strcategories = get_string('categories');
-    $strcategory = get_string('category');
-    $strcourses = get_string('courses');
-
-    if ($editingon && can_edit_in_category()) {
-        // Integrate into the admin tree only if the user can edit categories at the top level,
-        // otherwise the admin block does not appear to this user, and you get an error.
-        require_once($CFG->libdir . '/adminlib.php');
-        admin_externalpage_setup('coursemgmt', '', $urlparams, $CFG->wwwroot . '/course/category.php');
-        $PAGE->set_context($context);   // Ensure that we are actually showing blocks etc for the cat context
-
-        $settingsnode = $PAGE->settingsnav->find_active_node();
-        if ($settingsnode) {
-            $settingsnode->make_inactive();
-            $settingsnode->force_open();
-            $PAGE->navbar->add($settingsnode->text, $settingsnode->action);
+        if ($swapcourse and $movecourse) {
+            // check course's category
+            if ($movecourse->category != $id) {
+                print_error('coursedoesnotbelongtocategory');
+            }
+            $DB->set_field('course', 'sortorder', $swapcourse->sortorder, array('id' => $movecourse->id));
+            $DB->set_field('course', 'sortorder', $movecourse->sortorder, array('id' => $swapcourse->id));
         }
-        echo $OUTPUT->header();
-    } else {
-        $PAGE->set_title("$site->shortname: $category->name");
-        $PAGE->set_heading($site->fullname);
-        $PAGE->set_button(print_course_search('', true, 'navbar'));
-        $PAGE->set_pagelayout('coursecategory');
-        echo $OUTPUT->header();
     }
 
+} // End of editing stuff
+
+// Prepare the standard URL params for this page. We'll need them later.
+$urlparams = array('id' => $id);
+if ($page) {
+    $urlparams['page'] = $page;
+}
+if ($perpage) {
+    $urlparams['perpage'] = $perpage;
+}
+
+// Begin output
+if ($editingon && can_edit_in_category()) {
+    // Integrate into the admin tree only if the user can edit categories at the top level,
+    // otherwise the admin block does not appear to this user, and you get an error.
+    require_once($CFG->libdir . '/adminlib.php');
+    admin_externalpage_setup('coursemgmt', '', $urlparams, $CFG->wwwroot . '/course/category.php');
+    $PAGE->set_context($context);   // Ensure that we are actually showing blocks etc for the cat context
+
+    $settingsnode = $PAGE->settingsnav->find_active_node();
+    if ($settingsnode) {
+        $settingsnode->make_inactive();
+        $settingsnode->force_open();
+        $PAGE->navbar->add($settingsnode->text, $settingsnode->action);
+    }
+    echo $OUTPUT->header();
+} else {
+    $site = get_site();
+    $PAGE->set_title("$site->shortname: $category->name");
+    $PAGE->set_heading($site->fullname);
+    $PAGE->set_button(print_course_search('', true, 'navbar'));
+    $PAGE->set_pagelayout('coursecategory');
+    echo $OUTPUT->header();
+}
+
 /// Print the category selector
-    $displaylist = array();
-    $notused = array();
-    make_categories_list($displaylist, $notused);
+$displaylist = array();
+$notused = array();
+make_categories_list($displaylist, $notused);
 
-    echo '<div class="categorypicker">';
-    $select = new single_select(new moodle_url('category.php'), 'id', $displaylist, $category->id, null, 'switchcategory');
-    $select->set_label($strcategories.':');
-    echo $OUTPUT->render($select);
-    echo '</div>';
+echo '<div class="categorypicker">';
+$select = new single_select(new moodle_url('/course/category.php'), 'id', $displaylist, $category->id, null, 'switchcategory');
+$select->set_label(get_string('categories').':');
+echo $OUTPUT->render($select);
+echo '</div>';
 
 /// Print current category description
-    if (!$editingon && $category->description) {
-        echo $OUTPUT->box_start();
-        $options = new stdClass;
-        $options->noclean = true;
-        $options->para = false;
-        $options->overflowdiv = true;
-        if (!isset($category->descriptionformat)) {
-            $category->descriptionformat = FORMAT_MOODLE;
-        }
-        $text = file_rewrite_pluginfile_urls($category->description, 'pluginfile.php', $context->id, 'coursecat', 'description', null);
-        echo format_text($text, $category->descriptionformat, $options);
-        echo $OUTPUT->box_end();
+if (!$editingon && $category->description) {
+    echo $OUTPUT->box_start();
+    $options = new stdClass;
+    $options->noclean = true;
+    $options->para = false;
+    $options->overflowdiv = true;
+    if (!isset($category->descriptionformat)) {
+        $category->descriptionformat = FORMAT_MOODLE;
     }
-
-    if ($editingon && has_capability('moodle/category:manage', $context)) {
-        echo $OUTPUT->container_start('buttons');
-
-        // Print button to update this category
-        $options = array('id' => $category->id);
-        echo $OUTPUT->single_button(new moodle_url('/course/editcategory.php', $options), get_string('editcategorythis'), 'get');
-
-        // Print button for creating new categories
-        $options = array('parent' => $category->id);
-        echo $OUTPUT->single_button(new moodle_url('/course/editcategory.php', $options), get_string('addsubcategory'), 'get');
-
-        echo $OUTPUT->container_end();
+    $text = file_rewrite_pluginfile_urls($category->description, 'pluginfile.php', $context->id, 'coursecat', 'description', null);
+    echo format_text($text, $category->descriptionformat, $options);
+    echo $OUTPUT->box_end();
+}
+
+if ($editingon && $canmanage) {
+    echo $OUTPUT->container_start('buttons');
+
+    // Print button to update this category
+    $url = new moodle_url('/course/editcategory.php', array('id' => $category->id));
+    echo $OUTPUT->single_button($url, get_string('editcategorythis'), 'get');
+
+    // Print button for creating new categories
+    $url = new moodle_url('/course/editcategory.php', array('parent' => $category->id));
+    echo $OUTPUT->single_button($url, get_string('addsubcategory'), 'get');
+
+    echo $OUTPUT->container_end();
+}
+
+// Print out all the sub-categories
+// In order to view hidden subcategories the user must have the viewhiddencategories
+// capability in the current category.
+if (has_capability('moodle/category:viewhiddencategories', $context)) {
+    $categorywhere = '';
+} else {
+    $categorywhere = 'AND cc.visible = 1';
+}
+// We're going to preload the context for the subcategory as we know that we
+// need it later on for formatting.
+
+$ctxselect = context_helper::get_preload_record_columns_sql('ctx');
+$sql = "SELECT cc.*, $ctxselect
+          FROM {course_categories} cc
+          JOIN {context} ctx ON cc.id = ctx.instanceid
+         WHERE cc.parent = :parentid AND
+               ctx.contextlevel = :contextlevel
+               $categorywhere
+      ORDER BY cc.sortorder ASC";
+$subcategories = $DB->get_recordset_sql($sql, array('parentid' => $category->id, 'contextlevel' => CONTEXT_COURSECAT));
+// Prepare a table to display the sub categories.
+$table = new html_table;
+$table->attributes = array('border' => '0', 'cellspacing' => '2', 'cellpadding' => '4', 'class' => 'generalbox boxaligncenter category_subcategories');
+$table->head = array(new lang_string('subcategories'));
+$table->data = array();
+$baseurl = new moodle_url('/course/category.php');
+foreach ($subcategories as $subcategory) {
+    // Preload the context we will need it to format the category name shortly.
+    context_helper::preload_from_record($subcategory);
+    $context = get_context_instance(CONTEXT_COURSECAT, $subcategory->id);
+    // Prepare the things we need to create a link to the subcategory
+    $attributes = $subcategory->visible ? array() : array('class' => 'dimmed');
+    $text = format_string($subcategory->name, true, array('context' => $context));
+    // Add the subcategory to the table
+    $url->param('id', $subcategory->id);
+    $table->data[] = array(html_writer::link($url, $text, $attributes));
+}
+
+$subcategorieswereshown = (count($table->data) > 0);
+if ($subcategorieswereshown) {
+    echo html_writer::table($table);
+}
+
+// Print out all the courses
+$courses = get_courses_page($category->id, 'c.sortorder ASC',
+        'c.id,c.sortorder,c.shortname,c.fullname,c.summary,c.visible',
+        $totalcount, $page*$perpage, $perpage);
+$numcourses = count($courses);
+
+if (!$courses) {
+    if (empty($subcategorieswereshown)) {
+        echo $OUTPUT->heading(get_string("nocoursesyet"));
     }
 
-/// Print out all the sub-categories
-    if ($subcategories = $DB->get_records('course_categories', array('parent' => $category->id), 'sortorder ASC')) {
-        $firstentry = true;
-        foreach ($subcategories as $subcategory) {
-            if ($subcategory->visible || has_capability('moodle/category:viewhiddencategories', $context)) {
-                $subcategorieswereshown = true;
-                if ($firstentry) {
-                    echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter">';
-                    echo '<tr><th scope="col">'.get_string('subcategories').'</th></tr>';
-                    echo '<tr><td style="white-space: nowrap">';
-                    $firstentry = false;
-                }
-                $catlinkcss = $subcategory->visible ? '' : ' class="dimmed" ';
-                echo '<a '.$catlinkcss.' href="category.php?id='.$subcategory->id.'">'.
-                     format_string($subcategory->name, true, array('context' => get_context_instance(CONTEXT_COURSECAT, $subcategory->id))).'</a><br />';
-            }
-        }
-        if (!$firstentry) {
-            echo '</td></tr></table>';
-            echo '<br />';
-        }
-    }
+} else if ($numcourses <= COURSE_MAX_SUMMARIES_PER_PAGE and !$page and !$editingon) {
+    echo $OUTPUT->box_start('courseboxes');
+    print_courses($category);
+    echo $OUTPUT->box_end();
 
-/// Print out all the courses
-    $courses = get_courses_page($category->id, 'c.sortorder ASC',
-            'c.id,c.sortorder,c.shortname,c.fullname,c.summary,c.visible',
-            $totalcount, $page*$perpage, $perpage);
-    $numcourses = count($courses);
+} else {
+    echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "/course/category.php?id=$category->id&perpage=$perpage");
 
-    if (!$courses) {
-        if (empty($subcategorieswereshown)) {
-            echo $OUTPUT->heading(get_string("nocoursesyet"));
-        }
+    echo '<form id="movecourses" action="category.php" method="post"><div>';
+    echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
+    echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter"><tr>';
+    echo '<th class="header" scope="col">'.get_string('courses').'</th>';
+    if ($editingon) {
+        echo '<th class="header" scope="col">'.get_string('edit').'</th>';
+        echo '<th class="header" scope="col">'.get_string('select').'</th>';
+    } else {
+        echo '<th class="header" scope="col">&nbsp;</th>';
+    }
+    echo '</tr>';
 
-    } else if ($numcourses <= COURSE_MAX_SUMMARIES_PER_PAGE and !$page and !$editingon) {
-        echo $OUTPUT->box_start('courseboxes');
-        print_courses($category);
-        echo $OUTPUT->box_end();
+    $count = 0;
+    $abletomovecourses = false;  // for now
 
-    } else {
-        echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "/course/category.php?id=$category->id&perpage=$perpage");
-
-        $strcourses = get_string('courses');
-        $strselect = get_string('select');
-        $stredit = get_string('edit');
-        $strdelete = get_string('delete');
-        $strbackup = get_string('backup');
-        $strrestore = get_string('restore');
-        $strmoveup = get_string('moveup');
-        $strmovedown = get_string('movedown');
-        $strupdate = get_string('update');
-        $strhide = get_string('hide');
-        $strshow = get_string('show');
-        $strsummary = get_string('summary');
-        $strsettings = get_string('settings');
-
-
-        echo '<form id="movecourses" action="category.php" method="post"><div>';
-        echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-        echo '<table border="0" cellspacing="2" cellpadding="4" class="generalbox boxaligncenter"><tr>';
-        echo '<th class="header" scope="col">'.$strcourses.'</th>';
-        if ($editingon) {
-            echo '<th class="header" scope="col">'.$stredit.'</th>';
-            echo '<th class="header" scope="col">'.$strselect.'</th>';
+    // Checking if we are at the first or at the last page, to allow courses to
+    // be moved up and down beyond the paging border
+    if ($totalcount > $perpage) {
+        $atfirstpage = ($page == 0);
+        if ($perpage > 0) {
+            $atlastpage = (($page + 1) == ceil($totalcount / $perpage));
         } else {
-            echo '<th class="header" scope="col">&nbsp;</th>';
+            $atlastpage = true;
         }
-        echo '</tr>';
+    } else {
+        $atfirstpage = true;
+        $atlastpage = true;
+    }
 
+    $baseurl = new moodle_url('/course/category.php', $urlparams + array('sesskey' => sesskey()));
+    foreach ($courses as $acourse) {
+        $coursecontext = get_context_instance(CONTEXT_COURSE, $acourse->id);
 
-        $count = 0;
-        $abletomovecourses = false;  // for now
+        $count++;
+        $up = ($count > 1 || !$atfirstpage);
+        $down = ($count < $numcourses || !$atlastpage);
 
-        // Checking if we are at the first or at the last page, to allow courses to
-        // be moved up and down beyond the paging border
-        if ($totalcount > $perpage) {
-            $atfirstpage = ($page == 0);
-            if ($perpage > 0) {
-                $atlastpage = (($page + 1) == ceil($totalcount / $perpage));
-            } else {
-                $atlastpage = true;
+        $linkcss = $acourse->visible ? '' : ' class="dimmed" ';
+        echo '<tr>';
+        $coursename = get_course_display_name_for_list($acourse);
+        echo '<td><a '.$linkcss.' href="view.php?id='.$acourse->id.'">'. format_string($coursename) .'</a></td>';
+        if ($editingon) {
+            echo '<td>';
+            if (has_capability('moodle/course:update', $coursecontext)) {
+                $url = new moodle_url('/course/edit.php', array('id' => $acourse->id, 'category' => $id, 'returnto' => 'category'));
+                echo $OUTPUT->action_icon($url, new pix_icon('t/edit', get_string('settings')));
             }
-        } else {
-            $atfirstpage = true;
-            $atlastpage = true;
-        }
 
-        foreach ($courses as $acourse) {
-            $coursecontext = get_context_instance(CONTEXT_COURSE, $acourse->id);
-
-            $count++;
-            $up = ($count > 1 || !$atfirstpage);
-            $down = ($count < $numcourses || !$atlastpage);
-
-            $linkcss = $acourse->visible ? '' : ' class="dimmed" ';
-            echo '<tr>';
-            $coursename = get_course_display_name_for_list($acourse);
-            echo '<td><a '.$linkcss.' href="view.php?id='.$acourse->id.'">'. format_string($coursename) .'</a></td>';
-            if ($editingon) {
-                echo '<td>';
-                if (has_capability('moodle/course:update', $coursecontext)) {
-                    echo $OUTPUT->action_icon(new moodle_url('/course/edit.php',
-                            array('id' => $acourse->id, 'category' => $id, 'returnto' => 'category')),
-                            new pix_icon('t/edit', $strsettings));
-                }
+            // role assignment link
+            if (has_capability('moodle/course:enrolreview', $coursecontext)) {
+                $url = new moodle_url('/enrol/users.php', array('id' => $acourse->id));
+                echo $OUTPUT->action_icon($url, new pix_icon('i/users', get_string('enrolledusers', 'enrol')));
+            }
 
-                // role assignment link
-                if (has_capability('moodle/course:enrolreview', $coursecontext)) {
-                    echo $OUTPUT->action_icon(new moodle_url('/enrol/users.php', array('id' => $acourse->id)),
-                            new pix_icon('i/users', get_string('enrolledusers', 'enrol')));
-                }
+            if (can_delete_course($acourse->id)) {
+                $url = new moodle_url('/course/delete.php', array('id' => $acourse->id));
+                echo $OUTPUT->action_icon($url, new pix_icon('t/delete', get_string('delete')));
+            }
 
-                if (can_delete_course($acourse->id)) {
-                    echo $OUTPUT->action_icon(new moodle_url('/course/delete.php', array('id' => $acourse->id)),
-                            new pix_icon('t/delete', $strdelete));
+            // MDL-8885, users with no capability to view hidden courses, should not be able to lock themselves out
+            if (has_capability('moodle/course:visibility', $coursecontext) && has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
+                if (!empty($acourse->visible)) {
+                    $url = new moodle_url($baseurl, array('hide' => $acourse->id));
+                    echo $OUTPUT->action_icon($url, new pix_icon('t/hide', get_string('hide')));
+                } else {
+                    $url = new moodle_url($baseurl, array('show' => $acourse->id));
+                    echo $OUTPUT->action_icon($url, new pix_icon('t/show', get_string('show')));
                 }
+            }
 
-                // MDL-8885, users with no capability to view hidden courses, should not be able to lock themselves out
-                if (has_capability('moodle/course:visibility', $coursecontext) && has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
-                    if (!empty($acourse->visible)) {
-                        echo $OUTPUT->action_icon(new moodle_url('/course/category.php',
-                                array('id' => $category->id, 'page' => $page, 'perpage' => $perpage,
-                                        'hide' => $acourse->id, 'sesskey' => sesskey())),
-                                new pix_icon('t/hide', $strhide));
-                    } else {
-                        echo $OUTPUT->action_icon(new moodle_url('/course/category.php',
-                                array('id' => $category->id, 'page' => $page, 'perpage' => $perpage,
-                                        'show' => $acourse->id, 'sesskey' => sesskey())),
-                                new pix_icon('t/show', $strshow));
-                    }
-                }
+            if (has_capability('moodle/backup:backupcourse', $coursecontext)) {
+                $url = new moodle_url('/backup/backup.php', array('id' => $acourse->id));
+                echo $OUTPUT->action_icon($url, new pix_icon('t/backup', get_string('backup')));
+            }
 
-                if (has_capability('moodle/backup:backupcourse', $coursecontext)) {
-                    echo $OUTPUT->action_icon(new moodle_url('/backup/backup.php', array('id' => $acourse->id)),
-                            new pix_icon('t/backup', $strbackup));
-                }
+            if (has_capability('moodle/restore:restorecourse', $coursecontext)) {
+                $url = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id));
+                echo $OUTPUT->action_icon($url, new pix_icon('t/restore', get_string('restore')));
+            }
 
-                if (has_capability('moodle/restore:restorecourse', $coursecontext)) {
-                    echo $OUTPUT->action_icon(new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id)),
-                            new pix_icon('t/restore', $strrestore));
+            if ($canmanage) {
+                if ($up) {
+                    $url = new moodle_url($baseurl, array('moveup' => $acourse->id));
+                    echo $OUTPUT->action_icon($url, new pix_icon('t/up', get_string('moveup')));
                 }
 
-                if (has_capability('moodle/category:manage', $context)) {
-                    if ($up) {
-                        echo $OUTPUT->action_icon(new moodle_url('/course/category.php',
-                                array('id' => $category->id, 'page' => $page, 'perpage' => $perpage,
-                                        'moveup' => $acourse->id, 'sesskey' => sesskey())),
-                                new pix_icon('t/up', $strmoveup));
-                    }
-
-                    if ($down) {
-                        echo $OUTPUT->action_icon(new moodle_url('/course/category.php',
-                                array('id' => $category->id, 'page' => $page, 'perpage' => $perpage,
-                                        'movedown' => $acourse->id, 'sesskey' => sesskey())),
-                                new pix_icon('t/down', $strmovedown));
-                    }
-                    $abletomovecourses = true;
+                if ($down) {
+                    $url = new moodle_url($baseurl, array('movedown' => $acourse->id));
+                    echo $OUTPUT->action_icon($url, new pix_icon('t/down', get_string('movedown')));
                 }
+                $abletomovecourses = true;
+            }
 
-                echo '</td>';
-                echo '<td align="center">';
-                echo '<input type="checkbox" name="c'.$acourse->id.'" />';
-                echo '</td>';
-            } else {
-                echo '<td align="right">';
-                // print enrol info
-                if ($icons = enrol_get_course_info_icons($acourse)) {
-                    foreach ($icons as $pix_icon) {
-                        echo $OUTPUT->render($pix_icon);
-                    }
-                }
-                if (!empty($acourse->summary)) {
-                    $link = new moodle_url("/course/info.php?id=$acourse->id");
-                    echo $OUTPUT->action_link($link, '<img alt="'.get_string('info').'" class="icon" src="'.$OUTPUT->pix_url('i/info') . '" />',
-                        new popup_action('click', $link, 'courseinfo'), array('title'=>$strsummary));
+            echo '</td>';
+            echo '<td align="center">';
+            echo '<input type="checkbox" name="c'.$acourse->id.'" />';
+            echo '</td>';
+        } else {
+            echo '<td align="right">';
+            // print enrol info
+            if ($icons = enrol_get_course_info_icons($acourse)) {
+                foreach ($icons as $pix_icon) {
+                    echo $OUTPUT->render($pix_icon);
                 }
-                echo "</td>";
             }
-            echo "</tr>";
-        }
-
-        if ($abletomovecourses) {
-            $movetocategories = array();
-            $notused = array();
-            make_categories_list($movetocategories, $notused, 'moodle/category:manage');
-            $movetocategories[$category->id] = get_string('moveselectedcoursesto');
-            echo '<tr><td colspan="3" align="right">';
-            echo html_writer::select($movetocategories, 'moveto', $category->id, null, array('id'=>'movetoid'));
-            $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
-            echo '<input type="hidden" name="id" value="'.$category->id.'" />';
-            echo '</td></tr>';
+            if (!empty($acourse->summary)) {
+                $url = new moodle_url("/course/info.php?id=$acourse->id");
+                echo $OUTPUT->action_link($url, '<img alt="'.get_string('info').'" class="icon" src="'.$OUTPUT->pix_url('i/info') . '" />',
+                    new popup_action('click', $url, 'courseinfo'), array('title'=>get_string('summary')));
+            }
+            echo "</td>";
         }
-
-        echo '</table>';
-        echo '</div></form>';
-        echo '<br />';
+        echo "</tr>";
     }
 
-    echo '<div class="buttons">';
-    if (has_capability('moodle/category:manage', $context) and $numcourses > 1) {
-    /// Print button to re-sort courses by name
-        unset($options);
-        $options['id'] = $category->id;
-        $options['resort'] = 'name';
-        $options['sesskey'] = sesskey();
-        echo $OUTPUT->single_button(new moodle_url('category.php', $options), get_string('resortcoursesbyname'), 'get');
+    if ($abletomovecourses) {
+        $movetocategories = array();
+        $notused = array();
+        make_categories_list($movetocategories, $notused, 'moodle/category:manage');
+        $movetocategories[$category->id] = get_string('moveselectedcoursesto');
+        echo '<tr><td colspan="3" align="right">';
+        echo html_writer::select($movetocategories, 'moveto', $category->id, null, array('id'=>'movetoid'));
+        $PAGE->requires->js_init_call('M.util.init_select_autosubmit', array('movecourses', 'movetoid', false));
+        echo '<input type="hidden" name="id" value="'.$category->id.'" />';
+        echo '</td></tr>';
     }
 
-    if (has_capability('moodle/course:create', $context)) {
-    /// Print button to create a new course
-        unset($options);
-        $options['category'] = $category->id;
-        $options['returnto'] = 'category';
-        echo $OUTPUT->single_button(new moodle_url('edit.php', $options), get_string('addnewcourse'), 'get');
-    }
+    echo '</table>';
+    echo '</div></form>';
+    echo '<br />';
+}
 
-    if (!empty($CFG->enablecourserequests) && $category->id == $CFG->defaultrequestcategory) {
-        print_course_request_buttons(get_context_instance(CONTEXT_SYSTEM));
-    }
-    echo '</div>';
+echo '<div class="buttons">';
+if ($canmanage and $numcourses > 1) {
+    // Print button to re-sort courses by name
+    $url = new moodle_url('/course/category.php', array('id' => $category->id, 'resort' => 'name', 'sesskey' => sesskey()));
+    echo $OUTPUT->single_button($url, get_string('resortcoursesbyname'), 'get');
+}
+
+if (has_capability('moodle/course:create', $context)) {
+    // Print button to create a new course
+    $url = new moodle_url('/course/edit.php', array('category' => $category->id, 'returnto' => 'category'));
+    echo $OUTPUT->single_button($url, get_string('addnewcourse'), 'get');
+}
 
-    print_course_search();
+if (!empty($CFG->enablecourserequests) && $category->id == $CFG->defaultrequestcategory) {
+    print_course_request_buttons(get_context_instance(CONTEXT_SYSTEM));
+}
+echo '</div>';
 
-    echo $OUTPUT->footer();
+print_course_search();
 
+echo $OUTPUT->footer();
\ No newline at end of file
index 053d8bb..174872c 100644 (file)
@@ -65,18 +65,6 @@ if ($id) { // editing course
 // Prepare course and the editor
 $editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
 if (!empty($course)) {
-    $allowedmods = array();
-    if ($am = $DB->get_records('course_allowed_modules', array('course'=>$course->id))) {
-        foreach ($am as $m) {
-            $allowedmods[] = $m->module;
-        }
-    } else {
-        // this happens in case we edit course created before enabling module restrictions or somebody disabled everything :-(
-        if (empty($course->restrictmodules) and !empty($CFG->defaultallowedmodules)) {
-            $allowedmods = explode(',', $CFG->defaultallowedmodules);
-        }
-    }
-    $course->allowedmods = $allowedmods;
     //add context for editor
     $editoroptions['context'] = $coursecontext;
     $course = file_prepare_standard_editor($course, 'summary', $editoroptions, $coursecontext, 'course', 'summary', 0);
index d87c9d1..44ed742 100644 (file)
@@ -256,48 +256,6 @@ class course_edit_form extends moodleform {
             $mform->setDefault('completionstartonenrol',0);
         }
 
-//--------------------------------------------------------------------------------
-        if (has_capability('moodle/site:config', $systemcontext)) {
-            if (((!empty($course->requested) && $CFG->restrictmodulesfor == 'requested') || $CFG->restrictmodulesfor == 'all')) {
-                $mform->addElement('header', '', get_string('restrictmodules'));
-
-                $options = array();
-                $options['0'] = get_string('no');
-                $options['1'] = get_string('yes');
-                $mform->addElement('select', 'restrictmodules', get_string('restrictmodules'), $options);
-                if (!empty($CFG->restrictbydefault)) {
-                    $mform->setDefault('restrictmodules', 1);
-                }
-
-                $mods = array(0=>get_string('allownone'));
-                $allmods = $DB->get_records_menu('modules', array('visible' => 1),
-                        'name', 'id, name');
-                foreach ($allmods as $key => $value) {
-                    // Add module to list unless it cannot be added by users anyway
-                    if (plugin_supports('mod', $value, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER) !==
-                            MOD_ARCHETYPE_SYSTEM) {
-                        $mods[$key] = get_string('pluginname', $value);
-                    }
-                }
-                $mform->addElement('select', 'allowedmods', get_string('to'), $mods, array('multiple'=>'multiple', 'size'=>'10'));
-                $mform->disabledIf('allowedmods', 'restrictmodules', 'eq', 0);
-                // defaults are already in $course
-            } else {
-                // remove any mod restriction
-                $mform->addElement('hidden', 'restrictmodules', 0);
-                $mform->setType('restrictmodules', PARAM_INT);
-            }
-        } else {
-            $mform->addElement('hidden', 'restrictmodules');
-            $mform->setType('restrictmodules', PARAM_INT);
-            if (empty($course->id)) {
-                $mform->setConstant('restrictmodules', (int)($CFG->restrictmodulesfor == 'all'));
-            } else {
-                // keep previous
-                $mform->setConstant('restrictmodules', $course->restrictmodules);
-            }
-        }
-
 /// customizable role names in this course
 //--------------------------------------------------------------------------------
         $mform->addElement('header','rolerenaming', get_string('rolerenaming'));
index 9752cce..ff4bad5 100644 (file)
@@ -1,9 +1,29 @@
 <?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
 /**
  * Page for creating or editing course category name/parent/description.
  * When called with an id parameter, edits the category with that id.
  * Otherwise it creates a new category with default parent from the parent
  * parameter, which may be 0.
+ *
+ * @package    core
+ * @subpackage course
+ * @copyright  2007 Nicolas Connault
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
 require_once('../config.php');
@@ -108,6 +128,21 @@ if ($mform->is_cancelled()) {
     redirect('category.php?id='.$newcategory->id.'&categoryedit=on');
 }
 
+// Unfortunately the navigation never generates correctly for this page because technically
+// this page doesn't actually exist on the navigation you get here through the course
+// management page.
+try {
+    // First up we'll try to make the course management page active seeing as that is
+    // where the user thinks they are.
+    // The big prolem here is that the course management page is a common page
+    // for both editing users and common users.
+    $PAGE->settingsnav->get('root')->get('courses')->get('coursemgmt')->make_active();
+} catch (Exception $ex) {
+    // Failing that we'll override the URL, not as accurate and chances are things
+    // won't be 100% correct all the time but should work most times.
+    navigation_node::override_active_url(new moodle_url('/course/index.php', array('categoryedit' => 'on')));
+}
+
 $PAGE->set_title($title);
 $PAGE->set_heading($fullname);
 echo $OUTPUT->header();
index e873128..ce1466a 100644 (file)
@@ -177,6 +177,7 @@ if (!$categories = get_categories()) {    /// No category yet!
     $tempcat->context = get_context_instance(CONTEXT_COURSECAT, $tempcat->id);
     mark_context_dirty('/'.SYSCONTEXTID);
     fix_course_sortorder(); // Required to build course_categories.depth and .path.
+    set_config('defaultrequestcategory', $tempcat->id);
 }
 
 /// Move a category to a new parent if required
@@ -394,4 +395,4 @@ function print_category_edit($category, $displaylist, $parentslist, $depth=-1, $
             print_category_edit($cat, $displaylist, $parentslist, $depth+1, $up, $down);
         }
     }
-}
\ No newline at end of file
+}
index 6282112..dfc33df 100644 (file)
@@ -932,7 +932,7 @@ function print_recent_activity($course) {
 
 /// Next, have there been any modifications to the course structure?
 
-    $modinfo =& get_fast_modinfo($course);
+    $modinfo = get_fast_modinfo($course);
 
     $changelist = array();
 
@@ -3391,58 +3391,37 @@ function course_format_name ($course,$max=100) {
     }
 }
 
-function update_restricted_mods($course, $mods) {
-    global $DB;
-
-/// Delete all the current restricted list
-    $DB->delete_records('course_allowed_modules', array('course'=>$course->id));
-
-    if (empty($course->restrictmodules)) {
-        return;   // We're done
-    }
-
-/// Insert the new list of restricted mods
-    foreach ($mods as $mod) {
-        if ($mod == 0) {
-            continue; // this is the 'allow none' option
-        }
-        $am = new stdClass();
-        $am->course = $course->id;
-        $am->module = $mod;
-        $DB->insert_record('course_allowed_modules',$am);
-    }
-}
-
 /**
- * This function will take an int (module id) or a string (module name)
- * and return true or false, whether it's allowed in the given course (object)
- * $mod is not allowed to be an object, as the field for the module id is inconsistent
- * depending on where in the code it's called from (sometimes $mod->id, sometimes $mod->module)
+ * Is the user allowed to add this type of module to this course?
+ * @param object $course the course settings. Only $course->id is used.
+ * @param string $modname the module name. E.g. 'forum' or 'quiz'.
+ * @return bool whether the current user is allowed to add this type of module to this course.
  */
-
-function course_allowed_module($course,$mod) {
+function course_allowed_module($course, $modname) {
     global $DB;
 
-    if (empty($course->restrictmodules)) {
-        return true;
+    if (is_numeric($modname)) {
+        throw new coding_exception('Function course_allowed_module no longer
+                supports numeric module ids. Please update your code to pass the module name.');
     }
 
-    // Admins and admin-like people who can edit everything can also add anything.
-    // Originally there was a course:update test only, but it did not match the test in course edit form
-    if (has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) {
-        return true;
-    }
+    $capability = 'mod/' . $modname . ':addinstance';
+    if (!get_capability_info($capability)) {
+        // Debug warning that the capability does not exist, but no more than once per page.
+        static $warned = array();
+        $archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER);
+        if (!isset($warned[$modname]) && $archetype !== MOD_ARCHETYPE_SYSTEM) {
+            debugging('The module ' . $modname . ' does not define the standard capability ' .
+                    $capability , DEBUG_DEVELOPER);
+            $warned[$modname] = 1;
+        }
 
-    if (is_numeric($mod)) {
-        $modid = $mod;
-    } else if (is_string($mod)) {
-        $modid = $DB->get_field('modules', 'id', array('name'=>$mod));
-    }
-    if (empty($modid)) {
-        return false;
+        // If the capability does not exist, the module can always be added.
+        return true;
     }
 
-    return $DB->record_exists('course_allowed_modules', array('course'=>$course->id, 'module'=>$modid));
+    $coursecontext = context_course::instance($course->id);
+    return has_capability($capability, $coursecontext);
 }
 
 /**
@@ -3910,17 +3889,6 @@ function create_course($data, $editoroptions = NULL) {
 
     fix_course_sortorder();
 
-    // update module restrictions
-    if ($course->restrictmodules) {
-        if (isset($data->allowedmods)) {
-            update_restricted_mods($course, $data->allowedmods);
-        } else {
-            if (!empty($CFG->defaultallowedmodules)) {
-                update_restricted_mods($course, explode(',', $CFG->defaultallowedmodules));
-            }
-        }
-    }
-
     // new context created - better mark it as dirty
     mark_context_dirty($context->path);
 
@@ -3999,11 +3967,6 @@ function update_course($data, $editoroptions = NULL) {
     // Test for and remove blocks which aren't appropriate anymore
     blocks_remove_inappropriate($course);
 
-    // update module restrictions
-    if (isset($data->allowedmods)) {
-        update_restricted_mods($course, $data->allowedmods);
-    }
-
     // Save any custom role names.
     save_local_role_names($course->id, $data);
 
@@ -4316,9 +4279,6 @@ class course_request {
 
         // Set misc settings
         $data->requested = 1;
-        if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor != 'none' && !empty($CFG->restrictbydefault)) {
-            $data->restrictmodules = 1;
-        }
 
         // Apply course default settings
         $data->format             = $courseconfig->format;
index 9ed3f5d..63ea832 100644 (file)
@@ -59,7 +59,7 @@ if (!empty($add)) {
 
     $cw = get_course_section($section, $course->id);
 
-    if (!course_allowed_module($course, $module->id)) {
+    if (!course_allowed_module($course, $module->name)) {
         print_error('moduledisable');
     }
 
index fcf09fd..f33ef54 100644 (file)
@@ -82,7 +82,7 @@ echo $OUTPUT->heading(format_string($course->fullname) . ": $userinfo", 2);
 
 $mform->display();
 
-$modinfo =& get_fast_modinfo($course);
+$modinfo = get_fast_modinfo($course);
 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
 
 if (has_capability('moodle/course:viewhiddensections', $context)) {
index ce8b0f7..cb899f0 100644 (file)
@@ -27,6 +27,9 @@ class course_reset_form extends moodleform {
         $mform->addElement('header', 'rolesheader', get_string('roles'));
 
         $roles = get_assignable_roles(get_context_instance(CONTEXT_COURSE, $COURSE->id));
+        $roles[0] = get_string('noroles', 'role');
+        $roles = array_reverse($roles, true);
+
         $mform->addElement('select', 'unenrol_users', get_string('unenrolroleusers', 'enrol'), $roles, array('multiple' => 'multiple'));
         $mform->addElement('checkbox', 'reset_roles_overrides', get_string('deletecourseoverrides', 'role'));
         $mform->setAdvanced('reset_roles_overrides');
index 8b2621f..49bbbe8 100644 (file)
     // Course wrapper start.
     echo html_writer::start_tag('div', array('class'=>'course-content'));
 
-    $modinfo =& get_fast_modinfo($COURSE);
+    $modinfo = get_fast_modinfo($COURSE);
     get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
     foreach($mods as $modid=>$unused) {
         if (!isset($modinfo->cms[$modid])) {
             rebuild_course_cache($course->id);
-            $modinfo =& get_fast_modinfo($COURSE);
+            $modinfo = get_fast_modinfo($COURSE);
             debugging('Rebuilding course cache', DEBUG_DEVELOPER);
             break;
         }
index ce8d6d2..62b44f9 100644 (file)
@@ -354,9 +354,7 @@ class enrol_database_plugin extends enrol_plugin {
         }
         $preventfullunenrol = empty($externalcourses);
         if ($preventfullunenrol and $unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
-            if ($verbose) {
-                mtrace('  Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
-            }
+            mtrace('  Preventing unenrolment of all current users, because it might result in major data loss, there has to be at least one record in external enrol table, sorry.');
         }
 
         // first find all existing courses with enrol instance
index 6057831..5a268b4 100644 (file)
@@ -355,7 +355,7 @@ class grade_edit_tree {
      * @param string type "extra" or "weight": the type of the column hosting the weight input
      * @return string HTML
      */
-    function get_weight_input($item, $type) {
+    static function get_weight_input($item, $type) {
         global $OUTPUT;
 
         if (!is_object($item) || get_class($item) !== 'grade_item') {
@@ -387,7 +387,7 @@ class grade_edit_tree {
     //Trims trailing zeros
     //Used on the 'categories and items' page for grade items settings like aggregation co-efficient
     //Grader report has its own decimal place settings so they are handled elsewhere
-    function format_number($number) {
+    static function format_number($number) {
         $formatted = rtrim(format_float($number, 4),'0');
         if (substr($formatted, -1)=='.') { //if last char is the decimal point
             $formatted .= '0';
index bd6e396..a5c02c6 100644 (file)
@@ -73,8 +73,8 @@ class grade_export_form extends moodleform {
 
         if (!empty($features['includeseparator'])) {
             $radio = array();
-            $radio[] = &MoodleQuickForm::createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab');
-            $radio[] = &MoodleQuickForm::createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma');
+            $radio[] = $mform->createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab');
+            $radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma');
             $mform->addGroup($radio, 'separator', get_string('separator', 'grades'), ' ', false);
             $mform->setDefault('separator', 'comma');
         }
index 6021f60..76514b3 100644 (file)
@@ -46,8 +46,8 @@ class grade_import_form extends moodleform {
 
         if (!empty($features['includeseparator'])) {
             $radio = array();
-            $radio[] = &MoodleQuickForm::createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab');
-            $radio[] = &MoodleQuickForm::createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma');
+            $radio[] = $mform->createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab');
+            $radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma');
             $mform->addGroup($radio, 'separator', get_string('separator', 'grades'), ' ', false);
             $mform->setDefault('separator', 'comma');
         }
index 6cbaff1..890e204 100644 (file)
@@ -29,7 +29,6 @@ require_once $CFG->dirroot.'/grade/report/grader/lib.php';
 
 $courseid      = required_param('id', PARAM_INT);        // course id
 $page          = optional_param('page', 0, PARAM_INT);   // active page
-$perpageurl    = optional_param('perpage', 0, PARAM_INT);
 $edit          = optional_param('edit', -1, PARAM_BOOL); // sticky editting mode
 
 $sortitemid    = optional_param('sortitemid', 0, PARAM_ALPHANUM); // sort by which grade item
@@ -134,12 +133,6 @@ if ($data = data_submitted() and confirm_sesskey() and has_capability('moodle/gr
     $warnings = array();
 }
 
-
-// Override perpage if set in URL
-if ($perpageurl) {
-    $report->user_prefs['studentsperpage'] = $perpageurl;
-}
-
 // final grades MUST be loaded after the processing
 $report->load_users();
 $numusers = $report->get_numusers();
@@ -169,6 +162,7 @@ if ($USER->gradeediting[$course->id] && ($report->get_pref('showquickfeedback')
     echo '<input type="hidden" value="'.s($courseid).'" name="id" />';
     echo '<input type="hidden" value="'.sesskey().'" name="sesskey" />';
     echo '<input type="hidden" value="grader" name="report"/>';
+    echo '<input type="hidden" value="'.$page.'" name="page"/>';
     echo $reporthtml;
     echo '<div class="submit"><input type="submit" value="'.s(get_string('update')).'" /></div>';
     echo '</div></form>';
index eca29e3..8a71a42 100644 (file)
@@ -137,12 +137,11 @@ class grade_report_grader extends grade_report {
 
         $this->baseurl = new moodle_url('index.php', array('id' => $this->courseid));
 
-        $studentsperpage = $this->get_pref('studentsperpage');
-        if (!empty($studentsperpage)) {
-            $this->baseurl->params(array('perpage' => $studentsperpage, 'page' => $this->page));
+        if (!empty($this->page)) {
+            $this->baseurl->params(array('page' => $this->page));
         }
 
-        $this->pbarurl = new moodle_url('/grade/report/grader/index.php', array('id' => $this->courseid, 'perpage' => $studentsperpage));
+        $this->pbarurl = new moodle_url('/grade/report/grader/index.php', array('id' => $this->courseid));
 
         $this->setup_groups();
 
@@ -1207,7 +1206,7 @@ class grade_report_grader extends grade_report {
 
             foreach ($this->gtree->items as $itemid=>$unused) {
                 // emulate grade element
-                $item =& $this->gtree->get_item($itemid);
+                $item = $this->gtree->get_item($itemid);
 
                 $eid = $this->gtree->get_item_eid($item);
                 $element = $this->gtree->locate_element($eid);
index cf12016..3b23ad9 100644 (file)
@@ -35,10 +35,12 @@ $confirm  = optional_param('confirm', 0, PARAM_BOOL);
 
 // This script used to support group delete, but that has been moved. In case
 // anyone still links to it, let's redirect to the new script.
-if($delete) {
-    redirect('delete.php?courseid='.$courseid.'&groups='.$id);
+if ($delete) {
+    debugging('Deleting a group through group/group.php is deprecated and will be removed soon. Please use group/delete.php instead');
+    redirect(new moodle_url('delete.php', array('courseid' => $courseid, 'groups' => $id)));
 }
 
+
 if ($id) {
     if (!$group = $DB->get_record('groups', array('id'=>$id))) {
         print_error('invalidgroupid');
@@ -74,28 +76,6 @@ require_capability('moodle/course:managegroups', $context);
 
 $returnurl = $CFG->wwwroot.'/group/index.php?id='.$course->id.'&group='.$id;
 
-if ($id and $delete) {
-    if (!$confirm) {
-        $PAGE->set_title(get_string('deleteselectedgroup', 'group'));
-        $PAGE->set_heading($course->fullname . ': '. get_string('deleteselectedgroup', 'group'));
-        echo $OUTPUT->header();
-        $optionsyes = array('id'=>$id, 'delete'=>1, 'courseid'=>$courseid, 'sesskey'=>sesskey(), 'confirm'=>1);
-        $optionsno  = array('id'=>$courseid);
-        $formcontinue = new single_button(new moodle_url('group.php', $optionsyes), get_string('yes'), 'get');
-        $formcancel = new single_button(new moodle_url($baseurl, $optionsno), get_string('no'), 'get');
-        echo $OUTPUT->confirm(get_string('deletegroupconfirm', 'group', $group->name), $formcontinue, $formcancel);
-        echo $OUTPUT->footer();
-        die;
-
-    } else if (confirm_sesskey()){
-        if (groups_delete_group($id)) {
-            redirect('index.php?id='.$course->id);
-        } else {
-            print_error('erroreditgroup', 'group', $returnurl);
-        }
-    }
-}
-
 // Prepare the description editor: We do support files for group descriptions
 $editoroptions = array('maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$course->maxbytes, 'trust'=>false, 'context'=>$context, 'noclean'=>true);
 if (!empty($group->id)) {
index d302bf7..df0a266 100644 (file)
@@ -34,7 +34,7 @@ $cancel  = optional_param('cancel', false, PARAM_BOOL);
 $group = $DB->get_record('groups', array('id'=>$groupid), '*', MUST_EXIST);
 $course = $DB->get_record('course', array('id'=>$group->courseid), '*', MUST_EXIST);
 
-$PAGE->set_url('/groups/members.php', array('id'=>$groupid));
+$PAGE->set_url('/group/members.php', array('group'=>$groupid));
 $PAGE->set_pagelayout('standard');
 
 require_login($course);
index 6b6c8df..921dc7d 100644 (file)
@@ -171,7 +171,6 @@ $string['configdebugdisplay'] = 'Set to on, the error reporting will go to the H
 $string['configdebugpageinfo'] = 'Enable if you want page information printed in page footer.';
 $string['configdebugsmtp'] = 'Enable verbose debug information during sending of email messages to SMTP server.';
 $string['configdebugvalidators'] = 'Enable if you want to have links to external validator servers in page footer. You may need to create new user with username <em>w3cvalidator</em>, and enable guest access. These changes may allow unauthorized access to server, do not enable on production sites!';
-$string['configdefaultallowedmodules'] = 'For the courses which fall into the above category, which modules do you want to allow by default <b>when the course is created</b>?';
 $string['configdefaulthomepage'] = 'This determines the home page for logged in users';
 $string['configdefaultrequestcategory'] = 'Courses requested by users will be automatically placed in this category.';
 $string['configdefaultrequestedcategory'] = 'Default category to put courses that were requested into, if they\'re approved.';
@@ -285,8 +284,6 @@ $string['configrequestedstudentsname'] = 'Word for students used in requested co
 $string['configrequestedteachername'] = 'Word for teacher used in requested courses';
 $string['configrequestedteachersname'] = 'Word for teachers used in requested courses';
 $string['configrequiremodintro'] = 'Disable this option if you do not want to force users to enter description of each activity.';
-$string['configrestrictbydefault'] = 'Should new courses that are created that fall into the above category have their modules restricted by default?';
-$string['configrestrictmodulesfor'] = 'Which courses should have <b>the setting</b> for disabling some activity modules?  Note that this setting only applies to teachers, administrators will still be able to add any activity to a course.';
 $string['configrunclamavonupload'] = 'When enabled, clam AV will be used to scan all uploaded files.';
 $string['configrunclamonupload'] = 'Run clam AV on file upload? You will need a correct path in pathtoclam for this to work.  (Clam AV is a free virus scanner that you can get from http://www.clamav.net/)';
 $string['configuserquota'] = 'The maximum number of bytes that a user can store in their own private file area. {$a->bytes} bytes == {$a->displaysize}';
@@ -407,7 +404,6 @@ $string['debugsmtp'] = 'Debug email sending';
 $string['debugstringids'] = 'Show origin of languages strings';
 $string['debugstringids_desc'] = 'This option is designed to help translators. When this option is enabled, if you add the parameter strings=1 to a request URL, it will show the language file and string id beside each string that is output.';
 $string['debugvalidators'] = 'Show validator links';
-$string['defaultallowedmodules'] = 'Default allowed modules';
 $string['defaultcity'] = 'Default city';
 $string['defaultcity_help'] = 'A city entered here will be the default city when creating new user accounts.';
 $string['defaulthomepage'] = 'Default home page for users';
@@ -861,8 +857,6 @@ $string['purgecachesconfirm']= 'Moodle can cache themes, javascript, language st
 $string['purgecachesfinished']= 'All caches were purged.';
 $string['restorernewroleid'] = 'Restorers\' role in courses';
 $string['restorernewroleid_help'] = 'If the user does not already have the permission to manage the newly restored course, the user is automatically assigned this role and enrolled if necessary. Select "None" if you do not want restorers to be able to manage every restored course.';
-$string['restrictbydefault'] = 'Restrict modules by default';
-$string['restrictmodulesfor'] = 'Restrict modules for';
 $string['reverseproxy'] = 'Reverse proxy';
 $string['riskconfig'] = 'Users could change site configuration and behaviour';
 $string['riskconfigshort'] = 'Configuration risk';
index 1d54561..202ad87 100644 (file)
@@ -54,6 +54,8 @@ $string['blogentriesbyuseraboutmodule'] = 'Blog entries about this {$a->mod} by
 $string['blogentrybyuser'] = 'Blog entry by {$a}';
 $string['blogpreferences'] = 'Blog preferences';
 $string['blogs'] = 'Blogs';
+$string['blogscourse'] = 'Course blogs';
+$string['blogssite'] = 'Site blogs';
 $string['blogtags'] = 'Blog tags';
 $string['cannotviewcourseblog'] = 'You do not have the required permissions to view blogs in this course';
 $string['cannotviewcourseorgroupblog'] = 'You do not have the required permissions to view blogs in this course/group';
index 60993bc..5aa5f4e 100644 (file)
@@ -128,6 +128,7 @@ $string['settings'] = 'Settings';
 $string['settingssaved'] = 'Your settings have been saved';
 $string['showmessagewindow'] = 'Popup window on new message';
 $string['strftimedaydatetime'] = '%A, %d %B %Y, %I:%M %p';
+$string['thisconversation'] = 'this conversation';
 $string['timenosee'] = 'Minutes since I was last seen online';
 $string['timesent'] = 'Time sent';
 $string['touserdoesntexist'] = 'You can not send a message to a user id ({$a}) that doesn\'t exist';
index fd18d93..764d5db 100644 (file)
@@ -1385,7 +1385,6 @@ $string['restoreuserinfofailed'] = 'The restore process has stopped because you
 $string['restoreusersprecheck'] = 'Checking user data';
 $string['restoreusersprecheckerror'] = 'Some problems were detected when checking user data';
 $string['restricted'] = 'Restricted';
-$string['restrictmodules'] = 'Restrict activity modules?';
 $string['returningtosite'] = 'Returning to this web site?';
 $string['returntooriginaluser'] = 'Return to {$a}';
 $string['revert'] = 'Revert';
index 334bd44..7bb1d17 100644 (file)
@@ -366,7 +366,7 @@ class auth_plugin_base {
      * @param object object with submitted configuration settings (without system magic quotes)
      * @param array $err array of error messages
      */
-     function validate_form(&$form, &$err) {
+     function validate_form($form, &$err) {
         //override if needed
     }
 
index 90d990c..69b93da 100644 (file)
@@ -226,10 +226,13 @@ class block_manager {
 
         $pageformat = $this->page->pagetype;
         foreach($allblocks as $block) {
+            if (!$bi = block_instance($block->name)) {
+                continue;
+            }
             if ($block->visible &&
-                    (block_method_result($block->name, 'instance_allow_multiple') || !$this->is_block_present($block->name)) &&
+                    ($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) &&
                     blocks_name_allowed_in_format($block->name, $pageformat) &&
-                    block_method_result($block->name, 'user_can_addto', $this->page)) {
+                    $bi->user_can_addto($this->page)) {
                 $this->addableblocks[$block->name] = $block;
             }
         }
@@ -1850,7 +1853,11 @@ function blocks_remove_inappropriate($course) {
 function blocks_name_allowed_in_format($name, $pageformat) {
     $accept = NULL;
     $maxdepth = -1;
-    $formats = block_method_result($name, 'applicable_formats');
+    if (!$bi = block_instance($name)) {
+        return false;
+    }
+
+    $formats = $bi->applicable_formats();
     if (!$formats) {
         $formats = array();
     }
index 11c3def..818a774 100644 (file)
@@ -356,7 +356,7 @@ function cron_run() {
         require_once($CFG->dirroot . '/blog/lib.php');
         mtrace("Fetching external blog entries...", '');
         $sql = "timefetched < ? OR timefetched = 0";
-        $externalblogs = $DB->get_records_select('blog_external', $sql, array(mktime() - $CFG->externalblogcrontime));
+        $externalblogs = $DB->get_records_select('blog_external', $sql, array(time() - $CFG->externalblogcrontime));
 
         foreach ($externalblogs as $eb) {
             blog_sync_external_entries($eb);
index 0995948..03d728c 100644 (file)
@@ -1249,7 +1249,7 @@ class css_rule {
                 list($name, $value) = array_map('trim', $bits);
             }
             if (isset($name) && isset($value) && $name !== '' && $value !== '') {
-                $style = css_style::init($name, $value);
+                $style = css_style::init_automatic($name, $value);
             }
         } else if ($style instanceof css_style) {
             // Clone the style as it may be coming from another rule and we don't
@@ -1646,7 +1646,7 @@ abstract class css_style {
      * @param string $value The value of the style.
      * @return css_style_generic
      */
-    public static function init($name, $value) {
+    public static function init_automatic($name, $value) {
         $specificclass = 'css_style_'.preg_replace('#[^a-zA-Z0-9]+#', '', $name);
         if (class_exists($specificclass)) {
             return $specificclass::init($value);
index d88716e..92296fd 100644 (file)
@@ -289,7 +289,7 @@ class csv_import_reader {
      * @param string separator name
      * @return string encoded delimiter char
      */
-    function get_encoded_delimiter($delimiter_name) {
+    static function get_encoded_delimiter($delimiter_name) {
         global $CFG;
         if ($delimiter_name == 'cfg' and isset($CFG->CSV_ENCODE)) {
             return $CFG->CSV_ENCODE;
@@ -305,7 +305,7 @@ class csv_import_reader {
      * @param string who imports?
      * @return int iid
      */
-    function get_new_iid($type) {
+    static function get_new_iid($type) {
         global $USER;
 
         $filename = make_temp_directory('csvimport/'.$type.'/'.$USER->id);
index eeac75d..7f53bb4 100644 (file)
@@ -97,9 +97,8 @@
         <FIELD NAME="theme" TYPE="char" LENGTH="50" NOTNULL="true" SEQUENCE="false" PREVIOUS="lang" NEXT="timecreated"/>
         <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="theme" NEXT="timemodified"/>
         <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated" NEXT="requested"/>
-        <FIELD NAME="requested" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timemodified" NEXT="restrictmodules"/>
-        <FIELD NAME="restrictmodules" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="requested" NEXT="enablecompletion"/>
-        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="restrictmodules" NEXT="completionstartonenrol"/>
+        <FIELD NAME="requested" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timemodified" NEXT="enablecompletion"/>
+        <FIELD NAME="enablecompletion" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'completion' progress-tracking on this course. 0 = disable completion tracking on this course." PREVIOUS="requested" NEXT="completionstartonenrol"/>
         <FIELD NAME="completionstartonenrol" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 = allow use of 'activty completion' progress-tracking on this course. 0 = disable activity completion tracking on this course." PREVIOUS="enablecompletion" NEXT="completionnotify"/>
         <FIELD NAME="completionnotify" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Notify users when they complete this course" PREVIOUS="completionstartonenrol"/>
       </FIELDS>
         <INDEX NAME="course_section" UNIQUE="false" FIELDS="course, section"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections" NEXT="course_allowed_modules">
+    <TABLE NAME="course_request" COMMENT="course requests" PREVIOUS="course_sections" NEXT="filter_active">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="fullname"/>
         <FIELD NAME="fullname" TYPE="char" LENGTH="254" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="shortname"/>
         <INDEX NAME="shortname" UNIQUE="false" FIELDS="shortname"/>
       </INDEXES>
     </TABLE>
-    <TABLE NAME="course_allowed_modules" COMMENT="allowed modules foreach course" PREVIOUS="course_request" NEXT="filter_active">
-      <FIELDS>
-        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="course"/>
-        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="module"/>
-        <FIELD NAME="module" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="course"/>
-      </FIELDS>
-      <KEYS>
-        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
-      </KEYS>
-      <INDEXES>
-        <INDEX NAME="course" UNIQUE="false" FIELDS="course" NEXT="module"/>
-        <INDEX NAME="module" UNIQUE="false" FIELDS="module" PREVIOUS="course"/>
-      </INDEXES>
-    </TABLE>
-    <TABLE NAME="filter_active" COMMENT="Stores information about which filters are active in which contexts. Also the filter sort order. See get_active_filters in lib/filterlib.php for how this data is used." PREVIOUS="course_allowed_modules" NEXT="filter_config">
+    <TABLE NAME="filter_active" COMMENT="Stores information about which filters are active in which contexts. Also the filter sort order. See get_active_filters in lib/filterlib.php for how this data is used." PREVIOUS="course_request" NEXT="filter_config">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="filter"/>
         <FIELD NAME="filter" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false" COMMENT="The filter internal name, like 'filter/tex' or 'mod/glossary'." PREVIOUS="id" NEXT="contextid"/>
index c42d27c..a77878f 100644 (file)
@@ -212,7 +212,110 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2012030900.01);
     }
 
+    if ($oldversion < 2012031500.01) {
+        // Upgrade old course_allowed_modules data to be permission overrides.
+        if ($CFG->restrictmodulesfor === 'all') {
+            $courses = $DB->get_records_menu('course', array(), 'id', 'id, 1');
+        } else if ($CFG->restrictmodulesfor === 'requested') {
+            $courses = $DB->get_records_menu('course', array('retrictmodules' => 1), 'id', 'id, 1');
+        } else {
+            $courses = array();
+        }
+
+        if (!$dbman->table_exists('course_allowed_modules')) {
+            // Upgrade must already have been run on this server. This might happen,
+            // for example, during development of these changes.
+            $courses = array();
+        }
+
+        $modidtoname = $DB->get_records_menu('modules', array(), 'id', 'id, name');
+
+        $coursecount = count($courses);
+        if ($coursecount) {
+            $pbar = new progress_bar('allowedmods', 500, true);
+            $transaction = $DB->start_delegated_transaction();
+        }
+
+        $i = 0;
+        foreach ($courses as $courseid => $notused) {
+            $i += 1;
+            upgrade_set_timeout(60); // 1 minute per course should be fine.
+
+            $allowedmoduleids = $DB->get_records_menu('course_allowed_modules',
+            array('course' => $courseid), 'module', 'module, 1');
+            if (empty($allowedmoduleids)) {
+                // This seems to be the best match for backwards compatibility,
+                // not necessarily with the old code in course_allowed_module function,
+                // but with the code that used to be in the coures settings form.
+                $allowedmoduleids = explode(',', $CFG->defaultallowedmodules);
+                $allowedmoduleids = array_combine($allowedmoduleids, $allowedmoduleids);
+            }
+
+            $context = context_course::instance($courseid);
+
+            list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
+            list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
+            foreach ($managerroleids as $roleid) {
+                unset($roleids[$roleid]);
+            }
+
+            foreach ($modidtoname as $modid => $modname) {
+                if (isset($allowedmoduleids[$modid])) {
+                    // Module is allowed, no worries.
+                    continue;
+                }
+
+                $capability = 'mod/' . $modname . ':addinstance';
+                foreach ($roleids as $roleid) {
+                    assign_capability($capability, CAP_PREVENT, $roleid, $context);
+                }
+            }
+
+            $pbar->update($i, $coursecount, "Upgrading legacy course_allowed_modules data - $i/$coursecount.");
+        }
+
+        if ($coursecount) {
+            $transaction->allow_commit();
+        }
+
+        upgrade_main_savepoint(true, 2012031500.01);
+    }
+
+    if ($oldversion < 2012031500.02) {
+
+        // Define field retrictmodules to be dropped from course
+        $table = new xmldb_table('course');
+        $field = new xmldb_field('restrictmodules');
+
+        // Conditionally launch drop field requested
+        if ($dbman->field_exists($table, $field)) {
+            $dbman->drop_field($table, $field);
+        }
+
+        upgrade_main_savepoint(true, 2012031500.02);
+    }
+
+    if ($oldversion < 2012031500.03) {
+
+        // Define table course_allowed_modules to be dropped
+        $table = new xmldb_table('course_allowed_modules');
+
+        // Conditionally launch drop table for course_allowed_modules
+        if ($dbman->table_exists($table)) {
+            $dbman->drop_table($table);
+        }
+
+        upgrade_main_savepoint(true, 2012031500.03);
+    }
+
+    if ($oldversion < 2012031500.04) {
+        // Clean up the old admin settings.
+        unset_config('restrictmodulesfor');
+        unset_config('restrictbydefault');
+        unset_config('defaultallowedmodules');
+
+        upgrade_main_savepoint(true, 2012031500.04);
+    }
 
     return true;
 }
-
index 7fd29e6..befe5d2 100644 (file)
@@ -1733,9 +1733,10 @@ abstract class enrol_plugin {
      * Returns true if the plugin has one or more bulk operations that can be performed on
      * user enrolments.
      *
+     * @param course_enrolment_manager $manager
      * @return bool
      */
-    public function has_bulk_operations() {
+    public function has_bulk_operations(course_enrolment_manager $manager) {
        return false;
     }
 
@@ -1743,9 +1744,10 @@ abstract class enrol_plugin {
      * Return an array of enrol_bulk_enrolment_operation objects that define
      * the bulk actions that can be performed on user enrolments by the plugin.
      *
+     * @param course_enrolment_manager $manager
      * @return array
      */
-    public function get_bulk_operations() {
+    public function get_bulk_operations(course_enrolment_manager $manager) {
         return array();
     }
 }
index be2cfda..969b11c 100644 (file)
@@ -102,12 +102,13 @@ class MoodleQuickForm_date_selector extends MoodleQuickForm_group
         for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) {
             $years[$i] = $i;
         }
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true);
+        // E_STRICT creating elements without forms is nasty because it internally uses $this
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true);
         // If optional we add a checkbox which the user can use to turn if on
         if($this->_options['optional']) {
-            $this->_elements[] =MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
+            $this->_elements[] =@MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
         }
         foreach ($this->_elements as $element){
             if (method_exists($element, 'setHiddenLabel')){
index 1f8e4ca..f7468c2 100644 (file)
@@ -109,19 +109,20 @@ class MoodleQuickForm_date_time_selector extends MoodleQuickForm_group{
         for ($i=0; $i<60; $i+=$this->_options['step']) {
             $minutes[$i] = sprintf("%02d",$i);
         }
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
-        $this->_elements[] =& MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true);
+        // E_STRICT creating elements without forms is nasty because it internally uses $this
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'day', get_string('day', 'form'), $days, $this->getAttributes(), true);
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'month', get_string('month', 'form'), $months, $this->getAttributes(), true);
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'year', get_string('year', 'form'), $years, $this->getAttributes(), true);
         if (right_to_left()) {   // Switch order of elements for Right-to-Left
-            $this->_elements[] =MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true);
-            $this->_elements[] =MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true);
         } else {
-            $this->_elements[] =MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true);
-            $this->_elements[] =MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('select', 'hour', get_string('hour', 'form'), $hours, $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('select', 'minute', get_string('minute', 'form'), $minutes, $this->getAttributes(), true);
         }
         // If optional we add a checkbox which the user can use to turn if on
         if($this->_options['optional']) {
-            $this->_elements[] =MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
         }
         foreach ($this->_elements as $element){
             if (method_exists($element, 'setHiddenLabel')){
index 565d43b..06cd85a 100644 (file)
@@ -131,12 +131,13 @@ class MoodleQuickForm_duration extends MoodleQuickForm_group {
             $attributes['size'] = 3;
         }
         $this->_elements = array();
-        $this->_elements[] = MoodleQuickForm::createElement('text', 'number', get_string('time', 'form'), $attributes, true);
+        // E_STRICT creating elements without forms is nasty because it internally uses $this
+        $this->_elements[] = @MoodleQuickForm::createElement('text', 'number', get_string('time', 'form'), $attributes, true);
         unset($attributes['size']);
-        $this->_elements[] = MoodleQuickForm::createElement('select', 'timeunit', get_string('timeunit', 'form'), $this->get_units(), $attributes, true);
+        $this->_elements[] = @MoodleQuickForm::createElement('select', 'timeunit', get_string('timeunit', 'form'), $this->get_units(), $attributes, true);
         // If optional we add a checkbox which the user can use to turn if on
         if($this->_options['optional']) {
-            $this->_elements[] = MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
+            $this->_elements[] = @MoodleQuickForm::createElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
         }
         foreach ($this->_elements as $element){
             if (method_exists($element, 'setHiddenLabel')){
@@ -153,7 +154,7 @@ class MoodleQuickForm_duration extends MoodleQuickForm_group {
      * @param object $caller calling object
      * @return bool
      */
-    function onQuickFormEvent($event, $arg, $caller) {
+    function onQuickFormEvent($event, $arg, &$caller) {
         switch ($event) {
             case 'updateValue':
                 // constant values override both default and submitted ones
@@ -216,7 +217,7 @@ class MoodleQuickForm_duration extends MoodleQuickForm_group {
      * @param bool $required Whether a group is required
      * @param string $error An error message associated with a group
      */
-    function accept($renderer, $required = false, $error = null) {
+    function accept(&$renderer, $required = false, $error = null) {
         $renderer->renderElement($this, $required, $error);
     }
 
@@ -228,7 +229,7 @@ class MoodleQuickForm_duration extends MoodleQuickForm_group {
      * @param  bool  $notused Not used.
      * @return array field name => value. The value is the time interval in seconds.
      */
-    function exportValue($submitValues, $notused = false) {
+    function exportValue(&$submitValues, $notused = false) {
         // Get the values from all the child elements.
         $valuearray = array();
         foreach ($this->_elements as $element) {
index 33941e6..a993ffd 100644 (file)
@@ -361,8 +361,9 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element {
         if (count($formats)>1) {
             $str.= html_writer::select($formats, $elname.'[format]', $format, false);
         } else {
+            $keys = array_keys($formats);
             $str.= html_writer::empty_tag('input',
-                    array('name'=>$elname.'[format]', 'type'=> 'hidden', 'value' => array_pop(array_keys($formats))));
+                    array('name'=>$elname.'[format]', 'type'=> 'hidden', 'value' => array_pop($keys)));
         }
         $str .= '</div>';
 
index 042fb09..c232d99 100644 (file)
@@ -57,7 +57,7 @@ class MoodleQuickForm_header extends HTML_QuickForm_header
     *
     * @param HTML_QuickForm_Renderer $renderer a HTML_QuickForm_Renderer object
     */
-    function accept(&$renderer)
+    function accept(&$renderer, $required=false, $error=null)
     {
         $this->_text .= $this->getHelpButton();
         $renderer->renderHeader($this);
index 9f73b17..bdaa133 100644 (file)
@@ -150,7 +150,8 @@ class MoodleQuickForm_tags extends MoodleQuickForm_group {
 
             // Create the element.
             $size = min(5, count($officialtags));
-            $officialtagsselect = MoodleQuickForm::createElement('select', 'officialtags', $label, $officialtags, array('size' => $size));
+            // E_STRICT creating elements without forms is nasty because it internally uses $this
+            $officialtagsselect = @MoodleQuickForm::createElement('select', 'officialtags', $label, $officialtags, array('size' => $size));
             $officialtagsselect->setMultiple(true);
             if ($noofficial) {
                 $officialtagsselect->updateAttributes(array('disabled' => 'disabled'));
@@ -165,7 +166,8 @@ class MoodleQuickForm_tags extends MoodleQuickForm_group {
             } else {
                 $label = get_string('entertags', 'tag');
             }
-            $othertags = MoodleQuickForm::createElement('textarea', 'othertags', $label, array('cols'=>'40', 'rows'=>'5'));
+            // E_STRICT creating elements without forms is nasty because it internally uses $this
+            $othertags = @MoodleQuickForm::createElement('textarea', 'othertags', $label, array('cols'=>'40', 'rows'=>'5'));
             $this->_elements[] = $othertags;
         }
 
index 9fd09d9..a005064 100644 (file)
@@ -62,7 +62,9 @@ function pear_handle_error($error){
 }
 
 if (!empty($CFG->debug) and $CFG->debug >= DEBUG_ALL){
-    PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'pear_handle_error');
+    //TODO: this is a wrong place to init PEAR!
+    $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_CALLBACK;
+    $GLOBALS['_PEAR_default_error_options'] = 'pear_handle_error';
 }
 
 /**
@@ -1638,7 +1640,7 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
             }
             foreach ($elementList as $elementName) {
                 $value = $this->exportValue($elementName);
-                if (PEAR::isError($value)) {
+                if (@PEAR::isError($value)) {
                     return $value;
                 }
                 //oh, stock QuickFOrm was returning array of arrays!
index 97a78f7..ca67450 100644 (file)
@@ -1011,7 +1011,8 @@ class grade_category extends grade_object {
                                 'children'=>$course_category->get_children($include_category_items));
 
         $course_category->sortorder = $course_category->get_sortorder();
-        return grade_category::_fetch_course_tree_recursion($category_array, $course_category->get_sortorder());
+        $sortorder = $course_category->get_sortorder();
+        return grade_category::_fetch_course_tree_recursion($category_array, $sortorder);
     }
 
     /**
index e3568a3..a51586b 100644 (file)
@@ -400,7 +400,7 @@ class grade_grade extends grade_object {
      * @param array $items array of all grade item ids
      * @return void
      */
-    public function check_locktime_all($items) {
+    public static function check_locktime_all($items) {
         global $CFG, $DB;
 
         $now = time(); // no rounding needed, this is not supposed to be called every 10 seconds
index 5483ce0..d26f10a 100644 (file)
@@ -244,7 +244,7 @@ class grade_scale extends grade_object {
      *
      * @return object
      */
-    public function fetch_all_global() {
+    public static function fetch_all_global() {
         return grade_scale::fetch_all(array('courseid'=>0));
     }
 
index 8bf0367..baae4c0 100644 (file)
@@ -46,7 +46,11 @@ foreach ($files as $fsfile) {
         // does not exist
         continue;
     }
-    if (strpos($jsfile, $CFG->dirroot . DIRECTORY_SEPARATOR) !== 0) {
+    if ($CFG->dirroot === '/') {
+        // Some shared hosting sites serve files directly from '/',
+        // this is NOT supported, but at least allow JS when showing
+        // errors and warnings.
+    } else if (strpos($jsfile, $CFG->dirroot . DIRECTORY_SEPARATOR) !== 0) {
         // hackers - not in dirroot
         continue;
     }
diff --git a/lib/minify/README.txt b/lib/minify/README.txt
deleted file mode 100644 (file)
index 6f527a5..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-The files in this directory represent the default Minify setup designed to ease
-integration with your site. This app will combine and minify your Javascript or
-CSS files and serve them with HTTP compression and cache headers.
-
-
-RECOMMENDED
-
-It's recommended to edit config.php to set $min_cachePath to a writeable
-(by PHP) directory on your system. This will improve performance.
-
-
-GETTING STARTED
-
-The quickest way to get started is to use the Minify URI Builder application
-on your website: http://example.com/min/builder/
-
-
-MINIFYING A SINGLE FILE
-
-Let's say you want to serve this file:
-  http://example.com/wp-content/themes/default/default.css
-
-Here's the "Minify URL" for this file:
-  http://example.com/min/?f=wp-content/themes/default/default.css
-
-In other words, the "f" argument is set to the file path from root without the 
-initial "/". As CSS files may contain relative URIs, Minify will automatically
-"fix" these by rewriting them as root relative.
-
-
-COMBINING MULTIPLE FILES IN ONE DOWNLOAD
-
-Separate the paths given to "f" with commas.
-
-Let's say you have CSS files at these URLs:
-  http://example.com/scripts/jquery-1.2.6.js
-  http://example.com/scripts/site.js
-
-You can combine these files through Minify by requesting this URL:
-  http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js
-
-
-SIMPLIFYING URLS WITH A BASE PATH
-
-If you're combining files that share the same ancestor directory, you can use
-the "b" argument to set the base directory for the "f" argument. Do not include
-the leading or trailing "/" characters.
-
-E.g., the following URLs will serve the exact same content:
-  http://example.com/min/?f=scripts/jquery-1.2.6.js,scripts/site.js,scripts/home.js
-  http://example.com/min/?b=scripts&f=jquery-1.2.6.js,site.js,home.js
-
-
-MINIFY URLS IN HTML
-
-In (X)HTML files, don't forget to replace any "&" characters with "&amp;".
-
-
-SPECIFYING ALLOWED DIRECTORIES
-
-By default, Minify will serve any *.css/*.js files within the DOCUMENT_ROOT. If
-you'd prefer to limit Minify's access to certain directories, set the 
-$min_serveOptions['minApp']['allowDirs'] array in config.php. E.g. to limit 
-to the /js and /themes/default directories, use:
-
-$min_serveOptions['minApp']['allowDirs'] = array('//js', '//themes/default');
-
-
-GROUPS: FASTER PERFORMANCE AND BETTER URLS
-
-For the best performance, edit groupsConfig.php to pre-specify groups of files 
-to be combined under preset keys. E.g., here's an example configuration in 
-groupsConfig.php:
-
-return array(
-    'js' => array('//js/Class.js', '//js/email.js')
-);
-
-This pre-selects the following files to be combined under the key "js":
-  http://example.com/js/Class.js
-  http://example.com/js/email.js
-  
-You can now serve these files with this simple URL:
-  http://example.com/min/?g=js
-  
-
-GROUPS: SPECIFYING FILES OUTSIDE THE DOC_ROOT
-
-In the groupsConfig.php array, the "//" in the file paths is a shortcut for
-the DOCUMENT_ROOT, but you can also specify paths from the root of the filesystem
-or relative to the DOC_ROOT: 
-
-return array(
-    'js' => array(
-        '//js/file.js'            // file within DOC_ROOT
-        ,'//../file.js'           // file in parent directory of DOC_ROOT
-        ,'C:/Users/Steve/file.js' // file anywhere on filesystem
-    )
-);
-
-
-FAR-FUTURE EXPIRES HEADERS
-
-Minify can send far-future (one year) Expires headers. To enable this you must
-add a number to the querystring (e.g. /min/?g=js&1234 or /min/f=file.js&1234) 
-and alter it whenever a source file is changed. If you have a build process you 
-can use a build/source control revision number.
-
-If you serve files as a group, you can use the utility function Minify_groupUri()
-to get a "versioned" Minify URI for use in your HTML. E.g.:
-
-<?php
-// add /min/lib to your include_path first!
-require $_SERVER['DOCUMENT_ROOT'] . '/min/utils.php';
-
-$jsUri = Minify_groupUri('js'); 
-echo "<script type='text/javascript' src='{$jsUri}'></script>";
-
-
-DEBUG MODE
-
-In debug mode, instead of compressing files, Minify sends combined files with
-comments prepended to each line to show the line number in the original source
-file. To enable this, set $min_allowDebugFlag to true in config.php and append
-"&debug=1" to your URIs. E.g. /min/?f=script1.js,script2.js&debug=1
-
-Known issue: files with comment-like strings/regexps can cause problems in this mode.
-
-
-QUESTIONS?
-
-http://groups.google.com/group/minify
diff --git a/lib/minify/builder/_index.js b/lib/minify/builder/_index.js
deleted file mode 100644 (file)
index c4b6655..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-var MUB = {
-    _uid : 0
-    ,_minRoot : '/min/?'
-    ,checkRewrite : function () {
-        var testUri = location.pathname.replace(/\/[^\/]*$/, '/rewriteTest.js').substr(1);
-        function fail() {
-            $('#minRewriteFailed')[0].className = 'topNote';
-        };
-        $.ajax({
-            url : '../f=' + testUri + '&' + (new Date()).getTime()
-            ,success : function (data) {
-                if (data === '1') {
-                    MUB._minRoot = '/min/';
-                    $('span.minRoot').html('/min/');
-                } else
-                    fail();                
-            }
-            ,error : fail
-        });
-    }
-    /**
-     * Get markup for new source LI element
-     */
-    ,newLi : function () {
-        return '<li id="li' + MUB._uid + '">http://' + location.host + '/<input type=text size=20>' 
-        + ' <button title="Remove">x</button> <button title="Include Earlier">&uarr;</button>'
-        + ' <button title="Include Later">&darr;</button> <span></span></li>';
-    }
-    /**
-     * Add new empty source LI and attach handlers to buttons
-     */
-    ,addLi : function () {
-        $('#sources').append(MUB.newLi());
-        var li = $('#li' + MUB._uid)[0];
-        $('button[title=Remove]', li).click(function () {
-            $('#results').hide();
-            var hadValue = !!$('input', li)[0].value;
-            $(li).remove();
-        });
-        $('button[title$=Earlier]', li).click(function () {
-            $(li).prev('li').find('input').each(function () {
-                $('#results').hide();
-                // this = previous li input
-                var tmp = this.value;
-                this.value = $('input', li).val();
-                $('input', li).val(tmp);
-                MUB.updateAllTestLinks();
-            });
-        });
-        $('button[title$=Later]', li).click(function () {
-            $(li).next('li').find('input').each(function () {
-                $('#results').hide();
-                // this = next li input
-                var tmp = this.value;
-                this.value = $('input', li).val();
-                $('input', li).val(tmp);
-                MUB.updateAllTestLinks();
-            });
-        });
-        ++MUB._uid;
-    }
-    /**
-     * In the context of a source LI element, this will analyze the URI in
-     * the INPUT and check the URL on the site.
-     */
-    ,liUpdateTestLink : function () { // call in context of li element
-        if (! $('input', this)[0].value) 
-            return;
-        var li = this;
-        $('span', this).html('');
-        var url = 'http://' + location.host + '/' 
-                + $('input', this)[0].value.replace(/^\//, '');
-        $.ajax({
-            url : url
-            ,complete : function (xhr, stat) {
-                if ('success' == stat)
-                    $('span', li).html('&#x2713;');
-                else {
-                    $('span', li).html('<button><b>404! </b> recheck</button>')
-                        .find('button').click(function () {
-                            MUB.liUpdateTestLink.call(li);
-                        });
-                }
-            }
-            ,dataType : 'text'
-        });
-    }
-    /**
-     * Check all source URLs
-     */
-    ,updateAllTestLinks : function () {
-        $('#sources li').each(MUB.liUpdateTestLink);
-    }
-    /**
-     * In a given array of strings, find the character they all have at
-     * a particular index
-     * @param Array arr array of strings
-     * @param Number pos index to check
-     * @return mixed a common char or '' if any do not match
-     */
-    ,getCommonCharAtPos : function (arr, pos) {
-        var i
-           ,l = arr.length
-           ,c = arr[0].charAt(pos);
-        if (c === '' || l === 1)
-            return c;
-        for (i = 1; i < l; ++i)
-            if (arr[i].charAt(pos) !== c)
-                return '';
-        return c;
-    }
-    /**
-     * Get the shortest URI to minify the set of source files
-     * @param Array sources URIs
-     */
-    ,getBestUri : function (sources) {
-        var pos = 0
-           ,base = ''
-           ,c;
-        while (true) {
-            c = MUB.getCommonCharAtPos(sources, pos);
-            if (c === '')
-                break;
-            else
-                base += c;
-            ++pos;
-        }
-        base = base.replace(/[^\/]+$/, '');
-        var uri = MUB._minRoot + 'f=' + sources.join(',');
-        if (base.charAt(base.length - 1) === '/') {
-            // we have a base dir!
-            var basedSources = sources
-               ,i
-               ,l = sources.length;
-            for (i = 0; i < l; ++i) {
-                basedSources[i] = sources[i].substr(base.length);
-            }
-            base = base.substr(0, base.length - 1);
-            var bUri = MUB._minRoot + 'b=' + base + '&f=' + basedSources.join(',');
-            //window.console && console.log([uri, bUri]);
-            uri = uri.length < bUri.length
-                ? uri
-                : bUri;
-        }
-        return uri;
-    }
-    /**
-     * Create the Minify URI for the sources
-     */
-    ,update : function () {
-        MUB.updateAllTestLinks();
-        var sources = []
-           ,ext = false
-           ,fail = false;
-        $('#sources input').each(function () {
-            var m, val;
-            if (! fail && this.value && (m = this.value.match(/\.(css|js)$/))) {
-                var thisExt = m[1];
-                if (ext === false)
-                    ext = thisExt; 
-                else if (thisExt !== ext) {
-                    fail = true;
-                    return alert('extensions must match!');
-                }
-                this.value = this.value.replace(/^\//, '');
-                if (-1 != $.inArray(this.value, sources)) {
-                    fail = true;
-                    return alert('duplicate file!');
-                }
-                sources.push(this.value);
-            } 
-        });
-        if (fail || ! sources.length)
-            return;
-        $('#groupConfig').val("    'keyName' => array('//" + sources.join("', '//") + "'),");
-        var uri = MUB.getBestUri(sources)
-           ,uriH = uri.replace(/</, '&lt;').replace(/>/, '&gt;').replace(/&/, '&amp;');
-        $('#uriA').html(uriH)[0].href = uri;
-        $('#uriHtml').val(
-            ext === 'js' 
-            ? '<script type="text/javascript" src="' + uriH + '"></script>'
-            : '<link type="text/css" rel="stylesheet" href="' + uriH + '" />'
-        );
-        $('#results').show();
-    }
-    /**
-     * Handler for the "Add file +" button
-     */
-    ,addButtonClick : function () {
-        $('#results').hide();
-        MUB.addLi();
-        MUB.updateAllTestLinks();
-        $('#update').show().click(MUB.update);
-        $('#sources li:last input')[0].focus();
-    }
-    /**
-     * Runs on DOMready
-     */
-    ,init : function () {
-        $('#app').show();
-        $('#sources').html('');
-        $('#add button').click(MUB.addButtonClick);
-        // make easier to copy text out of
-        $('#uriHtml, #groupConfig').click(function () {
-            this.select();
-        }).focus(function () {
-            this.select();
-        });
-        $('a.ext').attr({target:'_blank'});
-        if (location.hash) {
-            // make links out of URIs from bookmarklet
-            $('#getBm').hide();
-            $('#bmUris').html('<p><strong>Found by bookmarklet:</strong> /<a href=#>'
-                + location.hash.substr(1).split(',').join('</a> | /<a href=#>')
-                + '</a></p>'
-            );
-            $('#bmUris a').click(function () {
-                MUB.addButtonClick();
-                $('#sources li:last input').val(this.innerHTML)
-                MUB.liUpdateTestLink.call($('#sources li:last')[0]);
-                $('#results').hide();
-                return false;
-            }).attr({title:'Add file +'});
-        } else {
-            // copy bookmarklet code into href
-            var bmUri = location.pathname.replace(/\/[^\/]*$/, '/bm.js').substr(1);
-            $.ajax({
-                url : '../?f=' + bmUri
-                ,success : function (code) {
-                    $('#bm')[0].href = code
-                        .replace('%BUILDER_URL%', location.href)
-                        .replace(/\n/g, ' ');
-                }
-                ,dataType : 'text'
-            });
-            $.browser.msie && $('#getBm p:last').append(' Sorry, not supported in MSIE!');
-            MUB.addButtonClick();
-        }
-        MUB.checkRewrite();
-    }
-};
-window.onload = MUB.init;
diff --git a/lib/minify/builder/bm.js b/lib/minify/builder/bm.js
deleted file mode 100644 (file)
index 703039b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-javascript:(function() {
-    var d = document
-       ,uris = []
-       ,i = 0
-       ,o
-       ,home = (location + '').split('/').splice(0, 3).join('/') + '/';
-    function add(uri) {
-        return (0 === uri.indexOf(home))
-            && (!/[\?&]/.test(uri))
-            && uris.push(escape(uri.substr(home.length)));
-    };
-    function sheet(ss) {
-        // we must check the domain with add() before accessing ss.cssRules
-        // otherwise a security exception will be thrown
-        if (ss.href && add(ss.href) && ss.cssRules) {
-            var i = 0, r;
-            while (r = ss.cssRules[i++])
-                r.styleSheet && sheet(r.styleSheet);
-        }
-    };
-    while (o = d.getElementsByTagName('script')[i++])
-        o.src && !(o.type && /vbs/i.test(o.type)) && add(o.src);
-    i = 0;
-    while (o = d.styleSheets[i++])
-    /* http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-DocumentStyle-styleSheets
-    document.styleSheet is a list property where [0] accesses the 1st element and 
-    [outOfRange] returns null. In IE, styleSheets is a function, and also throws an 
-    exception when you check the out of bounds index. (sigh) */
-        sheet(o);
-    if (uris.length)
-        window.open('%BUILDER_URL%#' + uris.join(','));
-    else
-        alert('No js/css files found with URLs within "' 
-            + home.split('/')[2]
-            + '".\n(This tool is limited to URLs with the same domain.)');
-})();
diff --git a/lib/minify/builder/index.php b/lib/minify/builder/index.php
deleted file mode 100644 (file)
index 1b20982..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-<?php 
-
-if (phpversion() < 5) {
-    exit('Minify requires PHP5 or greater.');
-}
-
-// check for auto-encoding
-$encodeOutput = (function_exists('gzdeflate')
-                 && !ini_get('zlib.output_compression'));
-
-require dirname(__FILE__) . '/../config.php';
-
-if (! $min_enableBuilder) {
-    header('Location: /');
-    exit();
-}
-
-ob_start();
-?>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<head>
-    <meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
-    <title>Minify URI Builder</title>
-    <style type="text/css">
-body {margin:1em 60px;}
-h1, h2, h3 {margin-left:-25px; position:relative;}
-h1 {margin-top:0;}
-#sources {margin:0; padding:0;}
-#sources li {margin:0 0 0 40px}
-#sources li input {margin-left:2px}
-#add {margin:5px 0 1em 40px}
-.hide {display:none}
-#uriTable {border-collapse:collapse;}
-#uriTable td, #uriTable th {padding-top:10px;}
-#uriTable th {padding-right:10px;}
-#groupConfig {font-family:monospace;}
-b {color:#c00}
-.topNote {background: #ff9; display:inline-block; padding:.5em .6em; margin:0 0 1em;}
-.topWarning {background:#c00; color:#fff; padding:.5em .6em; margin:0 0 1em;}
-    </style>
-</head>
-
-<?php if (! isset($min_cachePath)): ?>
-<p class=topNote><strong>Note:</strong> Please set <code>$min_cachePath</code> 
-in /min/config.php to improve performance.</p>
-<?php endIf; ?>
-
-<p id=minRewriteFailed class="hide"><strong>Note:</strong> Your webserver does not seem to
- support mod_rewrite (used in /min/.htaccess). Your Minify URIs will contain "?", which 
-<a href="http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/"
->may reduce the benefit of proxy cache servers</a>.</p>
-
-<h1>Minify URI Builder</h1>
-
-<noscript><p class="topNote">Javascript and a browser supported by jQuery 1.2.6 is required
-for this application.</p></noscript>
-
-<div id=app class=hide>
-
-<p>Create a list of Javascript or CSS files (or 1 is fine) you'd like to combine
-and click [Update].</p>
-
-<ol id=sources><li></li></ol>
-<div id=add><button>Add file +</button></div>
-
-<div id=bmUris></div>
-
-<p><button id=update class=hide>Update</button></p>
-
-<div id=results class=hide>
-
-<h2>Minify URI</h2>
-<p>Place this URI in your HTML to serve the files above combined, minified, compressed and
-with cache headers.</p>
-<table id=uriTable>
-    <tr><th>URI</th><td><a id=uriA class=ext>/min</a> <small>(opens in new window)</small></td></tr>
-    <tr><th>HTML</th><td><input id=uriHtml type=text size=100 readonly></td></tr>
-</table>
-
-<h2>How to serve these files as a group</h2>
-<p>For the best performance you can serve these files as a pre-defined group with a URI
-like: <code><span class=minRoot>/min/?</span>g=keyName</code></p>
-<p>To do this, add a line like this to /min/groupsConfig.php:</p>
-
-<pre><code>return array(
-    <span style="color:#666">... your existing groups here ...</span>
-<input id=groupConfig size=100 type=text readonly>
-);</code></pre>
-
-<p><em>Make sure to replace <code>keyName</code> with a unique key for this group.</em></p>
-</div>
-
-<div id=getBm>
-<h3>Find URIs on a Page</h3>
-<p>You can use the bookmarklet below to fetch all CSS &amp; Javascript URIs from a page
-on your site. When you active it, this page will open in a new window with a list of
-available URIs to add.</p>
-
-<p><a id=bm>Create Minify URIs</a> <small>(right-click, add to bookmarks)</small></p>
-</div>
-
-<h3>Combining CSS files that contain <code>@import</code></h3>
-<p>If your CSS files contain <code>@import</code> declarations, Minify will not 
-remove them. Therefore, you will want to remove those that point to files already
-in your list, and move any others to the top of the first file in your list 
-(imports below any styles will be ignored by browsers as invalid).</p>
-<p>If you desire, you can use Minify URIs in imports and they will not be touched
-by Minify. E.g. <code>@import "<span class=minRoot>/min/?</span>g=css2";</code></p>
-
-</div><!-- #app -->
-
-<hr>
-<p>Need help? Search or post to the <a class=ext 
-href="http://groups.google.com/group/minify">Minify discussion list</a>.</p>
-<p><small>This app is minified :) <a class=ext 
-href="http://code.google.com/p/minify/source/browse/trunk/min/builder/index.php">view 
-source</a></small></p>
-
-<script type="text/javascript" 
-src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
-
-<script type="text/javascript">
-$(function () {
-    // detection of double output encoding
-    var msg = '<\p class=topWarning><\strong>Warning:<\/strong> ';
-    var url = 'ocCheck.php?' + (new Date()).getTime();
-    $.get(url, function (ocStatus) {
-        $.get(url + '&hello=1', function (ocHello) {
-            if (ocHello != 'World!') {
-                msg += 'It appears output is being automatically compressed, interfering ' 
-                     + ' with Minify\'s own compression. ';
-                if (ocStatus == '1')
-                    msg += 'The option "zlib.output_compression" is enabled in your PHP configuration. '
-                         + 'Minify set this to "0", but it had no effect. This option must be disabled ' 
-                         + 'in php.ini or .htaccess.';
-                else
-                    msg += 'The option "zlib.output_compression" is disabled in your PHP configuration '
-                         + 'so this behavior is likely due to a server option.';
-                $(document.body).prepend(msg + '<\/p>');
-            } else
-                if (ocStatus == '1')
-                    $(document.body).prepend('<\p class=topNote><\strong>Note:</\strong> The option '
-                        + '"zlib.output_compression" is enabled in your PHP configuration, but has been '
-                        + 'successfully disabled via ini_set(). If you experience mangled output you '
-                        + 'may want to consider disabling this option in your PHP configuration.<\/p>'
-                    );
-        });
-    });
-});
-</script>
-<script type="text/javascript">
-    // workaround required to test when /min isn't child of web root
-    var src = location.pathname.replace(/\/[^\/]*$/, '/_index.js').substr(1);
-    document.write('<\script type="text/javascript" src="../?f=' + src + '"><\/script>');
-</script>
-
-<?php
-
-$serveOpts = array(
-    'content' => ob_get_contents()
-    ,'id' => __FILE__
-    ,'lastModifiedTime' => max(
-        // regenerate cache if either of these change
-        filemtime(__FILE__)
-        ,filemtime(dirname(__FILE__) . '/../config.php')
-    )
-    ,'minifyAll' => true
-    ,'encodeOutput' => $encodeOutput
-);
-ob_end_clean();
-
-set_include_path(dirname(__FILE__) . '/../lib' . PATH_SEPARATOR . get_include_path());
-
-require 'Minify.php';
-
-if (0 === stripos(PHP_OS, 'win')) {
-    Minify::setDocRoot(); // we may be on IIS
-}
-Minify::setCache(isset($min_cachePath) ? $min_cachePath : null);
-Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
-
-Minify::serve('Page', $serveOpts);
diff --git a/lib/minify/builder/ocCheck.php b/lib/minify/builder/ocCheck.php
deleted file mode 100644 (file)
index 8cc19af..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php 
-/**
- * AJAX checks for zlib.output_compression
- * 
- * @package Minify
- */
-
-$_oc = ini_get('zlib.output_compression');
-// allow access only if builder is enabled
-require dirname(__FILE__) . '/../config.php';
-if (! $min_enableBuilder) {
-    header('Location: /');
-    exit();
-}
-
-if (isset($_GET['hello'])) {
-    // echo 'World!'
-    
-    // try to prevent double encoding (may not have an effect)
-    ini_set('zlib.output_compression', '0');
-    
-    require $min_libPath . '/HTTP/Encoder.php';
-    HTTP_Encoder::$encodeToIe6  = true; // just in case
-    $he = new HTTP_Encoder(array(
-        'content' => 'World!'
-        ,'method' => 'deflate'
-    ));
-    $he->encode();
-    $he->sendAll();
-
-} else {
-    // echo status "0" or "1"
-    header('Content-Type: text/plain');
-    echo (int)$_oc;
-}
diff --git a/lib/minify/builder/rewriteTest.js b/lib/minify/builder/rewriteTest.js
deleted file mode 100644 (file)
index d00491f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-1
index 7e29c0b..e2f709c 100644 (file)
@@ -1,19 +1,40 @@
 <?php
 /**
- * Configuration for default Minify application
+ * Configuration for "min", the default application built with the Minify
+ * library
+ *
  * @package Minify
  */
 
-defined('MOODLE_INTERNAL') || die();
+
+defined('MOODLE_INTERNAL') || die(); // start of moodle modification
+
+// NOTE: Copy all necessary settings here, do not modify the rest.
+//       Minifier can not be accessed directly, only use PHP api.
+
+$min_enableBuilder = false;
+$min_errorLogger = false;
+$min_allowDebugFlag = debugging('', DEBUG_DEVELOPER);
+$min_cachePath = $CFG->tempdir;
+$min_documentRoot = $CFG->dirroot.'/lib/minify';
+$min_cacheFileLocking = true;
+$min_serveOptions['bubbleCssImports'] = false;
+$min_serveOptions['maxAge'] = 1800;
+$min_serveOptions['minApp']['groupsOnly'] = true;
+$min_symlinks = array();
+$min_uploaderHoursBehind = 0;
+$min_libPath = dirname(__FILE__) . '/lib';
+// do not change zlib compression or buffering here
+
+// TODO: locking setting, caching setting
+
+return; // end of moodle modification
+
 
 /**
- * In 'debug' mode, Minify can combine files with no minification and
- * add comments to indicate line #s of the original files.
- *
- * To allow debugging, set this option to true and add "&debug=1" to
- * a URI. E.g. /min/?f=script1.js,script2.js&debug=1
- */
-$min_allowDebugFlag = ($CFG->debug);
+ * Allow use of the Minify URI Builder app. Only set this to true while you need it.
+ **/
+$min_enableBuilder = true;
 
 
 /**
@@ -23,24 +44,38 @@ $min_allowDebugFlag = ($CFG->debug);
  *
  * If you want to use a custom error logger, set this to your logger
  * instance. Your object should have a method log(string $message).
- *
- * @todo cache system does not have error logging yet.
  */
 $min_errorLogger = false;
 
 
 /**
- * Allow use of the Minify URI Builder app. If you no longer need
- * this, set to false.
- **/
-$min_enableBuilder = false;
+ * To allow debug mode output, you must set this option to true.
+ *
+ * Once true, you can send the cookie minDebug to request debug mode output. The
+ * cookie value should match the URIs you'd like to debug. E.g. to debug
+ * /min/f=file1.js send the cookie minDebug=file1.js
+ * You can manually enable debugging by appending "&debug" to a URI.
+ * E.g. /min/?f=script1.js,script2.js&debug
+ *
+ * In 'debug' mode, Minify combines files with no minification and adds comments
+ * to indicate line #s of the original files.
+ */
+$min_allowDebugFlag = false;
 
 
 /**
  * For best performance, specify your temp directory here. Otherwise Minify
  * will have to load extra code to guess. Some examples below:
  */
-$min_cachePath = $CFG->tempdir.'';
+//$min_cachePath = 'c:\\WINDOWS\\Temp';
+//$min_cachePath = '/tmp';
+//$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
+/**
+ * To use APC/Memcache/ZendPlatform for cache storage, require the class and
+ * set $min_cachePath to an instance. Example below:
+ */
+//require dirname(__FILE__) . '/lib/Minify/Cache/APC.php';
+//$min_cachePath = new Minify_Cache_APC();
 
 
 /**
@@ -53,8 +88,8 @@ $min_cachePath = $CFG->tempdir.'';
  * If /min/ is directly inside your document root, just uncomment the
  * second line. The third line might work on some Apache servers.
  */
-$min_documentRoot = $CFG->dirroot.'/lib/minify';
-//$min_documentRoot = substr(__FILE__, 0, strlen(__FILE__) - 15);
+$min_documentRoot = '';
+//$min_documentRoot = substr(__FILE__, 0, -15);
 //$min_documentRoot = $_SERVER['SUBDOMAIN_DOCUMENT_ROOT'];
 
 
@@ -77,9 +112,9 @@ $min_serveOptions['bubbleCssImports'] = false;
 
 
 /**
- * Maximum age of browser cache in seconds. After this period, the browser
- * will send another conditional GET. Use a longer period for lower traffic
- * but you may want to shorten this before making changes if it's crucial
+ * Cache-Control: max-age value sent to browser (in seconds). After this period,
+ * the browser will send another conditional GET. Use a longer period for lower
+ * traffic but you may want to shorten this before making changes if it's crucial
  * those changes are seen immediately.
  *
  * Note: Despite this setting, if you include a number at the end of the
@@ -88,6 +123,18 @@ $min_serveOptions['bubbleCssImports'] = false;
 $min_serveOptions['maxAge'] = 1800;
 
 
+/**
+ * To use Google's Closure Compiler API (falling back to JSMin on failure),
+ * uncomment the following lines:
+ */
+/*function closureCompiler($js) {
+    require_once 'Minify/JS/ClosureCompiler.php';
+    return Minify_JS_ClosureCompiler::minify($js);
+}
+$min_serveOptions['minifiers']['application/x-javascript'] = 'closureCompiler';
+//*/
+
+
 /**
  * If you'd like to restrict the "f" option to files within/below
  * particular directories below DOCUMENT_ROOT, set this here.
@@ -102,12 +149,17 @@ $min_serveOptions['maxAge'] = 1800;
  * Set to true to disable the "f" GET parameter for specifying files.
  * Only the "g" parameter will be considered.
  */
-$min_serveOptions['minApp']['groupsOnly'] = true;
+$min_serveOptions['minApp']['groupsOnly'] = false;
+
 
 /**
- * Maximum # of files that can be specified in the "f" GET parameter
+ * By default, Minify will not minify files with names containing .min or -min
+ * before the extension. E.g. myFile.min.js will not be processed by JSMin
+ *
+ * To minify all files, set this option to null. You could also specify your
+ * own pattern that is matched against the filename.
  */
-$min_serveOptions['minApp']['maxFiles'] = 10;
+//$min_serveOptions['minApp']['noMinPattern'] = '@[-\\.]min\\.(?:js|css)$@i';
 
 
 /**
@@ -148,7 +200,7 @@ $min_uploaderHoursBehind = 0;
  * Path to Minify's lib folder. If you happen to move it, change
  * this accordingly.
  */
-$min_libPath = $CFG->libdir . '/minify/lib';
+$min_libPath = dirname(__FILE__) . '/lib';
 
 
 // try to disable output_compression (may not have an effect)
index 5639880..c900776 100644 (file)
@@ -7,28 +7,11 @@
 /** 
  * You may wish to use the Minify URI Builder app to suggest
  * changes. http://yourdomain/min/builder/
+ *
+ * See http://code.google.com/p/minify/wiki/CustomSource for other ideas
  **/
 
 return array(
     // 'js' => array('//js/file1.js', '//js/file2.js'),
     // 'css' => array('//css/file1.css', '//css/file2.css'),
-
-    // custom source example
-    /*'js2' => array(
-        dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
-        // do NOT process this file
-        new Minify_Source(array(
-            'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
-            'minifier' => create_function('$a', 'return $a;')
-        ))
-    ),//*/
-
-    /*'js3' => array(
-        dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
-        // do NOT process this file
-        new Minify_Source(array(
-            'filepath' => dirname(__FILE__) . '/../min_unit_tests/_test_files/js/before.js',
-            'minifier' => array('Minify_Packer', 'minify')
-        ))
-    ),//*/
-);
+);
\ No newline at end of file
index d9d1210..d301a64 100644 (file)
@@ -1065,7 +1065,7 @@ class FirePHP {
    * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
    * @author      Christoph Dorn <christoph@christophdorn.com>
    * @copyright   2005 Michal Migurski
-   * @version     CVS: $Id$
+   * @version     CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
    * @license     http://www.opensource.org/licenses/bsd-license.php
    * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
    */
index 823db05..93b7e75 100644 (file)
@@ -75,9 +75,8 @@ class HTTP_ConditionalGet {
     /**
      * @param array $spec options
      * 
-     * 'isPublic': (bool) if true, the Cache-Control header will contain 
-     * "public", allowing proxies to cache the content. Otherwise "private" will 
-     * be sent, allowing only browser caching. (default false)
+     * 'isPublic': (bool) if false, the Cache-Control header will contain
+     * "private", allowing only browser caching. (default false)
      * 
      * 'lastModifiedTime': (int) if given, both ETag AND Last-Modified headers
      * will be sent with content. This is recommended.
@@ -106,8 +105,6 @@ class HTTP_ConditionalGet {
      * seconds, and also set the Expires header to the equivalent GMT date. 
      * After the max-age period has passed, the browser will again send a 
      * conditional GET to revalidate its cache.
-     * 
-     * @return null
      */
     public function __construct($spec)
     {
@@ -150,7 +147,10 @@ class HTTP_ConditionalGet {
         } elseif (isset($spec['contentHash'])) { // Use the hash as the ETag
             $this->_setEtag($spec['contentHash'] . $etagAppend, $scope);
         }
-        $this->_headers['Cache-Control'] = "max-age={$maxAge}, {$scope}";
+        $privacy = ($scope === 'private')
+            ? ', private'
+            : '';
+        $this->_headers['Cache-Control'] = "max-age={$maxAge}{$privacy}";
         // invalidate cache if disabled, otherwise check
         $this->cacheIsValid = (isset($spec['invalidate']) && $spec['invalidate'])
             ? false
@@ -209,7 +209,9 @@ class HTTP_ConditionalGet {
     {
         $headers = $this->_headers;
         if (array_key_exists('_responseCode', $headers)) {
-            header($headers['_responseCode']);
+            // FastCGI environments require 3rd arg to header() to be set
+            list(, $code) = explode(' ', $headers['_responseCode'], 3);
+            header($headers['_responseCode'], true, $code);
             unset($headers['_responseCode']);
         }
         foreach ($headers as $name => $val) {
@@ -230,8 +232,6 @@ class HTTP_ConditionalGet {
      * "private" will be sent, allowing only browser caching.
      *
      * @param array $options (default empty) additional options for constructor
-     *
-     * @return null     
      */
     public static function check($lastModifiedTime = null, $isPublic = false, $options = array())
     {
@@ -267,13 +267,21 @@ class HTTP_ConditionalGet {
     protected $_lmTime = null;
     protected $_etag = null;
     protected $_stripEtag = false;
-    
+
+    /**
+     * @param string $hash
+     *
+     * @param string $scope
+     */
     protected function _setEtag($hash, $scope)
     {
         $this->_etag = '"' . substr($scope, 0, 3) . $hash . '"';
         $this->_headers['ETag'] = $this->_etag;
     }
 
+    /**
+     * @param int $time
+     */
     protected function _setLastModified($time)
     {
         $this->_lmTime = (int)$time;
@@ -282,6 +290,8 @@ class HTTP_ConditionalGet {
 
     /**
      * Determine validity of client cache and queue 304 header if valid
+     *
+     * @return bool
      */
     protected function _isCacheValid()
     {
@@ -298,6 +308,9 @@ class HTTP_ConditionalGet {
         return $isValid;
     }
 
+    /**
+     * @return bool
+     */
     protected function resourceMatchedEtag()
     {
         if (!isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
@@ -319,7 +332,12 @@ class HTTP_ConditionalGet {
         }
         return false;
     }
-    
+
+    /**
+     * @param string $etag
+     *
+     * @return string
+     */
     protected function normalizeEtag($etag) {
         $etag = trim($etag);
         return $this->_stripEtag
@@ -327,17 +345,17 @@ class HTTP_ConditionalGet {
             : $etag;
     }
 
+    /**
+     * @return bool
+     */
     protected function resourceNotModified()
     {
         if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
             return false;
         }
-        $ifModifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
-        if (false !== ($semicolon = strrpos($ifModifiedSince, ';'))) {
-            // IE has tacked on extra data to this header, strip it
-            $ifModifiedSince = substr($ifModifiedSince, 0, $semicolon);
-        }
-        if ($ifModifiedSince == self::gmtDate($this->_lmTime)) {
+        // strip off IE's extra data (semicolon)
+        list($ifModifiedSince) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE'], 2);
+        if (strtotime($ifModifiedSince) >= $this->_lmTime) {
             // Apache 2.2's behavior. If there was no ETag match, send the 
             // non-encoded version of the ETag value.
             $this->_headers['ETag'] = $this->normalizeEtag($this->_etag);
index 05ca552..8f34779 100644 (file)
@@ -59,7 +59,7 @@ class HTTP_Encoder {
      * 
      * @var bool
      */
-    public static $encodeToIe6 = false;
+    public static $encodeToIe6 = true;
     
     
     /**
@@ -85,13 +85,16 @@ class HTTP_Encoder {
      * method. If not set, the best method will be chosen by getAcceptedEncoding()
      * The available methods are 'gzip', 'deflate', 'compress', and '' (no
      * encoding)
-     * 
-     * @return null
      */
     public function __construct($spec) 
     {
+        $this->_useMbStrlen = (function_exists('mb_strlen')
+                               && (ini_get('mbstring.func_overload') !== '')
+                               && ((int)ini_get('mbstring.func_overload') & 2));
         $this->_content = $spec['content'];
-        $this->_headers['Content-Length'] = (string)strlen($this->_content);
+        $this->_headers['Content-Length'] = $this->_useMbStrlen
+            ? (string)mb_strlen($this->_content, '8bit')
+            : (string)strlen($this->_content);
         if (isset($spec['type'])) {
             $this->_headers['Content-Type'] = $spec['type'];
         }
@@ -109,7 +112,7 @@ class HTTP_Encoder {
      * 
      * Call after encode() for encoded content.
      * 
-     * return string
+     * @return string
      */
     public function getContent() 
     {
@@ -143,8 +146,6 @@ class HTTP_Encoder {
      * not handled purposefully.
      * 
      * @see getHeaders()
-     * 
-     * @return null
      */
     public function sendHeaders()
     {
@@ -161,8 +162,6 @@ class HTTP_Encoder {
      * You must call this before headers are sent and it probably cannot be
      * used in conjunction with zlib output buffering / mod_gzip. Errors are
      * not handled purposefully.
-     * 
-     * @return null
      */
     public function sendAll()
     {
@@ -195,7 +194,7 @@ class HTTP_Encoder {
         // @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
         
         if (! isset($_SERVER['HTTP_ACCEPT_ENCODING'])
-            || self::_isBuggyIe())
+            || self::isBuggyIe())
         {
             return array('', '');
         }
@@ -253,7 +252,9 @@ class HTTP_Encoder {
      */
     public function encode($compressionLevel = null)
     {
-        $this->_headers['Vary'] = 'Accept-Encoding';
+        if (! self::isBuggyIe()) {
+            $this->_headers['Vary'] = 'Accept-Encoding';
+        }
         if (null === $compressionLevel) {
             $compressionLevel = self::$compressionLevel;
         }
@@ -273,7 +274,9 @@ class HTTP_Encoder {
         if (false === $encoded) {
             return false;
         }
-        $this->_headers['Content-Length'] = strlen($encoded);
+        $this->_headers['Content-Length'] = $this->_useMbStrlen
+            ? (string)mb_strlen($encoded, '8bit')
+            : (string)strlen($encoded);
         $this->_headers['Content-Encoding'] = $this->_encodeMethod[1];
         $this->_content = $encoded;
         return true;
@@ -301,16 +304,17 @@ class HTTP_Encoder {
         $he->sendAll();
         return $ret;
     }
-    
-    protected $_content = '';
-    protected $_headers = array();
-    protected $_encodeMethod = array('', '');
 
     /**
-     * Is the browser an IE version earlier than 6 SP2?  
+     * Is the browser an IE version earlier than 6 SP2?
+     *
+     * @return bool
      */
-    protected static function _isBuggyIe()
+    public static function isBuggyIe()
     {
+        if (empty($_SERVER['HTTP_USER_AGENT'])) {
+            return false;
+        }
         $ua = $_SERVER['HTTP_USER_AGENT'];
         // quick escape for non-IEs
         if (0 !== strpos($ua, 'Mozilla/4.0 (compatible; MSIE ')
@@ -318,9 +322,14 @@ class HTTP_Encoder {
             return false;
         }
         // no regex = faaast
-        $version = (float)substr($ua, 30); 
+        $version = (float)substr($ua, 30);
         return self::$encodeToIe6
             ? ($version < 6 || ($version == 6 && false === strpos($ua, 'SV1')))
             : ($version < 7);
     }
+    
+    protected $_content = '';
+    protected $_headers = array();
+    protected $_encodeMethod = array('', '');
+    protected $_useMbStrlen = false;
 }
index 770e1c6..b6879f3 100644 (file)
@@ -1,16 +1,20 @@
 <?php
 /**
- * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
+ * JSMin.php - modified PHP implementation of Douglas Crockford's JSMin.
  *
- * This is a direct port of jsmin.c to PHP with a few PHP performance tweaks and
- * modifications to preserve some comments (see below). Also, rather than using
- * stdin/stdout, JSMin::minify() accepts a string as input and returns another
- * string as output.
+ * <code>
+ * $minifiedJs = JSMin::minify($js);
+ * </code>
+ *
+ * This is a modified port of jsmin.c. Improvements:
+ * 
+ * Does not choke on some regexp literals containing quote characters. E.g. /'/
  * 
- * Comments containing IE conditional compilation are preserved, as are multi-line
- * comments that begin with "/*!" (for documentation purposes). In the latter case
- * newlines are inserted around the comment to enhance readability.
+ * Spaces are preserved after some add/sub operators, so they are not mistakenly 
+ * converted to post-inc/dec. E.g. a + ++b -> a+ ++b
  *
+ * Preserves multi-line comments that begin with /*!
+ * 
  * PHP 5 or higher is required.
  *
  * Permission is hereby granted to use this version of the library under the
@@ -56,7 +60,7 @@ class JSMin {
     const ACTION_KEEP_A     = 1;
     const ACTION_DELETE_A   = 2;
     const ACTION_DELETE_A_B = 3;
-    
+
     protected $a           = "\n";
     protected $b           = '';
     protected $input       = '';
@@ -64,11 +68,13 @@ class JSMin {
     protected $inputLength = 0;
     protected $lookAhead   = null;
     protected $output      = '';
-    
+    protected $lastByteOut  = '';
+
     /**
-     * Minify Javascript
+     * Minify Javascript.
      *
      * @param string $js Javascript to be minified
+     *
      * @return string
      */
     public static function minify($js)
@@ -76,38 +82,55 @@ class JSMin {
         $jsmin = new JSMin($js);
         return $jsmin->min();
     }
-    
+
     /**
-     * Setup process
+     * @param string $input
      */
     public function __construct($input)
     {
-        $this->input       = str_replace("\r\n", "\n", $input);
-        $this->inputLength = strlen($this->input);
+        $this->input = $input;
     }
-    
+
     /**
      * Perform minification, return result
+     *
+     * @return string
      */
     public function min()
     {
         if ($this->output !== '') { // min already run
             return $this->output;
         }
+
+        $mbIntEnc = null;
+        if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
+            $mbIntEnc = mb_internal_encoding();
+            mb_internal_encoding('8bit');
+        }
+        $this->input = str_replace("\r\n", "\n", $this->input);
+        $this->inputLength = strlen($this->input);
+
         $this->action(self::ACTION_DELETE_A_B);
-        
+
         while ($this->a !== null) {
             // determine next command
             $command = self::ACTION_KEEP_A; // default
             if ($this->a === ' ') {
-                if (! $this->isAlphaNum($this->b)) {
+                if (($this->lastByteOut === '+' || $this->lastByteOut === '-') 
+                    && ($this->b === $this->lastByteOut)) {
+                    // Don't delete this space. If we do, the addition/subtraction
+                    // could be parsed as a post-increment
+                } elseif (! $this->isAlphaNum($this->b)) {
                     $command = self::ACTION_DELETE_A;
                 }
             } elseif ($this->a === "\n") {
                 if ($this->b === ' ') {
                     $command = self::ACTION_DELETE_A_B;
-                } elseif (false === strpos('{[(+-', $this->b) 
-                          && ! $this->isAlphaNum($this->b)) {
+                // in case of mbstring.func_overload & 2, must check for null b,
+                // otherwise mb_strpos will give WARNING
+                } elseif ($this->b === null
+                          || (false === strpos('{[(+-', $this->b)
+                              && ! $this->isAlphaNum($this->b))) {
                     $command = self::ACTION_DELETE_A;
                 }
             } elseif (! $this->isAlphaNum($this->a)) {
@@ -120,19 +143,38 @@ class JSMin {
             $this->action($command);
         }
         $this->output = trim($this->output);
+
+        if ($mbIntEnc !== null) {
+            mb_internal_encoding($mbIntEnc);
+        }
         return $this->output;
     }
-    
+
     /**
      * ACTION_KEEP_A = Output A. Copy B to A. Get the next B.
      * ACTION_DELETE_A = Copy B to A. Get the next B.
      * ACTION_DELETE_A_B = Get the next B.
+     *
+     * @param int $command
+     * @throws JSMin_UnterminatedRegExpException|JSMin_UnterminatedStringException
      */
     protected function action($command)
     {
+        if ($command === self::ACTION_DELETE_A_B 
+            && $this->b === ' '
+            && ($this->a === '+' || $this->a === '-')) {
+            // Note: we're at an addition/substraction operator; the inputIndex
+            // will certainly be a valid index
+            if ($this->input[$this->inputIndex] === $this->a) {
+                // This is "+ +" or "- -". Don't delete the space.
+                $command = self::ACTION_KEEP_A;
+            }
+        }
         switch ($command) {
             case self::ACTION_KEEP_A:
                 $this->output .= $this->a;
+                $this->lastByteOut = $this->a;
+                
                 // fallthrough
             case self::ACTION_DELETE_A:
                 $this->a = $this->b;
@@ -140,17 +182,22 @@ class JSMin {
                     $str = $this->a; // in case needed for exception
                     while (true) {
                         $this->output .= $this->a;
+                        $this->lastByteOut = $this->a;
+                        
                         $this->a       = $this->get();
                         if ($this->a === $this->b) { // end quote
                             break;
                         }
                         if (ord($this->a) <= self::ORD_LF) {
                             throw new JSMin_UnterminatedStringException(
-                                'Unterminated String: ' . var_export($str, true));
+                                "JSMin: Unterminated String at byte "
+                                . $this->inputIndex . ": {$str}");
                         }
                         $str .= $this->a;
                         if ($this->a === '\\') {
                             $this->output .= $this->a;
+                            $this->lastByteOut = $this->a;
+                            
                             $this->a       = $this->get();
                             $str .= $this->a;
                         }
@@ -173,16 +220,21 @@ class JSMin {
                             $pattern      .= $this->a;
                         } elseif (ord($this->a) <= self::ORD_LF) {
                             throw new JSMin_UnterminatedRegExpException(
-                                'Unterminated RegExp: '. var_export($pattern, true));
+                                "JSMin: Unterminated RegExp at byte "
+                                . $this->inputIndex .": {$pattern}");
                         }
                         $this->output .= $this->a;
+                        $this->lastByteOut = $this->a;
                     }
                     $this->b = $this->next();
                 }
             // end case ACTION_DELETE_A_B
         }
     }
-    
+
+    /**
+     * @return bool
+     */
     protected function isRegexpLiteral()
     {
         if (false !== strpos("\n{;(,=:[!&|?", $this->a)) { // we aren't dividing
@@ -207,9 +259,11 @@ class JSMin {
         }
         return false;
     }
-    
+
     /**
      * Get next char. Convert ctrl char to space.
+     *
+     * @return string
      */
     protected function get()
     {
@@ -231,24 +285,33 @@ class JSMin {
         }
         return $c;
     }
-    
+
     /**
      * Get next char. If is ctrl character, translate to a space or newline.
+     *
+     * @return string
      */
     protected function peek()
     {
         $this->lookAhead = $this->get();
         return $this->lookAhead;
     }
-    
+
     /**
      * Is $c a letter, digit, underscore, dollar sign, escape, or non-ASCII?
+     *
+     * @param string $c
+     *
+     * @return bool
      */
     protected function isAlphaNum($c)
     {
         return (preg_match('/^[0-9a-zA-Z_\\$\\\\]$/', $c) || ord($c) > 126);
     }
-    
+
+    /**
+     * @return string
+     */
     protected function singleLineComment()
     {
         $comment = '';
@@ -264,7 +327,11 @@ class JSMin {
             }
         }
     }
-    
+
+    /**
+     * @return string
+     * @throws JSMin_UnterminatedCommentException
+     */
     protected function multipleLineComment()
     {
         $this->get();
@@ -276,7 +343,7 @@ class JSMin {
                     $this->get();
                     // if comment preserved by YUI Compressor
                     if (0 === strpos($comment, '!')) {
-                        return "\n/*" . substr($comment, 1) . "*/\n";
+                        return "\n/*!" . substr($comment, 1) . "*/\n";
                     }
                     // if IE conditional comment
                     if (preg_match('/^@(?:cc_on|if|elif|else|end)\\b/', $comment)) {
@@ -285,15 +352,19 @@ class JSMin {
                     return ' ';
                 }
             } elseif ($get === null) {
-                throw new JSMin_UnterminatedCommentException('Unterminated Comment: ' . var_export('/*' . $comment, true));
+                throw new JSMin_UnterminatedCommentException(
+                    "JSMin: Unterminated comment at byte "
+                    . $this->inputIndex . ": /*{$comment}");
             }
             $comment .= $get;
         }
     }
-    
+
     /**
      * Get the next character, skipping over comments.
      * Some comments may be preserved.
+     *
+     * @return string
      */
     protected function next()
     {
index 08de880..5a3c5bd 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
- * JSMinPlus version 1.1
+ * JSMinPlus version 1.4
  *
  * Minifies a javascript file using a javascript parser
  *
  * Usage: $minified = JSMinPlus::minify($script [, $filename])
  *
  * Versionlog (see also changelog.txt):
+ * 23-07-2011 - remove dynamic creation of OP_* and KEYWORD_* defines and declare them on top
+ *              reduce memory footprint by minifying by block-scope
+ *              some small byte-saving and performance improvements
+ * 12-05-2009 - fixed hook:colon precedence, fixed empty body in loop and if-constructs
+ * 18-04-2009 - fixed crashbug in PHP 5.2.9 and several other bugfixes
  * 12-04-2009 - some small bugfixes and performance improvements
  * 09-04-2009 - initial open sourced version 1.0
  *
@@ -43,7 +48,7 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s): Tino Zijdel <crisp@tweakers.net>
- * PHP port, modifications and minifier routine are (C) 2009
+ * PHP port, modifications and minifier routine are (C) 2009-2011
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -65,7 +70,8 @@ define('TOKEN_IDENTIFIER', 3);
 define('TOKEN_STRING', 4);
 define('TOKEN_REGEXP', 5);
 define('TOKEN_NEWLINE', 6);
-define('TOKEN_CONDCOMMENT_MULTILINE', 7);
+define('TOKEN_CONDCOMMENT_START', 7);
+define('TOKEN_CONDCOMMENT_END', 8);
 
 define('JS_SCRIPT', 100);
 define('JS_BLOCK', 101);
@@ -82,10 +88,89 @@ define('JS_SETTER', 111);
 define('JS_GROUP', 112);
 define('JS_LIST', 113);
 
+define('JS_MINIFIED', 999);
+
 define('DECLARED_FORM', 0);
 define('EXPRESSED_FORM', 1);
 define('STATEMENT_FORM', 2);
 
+/* Operators */
+define('OP_SEMICOLON', ';');
+define('OP_COMMA', ',');
+define('OP_HOOK', '?');
+define('OP_COLON', ':');
+define('OP_OR', '||');
+define('OP_AND', '&&');
+define('OP_BITWISE_OR', '|');
+define('OP_BITWISE_XOR', '^');
+define('OP_BITWISE_AND', '&');
+define('OP_STRICT_EQ', '===');
+define('OP_EQ', '==');
+define('OP_ASSIGN', '=');
+define('OP_STRICT_NE', '!==');
+define('OP_NE', '!=');
+define('OP_LSH', '<<');
+define('OP_LE', '<=');
+define('OP_LT', '<');
+define('OP_URSH', '>>>');
+define('OP_RSH', '>>');
+define('OP_GE', '>=');
+define('OP_GT', '>');
+define('OP_INCREMENT', '++');
+define('OP_DECREMENT', '--');
+define('OP_PLUS', '+');
+define('OP_MINUS', '-');
+define('OP_MUL', '*');
+define('OP_DIV', '/');
+define('OP_MOD', '%');
+define('OP_NOT', '!');
+define('OP_BITWISE_NOT', '~');
+define('OP_DOT', '.');
+define('OP_LEFT_BRACKET', '[');
+define('OP_RIGHT_BRACKET', ']');
+define('OP_LEFT_CURLY', '{');
+define('OP_RIGHT_CURLY', '}');
+define('OP_LEFT_PAREN', '(');
+define('OP_RIGHT_PAREN', ')');
+define('OP_CONDCOMMENT_END', '@*/');
+
+define('OP_UNARY_PLUS', 'U+');
+define('OP_UNARY_MINUS', 'U-');
+
+/* Keywords */
+define('KEYWORD_BREAK', 'break');
+define('KEYWORD_CASE', 'case');
+define('KEYWORD_CATCH', 'catch');
+define('KEYWORD_CONST', 'const');
+define('KEYWORD_CONTINUE', 'continue');
+define('KEYWORD_DEBUGGER', 'debugger');
+define('KEYWORD_DEFAULT', 'default');
+define('KEYWORD_DELETE', 'delete');
+define('KEYWORD_DO', 'do');
+define('KEYWORD_ELSE', 'else');
+define('KEYWORD_ENUM', 'enum');
+define('KEYWORD_FALSE', 'false');
+define('KEYWORD_FINALLY', 'finally');
+define('KEYWORD_FOR', 'for');
+define('KEYWORD_FUNCTION', 'function');
+define('KEYWORD_IF', 'if');
+define('KEYWORD_IN', 'in');
+define('KEYWORD_INSTANCEOF', 'instanceof');
+define('KEYWORD_NEW', 'new');
+define('KEYWORD_NULL', 'null');
+define('KEYWORD_RETURN', 'return');
+define('KEYWORD_SWITCH', 'switch');
+define('KEYWORD_THIS', 'this');
+define('KEYWORD_THROW', 'throw');
+define('KEYWORD_TRUE', 'true');
+define('KEYWORD_TRY', 'try');
+define('KEYWORD_TYPEOF', 'typeof');
+define('KEYWORD_VAR', 'var');
+define('KEYWORD_VOID', 'void');
+define('KEYWORD_WHILE', 'while');
+define('KEYWORD_WITH', 'with');
+
+
 class JSMinPlus
 {
        private $parser;
@@ -107,7 +192,7 @@ class JSMinPlus
 
        private function __construct()
        {
-               $this->parser = new JSParser();
+               $this->parser = new JSParser($this);
        }
 
        public static function minify($js, $filename='')
@@ -136,42 +221,55 @@ class JSMinPlus
                return false;
        }
 
-       private function parseTree($n, $noBlockGrouping = false)
+       public function parseTree($n, $noBlockGrouping = false)
        {
                $s = '';
 
                switch ($n->type)
                {
-                       case KEYWORD_FUNCTION:
-                               $s .= 'function' . ($n->name ? ' ' . $n->name : '') . '(';
-                               $params = $n->params;
-                               for ($i = 0, $j = count($params); $i < $j; $i++)
-                                       $s .= ($i ? ',' : '') . $params[$i];
-                               $s .= '){' . $this->parseTree($n->body, true) . '}';
+                       case JS_MINIFIED:
+                               $s = $n->value;
                        break;
 
                        case JS_SCRIPT:
-                               // we do nothing with funDecls or varDecls
+                               // we do nothing yet with funDecls or varDecls
                                $noBlockGrouping = true;
-                       // fall through
+                       // FALL THROUGH
+
                        case JS_BLOCK:
                                $childs = $n->treeNodes;
+                               $lastType = 0;
                                for ($c = 0, $i = 0, $j = count($childs); $i < $j; $i++)
                                {
+                                       $type = $childs[$i]->type;
                                        $t = $this->parseTree($childs[$i]);
                                        if (strlen($t))
                                        {
                                                if ($c)
                                                {
-                                                       if ($childs[$i]->type == KEYWORD_FUNCTION && $childs[$i]->functionForm == DECLARED_FORM)
-                                                               $s .= "\n"; // put declared functions on a new line
+                                                       $s = rtrim($s, ';');
+
+                                                       if ($type == KEYWORD_FUNCTION && $childs[$i]->functionForm == DECLARED_FORM)
+                                                       {
+                                                               // put declared functions on a new line
+                                                               $s .= "\n";
+                                                       }
+                                                       elseif ($type == KEYWORD_VAR && $type == $lastType)
+                                                       {
+                                                               // mutiple var-statements can go into one
+                                                               $t = ',' . substr($t, 4);
+                                                       }
                                                        else
+                                                       {
+                                                               // add terminator
                                                                $s .= ';';
+                                                       }
                                                }
 
                                                $s .= $t;
 
                                                $c++;
+                                               $lastType = $type;
                                        }
                                }
 
@@ -181,31 +279,41 @@ class JSMinPlus
                                }
                        break;
 
+                       case KEYWORD_FUNCTION:
+                               $s .= 'function' . ($n->name ? ' ' . $n->name : '') . '(';
+                               $params = $n->params;
+                               for ($i = 0, $j = count($params); $i < $j; $i++)
+                                       $s .= ($i ? ',' : '') . $params[$i];
+                               $s .= '){' . $this->parseTree($n->body, true) . '}';
+                       break;
+
                        case KEYWORD_IF:
                                $s = 'if(' . $this->parseTree($n->condition) . ')';
                                $thenPart = $this->parseTree($n->thenPart);
                                $elsePart = $n->elsePart ? $this->parseTree($n->elsePart) : null;
 
-                               // quite a rancid hack to see if we should enclose the thenpart in brackets
-                               if ($thenPart[0] != '{')
-                               {
-                                       if (strpos($thenPart, 'if(') !== false)
-                                               $thenPart = '{' . $thenPart . '}';
-                                       elseif ($elsePart)
-                                               $thenPart .= ';';
-                               }
-
-                               $s .= $thenPart;
+                               // empty if-statement
+                               if ($thenPart == '')
+                                       $thenPart = ';';
 
                                if ($elsePart)
                                {
-                                       $s .= 'else';
+                                       // be carefull and always make a block out of the thenPart; could be more optimized but is a lot of trouble
+                                       if ($thenPart != ';' && $thenPart[0] != '{')
+                                               $thenPart = '{' . $thenPart . '}';
+
+                                       $s .= $thenPart . 'else';
 
+                                       // we could check for more, but that hardly ever applies so go for performance
                                        if ($elsePart[0] != '{')
                                                $s .= ' ';
 
                                        $s .= $elsePart;
                                }
+                               else
+                               {
+                                       $s .= $thenPart;
+                               }
                        break;
 
                        case KEYWORD_SWITCH:
@@ -219,26 +327,48 @@ class JSMinPlus
                                        else
                                                $s .= 'default:';
 
-                                       $statement = $this->parseTree($case->statements);
+                                       $statement = $this->parseTree($case->statements, true);
                                        if ($statement)
-                                               $s .= $statement . ';';
+                                       {
+                                               $s .= $statement;
+                                               // no terminator for last statement
+                                               if ($i + 1 < $j)
+                                                       $s .= ';';
+                                       }
                                }
-                               $s = rtrim($s, ';') . '}';
+                               $s .= '}';
                        break;
 
                        case KEYWORD_FOR:
                                $s = 'for(' . ($n->setup ? $this->parseTree($n->setup) : '')
                                        . ';' . ($n->condition ? $this->parseTree($n->condition) : '')
-                                       . ';' . ($n->update ? $this->parseTree($n->update) : '') . ')'
-                                       . $this->parseTree($n->body);
+                                       . ';' . ($n->update ? $this->parseTree($n->update) : '') . ')';
+
+                               $body  = $this->parseTree($n->body);
+                               if ($body == '')
+                                       $body = ';';
+
+                               $s .= $body;
                        break;
 
                        case KEYWORD_WHILE:
-                               $s = 'while(' . $this->parseTree($n->condition) . ')' . $this->parseTree($n->body);
+                               $s = 'while(' . $this->parseTree($n->condition) . ')';
+
+                               $body  = $this->parseTree($n->body);
+                               if ($body == '')
+                                       $body = ';';
+
+                               $s .= $body;
                        break;
 
                        case JS_FOR_IN:
-                               $s = 'for(' . ($n->varDecl ? $this->parseTree($n->varDecl) : $this->parseTree($n->iterator)) . ' in ' . $this->parseTree($n->object) . ')' . $this->parseTree($n->body);
+                               $s = 'for(' . ($n->varDecl ? $this->parseTree($n->varDecl) : $this->parseTree($n->iterator)) . ' in ' . $this->parseTree($n->object) . ')';
+
+                               $body  = $this->parseTree($n->body);
+                               if ($body == '')
+                                       $body = ';';
+
+                               $s .= $body;
                        break;
 
                        case KEYWORD_DO:
@@ -263,11 +393,19 @@ class JSMinPlus
                        break;
 
                        case KEYWORD_THROW:
-                               $s = 'throw ' . $this->parseTree($n->exception);
-                       break;
-
                        case KEYWORD_RETURN:
-                               $s = 'return' . ($n->value ? ' ' . $this->parseTree($n->value) : '');
+                               $s = $n->type;
+                               if ($n->value)
+                               {
+                                       $t = $this->parseTree($n->value);
+                                       if (strlen($t))
+                                       {
+                                               if ($this->isWordChar($t[0]) || $t[0] == '\\')
+                                                       $s .= ' ';
+
+                                               $s .= $t;
+                                       }
+                               }
                        break;
 
                        case KEYWORD_WITH:
@@ -288,12 +426,47 @@ class JSMinPlus
                                }
                        break;
 
+                       case KEYWORD_IN:
+                       case KEYWORD_INSTANCEOF:
+                               $left = $this->parseTree($n->treeNodes[0]);
+                               $right = $this->parseTree($n->treeNodes[1]);
+
+                               $s = $left;
+
+                               if ($this->isWordChar(substr($left, -1)))
+                                       $s .= ' ';
+
+                               $s .= $n->type;
+
+                               if ($this->isWordChar($right[0]) || $right[0] == '\\')
+                                       $s .= ' ';
+
+                               $s .= $right;
+                       break;
+
+                       case KEYWORD_DELETE:
+                       case KEYWORD_TYPEOF:
+                               $right = $this->parseTree($n->treeNodes[0]);
+
+                               $s = $n->type;
+
+                               if ($this->isWordChar($right[0]) || $right[0] == '\\')
+                                       $s .= ' ';
+
+                               $s .= $right;
+                       break;
+
+                       case KEYWORD_VOID:
+                               $s = 'void(' . $this->parseTree($n->treeNodes[0]) . ')';
+                       break;
+
                        case KEYWORD_DEBUGGER:
                                throw new Exception('NOT IMPLEMENTED: DEBUGGER');
                        break;
 
-                       case TOKEN_CONDCOMMENT_MULTILINE:
-                               $s = $n->value . ' ';
+                       case TOKEN_CONDCOMMENT_START:
+                       case TOKEN_CONDCOMMENT_END:
+                               $s = $n->value . ($n->type == TOKEN_CONDCOMMENT_START ? ' ' : '');
                                $childs = $n->treeNodes;
                                for ($i = 0, $j = count($childs); $i < $j; $i++)
                                        $s .= $this->parseTree($childs[$i]);
@@ -333,34 +506,32 @@ class JSMinPlus
 
                        case OP_PLUS:
                        case OP_MINUS:
-                               $s = $this->parseTree($n->treeNodes[0]) . $n->type;
-                               $nextTokenType = $n->treeNodes[1]->type;
-                               if (    $nextTokenType == OP_PLUS || $nextTokenType == OP_MINUS ||
-                                       $nextTokenType == OP_INCREMENT || $nextTokenType == OP_DECREMENT ||
-                                       $nextTokenType == OP_UNARY_PLUS || $nextTokenType == OP_UNARY_MINUS
-                               )
-                                       $s .= ' ';
-                               $s .= $this->parseTree($n->treeNodes[1]);
-                       break;
-
-                       case KEYWORD_IN:
-                               $s = $this->parseTree($n->treeNodes[0]) . ' in ' . $this->parseTree($n->treeNodes[1]);
-                       break;
+                               $left = $this->parseTree($n->treeNodes[0]);
+                               $right = $this->parseTree($n->treeNodes[1]);
 
-                       case KEYWORD_INSTANCEOF:
-                               $s = $this->parseTree($n->treeNodes[0]) . ' instanceof ' . $this->parseTree($n->treeNodes[1]);
-                       break;
-
-                       case KEYWORD_DELETE:
-                               $s = 'delete ' . $this->parseTree($n->treeNodes[0]);
-                       break;
+                               switch ($n->treeNodes[1]->type)
+                               {
+                                       case OP_PLUS:
+                                       case OP_MINUS:
+                                       case OP_INCREMENT:
+                                       case OP_DECREMENT:
+                                       case OP_UNARY_PLUS:
+                                       case OP_UNARY_MINUS:
+                                               $s = $left . $n->type . ' ' . $right;
+                                       break;
 
-                       case KEYWORD_VOID:
-                               $s = 'void(' . $this->parseTree($n->treeNodes[0]) . ')';
-                       break;
+                                       case TOKEN_STRING:
+                                               //combine concatted strings with same quotestyle
+                                               if ($n->type == OP_PLUS && substr($left, -1) == $right[0])
+                                               {
+                                                       $s = substr($left, 0, -1) . substr($right, 1);
+                                                       break;
+                                               }
+                                       // FALL THROUGH
 
-                       case KEYWORD_TYPEOF:
-                               $s = 'typeof ' . $this->parseTree($n->treeNodes[0]);
+                                       default:
+                                               $s = $left . $n->type . $right;
+                               }
                        break;
 
                        case OP_NOT:
@@ -452,13 +623,33 @@ class JSMinPlus
                                $s .= '}';
                        break;
 
+                       case TOKEN_NUMBER:
+                               $s = $n->value;
+                               if (preg_match('/^([1-9]+)(0{3,})$/', $s, $m))
+                                       $s = $m[1] . 'e' . strlen($m[2]);
+                       break;
+
                        case KEYWORD_NULL: case KEYWORD_THIS: case KEYWORD_TRUE: case KEYWORD_FALSE:
-                       case TOKEN_IDENTIFIER: case TOKEN_NUMBER: case TOKEN_STRING: case TOKEN_REGEXP:
+                       case TOKEN_IDENTIFIER: case TOKEN_STRING: case TOKEN_REGEXP:
                                $s = $n->value;
                        break;
 
                        case JS_GROUP:
-                               $s = '(' . $this->parseTree($n->treeNodes[0]) . ')';
+                               if (in_array(
+                                       $n->treeNodes[0]->type,
+                                       array(
+                                               JS_ARRAY_INIT, JS_OBJECT_INIT, JS_GROUP,
+                                               TOKEN_NUMBER, TOKEN_STRING, TOKEN_REGEXP, TOKEN_IDENTIFIER,
+                                               KEYWORD_NULL, KEYWORD_THIS, KEYWORD_TRUE, KEYWORD_FALSE
+                                       )
+                               ))
+                               {
+                                       $s = $this->parseTree($n->treeNodes[0]);
+                               }
+                               else
+                               {
+                                       $s = '(' . $this->parseTree($n->treeNodes[0]) . ')';
+                               }
                        break;
 
                        default:
@@ -472,17 +663,23 @@ class JSMinPlus
        {
                return preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $string) && !in_array($string, $this->reserved);
        }
+
+       private function isWordChar($char)
+       {
+               return $char == '_' || $char == '$' || ctype_alnum($char);
+       }
 }
 
 class JSParser
 {
        private $t;
+       private $minifier;
 
        private $opPrecedence = array(
                ';' => 0,
                ',' => 1,
                '=' => 2, '?' => 2, ':' => 2,
-               // The above all have to have the same precedence, see bug 330975.
+               // The above all have to have the same precedence, see bug 330975
                '||' => 4,
                '&&' => 5,
                '|' => 6,
@@ -523,11 +720,12 @@ class JSParser
                '.' => 2,
                JS_NEW_WITH_ARGS => 2, JS_INDEX => 2, JS_CALL => 2,
                JS_ARRAY_INIT => 1, JS_OBJECT_INIT => 1, JS_GROUP => 1,
-               TOKEN_CONDCOMMENT_MULTILINE => 1
+               TOKEN_CONDCOMMENT_START => 1, TOKEN_CONDCOMMENT_END => 1
        );
 
-       public function __construct()
+       public function __construct($minifier=null)
        {
+               $this->minifier = $minifier;
                $this->t = new JSTokenizer();
        }
 
@@ -551,6 +749,19 @@ class JSParser
                $n->funDecls = $x->funDecls;
                $n->varDecls = $x->varDecls;
 
+               // minify by scope
+               if ($this->minifier)
+               {
+                       $n->value = $this->minifier->parseTree($n);
+
+                       // clear tree from node to save memory
+                       $n->treeNodes = null;
+                       $n->funDecls = null;
+                       $n->varDecls = null;
+
+                       $n->type = JS_MINIFIED;
+               }
+
                return $n;
        }
 
@@ -809,7 +1020,7 @@ class JSParser
 
                        case KEYWORD_THROW:
                                $n = new JSNode($this->t);
-                               $n->exception = $this->Expression($x);
+                               $n->value = $this->Expression($x);
                        break;
 
                        case KEYWORD_RETURN:
@@ -835,7 +1046,8 @@ class JSParser
                                $n = $this->Variables($x);
                        break;
 
-                       case TOKEN_CONDCOMMENT_MULTILINE:
+                       case TOKEN_CONDCOMMENT_START:
+                       case TOKEN_CONDCOMMENT_END:
                                $n = new JSNode($this->t);
                        return $n;
 
@@ -994,37 +1206,47 @@ class JSParser
                                        // NB: cannot be empty, Statement handled that.
                                        break 2;
 
-                               case OP_ASSIGN:
                                case OP_HOOK:
-                               case OP_COLON:
                                        if ($this->t->scanOperand)
                                                break 2;
 
-                                       // Use >, not >=, for right-associative ASSIGN and HOOK/COLON.
                                        while ( !empty($operators) &&
-                                               (       $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt] ||
-                                                       ($tt == OP_COLON && end($operators)->type == OP_ASSIGN)
-                                               )
+                                               $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
                                        )
                                                $this->reduce($operators, $operands);
 
-                                       if ($tt == OP_COLON)
-                                       {
-                                               $n = end($operators);
-                                               if ($n->type != OP_HOOK)
-                                                       throw $this->t->newSyntaxError('Invalid label');
+                                       array_push($operators, new JSNode($this->t));
 
-                                               --$x->hookLevel;
-                                       }
-                                       else
-                                       {
-                                               array_push($operators, new JSNode($this->t));
-                                               if ($tt == OP_ASSIGN)
-                                                       end($operands)->assignOp = $this->t->currentToken()->assignOp;
-                                               else
-                                                       ++$x->hookLevel;
-                                       }
+                                       ++$x->hookLevel;
+                                       $this->t->scanOperand = true;
+                                       $n = $this->Expression($x);
+
+                                       if (!$this->t->match(OP_COLON))
+                                               break 2;
+
+                                       --$x->hookLevel;
+                                       array_push($operands, $n);
+                               break;
+
+                               case OP_COLON:
+                                       if ($x->hookLevel)
+                                               break 2;
+
+                                       throw $this->t->newSyntaxError('Invalid label');
+                               break;
 
+                               case OP_ASSIGN:
+                                       if ($this->t->scanOperand)
+                                               break 2;
+
+                                       // Use >, not >=, for right-associative ASSIGN
+                                       while ( !empty($operators) &&
+                                               $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
+                                       )
+                                               $this->reduce($operators, $operands);
+
+                                       array_push($operators, new JSNode($this->t));
+                                       end($operands)->assignOp = $this->t->currentToken()->assignOp;
                                        $this->t->scanOperand = true;
                                break;
 
@@ -1036,14 +1258,19 @@ class JSParser
                                                !$x->bracketLevel && !$x->curlyLevel &&
                                                !$x->parenLevel
                                        )
-                                       {
                                                break 2;
-                                       }
                                // FALL THROUGH
                                case OP_COMMA:
-                                       // Treat comma as left-associative so reduce can fold left-heavy
-                                       // COMMA trees into a single array.
-                                       // FALL THROUGH
+                                       // A comma operator should not be parsed if we're parsing the then part
+                                       // of a conditional expression unless it's parenthesized somehow.
+                                       if ($tt == OP_COMMA && $x->hookLevel &&
+                                               !$x->bracketLevel && !$x->curlyLevel &&
+                                               !$x->parenLevel
+                                       )
+                                               break 2;
+                               // Treat comma as left-associative so reduce can fold left-heavy
+                               // COMMA trees into a single array.
+                               // FALL THROUGH
                                case OP_OR:
                                case OP_AND:
                                case OP_BITWISE_OR:
@@ -1127,7 +1354,8 @@ class JSParser
                                        $this->t->scanOperand = false;
                                break;
 
-                               case TOKEN_CONDCOMMENT_MULTILINE:
+                               case TOKEN_CONDCOMMENT_START:
+                               case TOKEN_CONDCOMMENT_END:
                                        if ($this->t->scanOperand)
                                                array_push($operators, new JSNode($this->t));
                                        else
@@ -1312,7 +1540,7 @@ class JSParser
                }
 
                if ($x->hookLevel != $hl)
-                       throw $this->t->newSyntaxError('Missing : after ?');
+                       throw $this->t->newSyntaxError('Missing : in conditional expression');
 
                if ($x->parenLevel != $pl)
                        throw $this->t->newSyntaxError('Missing ) in parenthetical');
@@ -1443,7 +1671,7 @@ class JSNode
 
                if (($numargs = func_num_args()) > 2)
                {
-                       $args = func_get_args();;
+                       $args = func_get_args();
                        for ($i = 2; $i < $numargs; $i++)
                                $this->addNode($args[$i]);
                }
@@ -1465,6 +1693,14 @@ class JSNode
 
        public function addNode($node)
        {
+               if ($node !== null)
+               {
+                       if ($node->start < $this->start)
+                               $this->start = $node->start;
+                       if ($this->end < $node->end)
+                               $this->end = $node->end;
+               }
+
                $this->treeNodes[] = $node;
        }
 }
@@ -1499,44 +1735,11 @@ class JSTokenizer
        );
 
        private $opTypeNames = array(
-               ';'     => 'SEMICOLON',
-               ','     => 'COMMA',
-               '?'     => 'HOOK',
-               ':'     => 'COLON',
-               '||'    => 'OR',
-               '&&'    => 'AND',
-               '|'     => 'BITWISE_OR',
-               '^'     => 'BITWISE_XOR',
-               '&'     => 'BITWISE_AND',
-               '==='   => 'STRICT_EQ',
-               '=='    => 'EQ',
-               '='     => 'ASSIGN',
-               '!=='   => 'STRICT_NE',
-               '!='    => 'NE',
-               '<<'    => 'LSH',
-               '<='    => 'LE',
-               '<'     => 'LT',
-               '>>>'   => 'URSH',
-               '>>'    => 'RSH',
-               '>='    => 'GE',
-               '>'     => 'GT',
-               '++'    => 'INCREMENT',
-               '--'    => 'DECREMENT',
-               '+'     => 'PLUS',
-               '-'     => 'MINUS',
-               '*'     => 'MUL',
-               '/'     => 'DIV',
-               '%'     => 'MOD',
-               '!'     => 'NOT',
-               '~'     => 'BITWISE_NOT',
-               '.'     => 'DOT',
-               '['     => 'LEFT_BRACKET',
-               ']'     => 'RIGHT_BRACKET',
-               '{'     => 'LEFT_CURLY',
-               '}'     => 'RIGHT_CURLY',
-               '('     => 'LEFT_PAREN',
-               ')'     => 'RIGHT_PAREN',
-               '@*/'   => 'CONDCOMMENT_END'
+               ';', ',', '?', ':', '||', '&&', '|', '^',
+               '&', '===', '==', '=', '!==', '!=', '<<', '<=',
+               '<', '>>>', '>>', '>=', '>', '++', '--', '+',
+               '-', '*', '/', '%', '!', '~', '.', '[',
+               ']', '{', '}', '(', ')', '@*/'
        );
 
        private $assignOps = array('|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%');
@@ -1544,17 +1747,7 @@ class JSTokenizer
 
        public function __construct()
        {
-               $this->opRegExp = '#^(' . implode('|', array_map('preg_quote', array_keys($this->opTypeNames))) . ')#';
-
-               // this is quite a hidden yet convenient place to create the defines for operators and keywords
-               foreach ($this->opTypeNames as $operand => $name)
-                       define('OP_' . $name, $operand);
-
-               define('OP_UNARY_PLUS', 'U+');
-               define('OP_UNARY_MINUS', 'U-');
-
-               foreach ($this->keywords as $keyword)
-                       define('KEYWORD_' . strtoupper($keyword), $keyword);
+               $this->opRegExp = '#^(' . implode('|', array_map('preg_quote', $this->opTypeNames)) . ')#';
        }
 
        public function init($source, $filename = '', $lineno = 1)
@@ -1668,7 +1861,7 @@ class JSTokenizer
                        }
 
                        // Comments
-                       if (!preg_match('/^\/(?:\*(@(?:cc_on|if|elif|else|end))?(?:.|\n)*?\*\/|\/.*)/', $input, $match))
+                       if (!preg_match('/^\/(?:\*(@(?:cc_on|if|elif|else|end))?.*?\*\/|\/[^\n]*)/s', $input, $match))
                        {
                                if (!$chunksize)
                                        break;
@@ -1681,7 +1874,7 @@ class JSTokenizer
                        // check if this is a conditional (JScript) comment
                        if (!empty($match[1]))
                        {
-                               //$match[0] = '/*' . $match[1];
+                               $match[0] = '/*' . $match[1];
                                $conditional_comment = true;
                                break;
                        }
@@ -1699,28 +1892,44 @@ class JSTokenizer
                }
                elseif ($conditional_comment)
                {
-                       $tt = TOKEN_CONDCOMMENT_MULTILINE;
+                       $tt = TOKEN_CONDCOMMENT_START;
                }
                else
                {
                        switch ($input[0])
                        {
-                               case '0': case '1': case '2': case '3': case '4':
-                               case '5': case '6': case '7': case '8': case '9':
-                                       if (preg_match('/^\d+\.\d*(?:[eE][-+]?\d+)?|^\d+(?:\.\d*)?[eE][-+]?\d+/', $input, $match))
+                               case '0':
+                                       // hexadecimal
+                                       if (($input[1] == 'x' || $input[1] == 'X') && preg_match('/^0x[0-9a-f]+/i', $input, $match))
                                        {
                                                $tt = TOKEN_NUMBER;
+                                               break;
                                        }
-                                       elseif (preg_match('/^0[xX][\da-fA-F]+|^0[0-7]*|^\d+/', $input, $match))
+                               // FALL THROUGH
+
+                               case '1': case '2': case '3': case '4': case '5':
+                               case '6': case '7': case '8': case '9':
+                                       // should always match
+                                       preg_match('/^\d+(?:\.\d*)?(?:[eE][-+]?\d+)?/', $input, $match);
+                                       $tt = TOKEN_NUMBER;
+                               break;
+
+                               case "'":
+                                       if (preg_match('/^\'(?:[^\\\\\'\r\n]++|\\\\(?:.|\r?\n))*\'/', $input, $match))
                                        {
-                                               // this should always match because of \d+
-                                               $tt = TOKEN_NUMBER;
+                                               $tt = TOKEN_STRING;
+                                       }
+                                       else
+                                       {
+                                               if ($chunksize)
+                                                       return $this->get(null); // retry with a full chunk fetch
+
+                                               throw $this->newSyntaxError('Unterminated string literal');
                                        }
                                break;
 
                                case '"':
-                               case "'":
-                                       if (preg_match('/^"(?:\\\\(?:.|\r?\n)|[^\\\\"\r\n])*"|^\'(?:\\\\(?:.|\r?\n)|[^\\\\\'\r\n])*\'/', $input, $match))
+                                       if (preg_match('/^"(?:[^\\\\"\r\n]++|\\\\(?:.|\r?\n))*"/', $input, $match))
                                        {
                                                $tt = TOKEN_STRING;
                                        }
@@ -1739,7 +1948,7 @@ class JSTokenizer
                                                $tt = TOKEN_REGEXP;
                                                break;
                                        }
-                               // fall through
+                               // FALL THROUGH
 
                                case '|':
                                case '^':
@@ -1780,7 +1989,7 @@ class JSTokenizer
                                                $tt = TOKEN_NUMBER;
                                                break;
                                        }
-                               // fall through
+                               // FALL THROUGH
 
                                case ';':
                                case ',':
@@ -1799,7 +2008,14 @@ class JSTokenizer
                                break;
 
                                case '@':
-                                       throw $this->newSyntaxError('Illegal token');
+                                       // check end of conditional comment
+                                       if (substr($input, 0, 3) == '@*/')
+                                       {
+                                               $match = array('@*/');
+                                               $tt = TOKEN_CONDCOMMENT_END;
+                                       }
+                                       else
+                                               throw $this->newSyntaxError('Illegal token');
                                break;
 
                                case "\n":
@@ -1868,5 +2084,3 @@ class JSToken
        public $lineno;
        public $assignOp;
 }
-
-?>
index 25f0827..9634f22 100644 (file)
@@ -29,12 +29,13 @@ require_once 'Minify/Source.php';
  */
 class Minify {
     
-    const VERSION = '2.1.3';
+    const VERSION = '2.1.5';
     const TYPE_CSS = 'text/css';
     const TYPE_HTML = 'text/html';
     // there is some debate over the ideal JS Content-Type, but this is the
     // Apache default and what Yahoo! uses..
     const TYPE_JS = 'appli