From 6f2257ae0dfcc6a364e551829f16f4f8a530ce9a Mon Sep 17 00:00:00 2001 From: ptrkmkl Date: Sat, 8 Jan 2011 12:39:05 -0500 Subject: [PATCH 001/369] Removed white color from course section content and added white color to section content left side for topic number styling --- theme/binarius/style/core.css | 3 +++ theme/boxxie/style/core.css | 5 ++++- theme/leatherbound/style/core.css | 5 ++++- theme/nonzero/style/core.css | 3 +++ theme/serenity/style/core.css | 3 +++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/theme/binarius/style/core.css b/theme/binarius/style/core.css index 9a37fb8800d..c5faec790f1 100644 --- a/theme/binarius/style/core.css +++ b/theme/binarius/style/core.css @@ -126,6 +126,9 @@ fieldset#general { .course-content .current { background: #f14e16; +} + +.course-content .current .left { color: #fff; } diff --git a/theme/boxxie/style/core.css b/theme/boxxie/style/core.css index 4a4180d527b..19770e49f4a 100644 --- a/theme/boxxie/style/core.css +++ b/theme/boxxie/style/core.css @@ -312,9 +312,12 @@ h2.headingblock { .course-content .current { background:#69804e; - color:#fff; } +.course-content .current .left { + color: #fff; +} + .course-content .main .content { padding: 10px; background:#fff; diff --git a/theme/leatherbound/style/core.css b/theme/leatherbound/style/core.css index c7a4b442fac..cff9b92a7ca 100644 --- a/theme/leatherbound/style/core.css +++ b/theme/leatherbound/style/core.css @@ -163,7 +163,10 @@ h2.headingblock { .course-content .current { background: #da5013; - color: #fff; +} + +.course-content .current .left { + color: #fff; } .course-content .main .content { diff --git a/theme/nonzero/style/core.css b/theme/nonzero/style/core.css index 157a9a31784..e458e659b04 100644 --- a/theme/nonzero/style/core.css +++ b/theme/nonzero/style/core.css @@ -148,6 +148,9 @@ a:active { .course-content .current { background: #1f5480; +} + +.course-content .current .left { color: #fff; } diff --git a/theme/serenity/style/core.css b/theme/serenity/style/core.css index 911964e94a2..0f1918a7d4a 100644 --- a/theme/serenity/style/core.css +++ b/theme/serenity/style/core.css @@ -124,6 +124,9 @@ a:hover { .course-content .current { background: #9ca7b4; +} + +.course-content .current .left { color: #fff; } From ee3b46d8bf62c32a634e964a75c9aca0c7ec9efa Mon Sep 17 00:00:00 2001 From: ptrkmkl Date: Tue, 18 Jan 2011 08:42:48 -0500 Subject: [PATCH 002/369] MDL-26047 - added new theme called Nimble --- theme/nimble/config.php | 268 ++++++++++++++++++++++++++ theme/nimble/lang/en/theme_nimble.php | 75 +++++++ theme/nimble/layout/frontpage.php | 146 ++++++++++++++ theme/nimble/layout/general.php | 160 +++++++++++++++ theme/nimble/lib.php | 78 ++++++++ theme/nimble/pix/screenshot.png | Bin 0 -> 348116 bytes theme/nimble/settings.php | 52 +++++ theme/nimble/style/colors.css | 40 ++++ theme/nimble/style/core.css | 226 ++++++++++++++++++++++ theme/nimble/style/menu.css | 208 ++++++++++++++++++++ theme/nimble/style/pagelayout.css | 105 ++++++++++ 11 files changed, 1358 insertions(+) create mode 100644 theme/nimble/config.php create mode 100644 theme/nimble/lang/en/theme_nimble.php create mode 100644 theme/nimble/layout/frontpage.php create mode 100644 theme/nimble/layout/general.php create mode 100644 theme/nimble/lib.php create mode 100644 theme/nimble/pix/screenshot.png create mode 100644 theme/nimble/settings.php create mode 100644 theme/nimble/style/colors.css create mode 100644 theme/nimble/style/core.css create mode 100644 theme/nimble/style/menu.css create mode 100644 theme/nimble/style/pagelayout.css diff --git a/theme/nimble/config.php b/theme/nimble/config.php new file mode 100644 index 00000000000..a48466af429 --- /dev/null +++ b/theme/nimble/config.php @@ -0,0 +1,268 @@ +. + +/** + * Configuration for Moodle's fusion theme. + * + * DO NOT MODIFY THIS THEME! + * COPY IT FIRST, THEN RENAME THE COPY AND MODIFY IT INSTEAD. + * + * For full information about creating Moodle themes, see: + * http://docs.moodle.org/en/Development:Themes_2.0 + * + * @package moodlecore + * @copyright 2010 Patrick Malley (http://newschoollearning.com/) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$THEME->name = 'nimble'; + +//////////////////////////////////////////////////// +// Name of the theme. Most likely the name of +// the directory in which this file resides. +//////////////////////////////////////////////////// + + +$THEME->parents = array( + 'canvas', + 'base', +); + +///////////////////////////////////////////////////// +// Which existing theme(s) in the /theme/ directory +// do you want this theme to extend. A theme can +// extend any number of themes. Rather than +// creating an entirely new theme and copying all +// of the CSS, you can simply create a new theme, +// extend the theme you like and just add the +// changes you want to your theme. +//////////////////////////////////////////////////// + + +$THEME->sheets = array( + 'core', + 'pagelayout', + 'colors', + 'menu', +); + +//////////////////////////////////////////////////// +// Name of the stylesheet(s) you've including in +// this theme's /styles/ directory. +//////////////////////////////////////////////////// + +$THEME->parents_exclude_sheets = array( + 'base'=>array( + 'pagelayout', + ), + 'canvas'=>array( + 'pagelayout', + ), +); + + +$THEME->enable_dock = true; + +//////////////////////////////////////////////////// +// Do you want to use the new navigation dock? +//////////////////////////////////////////////////// + + +$THEME->editor_sheets = array('editor'); + +//////////////////////////////////////////////////// +// An array of stylesheets to include within the +// body of the editor. +//////////////////////////////////////////////////// + +$THEME->layouts = array( + 'base' => array( + 'file' => 'general.php', + 'regions' => array(), + ), + 'standard' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'course' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post' + ), + 'coursecategory' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'incourse' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'frontpage' => array( + 'file' => 'frontpage.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'admin' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'mydashboard' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + 'options' => array('langmenu'=>true), + ), + 'mypublic' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), + 'login' => array( + 'file' => 'general.php', + 'regions' => array(), + 'options' => array('langmenu'=>true), + ), + 'popup' => array( + 'file' => 'general.php', + 'regions' => array(), + 'options' => array('nofooter'=>true, 'noblocks'=>true, 'nonavbar'=>true), + ), + 'frametop' => array( + 'file' => 'general.php', + 'regions' => array(), + 'options' => array('nofooter'=>true), + ), + 'maintenance' => array( + 'file' => 'general.php', + 'regions' => array(), + 'options' => array('nofooter'=>true, 'nonavbar'=>true), + ), + 'embedded' => array( + 'theme' => 'canvas', + 'file' => 'embedded.php', + 'regions' => array(), + 'options' => array('nofooter'=>true, 'nonavbar'=>true), + ), + // Should display the content and basic headers only. + 'print' => array( + 'file' => 'general.php', + 'regions' => array(), + 'options' => array('nofooter'=>true, 'nonavbar'=>false, 'noblocks'=>true), + ), + 'report' => array( + 'file' => 'general.php', + 'regions' => array('side-post'), + 'defaultregion' => 'side-post', + ), +); + +/////////////////////////////////////////////////////////////// +// These are all of the possible layouts in Moodle. The +// simplest way to do this is to keep the theme and file +// variables the same for every layout. Including them +// all in this way allows some flexibility down the road +// if you want to add a different layout template to a +// specific page. +/////////////////////////////////////////////////////////////// + +// $THEME->csspostprocess = 'fusion_process_css'; + +//////////////////////////////////////////////////// +// Allows the user to provide the name of a function +// that all CSS should be passed to before being +// delivered. +//////////////////////////////////////////////////// + +// $THEME->filter_mediaplugin_colors + +//////////////////////////////////////////////////// +// Used to control the colours used in the small +// media player for the filters +//////////////////////////////////////////////////// + +// $THEME->javascripts + +//////////////////////////////////////////////////// +// An array containing the names of JavaScript files +// located in /javascript/ to include in the theme. +// (gets included in the head) +//////////////////////////////////////////////////// + +// $THEME->javascripts_footer + +//////////////////////////////////////////////////// +// As above but will be included in the page footer. +//////////////////////////////////////////////////// + +$THEME->larrow = '⟨'; + +//////////////////////////////////////////////////// +// Overrides the left arrow image used throughout +// Moodle +//////////////////////////////////////////////////// + +$THEME->rarrow = '⟩'; + +//////////////////////////////////////////////////// +// Overrides the right arrow image used throughout Moodle +//////////////////////////////////////////////////// + +// $THEME->layouts + +//////////////////////////////////////////////////// +// An array setting the layouts for the theme +//////////////////////////////////////////////////// + +// $THEME->parents_exclude_javascripts + +//////////////////////////////////////////////////// +// An array of JavaScript files NOT to inherit from +// the themes parents +//////////////////////////////////////////////////// + +// $THEME->parents_exclude_sheets + +//////////////////////////////////////////////////// +// An array of stylesheets not to inherit from the +// themes parents +//////////////////////////////////////////////////// + +// $THEME->plugins_exclude_sheets + +//////////////////////////////////////////////////// +// An array of plugin sheets to ignore and not +// include. +//////////////////////////////////////////////////// + +// $THEME->renderfactory + +//////////////////////////////////////////////////// +// Sets a custom render factory to use with the +// theme, used when working with custom renderers. +//////////////////////////////////////////////////// + +// $THEME->resource_mp3player_colors + +//////////////////////////////////////////////////// +// Controls the colours for the MP3 player +//////////////////////////////////////////////////// + +$THEME->csspostprocess = 'nimble_process_css'; \ No newline at end of file diff --git a/theme/nimble/lang/en/theme_nimble.php b/theme/nimble/lang/en/theme_nimble.php new file mode 100644 index 00000000000..643a084a882 --- /dev/null +++ b/theme/nimble/lang/en/theme_nimble.php @@ -0,0 +1,75 @@ +. + +/** + * Strings for component 'theme_nimble', language 'en', branch 'MOODLE_20_STABLE' + * + * @package moodlecore + * @copyright 2010 Patrick Malley + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['pluginname'] = 'Nimble'; +$string['region-side-post'] = 'Right'; +$string['region-side-pre'] = 'Left'; +$string['choosereadme'] = ' +
+
+ +

Nimble

+ + +

Theme Discussion Forum:

+

http://moodle.org/mod/forum/view.php?id=46

+ +

Theme Credits

+

http://docs.moodle.org/en/Theme_credits

+ +

Theme Documentation:

+

http://docs.moodle.org/en/Themes

Report a bug:

http://tracker.moodle.org

+
+ +
+ +

About

+

Nimble is a two-column, fluid-width theme coded for Moodle 2.0. It makes use of custom menus that appear above the site title on every page. It also includes a basic settings page allowing you to change link color, add a tagline next the site name on the front page, and add text to the footer.

+ +

Parents

+

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you wish to modify aspects of this theme beyond the settings offered, we advise creating a new theme using this theme, Base and Canvas all as parents so updates to any of those themes in the core will find their way into your new theme.

+ +

Credits

+

This design was created for Moodle by Patrick Malley (patrick@newschoollearning.com) with help from John Stabinger (john@newschoollearning.com). +

License

+

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License. +

+
'; + +$string['tagline'] = 'Tagline'; +$string['taglinedesc'] = 'Set a tagline to appear under the site name on the front page.'; + +$string['footerline'] = 'footerline'; +$string['footerlinedesc'] = 'Add some text (copyright info, etc.) to the footer.'; + +$string['backgroundcolor'] = 'Header Background'; +$string['backgroundcolordesc'] = 'Change the background color of the header.'; + +$string['linkcolor'] = 'Link Color'; +$string['linkcolordesc'] = 'Set the color of links in the theme, use html hex code.'; + +$string['linkhover'] = 'Menu Hover Color'; +$string['linkhoverdesc'] = 'Set the color of the menu on hover in the theme, use html hex code.'; + diff --git a/theme/nimble/layout/frontpage.php b/theme/nimble/layout/frontpage.php new file mode 100644 index 00000000000..ca987b18fa2 --- /dev/null +++ b/theme/nimble/layout/frontpage.php @@ -0,0 +1,146 @@ +heading); +$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); +$hasfooter = (empty($PAGE->layout_options['nofooter'])); +$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT); +$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); + +$custommenu = $OUTPUT->custom_menu(); +$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); + +$bodyclasses = array(); +if ($showsidepost) { + $bodyclasses[] = 'side-post-only'; +} else if (!$showsidepost) { + $bodyclasses[] = 'content-only'; +} +if ($hascustommenu) { + $bodyclasses[] = 'has_custom_menu'; +} + + +if (!empty($PAGE->theme->settings->tagline)) { + $tagline = $PAGE->theme->settings->tagline; +} else { + $tagline = "Another Moodle Theme"; +} + +if (!empty($PAGE->theme->settings->footerline)) { + $footnote = $PAGE->theme->settings->footerline; +} else { + $footnote = ''; +} + +echo $OUTPUT->doctype() ?> +htmlattributes() ?>> + + <?php echo $PAGE->title ?> + + + standard_head_html() ?> + + + +standard_top_of_body_html() ?> + +
+ +
+
+ +
+ + + + + + + + + +
+
+
+
+ +
+
+
+ +
+

heading ?>

+

+
+ + + +
+
+
+ + +
+
+
+
+ blocks_for_region('side-post') ?> +
+
+
+
+ + +
+
+
+
+ + + +
+ +
+
+ + + + + + + +
+ +standard_end_of_body_html() ?> + + \ No newline at end of file diff --git a/theme/nimble/layout/general.php b/theme/nimble/layout/general.php new file mode 100644 index 00000000000..7cb973ba892 --- /dev/null +++ b/theme/nimble/layout/general.php @@ -0,0 +1,160 @@ +heading); +$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); +$hasfooter = (empty($PAGE->layout_options['nofooter'])); +$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); + +$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); + +$custommenu = $OUTPUT->custom_menu(); +$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); + +$bodyclasses = array(); + if ($showsidepost) { + $bodyclasses[] = 'side-post-only'; +} else if (!$showsidepost) { + $bodyclasses[] = 'content-only'; +} +if ($hascustommenu) { + $bodyclasses[] = 'has_custom_menu'; +} + +if (!empty($PAGE->theme->settings->footertext)) { + $footnote = $PAGE->theme->settings->footertext; +} else { + $footnote = ''; +} + + +echo $OUTPUT->doctype() ?> +htmlattributes() ?>> + + <?php echo $PAGE->title ?> + + standard_head_html() ?> + + + +standard_top_of_body_html() ?> + +
+ + + +
+
+ +
+ + + + + + + + + + + + +
+
+
+
+ +
+
+
+ +
+

heading ?>

+
+ + + + + + +
+
+
+ + +
+
+
+
+ blocks_for_region('side-post') ?> +
+
+
+
+ + +
+
+
+
+ + + + +
+ +
+
+ + + + + + + + + + +
+standard_end_of_body_html() ?> + + \ No newline at end of file diff --git a/theme/nimble/lib.php b/theme/nimble/lib.php new file mode 100644 index 00000000000..bcbbda8a5c4 --- /dev/null +++ b/theme/nimble/lib.php @@ -0,0 +1,78 @@ +settings->linkcolor)) { + $linkcolor = $theme->settings->linkcolor; + } else { + $linkcolor = null; + } + $css = nimble_set_linkcolor($css, $linkcolor); + + // Set the link hover color + if (!empty($theme->settings->linkhover)) { + $linkhover = $theme->settings->linkhover; + } else { + $linkhover = null; + } + $css = nimble_set_linkhover($css, $linkhover); + + + // Set the background color + if (!empty($theme->settings->backgroundcolor)) { + $backgroundcolor = $theme->settings->backgroundcolor; + } else { + $backgroundcolor = null; + } + $css = nimble_set_backgroundcolor($css, $backgroundcolor); + + + + + // Return the CSS + return $css; +} + +/** + * Sets the link color variable in CSS + * + */ +function nimble_set_linkcolor($css, $linkcolor) { + $tag = '[[setting:linkcolor]]'; + $replacement = $linkcolor; + if (is_null($replacement)) { + $replacement = '#2a65b1'; + } + $css = str_replace($tag, $replacement, $css); + return $css; +} + +function nimble_set_linkhover($css, $linkhover) { + $tag = '[[setting:linkhover]]'; + $replacement = $linkhover; + if (is_null($replacement)) { + $replacement = '#222222'; + } + $css = str_replace($tag, $replacement, $css); + return $css; +} + + +function nimble_set_backgroundcolor($css, $backgroundcolor) { + $tag = '[[setting:backgroundcolor]]'; + $replacement = $backgroundcolor; + if (is_null($replacement)) { + $replacement = '#454545'; + } + $css = str_replace($tag, $replacement, $css); + return $css; +} + diff --git a/theme/nimble/pix/screenshot.png b/theme/nimble/pix/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..36e6d94bd6f9b66b7e415d46525f38fd04e5886e GIT binary patch literal 348116 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 z
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
}P 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 Ii~b1wKO?||cmMzZ literal 0 HcmV?d00001 diff --git a/theme/nimble/settings.php b/theme/nimble/settings.php new file mode 100644 index 00000000000..d6f21863fcf --- /dev/null +++ b/theme/nimble/settings.php @@ -0,0 +1,52 @@ +fulltree) { + + +// Tagline setting + $name = 'theme_nimble/tagline'; + $title = get_string('tagline','theme_nimble'); + $description = get_string('taglinedesc', 'theme_nimble'); + $setting = new admin_setting_configtext($name, $title, $description, ''); + $settings->add($setting); + + // footerline setting + $name = 'theme_nimble/footerline'; + $title = get_string('footerline','theme_nimble'); + $description = get_string('footerlinedesc', 'theme_nimble'); + $setting = new admin_setting_configtext($name, $title, $description, ''); + $settings->add($setting); + + + // Background color setting + $name = 'theme_nimble/backgroundcolor'; + $title = get_string('backgroundcolor','theme_nimble'); + $description = get_string('backgroundcolordesc', 'theme_nimble'); + $default = '#454545'; + $previewconfig = NULL; + $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, $previewconfig); + $settings->add($setting); + + // link color setting + $name = 'theme_nimble/linkcolor'; + $title = get_string('linkcolor','theme_nimble'); + $description = get_string('linkcolordesc', 'theme_nimble'); + $default = '#2a65b1'; + $previewconfig = NULL; + $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, $previewconfig); + $settings->add($setting); + + // link hover color setting + $name = 'theme_nimble/linkhover'; + $title = get_string('linkhover','theme_nimble'); + $description = get_string('linkhoverdesc', 'theme_nimble'); + $default = '#222222'; + $previewconfig = NULL; + $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, $previewconfig); + $settings->add($setting); + + + +} \ No newline at end of file diff --git a/theme/nimble/style/colors.css b/theme/nimble/style/colors.css new file mode 100644 index 00000000000..34029f12426 --- /dev/null +++ b/theme/nimble/style/colors.css @@ -0,0 +1,40 @@ +#page-header-wrapper { + background: [[setting:backgroundcolor]]; +} + +a { + color: [[setting:linkcolor]]; +} + +a:hover { + color: #000; +} + +.yui3-skin-sam .yui3-menu-label-active, +.yui3-skin-sam .yui3-menu-label-menuvisible { + color: #fff; + background: [[setting:linkhover]] !important; +} + +.yui3-skin-sam .yui3-menu .yui3-menu { + padding-top: 5px; + background: [[setting:linkhover]]; + +} + + + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu .yui3-menu-label-active, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu .yui3-menu-label-menuvisible { + color: #fff; + background-color: [[setting:linkhover]] !important; +} + + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content { + background: [[setting:linkhover]]; +} + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu .yui3-menu-content { + background: [[setting:linkhover]]; +} \ No newline at end of file diff --git a/theme/nimble/style/core.css b/theme/nimble/style/core.css new file mode 100644 index 00000000000..2d35e8816e4 --- /dev/null +++ b/theme/nimble/style/core.css @@ -0,0 +1,226 @@ +/* Core */ + +html,body { + background: #f7f7f7; +} +html,body { + font-family: Tahoma,Arial,Helvetica,sans-serif; +} + +h1,h2,h3,h4,h5,h6 { + font-family: Georgia, Times, "Times New Roman", serif; + color: #333; +} + +.shrinkwrapper { + width: 90%; + margin: 0 auto; +} + + +/* Header */ + + + +.headermenu { + float: right; + color: #ddd; +} + +.headermenu a { + color: #aaa; +} + +.headermenu a:hover { + color: #fff; +} + +#custommenu { + float: left; + margin-top: 40px; +} + +h1.headermain { + margin: 0 20px 25px 0; + font-size: 2.5em; + text-shadow: 0.03em 0.03em 0.05em #333; + color: #222; +} + +.inside h1.headermain { + font-size: 2.25em; + margin-bottom: 15px; +} + +.tagline { + float: left; + margin:13px 0 0 0; + font-size: 1em; + color: #333; + font-family: Georgia, Times, "Times New Roman", serif; + text-shadow: 0.1em 0.1em 0 #fff; +} + +.navbar { + margin-bottom: 15px; + border: 1px solid #e3e3e3; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; +} + +.navbar .wrapper { + border: 1px solid #fff; + padding: 5px; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; +} + +/* Content */ + +h2.headingblock { + text-shadow: 1px 1px 3px #aaa; + color: #445566; +} + +/* Region Post */ + +#region-post-wrap-1 { + border: 1px solid #ccc; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + margin-top: 25px; +} +#region-post-wrap-2 { + border: 1px solid #fff; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + padding: 10px; +} + +/* Blocks */ + +.block { + border: none; +} + +.block .title { + border-bottom: 1px solid #eee; +} +.block .title h2 { + text-shadow: 1px 1px 3px #aaa; + color: #333; + font-size: 1.25em; + border-bottom: 1px solid #fff; + margin: 0; +} + +/* Calendar */ + +.minicalendar td, +.minicalendar th { + font-size: 0.85em; + padding: 0 2px; + border-width: 2px 0; + border-color: #f7f7f7; +} + +.minicalendar .calendar_event_user, +.minicalendar .duration_user { + border-color: #dce7ec; +} + +.minicalendar .calendar_event_course, +.minicalendar .duration_course { + border-color: #ffd3bd; +} + +.minicalendar .calendar_event_global, +.minicalendar .duration_global { + border-color: #d6f8cd; +} + +.minicalendar .calendar_event_group, +.minicalendar .duration_group { + border-color: #fee7ae; +} + +/* Forums */ + +.forumpost .topic { + border: 1px solid #ddd; + border-radius: 10px 10px 0 0; + -moz-border-radius: 10px 10px 0 0; + -webkit-border-radius: 10px 10px 0 0; + border-bottom: 0; + padding: 5px 10px; + background: #eee; +} + +.forumpost .topic .subject { + font-weight: bold; + font-size: 1.2em; + color: #444; +} + +.forumpost .content { + border-width: 0 1px 0; + border-color: #ddd; + border-style: solid; + padding: 5px 10px; +} + +.forumpost .options { + border-width: 0 1px 1px; + border-color: #ddd; + border-style: solid; + border-radius: 0 0 10px 10px; + -moz-border-radius: 0 0 10px 10px; + -webkit-border-radius: 0 0 10px 10px; + font-size: 0.9em; + color: #333; + padding: 5px 10px; + background: #eee; +} + +/* Course */ + +.path-course-view .course-content li.section { + border-bottom: 1px solid #ddd; + border-top: 1px solid #fff; + margin-top: 0 !important; +} + +.path-course-view .course-content #section-0 { + border-top: 0; +} + +#page-course-view-weeks .course-content .section .content { + margin-left: 0; +} + +#page-course-view-weeks .course-content .left { + display: none; +} + +.path-course-view .course-content .current { + background: #fcfde0; +} + +#page-course-view-topics .course-content .section .left { + font-family: Georgia, Times, "Times New Roman", serif; + font-size: 1.5em; + text-shadow: 2px 2px 5px #fff; + font-weight: bold; + color: #445566; +} + + +/* Footer */ + +#page-footer { + margin-bottom: 25px; +} \ No newline at end of file diff --git a/theme/nimble/style/menu.css b/theme/nimble/style/menu.css new file mode 100644 index 00000000000..76ea418bf64 --- /dev/null +++ b/theme/nimble/style/menu.css @@ -0,0 +1,208 @@ +#custommenu { + font-size: 1.2em; + line-height: 1.2; + float: left; + width:60%; +} + +.yui3-skin-sam .yui3-menu-content, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content { + border: none; + padding: 0 !important; +} + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content { + + padding: 5px 0; + color: #fff; +} + + +/* Horizontal menus */ + +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-content { + + +} + + +.yui3-skin-sam .yui3-menu ul, +.yui3-skin-sam .yui3-menu ul ul { + +} + +.yui3-skin-sam .yui3-menu ul.first-of-type { +} + +.yui3-skin-sam .yui3-menu-horizontal ul { +} + + +.yui3-skin-sam .yui3-menu li, +.yui3-skin-sam .yui3-menu .yui3-menu li { + +} + +.yui3-skin-sam .yui3-menu-horizontal li { + +} + +.yui3-skin-sam .yui3-menubuttonnav li { + +} + +.yui3-skin-sam .yui3-splitbuttonnav li { + +} + +.yui3-skin-sam .yui3-menubuttonnav li li, +.yui3-skin-sam .yui3-splitbuttonnav li li { + +} + + +/* Menuitems and menu labels */ + + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu { + background: #333 !important; +} +.custom_menu_submenu .custom_menu_submenu { + +} + + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu { + padding-top: 0; + background: none; +} + +.yui3-skin-sam .yui3-menuitem-content, +.yui3-skin-sam .yui3-menu-label { + color: #fff !important; +} + +.yui3-skin-sam .yui3-menuitem-content, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-content { + padding-top: 3px; + padding-bottom: 4px; + color: #fff !important; + +} + +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label, +.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-content { + color: #fff !important; +} + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content { + color: #fff; + background-color: #333; + +} + +.yui3-skin-sam .yui3-menu-label, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label { + padding-top: 3px; + padding-bottom: 4px; + border-radius:0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + color: #fff !important; + +} + +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label { + border: solid #555; + border-width: 1px 1px 0 1px; + padding: 0 20px 0 20px; + margin: 0 10px 0 0; + background: #333; + border-radius: 10px 10px 0 0; + -moz-border-radius: 10px 10px 0 0; + -webkit-border-radius: 10px 10px 0 0; + +} + +.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label, +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label { + + +} + +.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label { + + +} + +.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label em { + + +} + + +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label { + + +} + +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label a { + + +} + +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label .yui3-menu-toggle { + + +} + + +/* Selected menuitem */ + + + +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-active, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-label-menuvisible { + color: #fff; + background-color: #333 !important; +} + +.yui3-skin-sam .yui3-menuitem-active .yui3-menuitem-content, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menuitem-active .yui3-menuitem-content { + color: #fff; + background-color: #333; + +} + + + + + +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-active, +.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-active .yui3-menuitem-content, +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label-menuvisible { +} + +.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-active, +.yui3-skin-sam .yui3-menubuttonnav .yui3-menuitem-active .yui3-menuitem-content, +.yui3-skin-sam .yui3-menubuttonnav .yui3-menu-label-menuvisible, +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-active, +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menuitem-active .yui3-menuitem-content, +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible { + + +} + +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible { + + +} + +.yui3-skin-sam .yui3-splitbuttonnav .yui3-menu-label-menuvisible .yui3-menu-toggle { + + +} + +#custommenu .yui3-menu-horizontal.javascript-disabled .yui3-menu-content, +#custommenu .yui3-menu-horizontal.javascript-disabled .yui3-menu-content .ul {border:none !important;} +#custommenu .yui3-menu-horizontal.javascript-disabled li a {padding:0 20px 0 0;} diff --git a/theme/nimble/style/pagelayout.css b/theme/nimble/style/pagelayout.css new file mode 100644 index 00000000000..9d69b953f62 --- /dev/null +++ b/theme/nimble/style/pagelayout.css @@ -0,0 +1,105 @@ +/** Path: theme pagelayout **/ + +/********************************************************************************************* + + right column: 28% + padding left/right column: 10px + padding center column: 20px + +**********************************************************************************************/ + +body { + margin: auto 0px; + width: auto; +} + +#page { + width: 100%; + overflow: hidden; +} + +#page-header { + float: left; + width: 100%; +} + +#page-content { + clear: both; + float: left; + overflow: hidden; + position: relative; + width: 100%; +} + +#page-content #region-main-box { + float: left; + right: 28%; + position: relative; + width: 100%; +} + +#page-content #region-post-box { + float: left; + right: 72%; + position: relative; + width: 100%; +} + +#page-content #region-main { + float: left; + overflow: hidden; + position: relative; + margin-right: 0px; + left: 100%; + width: 72%; +} + +#page-content #region-post { + float: left; + overflow: hidden; + position: relative; + left: 100%; + width: 28%; +} + +#page-content #region-main .region-content { + overflow: hidden; + padding: 20px 25px 20px 0; +} + +#page-content #region-post .region-content { + overflow: hidden; + padding: 0 0 0 0; +} + +#page-footer { + clear: both; + float: left; + width: 100%; +} + +/** No blocks whatsoever **/ + +.content-only #page-content #region-main-box { + right: 0%; +} + +.content-only #page-content #region-post-box { + right: 100%; +} + +.content-only #page-content #region-main { + left: 100%; + width: 100%; +} + +.content-only #page-content #region-pre { + width: 0%; +} + +.content-only #page-content #region-post { + width: 0%; +} + +.pagelayout-report #page-content #region-main {overflow:auto;} +.pagelayout-report #page-content #region-main .region-content {overflow:visible;} \ No newline at end of file From 731f8516bc9c5887dfefd94ad4e4d1dd4c44e3b3 Mon Sep 17 00:00:00 2001 From: andyjdavis Date: Wed, 16 Feb 2011 14:38:33 +0800 Subject: [PATCH 003/369] message MDL-26435 removed commented out code --- message/lib.php | 69 ------------------------------------------------- 1 file changed, 69 deletions(-) diff --git a/message/lib.php b/message/lib.php index 8dfc3e78189..df8535ca82d 100644 --- a/message/lib.php +++ b/message/lib.php @@ -432,18 +432,6 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ if ($countstrangers && ($countonlinecontacts + $countofflinecontacts == 0)) { // Extra help echo html_writer::tag('div','('.get_string('addsomecontactsincoming', 'message').')',array('class' => 'note')); } - - /*if ($refresh) { - $PAGE->requires->js_init_call('M.core_message.init_refresh_page', array(60*1000, $PAGE->url->out(false))); - - echo $OUTPUT->container_start('messagejsautorefresh note center'); - echo get_string('pagerefreshes', 'message', $CFG->message_contacts_refresh); - echo $OUTPUT->container_end(); - - echo $OUTPUT->container_start('messagejsmanualrefresh aligncenter'); - echo $OUTPUT->single_button(message_remove_url_params($PAGE->url), get_string('refresh')); - echo $OUTPUT->container_end(); - }*/ } /** @@ -607,8 +595,6 @@ function message_print_search($advancedsearch = false, $user1=null) { $combinedsearchstring = ''; } - //$PAGE->requires->js_init_call('M.core_message.init_search_page', array($combinedsearchstring)); - if ($doingsearch) { if ($advancedsearch) { @@ -641,26 +627,6 @@ function message_print_search($advancedsearch = false, $user1=null) { } } -/*function message_print_settings() { - global $USER, $OUTPUT, $PAGE; - - if ($frm = data_submitted() and confirm_sesskey()) { - - $pref = array(); - $pref['message_beepnewmessage'] = (isset($frm->beepnewmessage)) ? '1' : '0'; - $pref['message_blocknoncontacts'] = (isset($frm->blocknoncontacts)) ? '1' : '0'; - - set_user_preferences($pref); - - redirect(message_remove_url_params($PAGE->url), get_string('settingssaved', 'message'), 1); - } - - $cbbeepnewmessage = (get_user_preferences('message_beepnewmessage', 0) == '1') ? 'checked="checked"' : ''; - $cbblocknoncontacts = (get_user_preferences('message_blocknoncontacts', 0) == '1') ? 'checked="checked"' : ''; - - include('settings.html'); -}*/ - /** * Get the users recent conversations meaning all the people they've recently * sent or received a message from plus the most recent message sent to or received from each other user @@ -1244,9 +1210,6 @@ function message_print_search_results($frm, $showicontext=false, $user1=null) { echo $OUTPUT->notification(get_string('emptysearchstring', 'message')); } - //echo '
'; - //echo $OUTPUT->single_button(new moodle_url($PAGE->url, array('tab' => 'search')), get_string('newsearch', 'message')); - echo html_writer::end_tag('div'); } @@ -1419,7 +1382,6 @@ function message_history_link($userid1, $userid2, $return=false, $keywords='', $ 'resizable' => true); $link = new moodle_url('/message/index.php?history='.MESSAGE_HISTORY_ALL."&user=$userid1&id=$userid2$keywords$position"); - //$action = new popup_action('click', $link, "message_history_$userid1", $popupoptions); $action = null; $str = $OUTPUT->action_link($link, $fulllink, $action, array('title' => $strmessagehistory)); @@ -2153,37 +2115,6 @@ function message_move_userfrom_unread2read($userid) { return true; } -/*function message_get_popup_messages($destuserid, $fromuserid=NULL){ - global $DB; - - $processor = $DB->get_record('message_processors', array('name' => 'popup')); - - $messagesproc = $DB->get_records('message_working', array('processorid' => $processor->id), 'id ASC'); - - //for every message to process check if it's for current user and process - $messages = array(); - foreach ($messagesproc as $msgp){ - $query = array('id' => $msgp->unreadmessageid, 'useridto' => $destuserid); - if ($fromuserid){ - $query['useridfrom'] = $fromuserid; - } - if ($message = $DB->get_record('message', $query)){ - $messages[] = $message; - /// Move the entry to the other table - $message->timeread = time(); - $messageid = $message->id; - unset($message->id); - - //delete what we've processed and check if can move message - $DB->delete_records('message_working', array('id' => $msgp->id)); - if ( $DB->count_records('message_working', array('unreadmessageid' => $messageid)) == 0){ - message_mark_message_read($message, time(), true); - } - } - } - return $messages; -}*/ - /** * marks ALL messages being sent from $fromuserid to $touserid as read * @param int $touserid the id of the message recipient From 7bbe971548d2e09efd493ce48c8e56ff5734f0c8 Mon Sep 17 00:00:00 2001 From: andyjdavis Date: Wed, 16 Feb 2011 12:11:41 +0800 Subject: [PATCH 004/369] general MDL-26440 removed references to uid in SQL queries as its a reserved word in Oracle --- mod/quiz/overrides.php | 2 +- rating/index.php | 2 +- rating/lib.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mod/quiz/overrides.php b/mod/quiz/overrides.php index 05357931d40..5f5c6da6e20 100644 --- a/mod/quiz/overrides.php +++ b/mod/quiz/overrides.php @@ -98,7 +98,7 @@ if ($groupmode) { } else { $colname = get_string('user'); - $sql = 'SELECT o.*, u.firstname, u.lastname, u.id as uid + $sql = 'SELECT o.*, u.firstname, u.lastname FROM {quiz_overrides} o JOIN {user} u ON o.userid = u.id WHERE o.quiz = ? diff --git a/rating/index.php b/rating/index.php index 41d085ecb69..50a63bed791 100644 --- a/rating/index.php +++ b/rating/index.php @@ -97,7 +97,7 @@ if (!$ratings) { //Undo the aliasing of the user id column from user_picture::fields() //we could clone the rating object or preserve the rating id if we needed it again //but we don't - $rating->id = $rating->uid; + $rating->id = $rating->userid; echo ''; echo ""; diff --git a/rating/lib.php b/rating/lib.php index b53abf2c350..29313e2786a 100644 --- a/rating/lib.php +++ b/rating/lib.php @@ -217,7 +217,7 @@ class rating_manager { $sortclause = "ORDER BY $options->sort"; } - $userfields = user_picture::fields('u', null, 'uid'); + $userfields = user_picture::fields('u', null, 'userid'); $sql = "SELECT r.id, r.rating, r.itemid, r.userid, r.timemodified, $userfields FROM {rating} r LEFT JOIN {user} u ON r.userid = u.id From c76cd2ede13ac6a60ddf30344752ed05613309fd Mon Sep 17 00:00:00 2001 From: Joseph Rezeau Date: Fri, 18 Feb 2011 10:43:25 +0100 Subject: [PATCH 005/369] MDL-26113 Lesson: temporary fix of page content alignment That rendering method should not use cell style attribute at all. Instead, the alignment should be controlled by CSS. However, this will require more massive changes in the Lesson code to be done by the module maintainer. As a temporary fix, left alignment is set as it usually matches the layout that students see. --- mod/lesson/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/lesson/renderer.php b/mod/lesson/renderer.php index 82ad996f008..696b8b98a0b 100644 --- a/mod/lesson/renderer.php +++ b/mod/lesson/renderer.php @@ -283,7 +283,7 @@ class mod_lesson_renderer extends plugin_renderer_base { $cell = new html_table_cell(); $cell->colspan = 2; - $cell->style = 'text-align:center'; + $cell->style = 'text-align:left'; $cell->text = $page->contents; $pagetable->data[] = new html_table_row(array($cell)); From ffdf7f8a24cab276433de88d2328b8821bd1714d Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 18 Feb 2011 11:43:24 +0100 Subject: [PATCH 006/369] MDL-25899 Lesson: fixed page content rendering Form element 'header' used to be used for rendering the page contents. This led to layout problems in non-gecko browsers. This patch fixes the issue by using raw 'html' element to render the page contents. --- mod/lesson/pagetypes/essay.php | 6 ++++-- mod/lesson/pagetypes/matching.php | 6 ++++-- mod/lesson/pagetypes/multichoice.php | 9 +++++++-- mod/lesson/pagetypes/numerical.php | 6 ++++-- mod/lesson/pagetypes/shortanswer.php | 4 +++- mod/lesson/pagetypes/truefalse.php | 6 ++++-- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/mod/lesson/pagetypes/essay.php b/mod/lesson/pagetypes/essay.php index 2ae796f072f..2f7d4f9b485 100644 --- a/mod/lesson/pagetypes/essay.php +++ b/mod/lesson/pagetypes/essay.php @@ -252,7 +252,9 @@ class lesson_display_answer_form_essay extends moodleform { $mform = $this->_form; $contents = $this->_customdata['contents']; - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; @@ -270,4 +272,4 @@ class lesson_display_answer_form_essay extends moodleform { $this->add_action_buttons(null, get_string("pleaseenteryouranswerinthebox", "lesson")); } -} \ No newline at end of file +} diff --git a/mod/lesson/pagetypes/matching.php b/mod/lesson/pagetypes/matching.php index 43335c0267e..3e40c63f92a 100644 --- a/mod/lesson/pagetypes/matching.php +++ b/mod/lesson/pagetypes/matching.php @@ -483,7 +483,9 @@ class lesson_display_answer_form_matching extends moodleform { $lessonid = $this->_customdata['lessonid']; $contents = $this->_customdata['contents']; - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; @@ -514,4 +516,4 @@ class lesson_display_answer_form_matching extends moodleform { $this->add_action_buttons(null, get_string("pleasematchtheabovepairs", "lesson")); } -} \ No newline at end of file +} diff --git a/mod/lesson/pagetypes/multichoice.php b/mod/lesson/pagetypes/multichoice.php index a9d912fb0d4..f29268fe679 100644 --- a/mod/lesson/pagetypes/multichoice.php +++ b/mod/lesson/pagetypes/multichoice.php @@ -485,7 +485,10 @@ class lesson_display_answer_form_multichoice_singleanswer extends moodleform { $attempt = new stdClass(); $attempt->answerid = null; } - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; @@ -524,7 +527,9 @@ class lesson_display_answer_form_multichoice_multianswer extends moodleform { $lessonid = $this->_customdata['lessonid']; $contents = $this->_customdata['contents']; - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; diff --git a/mod/lesson/pagetypes/numerical.php b/mod/lesson/pagetypes/numerical.php index 56b1784678d..18fb54fa2c5 100644 --- a/mod/lesson/pagetypes/numerical.php +++ b/mod/lesson/pagetypes/numerical.php @@ -264,7 +264,9 @@ class lesson_display_answer_form_numerical extends moodleform { $mform = $this->_form; $contents = $this->_customdata['contents']; - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; @@ -282,4 +284,4 @@ class lesson_display_answer_form_numerical extends moodleform { $this->add_action_buttons(null, get_string("pleaseenteryouranswerinthebox", "lesson")); } -} \ No newline at end of file +} diff --git a/mod/lesson/pagetypes/shortanswer.php b/mod/lesson/pagetypes/shortanswer.php index 62e0a8ef6f7..821d6147fd1 100644 --- a/mod/lesson/pagetypes/shortanswer.php +++ b/mod/lesson/pagetypes/shortanswer.php @@ -331,7 +331,9 @@ class lesson_display_answer_form_shortanswer extends moodleform { $mform = $this->_form; $contents = $this->_customdata['contents']; - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass; $options->para = false; diff --git a/mod/lesson/pagetypes/truefalse.php b/mod/lesson/pagetypes/truefalse.php index 5bdbe2224fe..61a1a7e343d 100644 --- a/mod/lesson/pagetypes/truefalse.php +++ b/mod/lesson/pagetypes/truefalse.php @@ -299,7 +299,9 @@ class lesson_display_answer_form_truefalse extends moodleform { $attempt->answerid = null; } - $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + $mform->addElement('header', 'pageheader'); + + $mform->addElement('html', $OUTPUT->container($contents, 'contents')); $options = new stdClass(); $options->para = false; @@ -326,4 +328,4 @@ class lesson_display_answer_form_truefalse extends moodleform { $this->add_action_buttons(null, get_string("pleasecheckoneanswer", "lesson")); } -} \ No newline at end of file +} From cb6b7332328c7897e688771d21e2fa4dba4cb73d Mon Sep 17 00:00:00 2001 From: Daren Chandisingh Date: Fri, 18 Feb 2011 12:28:26 +0000 Subject: [PATCH 007/369] Change 'Simbian' to 'Symbian' --- lib/moodlelib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index c9542bdd672..41d32983127 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7454,14 +7454,14 @@ function check_php_version($version='5.2.4') { if (strpos($agent, 'AppleWebKit') === false) { return false; } - // Look for AppleWebKit, excluding strings with OmniWeb, Shiira and SimbianOS and any other mobile devices + // Look for AppleWebKit, excluding strings with OmniWeb, Shiira and SymbianOS and any other mobile devices if (strpos($agent, 'OmniWeb')) { // Reject OmniWeb return false; } if (strpos($agent, 'Shiira')) { // Reject Shiira return false; } - if (strpos($agent, 'SimbianOS')) { // Reject SimbianOS + if (strpos($agent, 'SymbianOS')) { // Reject SymbianOS return false; } if (strpos($agent, 'Android')) { // Reject Androids too From bbc2d0ba3138c633dc64c6fd34675a0c0ed95436 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 18 Feb 2011 12:31:38 +0000 Subject: [PATCH 008/369] MDL-26416 quiz overview report, clean up the code before making the real bug fix. Cleaning up the code like this will make the real bug-fix easier to understand. --- mod/quiz/report/overview/report.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/mod/quiz/report/overview/report.php b/mod/quiz/report/overview/report.php index 7a9b5e14577..b9b5d83f12a 100644 --- a/mod/quiz/report/overview/report.php +++ b/mod/quiz/report/overview/report.php @@ -202,18 +202,25 @@ class quiz_overview_report extends quiz_default_report { if (!$nostudents || ($attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL)) { // Construct the SQL - $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, 0)').' AS uniqueid, '; + $fields = $DB->sql_concat('u.id', "'#'", 'COALESCE(qa.attempt, 0)') . ' AS uniqueid,'; if ($qmsubselect) { - $fields .= - "(CASE " . - " WHEN $qmsubselect THEN 1" . - " ELSE 0 " . - "END) AS gradedattempt, "; + $fields .= "\n(CASE WHEN $qmsubselect THEN 1 ELSE 0 END) AS gradedattempt,"; } - $fields .='qa.uniqueid AS attemptuniqueid, qa.id AS attempt, ' . - 'u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, u.imagealt, u.email, '. - 'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration '; + $fields .= ' + qa.uniqueid AS attemptuniqueid, + qa.id AS attempt, + u.id AS userid, + u.idnumber, + u.firstname, + u.lastname, + u.picture, + u.imagealt, + u.email, + qa.sumgrades, + qa.timefinish, + qa.timestart, + qa.timefinish - qa.timestart AS duration'; // This part is the same for all cases - join users and quiz_attempts tables $from = '{user} u '; From 19a9f1124d03be35efae735639911f4c94b8407f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 18 Feb 2011 14:06:11 +0000 Subject: [PATCH 009/369] MDL-26416 avoid subtracting two unsigned ints, which breaks MySQL since 5.5.5. --- mod/quiz/report/overview/report.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mod/quiz/report/overview/report.php b/mod/quiz/report/overview/report.php index b9b5d83f12a..767e31cd967 100644 --- a/mod/quiz/report/overview/report.php +++ b/mod/quiz/report/overview/report.php @@ -220,7 +220,15 @@ class quiz_overview_report extends quiz_default_report { qa.sumgrades, qa.timefinish, qa.timestart, - qa.timefinish - qa.timestart AS duration'; + CASE WHEN qa.timefinish = 0 THEN null + WHEN qa.timefinish > qa.timestart THEN qa.timefinish - qa.timestart + ELSE 0 END AS duration'; + // To explain that last bit, in MySQL, qa.timestart and qa.timefinish + // are unsigned. Since MySQL 5.5.5, when they introduced strict mode, + // subtracting a larger unsigned int from a smaller one gave an error. + // Therefore, we avoid doing that. timefinish can be non-zero and less + // than timestart when you have two load-balanced servers with very + // badly synchronised clocks, and a student does a really quick attempt. // This part is the same for all cases - join users and quiz_attempts tables $from = '{user} u '; From 79c6e3a0968ee1fedcf8a1f14f8086fcd9dbd3f6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 18 Feb 2011 17:37:23 +0000 Subject: [PATCH 010/369] MDL-25122 Quiz review page does not check and enforce separate groups mode. --- mod/quiz/attemptlib.php | 23 +++++++++++++++++++++++ mod/quiz/lang/en/quiz.php | 1 + mod/quiz/review.php | 18 +++++++----------- mod/quiz/reviewquestion.php | 21 ++++++--------------- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/mod/quiz/attemptlib.php b/mod/quiz/attemptlib.php index 9039f2578b6..7817e981574 100644 --- a/mod/quiz/attemptlib.php +++ b/mod/quiz/attemptlib.php @@ -592,6 +592,29 @@ class quiz_attempt extends quiz { (!$this->is_preview_user() || $this->attempt->preview); } + /** + * Is the current user allowed to review this attempt. This applies when + * {@link is_own_attempt()} returns false. + * @return bool whether the review should be allowed. + */ + public function is_review_allowed() { + if (!$this->has_capability('mod/quiz:viewreports')) { + return false; + } + + $cm = $this->get_cm(); + if ($this->has_capability('moodle/site:accessallgroups') || + groups_get_activity_groupmode($cm) != SEPARATEGROUPS) { + return true; + } + + // Check the users have at least one group in common. + $teachersgroups = groups_get_activity_allowed_groups($cm); + $studentsgroups = groups_get_all_groups($cm->course, $this->attempt->userid, $cm->groupingid); + return $teachersgroups && $studentsgroups && + array_intersect(array_keys($teachersgroups), array_keys($studentsgroups)); + } + /** * Check the appropriate capability to see whether this user may review their own attempt. * If not, prints an error. diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index dcb90e798eb..353cc162f86 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -531,6 +531,7 @@ $string['noquestionsnotinuse'] = 'This random question is not in use, since its $string['noquestionsonpage'] = 'Empty page'; $string['noresponse'] = 'No response'; $string['noreview'] = 'You are not allowed to review this quiz'; +$string['noreviewattempt'] = 'You are not allowed to review this attempt.'; $string['noreviewshort'] = 'Not permitted'; $string['noreviewuntil'] = 'You are not allowed to review this quiz until {$a}'; $string['noreviewuntilshort'] = 'Available {$a}'; diff --git a/mod/quiz/review.php b/mod/quiz/review.php index e3714d02ec5..240de7bdfc5 100644 --- a/mod/quiz/review.php +++ b/mod/quiz/review.php @@ -34,21 +34,17 @@ $accessmanager = $attemptobj->get_access_manager(time()); $options = $attemptobj->get_review_options(); -/// Permissions checks for normal users who do not have quiz:viewreports capability. - if (!$attemptobj->has_capability('mod/quiz:viewreports')) { - /// Can't review other users' attempts. - if (!$attemptobj->is_own_attempt()) { - quiz_error($attemptobj->get_quiz(), 'notyourattempt'); - } - /// Can't review during the attempt - send them back to the attempt page. + // Check permissions. + if ($attemptobj->is_own_attempt()) { if (!$attemptobj->is_finished()) { redirect($attemptobj->attempt_url(0, $page)); - } - /// Can't review unless Students may review -> Responses option is turned on. - if (!$options->responses) { + } else if (!$options->responses) { $accessmanager->back_to_view_page($attemptobj->is_preview_user(), - $accessmanager->cannot_review_message($options)); + $accessmanager->cannot_review_message($attemptobj->get_attempt_state())); } + + } else if (!$attemptobj->is_review_allowed()) { + throw new moodle_quiz_exception($attemptobj, 'noreviewattempt'); } /// Load the questions and states needed by this page. diff --git a/mod/quiz/reviewquestion.php b/mod/quiz/reviewquestion.php index 48d87edecb5..a61851e4b3b 100644 --- a/mod/quiz/reviewquestion.php +++ b/mod/quiz/reviewquestion.php @@ -32,27 +32,15 @@ $accessmanager = $attemptobj->get_access_manager(time()); $options = $attemptobj->get_review_options(); -/// Permissions checks for normal users who do not have quiz:viewreports capability. - if (!$attemptobj->has_capability('mod/quiz:viewreports')) { - /// Can't review during the attempt - send them back to the attempt page. + // Check permissions. + if ($attemptobj->is_own_attempt()) { if (!$attemptobj->is_finished()) { echo $OUTPUT->header(); echo $OUTPUT->notification(get_string('cannotreviewopen', 'quiz')); echo $OUTPUT->close_window_button(); echo $OUTPUT->footer(); die; - } - /// Can't review other users' attempts. - if (!$attemptobj->is_own_attempt()) { - echo $OUTPUT->header(); - echo $OUTPUT->notification(get_string('notyourattempt', 'quiz')); - echo $OUTPUT->close_window_button(); - echo $OUTPUT->footer(); - die; - } - - /// Can't review unless Students may review -> Responses option is turned on. - if (!$options->responses) { + } else if (!$options->responses) { $accessmanager = $attemptobj->get_access_manager(time()); echo $OUTPUT->header(); echo $OUTPUT->notification($accessmanager->cannot_review_message($attemptobj->get_review_options())); @@ -60,6 +48,9 @@ echo $OUTPUT->footer(); die; } + + } else if (!$attemptobj->is_review_allowed()) { + throw new moodle_quiz_exception($attemptobj, 'noreviewattempt'); } /// Load the questions and states. From 7cc5cec6e1b3d9fe40795c240132d5cbe0f0a85f Mon Sep 17 00:00:00 2001 From: Andreas Grabs Date: Sun, 20 Feb 2011 17:45:10 +0100 Subject: [PATCH 011/369] MDL-26060 - Sorting by date on user list for responses list throws an error --- mod/feedback/show_entries.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/feedback/show_entries.php b/mod/feedback/show_entries.php index 429f374a419..3a4edd7f1c5 100644 --- a/mod/feedback/show_entries.php +++ b/mod/feedback/show_entries.php @@ -104,7 +104,7 @@ if($do_show == 'showentries'){ $baseurl = new moodle_url('/mod/feedback/show_entries.php'); $baseurl->params(array('id'=>$id, 'do_show'=>$do_show, 'showall'=>$showall)); - $tablecolumns = array('userpic', 'fullname', 'timemodified'); + $tablecolumns = array('userpic', 'fullname', 'c.timemodified'); $tableheaders = array(get_string('userpic'), get_string('fullnameuser'), get_string('date')); if(has_capability('mod/feedback:deletesubmissions', $context)) { From 5cf4fa46841e1bb753b2809563653f4dc0e7c1cc Mon Sep 17 00:00:00 2001 From: Andreas Grabs Date: Sun, 20 Feb 2011 18:18:44 +0100 Subject: [PATCH 012/369] MDL-26524 - Group Filtering Errors --- mod/feedback/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index aed8b5c4a92..1d238e9f97a 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -2111,7 +2111,7 @@ function feedback_get_group_values($item, $groupid = false, $courseid = false, $ //if the groupid is given? if (intval($groupid) > 0) { if($ignore_empty) { - $ignore_empty_select = "AND fbc.value != ''"; + $ignore_empty_select = "AND fbv.value != ''"; } else { $ignore_empty_select = ""; From aafa4f324a4880c26001ab745ee06b32ee57cb31 Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Mon, 21 Feb 2011 10:48:38 +0800 Subject: [PATCH 013/369] rating MDL-26461 fixed an off by 1 bug that made the safeguard against too high ratings not work --- rating/index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rating/index.php b/rating/index.php index 41d085ecb69..8f4cf708b71 100644 --- a/rating/index.php +++ b/rating/index.php @@ -92,7 +92,8 @@ if (!$ratings) { echo "
$strtime"; echo ""; - $maxrating = count($scalemenu); + //if the scale was changed after ratings were submitted some ratings may have a value above the current maximum + $maxrating = count($scalemenu) - 1; foreach ($ratings as $rating) { //Undo the aliasing of the user id column from user_picture::fields() //we could clone the rating object or preserve the rating id if we needed it again From d042ff06b35fe91b6bb097cc8cdfd4be5e8b42f0 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Mon, 21 Feb 2011 15:43:30 +0800 Subject: [PATCH 014/369] assignment MDL-26532 fixed regression in assignment_cron() while processing messaging. --- mod/assignment/lib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 9c51c0942db..82113ba64ec 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -2612,6 +2612,11 @@ function assignment_cron () { $eventdata->fullmessageformat = FORMAT_PLAIN; $eventdata->fullmessagehtml = $posthtml; $eventdata->smallmessage = ''; + + $eventdata->name = 'assignment_updates'; + $eventdata->component = 'mod_assignment'; + $eventdata->notification = 1; + message_send($eventdata); } From fdef13e6929f639c8f7c307ac9d1c6642067eef6 Mon Sep 17 00:00:00 2001 From: Charles Fulton Date: Sun, 20 Feb 2011 13:55:58 -0800 Subject: [PATCH 015/369] MDL-26507: improper use of assignment operater causes grade checks to fail --- lib/conditionlib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/conditionlib.php b/lib/conditionlib.php index 6b862e8b82e..83b79d343d2 100644 --- a/lib/conditionlib.php +++ b/lib/conditionlib.php @@ -557,7 +557,7 @@ WHERE */ private function get_cached_grade_score($gradeitemid, $grabthelot=false, $userid=0) { global $USER, $DB, $SESSION; - if ($userid==0 || $userid=$USER->id) { + if ($userid==0 || $userid==$USER->id) { // For current user, go via cache in session if (empty($SESSION->gradescorecache) || $SESSION->gradescorecacheuserid!=$USER->id) { $SESSION->gradescorecache = array(); From e4f72d14284c7ddd89eee60ea5961bd483fdf4ec Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sat, 19 Feb 2011 22:27:37 +0100 Subject: [PATCH 016/369] MDL-26513 restore - observe target site restrictmodulesfor setting --- backup/moodle2/restore_stepslib.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 29396758ea4..eace0149591 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -1021,8 +1021,6 @@ class restore_course_structure_step extends restore_structure_step { global $CFG, $DB; $data = (object)$data; - $coursetags = isset($data->tags['tag']) ? $data->tags['tag'] : array(); - $coursemodules = isset($data->allowed_modules['module']) ? $data->allowed_modules['module'] : array(); $oldid = $data->id; // We'll need this later $fullname = $this->get_setting_value('course_fullname'); @@ -1038,6 +1036,9 @@ class restore_course_structure_step extends restore_structure_step { $data->shortname= $shortname; $data->idnumber = ''; + // Only restrict modules if original course was and target site too for new courses + $data->restrictmodules = $data->restrictmodules && !empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all'; + $data->startdate= $this->apply_date_offset($data->startdate); if ($data->defaultgroupingid) { $data->defaultgroupingid = $this->get_mappingid('grouping', $data->defaultgroupingid); From dd2645d3049eb0f02409c6e2379d10a2c9864823 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Mon, 21 Feb 2011 16:00:12 +0100 Subject: [PATCH 017/369] MDL-26537 Portfolio: Flickr setup instruction contains correct callback URL There was a bug due to the code copied from portfolio_boxnet plugin. --- portfolio/flickr/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portfolio/flickr/lib.php b/portfolio/flickr/lib.php index 4c64fa7c830..fe63d9dbb17 100755 --- a/portfolio/flickr/lib.php +++ b/portfolio/flickr/lib.php @@ -107,7 +107,7 @@ class portfolio_plugin_flickr extends portfolio_plugin_push_base { $a = new stdClass(); $a->applyurl = 'http://www.flickr.com/services/api/keys/apply/'; $a->keysurl = 'http://www.flickr.com/services/api/keys/'; - $a->callbackurl = $CFG->wwwroot . '/portfolio/add.php?postcontrol=1&type=boxnet'; + $a->callbackurl = $CFG->wwwroot . '/portfolio/add.php?postcontrol=1&type=flickr'; $mform->addElement('static', 'setupinfo', get_string('setupinfo', 'portfolio_flickr'), get_string('setupinfodetails', 'portfolio_flickr', $a)); } From d5a1cca1affb49685b5bc07e689bcb850eb40472 Mon Sep 17 00:00:00 2001 From: AMOS bot Date: Tue, 22 Feb 2011 00:27:05 +0100 Subject: [PATCH 018/369] Automatic installer lang files (20110222) --- install/lang/cs/install.php | 4 ++++ install/lang/eu/admin.php | 2 +- install/lang/fr/admin.php | 4 +++- install/lang/pl/admin.php | 1 + install/lang/pt/error.php | 6 +++--- install/lang/pt_br/install.php | 20 ++++++++++---------- install/lang/ru/install.php | 26 +++++++++++++++++++++++++- install/lang/zh_cn/install.php | 6 ++++-- 8 files changed, 51 insertions(+), 18 deletions(-) diff --git a/install/lang/cs/install.php b/install/lang/cs/install.php index a4e59623826..5c65252c8a2 100644 --- a/install/lang/cs/install.php +++ b/install/lang/cs/install.php @@ -64,6 +64,10 @@ $string['pathserrcreatedataroot'] = 'Datový adresář ({$a->dataroot}) nemůže $string['pathshead'] = 'Potvrdit cesty'; $string['pathsrodataroot'] = 'Do datového adresáře nelze zapisovat.'; $string['pathsroparentdataroot'] = 'Do nadřazeného adresáře ({$a->parent}) nelze zapisovat. Datový adresář ({$a->dataroot}) nemůže být tímto průvodcem instalací vytvořen.'; +$string['pathssubdirroot'] = 'Absolutní cesta k adresáři s instalací Moodle'; +$string['pathsunsecuredataroot'] = 'Umístění datového adresáře není bezpečné'; +$string['pathswrongadmindir'] = 'Adresář pro správu serveru (admin) neexistuje'; +$string['phpextension'] = '{$a} PHP rozšíření'; $string['phpversion'] = 'Verze PHP'; $string['phpversionhelp'] = '

Moodle vyžaduje PHP alespoň verze 4.3.0 nebo 5.1.0 (PHP 5.0.x obsahuje množství chyb).

Nyní používáte PHP verze {$a}.

diff --git a/install/lang/eu/admin.php b/install/lang/eu/admin.php index ae09a009a07..1183ec82ae7 100644 --- a/install/lang/eu/admin.php +++ b/install/lang/eu/admin.php @@ -36,6 +36,6 @@ $string['clitypevalue'] = 'Sartu balorea'; $string['clitypevaluedefault'] = 'sartu balorea, sakatu Enter-i berezko balorea erabiltzeko ({$a})'; $string['cliunknowoption'] = 'Aukera ezezagunak:{$a} Mesedez, erabili --laguntza aukera.'; -$string['cliyesnoprompt'] = 'idatzi b(bai esateko) edo e (ez esateko)'; +$string['cliyesnoprompt'] = 'idatzi b (bai esateko) edo e (ez esateko)'; $string['environmentrequireinstall'] = 'derrigorrezkoa da instalatuta etagaituta izatea'; $string['environmentrequireversion'] = '{$a->needed} bertsioa beharrezkoa da eta zu {$a->current} ari zara egikaritzen'; diff --git a/install/lang/fr/admin.php b/install/lang/fr/admin.php index 922e1f50417..3c86bb7312c 100644 --- a/install/lang/fr/admin.php +++ b/install/lang/fr/admin.php @@ -34,7 +34,9 @@ $string['cliincorrectvalueerror'] = 'Erreur, valeur incorrecte « {$a->value}  $string['cliincorrectvalueretry'] = 'Valeur incorrecte, veuillez réessayer'; $string['clitypevalue'] = 'type valeur'; $string['clitypevaluedefault'] = 'type valeur, tapez Entrée pour utiliser la valeur par défaut ({$a})'; -$string['cliunknowoption'] = 'Options non reconnues :n {$a}n. Utilisez l\'option --help.'; +$string['cliunknowoption'] = 'Options non reconnues : + {$a}. +Utilisez l\'option --help.'; $string['cliyesnoprompt'] = 'Tapez y (pour oui) ou n (pour non)'; $string['environmentrequireinstall'] = 'doit être installé et activé'; $string['environmentrequireversion'] = 'la version {$a->needed} est requise ; vous utilisez actuellement la version {$a->current}'; diff --git a/install/lang/pl/admin.php b/install/lang/pl/admin.php index 499fe84c09f..1f5ef1cbd71 100644 --- a/install/lang/pl/admin.php +++ b/install/lang/pl/admin.php @@ -29,6 +29,7 @@ */ $string['cliincorrectvalueerror'] = 'Błąd, niepoprawna wartość "{$a->value}" dla "{$a->option}"'; +$string['cliincorrectvalueretry'] = 'Nieprawidłowa wartość, spróbuj ponownie'; $string['clitypevalue'] = 'typ wartości'; $string['clitypevaluedefault'] = 'typ wartości, naciśnij Enter, aby użyć wartości domyślnej ({$a})'; $string['cliyesnoprompt'] = 'wpisz y (czyli tak) lub n (czyli nie)'; diff --git a/install/lang/pt/error.php b/install/lang/pt/error.php index 73691ec1a01..666c1cece9d 100644 --- a/install/lang/pt/error.php +++ b/install/lang/pt/error.php @@ -30,9 +30,9 @@ $string['cannotcreatelangdir'] = 'Não é possível criar o directório para pacotes linguísticos'; $string['cannotcreatetempdir'] = 'Não é possível criar o directório temporário'; -$string['cannotdownloadcomponents'] = 'Não é possível descarregar a cópia dos componentes'; -$string['cannotdownloadzipfile'] = 'Não é possível descarregar a cópia do ficheiro ZIP'; -$string['cannotfindcomponent'] = 'Não foi encontrado um componente'; +$string['cannotdownloadcomponents'] = 'Não é possível descarregar componentes'; +$string['cannotdownloadzipfile'] = 'Não é possível descarregar o ficheiro ZIP'; +$string['cannotfindcomponent'] = 'O componente não foi encontrado'; $string['cannotsavemd5file'] = 'Não é possível gravar ficheiro md5'; $string['cannotsavezipfile'] = 'Não é possível gravar ficheiro ZIP'; $string['cannotunzipfile'] = 'Não é possível descompactar ficheiro ZIP'; diff --git a/install/lang/pt_br/install.php b/install/lang/pt_br/install.php index 2fb9431a7cb..85c7dcced1b 100644 --- a/install/lang/pt_br/install.php +++ b/install/lang/pt_br/install.php @@ -28,16 +28,16 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['admindirname'] = 'Diretório Admin'; -$string['availablelangs'] = 'Pacotes de idioma disponíveis'; +$string['admindirname'] = 'Diretório admin'; +$string['availablelangs'] = 'Lista de idiomas disponíveis'; $string['chooselanguagehead'] = 'Escolha um idioma'; -$string['chooselanguagesub'] = 'Escolha um idioma a ser usado durante a instalação. Após a instalação você pode definir o idioma principal do site e outros idiomas a serem utilizados pelos usuários.'; +$string['chooselanguagesub'] = 'Por favor, escolha o idioma para a instalação.Este idioma também será utilizado como idioma padrão do site, embora você possa mudar mais tarde.'; $string['clialreadyinstalled'] = 'O arquivo config.php já existe, por favor use admin/cli/upgrade.php, se você quiser atualizar o seu site.'; $string['cliinstallheader'] = 'Programa de instalação por linha de comando do Moodle {$a}'; -$string['databasehost'] = 'Host da Base de Dados.'; -$string['databasename'] = 'Nome da Base de Dados'; +$string['databasehost'] = 'Host da base de dados'; +$string['databasename'] = 'Nome da base de dados'; $string['databasetypehead'] = 'Escolha o driver da base de dados'; -$string['dataroot'] = 'Diretório de Dados'; +$string['dataroot'] = 'Diretório de dados'; $string['dbprefix'] = 'Prefixo das tabelas'; $string['dirroot'] = 'Diretório Moodle'; $string['environmenthead'] = 'Verificando o ambiente ...'; @@ -45,7 +45,7 @@ $string['environmentsub2'] = 'Cada release do Moodle requer uma versão mínima A verificação completa do ambiente é feita antes de cada instalação e atualização.'; $string['errorsinenvironment'] = 'Verificação do Ambiente falhou!'; $string['installation'] = 'Instalação'; -$string['langdownloaderror'] = 'Infelizmente o idioma "{$a}" não foi instalado. A instalação vai continuar em Inglês.'; +$string['langdownloaderror'] = 'Infelizmente não foi possível fazer download do idioma "{$a}". O processo de instalação continuará em Inglês.'; $string['memorylimithelp'] = '

O limite de memória do PHP configurado atualmente no seu servidor é de {$a}.

Este limite pode causar problemas no futuro, especialmente quando muitos módulos estiverem ativados ou em caso de um número elevado de usuários.

@@ -60,10 +60,10 @@ Com esta operação Moodle será capaz de configurar o limite de memória sózin

Alguns servidores não aceitam este procedimento e todas as páginas PHP do servidor ficam bloqueadas ou imprimem mensagens de erro. Neste caso será necessário excluir o arquivo .htaccess .

'; $string['paths'] = 'Caminhos'; -$string['pathserrcreatedataroot'] = 'O Diretório de Dados ({&a->dataroot}) não pode ser criado pelo instalador.'; +$string['pathserrcreatedataroot'] = 'O diretório de dados ({$a->dataroot}) não pode ser criado pelo instalador.'; $string['pathshead'] = 'Confirme os caminhos'; -$string['pathsrodataroot'] = 'O Diretório de Dados raiz não pode ser acessada para escrita.'; -$string['pathsroparentdataroot'] = 'O diretório pai ({$a->parent}) não pode ser escrito. O diretório de dados ({$a->dataroot)) não pode ser criado pelo instalador.'; +$string['pathsrodataroot'] = 'O diretório de dados raiz não pode ser acessado para escrita.'; +$string['pathsroparentdataroot'] = 'O diretório pai ({$a->parent}) não pode ser escrito. O diretório de dados ({$a->dataroot}) não pode ser criado pelo instalador.'; $string['pathssubadmindir'] = 'Alguns poucos webhosts usam /admin como um URL especial para acesso ao painel de controle ou outras coisas. Infelizmente isto conflita com a localizaçao padrão das páginas do administrador Moodle. Você pode corrigir isso renomeando a pasta admin na sua instalação, e colocando esse novo nome aqui. Por exemplo: moodleadmin. Isto irá corrigir os links das páginas do administrador Moodle.'; $string['pathssubdataroot'] = 'Você precisa de um local onde o Moodle possa salvar arquivos enviados. Este diretório deve possuir permissões de leitura e escrita pelo usuário do servidor web (geralmente \'nobody\' ou \'apache \'), mas não deverá ser acessível diretamente através da web. O instalador irá tentar criá-lo se ele não existir.'; diff --git a/install/lang/ru/install.php b/install/lang/ru/install.php index 65dae11b0cb..c82760d9209 100644 --- a/install/lang/ru/install.php +++ b/install/lang/ru/install.php @@ -32,10 +32,18 @@ $string['admindirname'] = 'Каталог администратора'; $string['availablelangs'] = 'Доступные языковые пакеты'; $string['chooselanguagehead'] = 'Выберите язык'; $string['chooselanguagesub'] = 'Сейчас необходимо выбрать язык ТОЛЬКО для сообщений во время установки. Язык сайта и пользовательских интерфейсов можно будет указать далее в процессе установки.'; +$string['clialreadyinstalled'] = 'Файл config.php уже существует. Если вы хотите обновить сайт, пожалуйста, используйте скрипт admin/cli/upgrade.php.'; +$string['cliinstallheader'] = 'Программа установки Moodle {$a} в режиме командной строки'; +$string['databasehost'] = 'Сервер баз данных'; +$string['databasename'] = 'Название базы данных'; +$string['databasetypehead'] = 'Выберите драйвер базы данных'; $string['dataroot'] = 'Каталог данных'; $string['dbprefix'] = 'Префикс имён таблиц'; $string['dirroot'] = 'Каталог Moodle'; -$string['environmenthead'] = 'Проверка окружения...'; +$string['environmenthead'] = 'Проверка среды...'; +$string['environmentsub2'] = 'У каждой версии Moodle есть минимальные требования к версии PHP и набор обязательных расширений PHP. +Полная проверка среды осуществляется перед каждой установкой и обновлением. +Пожалуйста, свяжитесь с администратором сервера, если не знаете, как установить новую версию или включить расширения PHP.'; $string['installation'] = 'Установка'; $string['langdownloaderror'] = 'К несчастью, не удалось установить язык "{$a}". Процесс установки продолжится на английском.'; $string['memorylimithelp'] = '

Сейчас ограничение памяти в PHP на Вашем сервере установлено в {$a}.

@@ -53,6 +61,22 @@ $string['memorylimithelp'] = '

Сейчас ограничение памят

php_value memory_limit 40M

Тем не менее, на некоторых серверах из-за этого могут перестать работать все страницы PHP (Вы увидите ошибки на страницах). В этом случае файл придётся удалить файл .htaccess.

'; +$string['paths'] = 'Пути'; +$string['pathserrcreatedataroot'] = 'Программа установки не может создать каталог данных ({$a->dataroot}).'; +$string['pathshead'] = 'Подтвердите пути'; +$string['pathsrodataroot'] = 'Каталог данных недоступен для записи.'; +$string['pathsroparentdataroot'] = 'Родительский каталог ({$a->parent}) не доступен для записи. Программа установки не может создать каталог данных ({$a->dataroot}).'; +$string['pathssubadmindir'] = 'На небольшом числе веб-хостингов путь /admin используется для доступа к панели управления или чему-то еще. К сожалению, это противоречит стандартному расположению страниц управления Moodle. Это можно исправить путем переименования папки admin в каталоге Moodle и указания нового имени здесь. Например: moodleadmin. При этом все ссылки на панель управления Moodle исправятся автоматически.'; +$string['pathssubdataroot'] = 'Необходимо указать место, где Moodle будет хранить загружаемые файлы. Этот каталог должен быть доступен для чтения и ЗАПИСИ тому пользователю, от чьего имени запускается веб-сервер (обычно \'nobody\' или \'apache\'), но при этом не должен быть доступен напрямую через Интернет. Программа установки попробует создать этот каталог, если он не существует.'; +$string['pathssubdirroot'] = 'Полный путь к каталогу установки Moodle.'; +$string['pathssubwwwroot'] = 'Полный веб-адрес, по которому будет доступен Moodle. +Использовать для доступа к Moodle несколько публичных адресов невозможно. +Если у вашего сайта есть еще несколько публичных адресов, вам следует настроить постоянные перенаправления с этих адресов на указанный. +Если ваш сайт доступен как из Интернета, так и из локальной сети, укажите здесь публичный адрес и настройте DNS таким образом, чтобы этот адрес был доступен и локальным пользователям. +Если указанный здесь адрес неверный, измените URL в строке адреса браузера, чтобы перезапустить установку с другим значением.'; +$string['pathsunsecuredataroot'] = 'Расположение каталога данных не отвечает требованиям безопасности'; +$string['pathswrongadmindir'] = 'Каталог admin не существует'; +$string['phpextension'] = 'Расширение PHP "{$a}"'; $string['phpversion'] = 'Версия PHP'; $string['phpversionhelp'] = '

Для Moodle необходим PHP версии 4.3.0 и выше или 5.1.0 и выше (известны некоторые проблемы с версией 5.0.x).

Сейчас у Вас используется версия {$a}

diff --git a/install/lang/zh_cn/install.php b/install/lang/zh_cn/install.php index a027f1e24ee..cf5555d29db 100644 --- a/install/lang/zh_cn/install.php +++ b/install/lang/zh_cn/install.php @@ -57,13 +57,15 @@ $string['memorylimithelp'] = '

您的服务器的PHP内存限制是${a}。

php_value memory_limit 16M

然而,在一些服务器上这会让所有PHP页面无法正常工作(在访问页面时会有错误),因此您可能不得不删除.htaccess文件。

'; +$string['paths'] = '路径'; $string['pathserrcreatedataroot'] = '安装程序无法建立数据目录({$a->dataroot})。'; +$string['pathshead'] = '确认路径'; $string['pathsrodataroot'] = '数据目录不可写'; $string['pathsroparentdataroot'] = '父目录({$a->parent})不可写。安装程序无法建立数据目录({$a->dataroot})。'; $string['pathssubadmindir'] = '有些网络主机使用/admin这个URL来访问控制面板或其它功能。很不幸,这个设置和Moodle管理页面的标准路径冲突。这个问题可以解决,只需在您的安装目录中把admin目录换名,然后把新名字输入到这里。例如moodleadmin。这么做会改变Moodle中的管理链接。'; $string['pathssubdataroot'] = 'Moodle需要一个位置存放上传的文件。这个目录对于Web服务器用户(通常是“nobody”或“apache”)应当是可读可写的,但应当不能直接通过Web访问它。如果它不存在,安装程序会尝试建立。'; -$string['pathssubdirroot'] = 'moodle安装的完整路径。'; -$string['pathssubwwwroot'] = 'moodle的完整网址。 +$string['pathssubdirroot'] = 'Moodle安装的完整路径。'; +$string['pathssubwwwroot'] = '可以访问到Moodle的完整网址。 Moodle不支持通过多个地址访问。如果您的网站有多个公开地址,您必须把这个地址以外的所有地址都设为永久重定向。如果您的网站既可以通过内部地址访问,也可以通过这个公开地址访问,那么请配置DNS使内部网用户也能使用公开地址。如果此地址不正确,请在浏览器中修改URL来重新安装,并设定另一个地址。'; $string['pathsunsecuredataroot'] = '数据目录所在位置不安全'; $string['pathswrongadmindir'] = '管理目录不存在'; From 7c26c3f87564ab65a2135dff746eccd290bd4c87 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Tue, 22 Feb 2011 00:54:13 +0100 Subject: [PATCH 019/369] MDL-26546 Workshop: fixed incorrect mapping name in the restore of assessment forms There was a regression of 8fa86f and ac0f8f where I changed the mapping names but did not use the new names in add_related_files() call. All credit goes to Eloy Lafuente for spotting the problem and giving me a hint on how to fix it. --- .../restore_workshopform_accumulative_subplugin.class.php | 2 +- .../moodle2/restore_workshopform_comments_subplugin.class.php | 2 +- .../moodle2/restore_workshopform_numerrors_subplugin.class.php | 2 +- .../moodle2/restore_workshopform_rubric_subplugin.class.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/workshop/form/accumulative/backup/moodle2/restore_workshopform_accumulative_subplugin.class.php b/mod/workshop/form/accumulative/backup/moodle2/restore_workshopform_accumulative_subplugin.class.php index 69e56c93ff5..dc2418b686a 100644 --- a/mod/workshop/form/accumulative/backup/moodle2/restore_workshopform_accumulative_subplugin.class.php +++ b/mod/workshop/form/accumulative/backup/moodle2/restore_workshopform_accumulative_subplugin.class.php @@ -112,7 +112,7 @@ class restore_workshopform_accumulative_subplugin extends restore_subplugin { $this->set_mapping($this->get_namefor('dimension'), $oldid, $newitemid, true); // Process files for this workshopform_accumulative->id only - $this->add_related_files('workshopform_accumulative', 'description', 'workshopform_accumulative', null, $oldid); + $this->add_related_files('workshopform_accumulative', 'description', $this->get_namefor('dimension'), null, $oldid); } /** diff --git a/mod/workshop/form/comments/backup/moodle2/restore_workshopform_comments_subplugin.class.php b/mod/workshop/form/comments/backup/moodle2/restore_workshopform_comments_subplugin.class.php index 8374ef0a7e6..d72d72de381 100644 --- a/mod/workshop/form/comments/backup/moodle2/restore_workshopform_comments_subplugin.class.php +++ b/mod/workshop/form/comments/backup/moodle2/restore_workshopform_comments_subplugin.class.php @@ -109,7 +109,7 @@ class restore_workshopform_comments_subplugin extends restore_subplugin { $this->set_mapping($this->get_namefor('dimension'), $oldid, $newitemid, true); // Process files for this workshopform_comments->id only - $this->add_related_files('workshopform_comments', 'description', 'workshopform_comments', null, $oldid); + $this->add_related_files('workshopform_comments', 'description', $this->get_namefor('dimension'), null, $oldid); } /** diff --git a/mod/workshop/form/numerrors/backup/moodle2/restore_workshopform_numerrors_subplugin.class.php b/mod/workshop/form/numerrors/backup/moodle2/restore_workshopform_numerrors_subplugin.class.php index 33a19c287cd..ce81fcb5eda 100644 --- a/mod/workshop/form/numerrors/backup/moodle2/restore_workshopform_numerrors_subplugin.class.php +++ b/mod/workshop/form/numerrors/backup/moodle2/restore_workshopform_numerrors_subplugin.class.php @@ -124,7 +124,7 @@ class restore_workshopform_numerrors_subplugin extends restore_subplugin { $this->set_mapping($this->get_namefor('dimension'), $oldid, $newitemid, true); // Process files for this workshopform_numerrors->id only - $this->add_related_files('workshopform_numerrors', 'description', 'workshopform_numerrors', null, $oldid); + $this->add_related_files('workshopform_numerrors', 'description', $this->get_namefor('dimension'), null, $oldid); } /** diff --git a/mod/workshop/form/rubric/backup/moodle2/restore_workshopform_rubric_subplugin.class.php b/mod/workshop/form/rubric/backup/moodle2/restore_workshopform_rubric_subplugin.class.php index 472af01a312..35b40006b32 100644 --- a/mod/workshop/form/rubric/backup/moodle2/restore_workshopform_rubric_subplugin.class.php +++ b/mod/workshop/form/rubric/backup/moodle2/restore_workshopform_rubric_subplugin.class.php @@ -128,7 +128,7 @@ class restore_workshopform_rubric_subplugin extends restore_subplugin { $this->set_mapping($this->get_namefor('dimension'), $oldid, $newitemid, true); // Process files for this workshopform_rubric->id only - $this->add_related_files('workshopform_rubric', 'description', 'workshopform_rubric', null, $oldid); + $this->add_related_files('workshopform_rubric', 'description', $this->get_namefor('dimension'), null, $oldid); } /** From 6c0f13a5bcb94de5d921a64c25e1c8c7b43aef79 Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Tue, 22 Feb 2011 16:05:01 +0800 Subject: [PATCH 020/369] message MDL-25816 added safety checks in form processing --- message/output/email/message_output_email.php | 4 +++- message/output/jabber/message_output_jabber.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/message/output/email/message_output_email.php b/message/output/email/message_output_email.php index 90bf792396d..dff487450e0 100644 --- a/message/output/email/message_output_email.php +++ b/message/output/email/message_output_email.php @@ -85,7 +85,9 @@ class message_output_email extends message_output { * @param array $preferences preferences array */ function process_form($form, &$preferences){ - $preferences['message_processor_email_email'] = $form->email_email; + if (isset($form->email_email)) { + $preferences['message_processor_email_email'] = $form->email_email; + } } /** diff --git a/message/output/jabber/message_output_jabber.php b/message/output/jabber/message_output_jabber.php index a6f9f65d5da..945d790f895 100644 --- a/message/output/jabber/message_output_jabber.php +++ b/message/output/jabber/message_output_jabber.php @@ -106,7 +106,9 @@ class message_output_jabber extends message_output { * @param array $preferences preferences array */ function process_form($form, &$preferences){ - $preferences['message_processor_jabber_jabberid'] = $form->jabber_jabberid; + if (isset($form->jabber_jabberid)) { + $preferences['message_processor_jabber_jabberid'] = $form->jabber_jabberid; + } } /** From 6cb66ae00ec7aca32f098bb09f1755c90e1825e7 Mon Sep 17 00:00:00 2001 From: Helen Foster Date: Tue, 22 Feb 2011 14:15:58 +0100 Subject: [PATCH 021/369] MDL-21250 Get rid of capitalized words in titles --- enrol/authorize/lang/en/enrol_authorize.php | 100 +++++++++--------- enrol/ldap/lang/en/enrol_ldap.php | 9 +- enrol/paypal/lang/en/enrol_paypal.php | 2 +- portfolio/boxnet/lang/en/portfolio_boxnet.php | 4 +- portfolio/flickr/lang/en/portfolio_flickr.php | 4 +- portfolio/mahara/lang/en/portfolio_mahara.php | 12 +-- theme/arialist/lang/en/theme_arialist.php | 20 ++-- theme/brick/lang/en/theme_brick.php | 16 +-- theme/fusion/lang/en/theme_fusion.php | 17 ++- theme/nonzero/lang/en/theme_nonzero.php | 4 +- theme/overlay/lang/en/theme_overlay.php | 4 +- theme/sky_high/lang/en/theme_sky_high.php | 4 +- theme/splash/lang/en/theme_splash.php | 4 +- 13 files changed, 99 insertions(+), 101 deletions(-) diff --git a/enrol/authorize/lang/en/enrol_authorize.php b/enrol/authorize/lang/en/enrol_authorize.php index c24a38e606a..6250d2ef7c9 100644 --- a/enrol/authorize/lang/en/enrol_authorize.php +++ b/enrol/authorize/lang/en/enrol_authorize.php @@ -33,25 +33,25 @@ $string['adminacceptccs'] = 'Which credit card types will be accepted?'; $string['adminaccepts'] = 'Select payment methods allowed and their types'; $string['anauthcode'] = 'Obtain authcode'; $string['anauthcodedesc'] = 'If a user\'s credit card cannot be captured on the internet directly, obtain authorization code over the phone from customer\'s bank.'; -$string['adminauthorizeccapture'] = 'Order Review & Scheduled-Capture Settings'; -$string['adminauthorizeemail'] = 'Email Sending Settings'; -$string['adminauthorizesettings'] = 'Authorize.Net Merchant Account Settings'; -$string['adminauthorizewide'] = 'General Settings'; +$string['adminauthorizeccapture'] = 'Order review and scheduled-capture settings'; +$string['adminauthorizeemail'] = 'Email sending settings'; +$string['adminauthorizesettings'] = 'Authorize.Net merchant account settings'; +$string['adminauthorizewide'] = 'General settings'; $string['anavs'] = 'Address Verification System'; -$string['anavsdesc'] = 'Check this if you have activated Address Verification System (AVS) in your authorize.Net merchant account. This demands address fields like street, state, country and zip when user fills out payment form.'; +$string['anavsdesc'] = 'Check this if you have activated Address Verification System (AVS) in your Authorize.Net merchant account. This demands address fields like street, state, country and zip when user fills out payment form.'; $string['adminconfighttps'] = 'Please ensure that you have "turned loginhttps ON" to use this plugin
in Admin >> Variables >> Security >> HTTP security.'; $string['adminconfighttpsgo'] = 'Go to the secure page to configure this plugin.'; $string['admincronsetup'] = 'The cron.php maintenance script has not been run for at least 24 hours.
Cron must be enabled if you want to use scheduled-capture feature.
Enable \'Authorize.Net plugin\' and setup cron properly; or uncheck an_review again.
If you disable scheduled-capture, transactions will be cancelled unless you review them within 30 days.
Check an_review and enter \'0\' to an_capture_day field
if you want to manually accept/deny payments within 30 days.'; $string['anemailexpired'] = 'Expiry notification'; -$string['anemailexpireddesc'] = 'This is useful for \'Manual-Capture\'. Admins are notified the specified amount of days prior to pending orders expiring.'; +$string['anemailexpireddesc'] = 'This is useful for \'manual-capture\'. Admins are notified the specified amount of days prior to pending orders expiring.'; $string['adminemailexpiredsort'] = 'When the number of pending orders expiring are sent to the teachers via email, which one is important?'; $string['adminemailexpiredsortcount'] = 'Order count'; $string['adminemailexpiredsortsum'] = 'Total amount'; $string['anemailexpiredteacher'] = 'Expiry notification - Teacher'; $string['anemailexpiredteacherdesc'] = 'If you have enabled manual-capture (see above) and teachers can manage the payments, they may also notified about pending orders expiring. This will send an email to each course teachers about the count of the pending orders to expire.'; $string['adminemailexpsetting'] = '(0=disable sending email, default=2, max=5)
(Manual capture settings for sending email: cron=enabled, an_review=checked, an_capture_day=0, an_emailexpired=1-5)'; -$string['adminhelpcapturetitle'] = 'Scheduled-Capture Day'; -$string['adminhelpreviewtitle'] = 'Order Review'; +$string['adminhelpcapturetitle'] = 'Scheduled-capture day'; +$string['adminhelpreviewtitle'] = 'Order review'; $string['adminneworder'] = 'Dear Admin, You have received a new pending order: @@ -70,33 +70,33 @@ $string['adminneworder'] = 'Dear Admin, You can also accept/deny the payment to enrol the student immediately following this link: {$a->url}'; -$string['adminnewordersubject'] = '{$a->course}; New Pending Order: {$a->orderid}'; -$string['adminpendingorders'] = 'You have disabled scheduled-capture feature.
Total {$a->count} transactions with the status of \'Authorized/Pending Capture\' are to be cancelled unless you check them.
To accept/deny payments, go to url}\'>Payment Management page.'; +$string['adminnewordersubject'] = '{$a->course}: New pending order: {$a->orderid}'; +$string['adminpendingorders'] = 'You have disabled scheduled-capture feature.
Total {$a->count} transactions with the status of \'Authorized/Pending capture\' are to be cancelled unless you check them.
To accept/deny payments, go to url}\'>Payment Management page.'; $string['anreview'] = 'Review'; $string['anreviewdesc'] = 'Review order before processing the credit card.'; $string['adminteachermanagepay'] = 'Teachers can manage the payments of the course.'; -$string['allpendingorders'] = 'All Pending Orders'; +$string['allpendingorders'] = 'All pending orders'; $string['amount'] = 'Amount'; $string['anlogin'] = 'Authorize.Net: Login name'; $string['anpassword'] = 'Authorize.Net: Password'; $string['anreferer'] = 'Referer'; -$string['anrefererdesc'] = 'Define the URL referer if you have set up this in your authorize.Net merchant account. This will send a line "Referer: URL" embedded in the web request.'; +$string['anrefererdesc'] = 'Define the URL referer if you have set up this in your Authorize.Net merchant account. This will send a line "Referer: URL" embedded in the web request.'; $string['antestmode'] = 'Test mode'; $string['antestmodedesc'] = 'Run transactions in test mode only (no money will be drawn)'; -$string['antrankey'] = 'Authorize.Net: Transaction Key'; -$string['approvedreview'] = 'Approved Review'; +$string['antrankey'] = 'Authorize.Net: Transaction key'; +$string['approvedreview'] = 'Approved review'; $string['authcaptured'] = 'Authorized / Captured'; -$string['authcode'] = 'Authorization Code'; -$string['authorizedpendingcapture'] = 'Authorized / Pending Capture'; -$string['authorizeerror'] = 'Authorize.Net Error: {$a}'; +$string['authcode'] = 'Authorization code'; +$string['authorizedpendingcapture'] = 'Authorized / Pending capture'; +$string['authorizeerror'] = 'Authorize.Net error: {$a}'; $string['avsa'] = 'Address (street) matches, postal code does not'; $string['avsb'] = 'Address information not provided'; -$string['avse'] = 'Address Verification System Error'; -$string['avsg'] = 'Non-U.S. Card Issuing Bank'; +$string['avse'] = 'Address Verification System error'; +$string['avsg'] = 'Non-U.S. card issuing bank'; $string['avsn'] = 'No match on address (street) nor postal code'; $string['avsp'] = 'Address Verification System not applicable'; -$string['avsr'] = 'Retry - System unavailable or timed out'; -$string['avsresult'] = 'AVS Result: {$a}'; +$string['avsr'] = 'Retry - system unavailable or timed out'; +$string['avsresult'] = 'AVS result: {$a}'; $string['avss'] = 'Service not supported by issuer'; $string['avsu'] = 'Address information is unavailable'; $string['avsw'] = '9 digit postal code matches, address (street) does not'; @@ -106,32 +106,32 @@ $string['avsz'] = '5 digit postal code matches, address (street) does not'; $string['canbecredit'] = 'Can be refunded to {$a->upto}'; $string['cancelled'] = 'Cancelled'; $string['capture'] = 'Capture'; -$string['capturedpendingsettle'] = 'Captured / Pending Settlement'; +$string['capturedpendingsettle'] = 'Captured / Pending settlement'; $string['capturedsettled'] = 'Captured / Settled'; $string['captureyes'] = 'The credit card will be captured and the student will be enrolled to the course. Are you sure?'; -$string['ccexpire'] = 'Expiry Date'; +$string['ccexpire'] = 'Expiry date'; $string['ccexpired'] = 'The credit card has expired'; $string['ccinvalid'] = 'Invalid card number'; $string['cclastfour'] = 'CC last four'; -$string['ccno'] = 'Credit Card Number'; -$string['cctype'] = 'Credit Card Type'; -$string['ccvv'] = 'Card Verification'; +$string['ccno'] = 'Credit card number'; +$string['cctype'] = 'Credit card type'; +$string['ccvv'] = 'Card verification'; $string['ccvvhelp'] = 'Look at the back of card (last 3 digits)'; $string['costdefaultdesc'] = 'In course settings, enter -1 to use this default cost to course cost field.'; $string['cutofftime'] = 'Cut-off time'; -$string['cutofftimedesc'] = 'Transaction Cut-Off Time. When the last transaction is picked up for settlement?'; +$string['cutofftimedesc'] = 'Transaction cut-off time. When the last transaction is picked up for settlement?'; $string['dataentered'] = 'Data entered'; $string['delete'] = 'Destroy'; $string['description'] = 'The Authorize.Net module allows you to set up paid courses via payment providers. Two ways to set the course cost (1) a site-wide cost as a default for the whole site or (2) a course setting that you can set for each course individually. The course cost overrides the site cost.'; -$string['echeckabacode'] = 'Bank ABA Number'; -$string['echeckaccnum'] = 'Bank Account Number'; -$string['echeckacctype'] = 'Bank Account Type'; -$string['echeckbankname'] = 'Bank Name'; -$string['echeckbusinesschecking'] = 'Business Checking'; -$string['echeckfirslasttname'] = 'Bank Account Owner'; +$string['echeckabacode'] = 'Bank ABA number'; +$string['echeckaccnum'] = 'Bank account number'; +$string['echeckacctype'] = 'Bank account type'; +$string['echeckbankname'] = 'Bank name'; +$string['echeckbusinesschecking'] = 'Business checking'; +$string['echeckfirslasttname'] = 'Bank account owner'; $string['echeckchecking'] = 'Checking'; $string['echecksavings'] = 'Savings'; -$string['enrolname'] = 'Authorize.Net Payment Gateway'; +$string['enrolname'] = 'Authorize.Net payment gateway'; $string['expired'] = 'Expired'; $string['haveauthcode'] = 'I have already an authorization code'; $string['howmuch'] = 'How much?'; @@ -144,8 +144,8 @@ $string['invalidacctype'] = 'Invalid account type'; $string['isbusinesschecking'] = 'Is business checking?'; $string['logindesc'] = 'This option must be ON.

Please ensure that you have turned loginhttps ON in Admin >> Variables >> Security.

Turning this on will make Moodle use a secure https connection just for the login and payment pages.'; $string['logininfo'] = 'When configuring your Authorize.Net account, the login name is required and you must enter either the transaction key or the password in the appropriate box. We recommend you enter the transaction key due to security precautions.'; -$string['methodcc'] = 'Credit Card'; -$string['methodccdesc'] = 'Select Credit Card and accepted types below'; +$string['methodcc'] = 'Credit card'; +$string['methodccdesc'] = 'Select credit card and accepted types below'; $string['methodecheck'] = 'eCheck (ACH)'; $string['methodecheckdesc'] = 'Select eCheck and accepted types below'; $string['missingaba'] = 'Missing ABA number'; @@ -159,14 +159,14 @@ $string['missingcctype'] = 'Missing card type'; $string['missingcvv'] = 'Missing verification number'; $string['missingzip'] = 'Missing postal code'; $string['mypaymentsonly'] = 'Show my payments only'; -$string['nameoncard'] = 'Name on Card'; +$string['nameoncard'] = 'Name on card'; $string['new'] = 'New'; $string['noreturns'] = 'No returns!'; $string['notsettled'] = 'Not settled'; -$string['orderdetails'] = 'Order Details'; +$string['orderdetails'] = 'Order details'; $string['orderid'] = 'OrderID'; -$string['paymentmanagement'] = 'Payment Management'; -$string['paymentmethod'] = 'Payment Method'; +$string['paymentmanagement'] = 'Payment management'; +$string['paymentmethod'] = 'Payment method'; $string['paymentpending'] = 'Your payment is pending for this course with this order number {$a->orderid}. See url}\'>Order Details.'; $string['pendingecheckemail'] = 'Dear manager, @@ -206,11 +206,11 @@ $string['reason245'] = 'This eCheck type is not allowed when using the payment g $string['reason246'] = 'This eCheck type is not allowed.'; $string['reason27'] = 'The transaction resulted in an AVS mismatch. The address provided does not match billing address of cardholder.'; $string['reason28'] = 'The merchant does not accept this type of credit card.'; -$string['reason30'] = 'The configuration with the processor is invalid. Call Merchant Service Provider.'; +$string['reason30'] = 'The configuration with the processor is invalid. Call merchant service provider.'; $string['reason39'] = 'The supplied currency code is either invalid, not supported, not allowed for this merchant or doesn\'t have an exchange rate.'; -$string['reason43'] = 'The merchant was incorrectly set up at the processor. Call your Merchant Service Provider.'; -$string['reason44'] = 'This transaction has been declined. Card Code filter error!'; -$string['reason45'] = 'This transaction has been declined. Card Code / AVS filter error!'; +$string['reason43'] = 'The merchant was incorrectly set up at the processor. Call your merchant service provider.'; +$string['reason44'] = 'This transaction has been declined. Card code filter error!'; +$string['reason45'] = 'This transaction has been declined. Card code / AVS filter error!'; $string['reason47'] = 'The amount requested for settlement may not be greater than the original amount authorized.'; $string['reason5'] = 'A valid amount is required.'; $string['reason50'] = 'This transaction is awaiting settlement and cannot be refunded.'; @@ -223,23 +223,23 @@ $string['refunded'] = 'Refunded'; $string['returns'] = 'Returns'; $string['ancaptureday'] = 'Capture day'; $string['ancapturedaydesc'] = 'Capture the credit card automatically unless a teacher or administrator review the order within the specified days. CRON MUST BE ENABLED.
(0 days means it will disable scheduled-capture, also means teacher or admin review order manually. Transaction will be cancelled if you disable scheduled-capture or unless you review it within 30 days.)'; -$string['reviewfailed'] = 'Review Failed'; +$string['reviewfailed'] = 'Review failed'; $string['reviewnotify'] = 'Your payment will be reviewed. Expect an email within a few days from your teacher.'; -$string['sendpaymentbutton'] = 'Send Payment'; +$string['sendpaymentbutton'] = 'Send payment'; $string['settled'] = 'Settled'; -$string['settlementdate'] = 'Settlement Date'; +$string['settlementdate'] = 'Settlement date'; $string['shopper'] = 'Shopper'; $string['subvoidyes'] = 'The transaction refunded ({$a->transid}) is going to be cancelled and this will cause crediting {$a->amount} to your account. Are you sure?'; $string['tested'] = 'Tested'; $string['testmode'] = '[TEST MODE]'; $string['testwarning'] = 'Capturing/Voiding/Refunding seems working in test mode, but no record was updated or inserted in database.'; $string['transid'] = 'TransactionID'; -$string['underreview'] = 'Under Review'; +$string['underreview'] = 'Under review'; $string['unenrolstudent'] = 'Unenrol student?'; $string['uploadcsv'] = 'Upload a CSV file'; $string['usingccmethod'] = 'Enrol using Credit Card'; $string['usingecheckmethod'] = 'Enrol using eCheck'; -$string['verifyaccount'] = 'Verify your authorize.Net merchant account'; +$string['verifyaccount'] = 'Verify your Authorize.Net merchant account'; $string['verifyaccountresult'] = 'Verification result: {$a}'; $string['void'] = 'Void'; $string['voidyes'] = 'The transaction will be cancelled. Are you sure?'; @@ -253,7 +253,7 @@ You may view your payment details or edit your profile: {$a->paymenturl} {$a->profileurl}'; $string['youcantdo'] = 'You can\'t do this action: {$a->action}'; -$string['zipcode'] = 'Zip Code'; +$string['zipcode'] = 'Zip code'; $string['cost'] = 'Cost'; $string['currency'] = 'Currency'; $string['enrolperiod'] = 'Enrolment period'; diff --git a/enrol/ldap/lang/en/enrol_ldap.php b/enrol/ldap/lang/en/enrol_ldap.php index 057a3de8925..aa92c84c6c4 100644 --- a/enrol/ldap/lang/en/enrol_ldap.php +++ b/enrol/ldap/lang/en/enrol_ldap.php @@ -66,13 +66,13 @@ $string['extremovedsuspend'] = "Disabled enrolment for user '{\$a->user_usernam $string['extremovedsuspendnoroles'] = "Disabled enrolment and removed roles for user '{\$a->user_username}' in course '{\$a->course_shortname}' (id {\$a->course_id})"; $string['extremovedunenrol'] = "Unenrol user '{\$a->user_username}' from course '{\$a->course_shortname}' (id {\$a->course_id})"; $string['failed'] = "Failed!\n"; -$string['general_options'] = 'General Options'; +$string['general_options'] = 'General options'; $string['group_memberofattribute'] = 'Name of the attribute that specifies which groups a given user or group belongs to (e.g., memberOf, groupMembership, etc.)'; $string['group_memberofattribute_key'] = '\'Member of\' attribute'; $string['host_url'] = 'Specify LDAP host in URL-form like \'ldap://ldap.myorg.com/\' or \'ldaps://ldap.myorg.com/\''; $string['host_url_key'] = 'Host URL'; $string['idnumber_attribute'] = 'If the group membership contains distinguised names, specify the same attribute you have used for the user \'ID Number\' mapping in the LDAP authentication settings'; -$string['idnumber_attribute_key'] = 'ID Number attribute'; +$string['idnumber_attribute_key'] = 'ID number attribute'; $string['ldap_encoding'] = 'Specify encoding used by LDAP server. Most probably utf-8, MS AD v2 uses default platform encoding such as cp1252, cp1250, etc.'; $string['ldap_encoding_key'] = 'LDAP encoding'; $string['ldap:manage'] = 'Manage LDAP enrol instances'; @@ -95,7 +95,7 @@ $string['pluginnotenabled'] = 'Plugin not enabled!'; $string['role_mapping'] = '

For each rol that you want to assign from LDAP, you need to specify the list of contexts where the role courses\'s groups are located. Separate different contexts with \';\'.

You also need to specify the attribute your LDAP server uses to hold the members of a group. Usually \'member\' or \'memberUid\'

'; $string['role_mapping_key'] = 'Map roles from LDAP '; $string['roles'] = 'Role mapping'; -$string['server_settings'] = 'LDAP Server Settings'; +$string['server_settings'] = 'LDAP server settings'; $string['synccourserole'] = "== Synching course '{\$a->idnumber}' for role '{\$a->role_shortname}'\n"; $string['template'] = 'Optional: auto-created courses can copy their settings from a template course'; $string['template_key'] = 'Template'; @@ -104,7 +104,7 @@ $string['unassignroleid'] = "Unassigning role id '{\$a->role_id}' to user id '{ $string['unassignrolefailed'] = "Failed to unassign role '{\$a->role_shortname}' to user '{\$a->user_username}' from course '{\$a->course_shortname}' (id {\$a->course_id})\n"; $string['updatelocal'] = 'Update local data'; $string['user_attribute'] = 'If the group membership contains distinguised names, specify the attribute used to name/search users. If you are using LDAP authentication, this value should match the attribute specified in the \'ID Number\' mapping in the LDAP authentication plugin'; -$string['user_attribute_key'] = 'ID Number attribute'; +$string['user_attribute_key'] = 'ID number attribute'; $string['user_contexts'] = 'If the group membership contains distinguised names, specify the list of contexts where users are located. Separate different contexts with \';\'. For example: \'ou=users,o=org; ou=others,o=org\''; $string['user_contexts_key'] = 'Contexts'; $string['user_search_sub'] = 'If the group membership contains distinguised names, specify if the search for users is done in subcontexts too'; @@ -114,4 +114,3 @@ $string['user_type'] = 'If the group membership contains distinguished names, sp $string['user_type_key'] = 'User type'; $string['version'] = 'The version of the LDAP protocol your server is using'; $string['version_key'] = 'Version'; - diff --git a/enrol/paypal/lang/en/enrol_paypal.php b/enrol/paypal/lang/en/enrol_paypal.php index aa3c0cc6e21..9f8030aa9f4 100644 --- a/enrol/paypal/lang/en/enrol_paypal.php +++ b/enrol/paypal/lang/en/enrol_paypal.php @@ -27,7 +27,7 @@ $string['assignrole'] = 'Assign role'; $string['businessemail'] = 'PayPal business email'; $string['businessemail_desc'] = 'The email address of your business PayPal account'; -$string['cost'] = 'Enrol Cost'; +$string['cost'] = 'Enrol cost'; $string['costerror'] = 'The enrolment cost is not numeric'; $string['costorkey'] = 'Please choose one of the following methods of enrolment.'; $string['currency'] = 'Currency'; diff --git a/portfolio/boxnet/lang/en/portfolio_boxnet.php b/portfolio/boxnet/lang/en/portfolio_boxnet.php index d6439c4d391..ed67b3bd9bb 100644 --- a/portfolio/boxnet/lang/en/portfolio_boxnet.php +++ b/portfolio/boxnet/lang/en/portfolio_boxnet.php @@ -24,8 +24,8 @@ */ $string['apikey'] = 'API key'; -$string['err_noapikey'] = 'No API Key'; -$string['err_noapikey_help'] = 'There is no API Key configured for this plugin. You can get one of these from http://enabled.box.net'; +$string['err_noapikey'] = 'No API key'; +$string['err_noapikey_help'] = 'There is no API key configured for this plugin. You can get one of these from OpenBox development page.'; $string['existingfolder'] = 'Existing folder to put file(s) into'; $string['folderclash'] = 'The folder you asked to create already exists!'; $string['foldercreatefailed'] = 'Failed to create your target folder on box.net'; diff --git a/portfolio/flickr/lang/en/portfolio_flickr.php b/portfolio/flickr/lang/en/portfolio_flickr.php index 6b08527a2e8..50dccac8249 100644 --- a/portfolio/flickr/lang/en/portfolio_flickr.php +++ b/portfolio/flickr/lang/en/portfolio_flickr.php @@ -25,8 +25,8 @@ $string['apikey'] = 'API key'; $string['contenttype'] = 'Content types'; -$string['err_noapikey'] = 'No API Key'; -$string['err_noapikey_help'] = 'There is no API Key configured for this plugin. You can get one of these from http://flickr.com/services/api/keys/apply'; +$string['err_noapikey'] = 'No API key'; +$string['err_noapikey_help'] = 'There is no API key configured for this plugin. You can get one of these from Flickr services page.'; $string['hidefrompublicsearches'] = 'Hide these images from public searches?'; $string['isfamily'] = 'Visible to family'; $string['isfriend'] = 'Visible to friends'; diff --git a/portfolio/mahara/lang/en/portfolio_mahara.php b/portfolio/mahara/lang/en/portfolio_mahara.php index bc5883dd2ec..fdaf5ad66f5 100644 --- a/portfolio/mahara/lang/en/portfolio_mahara.php +++ b/portfolio/mahara/lang/en/portfolio_mahara.php @@ -23,18 +23,18 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['enableleap2a'] = 'Enable Leap2a Portfolio support (requires Mahara 1.3)'; +$string['enableleap2a'] = 'Enable Leap2A portfolio support (requires Mahara 1.3 or higher)'; $string['err_invalidhost'] = 'Invalid MNet host'; $string['err_invalidhost_help'] = 'This plugin is misconfigured to point to an invalid (or deleted) MNet host. This plugin relies on Moodle Networking peers with SSO IDP published, SSO_SP subscribed, and portfolio subscribed and published.'; -$string['err_networkingoff'] = 'Moodle Networking is off'; -$string['err_networkingoff_help'] = 'Moodle Networking is off entirely. Please enable it before trying to configure this pugin. Any instances of this plugin have been set to not visible until this is fixed - you will need to set them to visible again manully. They cannot be used until this happens'; +$string['err_networkingoff'] = 'MNet is off'; +$string['err_networkingoff_help'] = 'MNet is off entirely. Please enable it before trying to configure this pugin. Any instances of this plugin have been set to not visible until this is fixed - you will need to set them to visible again manully. They cannot be used until this happens'; $string['err_nomnetauth'] = 'The MNet authentication plugin is disabled'; $string['err_nomnetauth_help'] = 'The MNet authentication plugin is disabled, but is required for this service'; -$string['err_nomnethosts'] = 'Relies on Moodle Networking'; -$string['err_nomnethosts_help'] = 'This plugin relies on Moodle Networking peers with SSO IDP published, SSO SP subscribed, portfolio services published and subscribed as well as the MNet authentication plugin. Any instances of this plugin have been hidden until these conditions are met. They will then manually need setting to visible again.'; +$string['err_nomnethosts'] = 'Relies on MNet'; +$string['err_nomnethosts_help'] = 'This plugin relies on MNet peers with SSO IDP published, SSO SP subscribed, portfolio services published and subscribed as well as the MNet authentication plugin. Any instances of this plugin have been hidden until these conditions are met. They will then manually need setting to visible again.'; $string['failedtojump'] = 'Failed to start communication with remote server'; $string['failedtoping'] = 'Failed to start communication with remote server: {$a}'; -$string['mnethost'] = 'MNet Host'; +$string['mnethost'] = 'MNet host'; $string['mnet_nofile'] = 'Could not find file in transfer object - weird error'; $string['mnet_nofilecontents'] = 'Found file in transfer object, but could not get contents - weird error: {$a}'; $string['mnet_noid'] = 'Could not find the matching transfer record for this token'; diff --git a/theme/arialist/lang/en/theme_arialist.php b/theme/arialist/lang/en/theme_arialist.php index d54ad2aded3..4353beb4a23 100644 --- a/theme/arialist/lang/en/theme_arialist.php +++ b/theme/arialist/lang/en/theme_arialist.php @@ -29,40 +29,40 @@ $string['region-side-pre'] = 'Left'; $string['choosereadme'] = '
- +

Arialist

- +

Theme Discussion Forum:

http://moodle.org/mod/forum/view.php?id=46

- +

Theme Credits

http://docs.moodle.org/en/Theme_credits

- +

Theme Documentation:

http://docs.moodle.org/en/Themes

- +

Report a bug:

http://tracker.moodle.org

- +
- +

About

Arialist is a very clean and simple two-column, fluid-width theme for Moodle 2.0.

- +

Tweaks

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it, then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

Credits

-

This theme was coded and is maintained by Patrick Malley of NewSchool Learning. He can be contacted by email at contact@newschoollearning.com.

+

This theme was coded and is maintained by Patrick Malley of NewSchool Learning. He can be contacted by email at contact@newschoollearning.com.

License

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License.

'; -$string['linkcolor'] = 'Link Color'; +$string['linkcolor'] = 'Link color'; $string['linkcolordesc'] = 'This sets the link color for the theme.'; $string['configtitle'] = 'Arialist settings'; $string['customcss'] = 'Custom CSS'; diff --git a/theme/brick/lang/en/theme_brick.php b/theme/brick/lang/en/theme_brick.php index 1aec341a1ad..1b73d2ba255 100644 --- a/theme/brick/lang/en/theme_brick.php +++ b/theme/brick/lang/en/theme_brick.php @@ -40,30 +40,30 @@ $string['choosereadme'] = '
- +

About

Brick is a two-column, fluid-width theme for Moodle 2.0. You can change the theme color scheme via the theme settings page.

- +

Tweaks

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you wish to modify aspects of this theme beyond the settings offered, we advise creating a new theme that uses this theme, Base, and Canvas all as parents. This will ensure updates to any of those themes in the core will find their way into your new theme.

- +

Credits

This theme was coded and is maintained by John Stabinger of NewSchool Learning. He can be contacted by email at contact@newschoollearning.com.

- +

License

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License.

'; -$string['configtitle'] = 'Brick Settings'; +$string['configtitle'] = 'Brick settings'; $string['logo'] = 'logo'; $string['logodesc'] = 'Change the logo of this theme by entering the URL to a new one (i.e., http://www.somesite/animage.png). As a reference, the default logo is 265px wide by 60px high. A transparent PNG will work best.'; diff --git a/theme/fusion/lang/en/theme_fusion.php b/theme/fusion/lang/en/theme_fusion.php index 185520a7a64..cbc4f653e53 100644 --- a/theme/fusion/lang/en/theme_fusion.php +++ b/theme/fusion/lang/en/theme_fusion.php @@ -29,28 +29,28 @@ $string['region-side-pre'] = 'Left'; $string['choosereadme'] = '
- +

Fusion

- +

Theme Discussion Forum:

http://moodle.org/mod/forum/view.php?id=46

- +

Theme Credits

http://docs.moodle.org/en/Theme_credits

- +

Theme Documentation:

http://docs.moodle.org/en/Themes

Report a bug:

http://tracker.moodle.org

- +

About

Fusion is a two-column, fluid-width theme coded for Moodle 2.0. It makes use of custom menus that appear above the site title on every page. It also includes a basic settings page allowing you to change link color, add a tagline above the site name on the front page, and add text to the footer.

- +

Parents

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you wish to modify aspects of this theme beyond the settings offered, we advise creating a new theme using this theme, Base and Canvas all as parents so updates to any of those themes in the core will find their way into your new theme.

- +

Credits

This design was originally created by Digital Nature (hello@digitalnature.ro) before being ported to Moodle by Patrick Malley (patrick@newschoollearning.com).

License

@@ -58,7 +58,7 @@ $string['choosereadme'] = '
'; -$string['linkcolor'] = 'Link Color'; +$string['linkcolor'] = 'Link color'; $string['linkcolordesc'] = 'This sets the link color for the theme.'; $string['configtitle'] = 'Fusion settings'; $string['customcss'] = 'Custom CSS'; @@ -67,4 +67,3 @@ $string['tagline'] = 'Tagline'; $string['taglinedesc'] = 'A short tagline to be displayed under the site name on the front page.
'; $string['footertext'] = 'Footertext'; $string['footertextdesc'] = 'Set a footnote or footer text.'; - diff --git a/theme/nonzero/lang/en/theme_nonzero.php b/theme/nonzero/lang/en/theme_nonzero.php index 9c8d002395c..32cb24dc378 100644 --- a/theme/nonzero/lang/en/theme_nonzero.php +++ b/theme/nonzero/lang/en/theme_nonzero.php @@ -30,10 +30,10 @@ $string['choosereadme'] = '
< // Config -$string['configtitle'] = 'Nonzero Settings'; +$string['configtitle'] = 'Nonzero settings'; $string['customcss'] = 'Custom CSS'; $string['customcssdesc'] = 'Any CSS you enter here will be added to every page allowing your to easily customise this theme.'; $string['regionprewidth'] = 'Left column width'; $string['regionprewidthdesc'] = 'This sets the width of the block region that forms the left column. This column is displayed in the middle of the page while using blog layout'; $string['regionpostwidth'] = 'Right column width'; -$string['regionpostwidthdesc'] = 'This sets the width of the block region that forms the right column.'; \ No newline at end of file +$string['regionpostwidthdesc'] = 'This sets the width of the block region that forms the right column.'; diff --git a/theme/overlay/lang/en/theme_overlay.php b/theme/overlay/lang/en/theme_overlay.php index d25913f1426..20e8e66d408 100644 --- a/theme/overlay/lang/en/theme_overlay.php +++ b/theme/overlay/lang/en/theme_overlay.php @@ -30,7 +30,7 @@ $string['choosereadme'] = '
< // Config -$string['linkcolor'] = 'Link Color'; +$string['linkcolor'] = 'Link color'; $string['linkcolordesc'] = 'This sets the link color for the theme.'; $string['configtitle'] = 'Overlay settings'; $string['customcss'] = 'Custom CSS'; @@ -38,4 +38,4 @@ $string['customcssdesc'] = 'Any CSS you enter here will be added to every page a $string['headercolor'] = 'Headercolor'; $string['headercolordesc'] = 'Header background color.'; $string['footertext'] = 'Footertext'; -$string['footertextdesc'] = 'Set a footnote or footer text.'; \ No newline at end of file +$string['footertextdesc'] = 'Set a footnote or footer text.'; diff --git a/theme/sky_high/lang/en/theme_sky_high.php b/theme/sky_high/lang/en/theme_sky_high.php index 8ee53222870..5cdaa767c93 100644 --- a/theme/sky_high/lang/en/theme_sky_high.php +++ b/theme/sky_high/lang/en/theme_sky_high.php @@ -27,7 +27,7 @@ $string['pluginname'] = 'Sky High'; $string['region-side-post'] = 'Right'; $string['region-side-pre'] = 'Left'; $string['choosereadme'] = '

About

Serenity is a fluid-width, three-column theme for Moodle 2.0.

Tweaks

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

Credits

This theme was designed by Julian Ridden (julian@moodle.com.au). It was coded and is maintained by John Stabinger of NewSchool Learning (contact@newschoollearning.com).

License

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License.

'; -$string['configtitle'] = 'Sky High Settings'; +$string['configtitle'] = 'Sky High settings'; $string['customcss'] = 'Custom CSS'; $string['customcssdesc'] = 'Any CSS you enter here will be added to every page allowing your to easily customise this theme.'; $string['footnote'] = 'Footnote'; @@ -37,4 +37,4 @@ $string['taglinedesc'] = 'The content from this textarea will be displayed under $string['logo'] = 'Logo'; $string['logodesc'] = 'Enter the URL to an image to use as the logo for this site. Should be http://www.yoursite.com/path/to/logo.png. The logo should be 50px high.'; $string['regionwidth'] = 'Column width'; -$string['regionwidthdesc'] = 'This sets the width of the two block regions that form the left and right columns.'; \ No newline at end of file +$string['regionwidthdesc'] = 'This sets the width of the two block regions that form the left and right columns.'; diff --git a/theme/splash/lang/en/theme_splash.php b/theme/splash/lang/en/theme_splash.php index d64172f73ce..36c02ecc8e0 100644 --- a/theme/splash/lang/en/theme_splash.php +++ b/theme/splash/lang/en/theme_splash.php @@ -25,13 +25,13 @@ $string['choosereadme'] = '

About

Splash is a fluid-width, three-column theme for Moodle 2.0.

Tweaks

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

Credits

This theme was coded and is maintained by Caroline Kennedy of Synergy Learning. She can be contacted by email at caroline.kennedy@synergy-learningw.com.

License

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License.

'; -$string['configtitle'] = 'Splash Theme Settings'; +$string['configtitle'] = 'Splash Theme settings'; $string['customcss'] = 'Custom CSS'; $string['customcssdesc'] = 'Any CSS you enter here will be added to every page allowing your to easily customise this theme.'; $string['defaulttagline'] = 'Virtual learning center'; $string['footnote'] = 'Footnote'; $string['footnotedesc'] = 'The content from this textarea will be displayed in the footer of every page. E.g: your copyright info.'; -$string['hide_tagline'] = 'Hide Tagline'; +$string['hide_tagline'] = 'Hide tagline'; $string['hide_taglinedesc'] = 'Check this box to hide the tagline under the logo.'; $string['loginhere'] = 'Login here!'; $string['logo'] = 'Logo'; From 1dade8b185111df4b39693bc45d8d49e928e7d7a Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Tue, 22 Feb 2011 22:19:16 +0100 Subject: [PATCH 022/369] MDL-26546 Workshop: fixed embedded images in Number of errors grading form Because of this typo, embedded images were not loaded when the assessment form was re-edited. Thanks Helen Foster for spotting this. --- mod/workshop/form/numerrors/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/workshop/form/numerrors/lib.php b/mod/workshop/form/numerrors/lib.php index 078dd61243a..f43d17592f1 100644 --- a/mod/workshop/form/numerrors/lib.php +++ b/mod/workshop/form/numerrors/lib.php @@ -124,7 +124,7 @@ class workshop_numerrors_strategy implements workshop_strategy { for ($i = 0; $i < $nodimensions; $i++) { // prepare all editor elements $fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts, - $PAGE->context, 'workshopform_numerror', 'description', $fields->{'dimensionid__idx_'.$i}); + $PAGE->context, 'workshopform_numerrors', 'description', $fields->{'dimensionid__idx_'.$i}); } $customdata = array(); From b2bce32ff05c9c841036f42d43eefbb1e5eff609 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 20 Feb 2011 10:25:21 +0800 Subject: [PATCH 023/369] message MDL-26404 trimming course short to prevent long names messing up the UI --- message/lib.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/message/lib.php b/message/lib.php index df8535ca82d..e31a4d87230 100644 --- a/message/lib.php +++ b/message/lib.php @@ -68,6 +68,7 @@ define('SHOW_ACTION_LINKS_IN_CONTACT_LIST', true); define('MESSAGE_SEARCH_MAX_RESULTS', 200); define('MESSAGE_CONTACTS_PER_PAGE',10); +define('MESSAGE_MAX_COURSE_NAME_LENGTH', 30); if (!isset($CFG->message_contacts_refresh)) { // Refresh the contacts list every 60 seconds $CFG->message_contacts_refresh = 60; @@ -463,7 +464,13 @@ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $ foreach($courses as $course) { if (has_capability('moodle/course:viewparticipants', $coursecontexts[$course->id])) { - $courses_options[VIEW_COURSE.$course->id] = $course->shortname; + //Not using short_text() as we want the end of the course name. Not the beginning. + $textlib = textlib_get_instance(); + if ($textlib->strlen($course->shortname) > MESSAGE_MAX_COURSE_NAME_LENGTH) { + $courses_options[VIEW_COURSE.$course->id] = '...'.$textlib->substr($course->shortname, -MESSAGE_MAX_COURSE_NAME_LENGTH); + } else { + $courses_options[VIEW_COURSE.$course->id] = $course->shortname; + } } } From 92c4354ff9d76bcad165e4c6294bf32b1d29271b Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Feb 2011 11:42:37 +0000 Subject: [PATCH 024/369] MDL-26576 avoid notices one quizzes with no overall feedback. --- mod/quiz/locallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index 06914cdfdad..b66c4260b70 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -463,7 +463,7 @@ function quiz_feedback_for_grade($grade, $quiz, $context, $cm=null) { $feedback = $DB->get_record_select('quiz_feedback', "quizid = ? AND mingrade <= ? AND $grade < maxgrade", array($quiz->id, $grade)); if (empty($feedback->feedbacktext)) { - $feedback->feedbacktext = ''; + return ''; } // Clean the text, ready for display. From 2b37004c28a62f92aa48ab4d47504c9f409eb43e Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Wed, 23 Feb 2011 20:03:30 +0100 Subject: [PATCH 025/369] weekly release --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index db0c13366ec..0b05d606446 100644 --- a/version.php +++ b/version.php @@ -32,4 +32,4 @@ defined('MOODLE_INTERNAL') || die(); $version = 2011022100.00; // YYYYMMDD = date of the last version bump // XX = daily increments -$release = '2.0.2 (Build: 20110221)'; // Human-friendly version name +$release = '2.0.2+ (Build: 20110223)'; // Human-friendly version name From 303c04f7d0e0dacf01c161b1c070d28efcb24913 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 21 Feb 2011 02:01:03 +0100 Subject: [PATCH 026/369] MDL-26442 restore - missing new in qtype match exception --- .../match/backup/moodle2/restore_qtype_match_plugin.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/match/backup/moodle2/restore_qtype_match_plugin.class.php b/question/type/match/backup/moodle2/restore_qtype_match_plugin.class.php index 21e287016f3..eaf35397396 100644 --- a/question/type/match/backup/moodle2/restore_qtype_match_plugin.class.php +++ b/question/type/match/backup/moodle2/restore_qtype_match_plugin.class.php @@ -115,7 +115,7 @@ class restore_qtype_match_plugin extends restore_qtype_plugin { $this->set_mapping('question_match_sub', $oldid, $sub->id); // Something went really wrong, cannot map subquestion for one match question } else { - throw restore_step_exception('error_question_match_sub_missing_in_db', $data); + throw new restore_step_exception('error_question_match_sub_missing_in_db', $data); } } } From b9825e8e298567298745ac19236e8fb561d15934 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Thu, 24 Feb 2011 10:56:30 +0800 Subject: [PATCH 027/369] REPOSITORY MDL-23951 alfresco repository plugin supports returning external links --- repository/alfresco/lib.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/repository/alfresco/lib.php b/repository/alfresco/lib.php index 55cc4002671..02ac7174a9e 100755 --- a/repository/alfresco/lib.php +++ b/repository/alfresco/lib.php @@ -203,6 +203,18 @@ class repository_alfresco extends repository { return array('path'=>$path, 'url'=>$url); } + /** + * Return file URL + * + * @param string $url the url of file + * @return string + */ + public function get_link($uuid) { + $node = $this->user_session->getNode($this->store, $uuid); + $url = $this->get_url($node); + return $url; + } + public function print_search() { $str = parent::print_search(); $str .= '
'; echo ''; echo ''; $table = new html_table(); -$table->head = array (get_string('fullname'), +$table->head = array (get_string('fullnameuser'), get_string('content', 'notes'), get_string('publishstate', 'notes') . $OUTPUT->help_icon('publishstate', 'notes'), ); From a8ccca532536e0407e2c5d04e50b07b234686f67 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 28 Feb 2011 10:35:21 +0100 Subject: [PATCH 033/369] MDL-26404 messages - move textlib instance out from loop --- message/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message/lib.php b/message/lib.php index e31a4d87230..c2cb7af8bc3 100644 --- a/message/lib.php +++ b/message/lib.php @@ -448,6 +448,7 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ */ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $countunreadtotal, $countblocked, $strunreadmessages) { $options = array(); + $textlib = textlib_get_instance(); // going to use textlib services if ($countunreadtotal>0) { //if there are unread messages $options[VIEW_UNREAD_MESSAGES] = $strunreadmessages; @@ -465,7 +466,6 @@ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $ foreach($courses as $course) { if (has_capability('moodle/course:viewparticipants', $coursecontexts[$course->id])) { //Not using short_text() as we want the end of the course name. Not the beginning. - $textlib = textlib_get_instance(); if ($textlib->strlen($course->shortname) > MESSAGE_MAX_COURSE_NAME_LENGTH) { $courses_options[VIEW_COURSE.$course->id] = '...'.$textlib->substr($course->shortname, -MESSAGE_MAX_COURSE_NAME_LENGTH); } else { From 8ef8ec689eeb467360a7ae443817fd5e98ec2215 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 28 Feb 2011 12:28:44 +0100 Subject: [PATCH 034/369] MDL-26047 nimble theme - changing 2 "fusion" ocurrences --- theme/nimble/config.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/theme/nimble/config.php b/theme/nimble/config.php index a48466af429..1f9f380f5f0 100644 --- a/theme/nimble/config.php +++ b/theme/nimble/config.php @@ -16,7 +16,7 @@ // along with Moodle. If not, see . /** - * Configuration for Moodle's fusion theme. + * Configuration for Moodle's nimble theme. * * DO NOT MODIFY THIS THEME! * COPY IT FIRST, THEN RENAME THE COPY AND MODIFY IT INSTEAD. @@ -183,7 +183,7 @@ $THEME->layouts = array( // specific page. /////////////////////////////////////////////////////////////// -// $THEME->csspostprocess = 'fusion_process_css'; +// $THEME->csspostprocess = 'nimble_process_css'; //////////////////////////////////////////////////// // Allows the user to provide the name of a function @@ -265,4 +265,4 @@ $THEME->rarrow = '⟩'; // Controls the colours for the MP3 player //////////////////////////////////////////////////// -$THEME->csspostprocess = 'nimble_process_css'; \ No newline at end of file +$THEME->csspostprocess = 'nimble_process_css'; From 2a921ee985f8040991e7c1282c333c50c6179b74 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 1 Mar 2011 12:11:31 +0100 Subject: [PATCH 035/369] MDL-26047 fix string letter case and whitespace --- theme/nimble/lang/en/theme_nimble.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/theme/nimble/lang/en/theme_nimble.php b/theme/nimble/lang/en/theme_nimble.php index 643a084a882..ce9e34f9e93 100644 --- a/theme/nimble/lang/en/theme_nimble.php +++ b/theme/nimble/lang/en/theme_nimble.php @@ -29,28 +29,28 @@ $string['region-side-pre'] = 'Left'; $string['choosereadme'] = '
- +

Nimble

- +

Theme Discussion Forum:

http://moodle.org/mod/forum/view.php?id=46

- +

Theme Credits

http://docs.moodle.org/en/Theme_credits

- +

Theme Documentation:

http://docs.moodle.org/en/Themes

Report a bug:

http://tracker.moodle.org

- +

About

Nimble is a two-column, fluid-width theme coded for Moodle 2.0. It makes use of custom menus that appear above the site title on every page. It also includes a basic settings page allowing you to change link color, add a tagline next the site name on the front page, and add text to the footer.

- +

Parents

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you wish to modify aspects of this theme beyond the settings offered, we advise creating a new theme using this theme, Base and Canvas all as parents so updates to any of those themes in the core will find their way into your new theme.

- +

Credits

This design was created for Moodle by Patrick Malley (patrick@newschoollearning.com) with help from John Stabinger (john@newschoollearning.com).

License

@@ -61,15 +61,15 @@ $string['choosereadme'] = ' $string['tagline'] = 'Tagline'; $string['taglinedesc'] = 'Set a tagline to appear under the site name on the front page.'; -$string['footerline'] = 'footerline'; +$string['footerline'] = 'Footerline'; $string['footerlinedesc'] = 'Add some text (copyright info, etc.) to the footer.'; -$string['backgroundcolor'] = 'Header Background'; +$string['backgroundcolor'] = 'Header background'; $string['backgroundcolordesc'] = 'Change the background color of the header.'; -$string['linkcolor'] = 'Link Color'; +$string['linkcolor'] = 'Link color'; $string['linkcolordesc'] = 'Set the color of links in the theme, use html hex code.'; -$string['linkhover'] = 'Menu Hover Color'; +$string['linkhover'] = 'Menu hover color'; $string['linkhoverdesc'] = 'Set the color of the menu on hover in the theme, use html hex code.'; From 431ac39634774bb8157d8df1e953c847067771a3 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 1 Mar 2011 12:26:49 +0100 Subject: [PATCH 036/369] MDL-26623 fix file permissions The permissions are now going to be verified as part of the weekly release process. --- admin/generator.php | 0 admin/langimport.php | 0 admin/process_email.php | 0 admin/report/spamcleaner/index.php | 0 admin/report/unittest/coveragefile.php | 0 admin/roles/allow.php | 0 admin/roles/assign.php | 0 admin/roles/check.php | 0 admin/roles/define.php | 0 admin/roles/manage.php | 0 admin/roles/managetabs.php | 0 admin/roles/override.php | 0 admin/uploaduser.php | 0 admin/user/user_bulk.php | 0 admin/user/user_bulk_confirm.php | 0 admin/user/user_bulk_delete.php | 0 admin/user/user_bulk_display.php | 0 admin/user/user_bulk_download.php | 0 admin/user/user_bulk_message.php | 0 auth/ldap/cli/sync_users.php | 0 auth/shibboleth/config.html | 0 backup/backupfilesedit.php | 0 backup/cc/cc2moodle.php | 0 backup/cc/entities.class.php | 0 backup/cc/entity.forum.class.php | 0 backup/cc/entity.label.class.php | 0 backup/cc/entity.quiz.class.php | 0 backup/cc/entity.resource.class.php | 0 backup/cc/includes/constants.php | 0 backup/cc/restore_cc.php | 0 backup/cc/schemas/cclibxml2validator.xsd | 0 backup/cc/schemas/config.xml | 0 .../cc/schemas/domainProfile_0/imsccauth_v1p0.xsd | 0 .../imsccauth_v1p0_constraintsDocument.scmt | 0 .../domainProfile_0/imsccauth_v1p0_localised.xsd | 0 backup/cc/schemas/domainProfile_1/anyElement.xsd | 0 .../domainProfile_1/anyElement_localised.xsd | 0 .../schemas/domainProfile_1/common/anyElement.xsd | 0 .../cc/schemas/domainProfile_1/common/dataTypes.xsd | 0 .../schemas/domainProfile_1/common/elementNames.xsd | 0 .../schemas/domainProfile_1/common/elementTypes.xsd | 0 .../schemas/domainProfile_1/common/rootElement.xsd | 0 .../schemas/domainProfile_1/common/vocabTypes.xsd | 0 .../schemas/domainProfile_1/common/vocabValues.xsd | 0 .../schemas/domainProfile_1/dataTypes_localised.xsd | 0 .../domainProfile_1/elementNames_localised.xsd | 0 .../domainProfile_1/elementTypes_localised.xsd | 0 backup/cc/schemas/domainProfile_1/extend/custom.xsd | 0 .../schemas/domainProfile_1/imscc_m_definition.xsd | 0 backup/cc/schemas/domainProfile_1/lomLoose.xsd | 0 .../lomLoose_constraintsDocument.scmt | 0 .../schemas/domainProfile_1/lomLoose_localised.xsd | 0 backup/cc/schemas/domainProfile_1/loose.xsd | 0 .../domainProfile_1/rootElement_localised.xsd | 0 backup/cc/schemas/domainProfile_1/unique/loose.xsd | 0 backup/cc/schemas/domainProfile_1/vocab/loose.xsd | 0 .../domainProfile_1/vocabTypes_localised.xsd | 0 .../domainProfile_1/vocabValues_localised.xsd | 0 backup/cc/schemas/domainProfile_2/anyElement.xsd | 0 .../domainProfile_2/anyElement_localised.xsd | 0 .../schemas/domainProfile_2/common/anyElement.xsd | 0 .../cc/schemas/domainProfile_2/common/dataTypes.xsd | 0 .../schemas/domainProfile_2/common/elementNames.xsd | 0 .../schemas/domainProfile_2/common/elementTypes.xsd | 0 .../schemas/domainProfile_2/common/rootElement.xsd | 0 .../schemas/domainProfile_2/common/vocabTypes.xsd | 0 .../schemas/domainProfile_2/common/vocabValues.xsd | 0 .../schemas/domainProfile_2/dataTypes_localised.xsd | 0 .../domainProfile_2/elementNames_localised.xsd | 0 .../domainProfile_2/elementTypes_localised.xsd | 0 backup/cc/schemas/domainProfile_2/extend/custom.xsd | 0 .../schemas/domainProfile_2/imscc_mR_definition.xsd | 0 backup/cc/schemas/domainProfile_2/lomLoose.xsd | 0 .../lomLoose_constraintsDocument.scmt | 0 .../schemas/domainProfile_2/lomLoose_localised.xsd | 0 backup/cc/schemas/domainProfile_2/loose.xsd | 0 .../domainProfile_2/rootElement_localised.xsd | 0 backup/cc/schemas/domainProfile_2/unique/loose.xsd | 0 backup/cc/schemas/domainProfile_2/vocab/loose.xsd | 0 .../domainProfile_2/vocabTypes_localised.xsd | 0 .../domainProfile_2/vocabValues_localised.xsd | 0 .../schemas/domainProfile_3/imscp_extensionv1p2.xsd | 0 .../imscp_extensionv1p2_constraintsDocument.scmt | 0 .../imscp_extensionv1p2_localised.xsd | 0 .../cc/schemas/domainProfile_4/ims_qtiasiv1p2.xsd | 0 .../domainProfile_4/ims_qtiasiv1p2_def_copy.xsd | 0 .../domainProfile_4/ims_qtiasiv1p2_localised.xsd | 0 .../schemas/domainProfile_4/imscc_q_definition.xsd | 0 backup/cc/schemas/domainProfile_4/xml.xsd | 0 backup/cc/schemas/domainProfile_5/imswl_v1p0.xsd | 0 .../domainProfile_5/imswl_v1p0_localised.xsd | 0 backup/cc/schemas/domainProfile_6/imsdt_v1p0.xsd | 0 .../domainProfile_6/imsdt_v1p0_localised.xsd | 0 backup/cc/schemas/imscc_c1p2maeV0p15_definition.xsd | 0 backup/cc/schemas/imscp_v1p2.xsd | 0 .../cc/schemas/imscp_v1p2_constraintsDocument.scmt | 0 backup/cc/schemas/imscp_v1p2_localised.xsd | 0 backup/cc/sheets/base.xml | 0 backup/cc/sheets/course_blocks_block.xml | 0 backup/cc/sheets/course_header.xml | 0 backup/cc/sheets/course_modules_mod_forum.xml | 0 backup/cc/sheets/course_modules_mod_label.xml | 0 backup/cc/sheets/course_modules_mod_quiz.xml | 0 .../cc/sheets/course_modules_mod_quiz_feedback.xml | 0 .../course_modules_mod_quiz_question_instance.xml | 0 backup/cc/sheets/course_modules_mod_resource.xml | 0 backup/cc/sheets/course_question_categories.xml | 0 ...course_question_categories_question_category.xml | 0 ...estion_categories_question_category_question.xml | 0 ...categories_question_category_question_answer.xml | 0 ..._categories_question_category_question_eesay.xml | 0 ...s_question_category_question_multiple_choice.xml | 0 ...ories_question_category_question_shortanswer.xml | 0 ...gories_question_category_question_true_false.xml | 0 backup/cc/sheets/course_sections_section.xml | 0 .../cc/sheets/course_sections_section_mods_mod.xml | 0 backup/cc/sheets/info_details_mod.xml | 0 backup/cc/sheets/info_details_mod_instance.xml | 0 backup/restorefile.php | 0 backup/restorefile_form.php | 0 .../util/xml/parser/simpletest/fixtures/test4.xml | 0 blocks/blog_menu/block_blog_menu.php | 0 blocks/html/block_html.php | 0 blocks/mentees/block_mentees.php | 0 blocks/mentees/lang/en/block_mentees.php | 0 blocks/private_files/block_private_files.php | 0 blocks/rss_client/lang/en/block_rss_client.php | 0 blocks/section_links/config_instance.html | 0 blocks/section_links/settings.php | 0 blog/edit.php | 0 blog/index.php | 0 blog/preferences.php | 0 blog/rsslib.php | 0 course/format/scorm/config.php | 0 course/format/social/config.php | 0 course/format/topics/config.php | 0 course/format/weeks/config.php | 0 course/reset.php | 0 course/simpletest/testcourselib.php | 0 enrol/authorize/enrol_form.php | 0 enrol/authorize/version.php | 0 files/externallib.php | 0 files/filebrowser_ajax.php | 0 filter/algebra/AlgParser.pm | 0 filter/algebra/algebra2tex.pl | 0 filter/mediaplugin/mp3player.swf | Bin filter/tex/mimetex.exe | Bin grade/edit/outcome/course_form.html | 0 grade/edit/tree/functions.js | 0 grade/edit/tree/grade_form.php | 0 grade/edit/tree/lib.php | 0 grade/export/grade_export_form.php | 0 grade/export/lib.php | 0 grade/export/ods/export.php | 0 grade/export/ods/grade_export_ods.php | 0 grade/export/ods/index.php | 0 grade/export/txt/export.php | 0 grade/export/txt/grade_export_txt.php | 0 grade/export/txt/index.php | 0 grade/export/txt/version.php | 0 grade/export/xls/export.php | 0 grade/export/xls/grade_export_xls.php | 0 grade/export/xls/index.php | 0 grade/export/xml/export.php | 0 grade/export/xml/grade_export_xml.php | 0 grade/export/xml/index.php | 0 grade/import/xml/index.php | 0 install/welcome.html | 0 lang/en/blog.php | 0 lang/en/error.php | 0 lang/en/install.php | 0 lang/en/notes.php | 0 lib/accesslib.php | 0 lib/ajax/section_classes.js | 0 lib/alfresco/Service/Association.php | 0 lib/alfresco/Service/BaseObject.php | 0 lib/alfresco/Service/ChildAssociation.php | 0 lib/alfresco/Service/ContentData.php | 0 lib/alfresco/Service/Functions.php | 0 lib/alfresco/Service/Logger/Logger.php | 0 lib/alfresco/Service/Logger/LoggerConfig.php | 0 lib/alfresco/Service/NamespaceMap.php | 0 lib/alfresco/Service/Node.php | 0 lib/alfresco/Service/Repository.php | 0 lib/alfresco/Service/Session.php | 0 lib/alfresco/Service/SpacesStore.php | 0 lib/alfresco/Service/Store.php | 0 lib/alfresco/Service/Version.php | 0 lib/alfresco/Service/VersionHistory.php | 0 .../Service/WebService/AlfrescoWebService.php | 0 .../Service/WebService/WebServiceFactory.php | 0 lib/boxlib.php | 0 lib/ddl/simpletest/testddl.php | 0 lib/dml/simpletest/testdml.php | 0 .../3.3.9.2/plugins/moodlemedia/css/media.css | 0 .../3.3.9.2/plugins/moodlemedia/editor_plugin.js | 0 .../plugins/moodlemedia/editor_plugin_src.js | 0 .../3.3.9.2/plugins/moodlemedia/js/media.js | 0 .../3.3.9.2/plugins/moodlemedia/moodlemedia.htm | 0 lib/eventslib.php | 0 lib/flickrlib.php | 0 lib/form/selectwithlink.php | 0 lib/form/url.php | 0 lib/grade/simpletest/testgradecategory.php | 0 lib/grade/simpletest/testgradegrades.php | 0 lib/grade/simpletest/testgradeitem.php | 0 lib/grade/simpletest/testgradescale.php | 0 .../AutoFormat.RemoveSpansWithoutAttributes.txt | 0 lib/htmlpurifier/HTMLPurifier/PropertyList.php | 0 .../HTMLPurifier/PropertyListIterator.php | 0 lib/jabber/XMPP/Exception.php | 0 lib/markdown.php | 0 lib/odbc.php | 0 lib/pear/HTTP/WebDAV/Server.php | 0 lib/pear/OLE.php | 0 lib/pear/OLE/PPS.php | 0 lib/pear/OLE/PPS/File.php | 0 lib/pear/OLE/PPS/Root.php | 0 lib/pear/PHP/runsniffer | 0 lib/phpmailer/language/phpmailer.lang-cz.php | 0 lib/phpmailer/language/phpmailer.lang-de.php | 0 lib/phpmailer/language/phpmailer.lang-es.php | 0 lib/phpmailer/language/phpmailer.lang-fr.php | 0 lib/phpmailer/language/phpmailer.lang-it.php | 0 lib/phpmailer/language/phpmailer.lang-nl.php | 0 lib/phpmailer/language/phpmailer.lang-no.php | 0 lib/phpmailer/language/phpmailer.lang-se.php | 0 lib/phpmailer/language/phpmailer.lang-tr.php | 0 lib/profilerlib.php | 0 lib/simpletest/testeventslib.php | 0 lib/simpletest/testmathslib.php | 0 lib/simpletest/testportfoliolib.php | 0 lib/tcpdf/README.TXT | 0 lib/tcpdf/config/tcpdf_config.php | 0 lib/tcpdf/fonts/README.TXT | 0 lib/tcpdf/fonts/freemono.php | 0 lib/tcpdf/fonts/freemonob.php | 0 lib/tcpdf/fonts/freemonobi.php | 0 lib/tcpdf/fonts/freemonoi.php | 0 lib/tcpdf/fonts/freesans.php | 0 lib/tcpdf/fonts/freesansb.php | 0 lib/tcpdf/fonts/freesansbi.php | 0 lib/tcpdf/fonts/freesansi.php | 0 lib/tcpdf/fonts/freeserif.php | 0 lib/tcpdf/fonts/freeserifb.php | 0 lib/tcpdf/fonts/freeserifbi.php | 0 lib/tcpdf/fonts/freeserifi.php | 0 lib/tcpdf/tcpdf.php | 0 lib/validateurlsyntax.php | 0 lib/zend/Zend/Amf/Adobe/Auth.php | 0 lib/zend/Zend/Amf/Adobe/DbInspector.php | 0 lib/zend/Zend/Amf/Adobe/Introspector.php | 0 lib/zend/Zend/Amf/Auth/Abstract.php | 0 lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php | 0 lib/zend/Zend/Amf/Parse/Resource/Stream.php | 0 .../Zend/Amf/Value/Messaging/ArrayCollection.php | 0 lib/zend/Zend/Gdata/Books.php | 0 lib/zend/Zend/Gdata/Books/VolumeQuery.php | 0 lib/zend/Zend/Gdata/Docs.php | 0 lib/zend/Zend/Gdata/Docs/DocumentListEntry.php | 0 lib/zend/Zend/Gdata/Docs/DocumentListFeed.php | 0 lib/zend/Zend/Gdata/Docs/Query.php | 0 lib/zend/Zend/Gdata/DublinCore.php | 0 lib/zend/Zend/Gdata/Exif.php | 0 lib/zend/Zend/Gdata/Exif/Entry.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Distance.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Exposure.php | 0 lib/zend/Zend/Gdata/Exif/Extension/FStop.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Flash.php | 0 lib/zend/Zend/Gdata/Exif/Extension/FocalLength.php | 0 .../Zend/Gdata/Exif/Extension/ImageUniqueId.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Iso.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Make.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Model.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Tags.php | 0 lib/zend/Zend/Gdata/Exif/Extension/Time.php | 0 lib/zend/Zend/Gdata/Exif/Feed.php | 0 lib/zend/Zend/Gdata/Geo.php | 0 lib/zend/Zend/Gdata/Geo/Entry.php | 0 lib/zend/Zend/Gdata/Geo/Extension/GeoRssWhere.php | 0 lib/zend/Zend/Gdata/Geo/Extension/GmlPoint.php | 0 lib/zend/Zend/Gdata/Geo/Extension/GmlPos.php | 0 lib/zend/Zend/Gdata/Geo/Feed.php | 0 lib/zend/Zend/Gdata/Health.php | 0 lib/zend/Zend/Gdata/Health/Extension/Ccr.php | 0 lib/zend/Zend/Gdata/Health/ProfileEntry.php | 0 lib/zend/Zend/Gdata/Health/ProfileFeed.php | 0 lib/zend/Zend/Gdata/Health/ProfileListEntry.php | 0 lib/zend/Zend/Gdata/Health/ProfileListFeed.php | 0 lib/zend/Zend/Gdata/Health/Query.php | 0 lib/zend/Zend/Gdata/Media.php | 0 lib/zend/Zend/Gdata/Media/Entry.php | 0 .../Zend/Gdata/Media/Extension/MediaCategory.php | 0 .../Zend/Gdata/Media/Extension/MediaContent.php | 0 .../Zend/Gdata/Media/Extension/MediaCopyright.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaCredit.php | 0 .../Zend/Gdata/Media/Extension/MediaDescription.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaGroup.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaHash.php | 0 .../Zend/Gdata/Media/Extension/MediaKeywords.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaPlayer.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaRating.php | 0 .../Zend/Gdata/Media/Extension/MediaRestriction.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaText.php | 0 .../Zend/Gdata/Media/Extension/MediaThumbnail.php | 0 lib/zend/Zend/Gdata/Media/Extension/MediaTitle.php | 0 lib/zend/Zend/Gdata/Media/Feed.php | 0 lib/zend/Zend/Gdata/Photos.php | 0 lib/zend/Zend/Gdata/Photos/AlbumEntry.php | 0 lib/zend/Zend/Gdata/Photos/AlbumFeed.php | 0 lib/zend/Zend/Gdata/Photos/AlbumQuery.php | 0 lib/zend/Zend/Gdata/Photos/CommentEntry.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Access.php | 0 lib/zend/Zend/Gdata/Photos/Extension/AlbumId.php | 0 lib/zend/Zend/Gdata/Photos/Extension/BytesUsed.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Checksum.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Client.php | 0 .../Zend/Gdata/Photos/Extension/CommentCount.php | 0 .../Gdata/Photos/Extension/CommentingEnabled.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Height.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Id.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Location.php | 0 .../Gdata/Photos/Extension/MaxPhotosPerAlbum.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Name.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Nickname.php | 0 lib/zend/Zend/Gdata/Photos/Extension/NumPhotos.php | 0 .../Gdata/Photos/Extension/NumPhotosRemaining.php | 0 lib/zend/Zend/Gdata/Photos/Extension/PhotoId.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Position.php | 0 .../Zend/Gdata/Photos/Extension/QuotaCurrent.php | 0 lib/zend/Zend/Gdata/Photos/Extension/QuotaLimit.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Rotation.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Size.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Thumbnail.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Timestamp.php | 0 lib/zend/Zend/Gdata/Photos/Extension/User.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Version.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Weight.php | 0 lib/zend/Zend/Gdata/Photos/Extension/Width.php | 0 lib/zend/Zend/Gdata/Photos/PhotoEntry.php | 0 lib/zend/Zend/Gdata/Photos/PhotoFeed.php | 0 lib/zend/Zend/Gdata/Photos/PhotoQuery.php | 0 lib/zend/Zend/Gdata/Photos/TagEntry.php | 0 lib/zend/Zend/Gdata/Photos/UserEntry.php | 0 lib/zend/Zend/Gdata/Photos/UserFeed.php | 0 lib/zend/Zend/Gdata/Photos/UserQuery.php | 0 lib/zend/Zend/Gdata/YouTube/Extension/Control.php | 0 lib/zend/Zend/Gdata/YouTube/Extension/CountHint.php | 0 lib/zend/Zend/Gdata/YouTube/Extension/Link.php | 0 .../Zend/Gdata/YouTube/Extension/MediaContent.php | 0 .../Zend/Gdata/YouTube/Extension/MediaGroup.php | 0 .../Zend/Gdata/YouTube/Extension/MediaRating.php | 0 lib/zend/Zend/Gdata/YouTube/Extension/Private.php | 0 lib/zend/Zend/Gdata/YouTube/Extension/Token.php | 0 lib/zend/Zend/Gdata/YouTube/MediaEntry.php | 0 lib/zend/Zend/Http/Client/Adapter/Stream.php | 0 lib/zend/Zend/Http/Response/Stream.php | 0 lib/zend/Zend/Service/Amazon/Exception.php | 0 lib/zend/Zend/Service/Amazon/S3.php | 0 lib/zend/Zend/Service/Amazon/S3/Exception.php | 0 lib/zend/Zend/Service/Amazon/S3/Stream.php | 0 lib/zend/Zend/Service/Twitter.php | 0 lib/zend/Zend/Service/Twitter/Exception.php | 0 message/output/email/version.php | 0 message/output/jabber/version.php | 0 message/output/popup/version.php | 0 mod/assignment/pix/icon.gif | Bin mod/chat/beep.wav | Bin mod/chat/chatd.php | 0 mod/chat/gui_ajax/theme/bubble/bubbles.png | Bin mod/chat/gui_ajax/theme/bubble/chat.css | 0 mod/chat/gui_ajax/theme/bubble/config.php | 0 mod/chat/gui_ajax/theme/bubble/horizontal.png | Bin mod/chat/gui_ajax/theme/bubble/input.png | Bin mod/chat/gui_ajax/theme/bubble/vertical.png | Bin mod/chat/gui_ajax/theme/compact/chat.css | 0 mod/chat/gui_ajax/theme/compact/config.php | 0 mod/chat/pix/icon.gif | Bin mod/data/css.php | 0 mod/data/edit.php | 0 mod/data/field.php | 0 mod/data/field/checkbox/field.class.php | 0 mod/data/field/checkbox/mod.html | 0 mod/data/field/date/field.class.php | 0 mod/data/field/date/mod.html | 0 mod/data/field/file/field.class.php | 0 mod/data/field/file/mod.html | 0 mod/data/field/latlong/field.class.php | 0 mod/data/field/latlong/mod.html | 0 mod/data/field/menu/field.class.php | 0 mod/data/field/menu/mod.html | 0 mod/data/field/multimenu/field.class.php | 0 mod/data/field/multimenu/mod.html | 0 mod/data/field/number/field.class.php | 0 mod/data/field/number/mod.html | 0 mod/data/field/picture/field.class.php | 0 mod/data/field/picture/mod.html | 0 mod/data/field/radiobutton/field.class.php | 0 mod/data/field/radiobutton/mod.html | 0 mod/data/field/text/field.class.php | 0 mod/data/field/text/mod.html | 0 mod/data/field/textarea/field.class.php | 0 mod/data/field/textarea/mod.html | 0 mod/data/field/url/field.class.php | 0 mod/data/field/url/mod.html | 0 mod/data/import.php | 0 mod/data/index.php | 0 mod/data/lang/en/data.php | 0 mod/data/lib.php | 0 mod/data/pix/field/checkbox.gif | Bin mod/data/pix/field/date.gif | Bin mod/data/pix/field/file.gif | Bin mod/data/pix/field/latlong.gif | Bin mod/data/pix/field/menu.gif | Bin mod/data/pix/field/multimenu.gif | Bin mod/data/pix/field/number.gif | Bin mod/data/pix/field/picture.gif | Bin mod/data/pix/field/radiobutton.gif | Bin mod/data/pix/field/text.gif | Bin mod/data/pix/field/textarea.gif | Bin mod/data/pix/field/url.gif | Bin mod/data/pix/icon.gif | Bin mod/data/tabs.php | 0 mod/data/templates.php | 0 mod/data/view.php | 0 mod/forum/pix/icon.gif | Bin mod/glossary/db/install.xml | 0 mod/glossary/formats/TEMPLATE/TEMPLATE_format.php | 0 mod/label/pix/icon.gif | Bin mod/lesson/pix/icon.gif | Bin mod/quiz/db/install.xml | 0 mod/quiz/pix/icon.gif | Bin mod/scorm/aicc.php | 0 mod/scorm/datamodel.php | 0 mod/scorm/datamodels/sequencinglib.php | 0 mod/scorm/index.php | 0 mod/scorm/lib.php | 0 mod/scorm/loadSCO.php | 0 mod/scorm/locallib.php | 0 mod/scorm/pix/browsed.gif | Bin mod/scorm/pix/completed.gif | Bin mod/scorm/pix/failed.gif | Bin mod/scorm/pix/icon.gif | Bin mod/scorm/pix/incomplete.gif | Bin mod/scorm/pix/minus.gif | Bin mod/scorm/pix/notattempted.gif | Bin mod/scorm/pix/passed.gif | Bin mod/scorm/pix/plus.gif | Bin mod/scorm/pix/popdown.gif | Bin mod/scorm/pix/popup.gif | Bin mod/scorm/pix/spacer.gif | Bin mod/scorm/player.php | 0 mod/scorm/report.php | 0 mod/scorm/view.php | 0 mod/survey/pix/icon.gif | Bin mod/workshop/pix/userplan/task-info.gif | Bin pix/a/l_breadcrumb.gif | Bin pix/adv.gif | Bin pix/b.gif | Bin pix/f/audio.gif | Bin pix/f/folder.gif | Bin pix/f/odt.gif | Bin pix/f/parent.gif | Bin pix/f/powerpoint.gif | Bin pix/f/video.gif | Bin pix/f/web.gif | Bin pix/f/xml.gif | Bin pix/f/zip.gif | Bin pix/g/f1.png | Bin pix/g/f2.png | Bin pix/help.gif | Bin pix/i/admin.gif | Bin pix/i/agg_sum.gif | Bin pix/i/all.gif | Bin pix/i/backup.gif | Bin pix/i/course.gif | Bin pix/i/db.gif | Bin pix/i/edit.gif | Bin pix/i/email.gif | Bin pix/i/feedback.gif | Bin pix/i/files.gif | Bin pix/i/grades.gif | Bin pix/i/group.gif | Bin pix/i/guest.gif | Bin pix/i/hide.gif | Bin pix/i/info.gif | Bin pix/i/key.gif | Bin pix/i/lock.gif | Bin pix/i/marked.gif | Bin pix/i/marker.gif | Bin pix/i/new.gif | Bin pix/i/news.gif | Bin pix/i/one.gif | Bin pix/i/reload.gif | Bin pix/i/report.gif | Bin pix/i/restore.gif | Bin pix/i/return.gif | Bin pix/i/roles.gif | Bin pix/i/scales.gif | Bin pix/i/search.gif | Bin pix/i/settings.gif | Bin pix/i/show.gif | Bin pix/i/stats.gif | Bin pix/i/switch.gif | Bin pix/i/unlock.gif | Bin pix/i/user.gif | Bin pix/i/users.gif | Bin pix/m/USD.gif | Bin pix/madewithmoodle.gif | Bin pix/moodlelogo-med-white.gif | Bin pix/moodlelogo-med.gif | Bin pix/moodlelogo.gif | Bin pix/movehere.gif | Bin pix/s/angry.gif | Bin pix/s/approve.gif | Bin pix/s/biggrin.gif | Bin pix/s/blackeye.gif | Bin pix/s/blush.gif | Bin pix/s/clown.gif | Bin pix/s/cool.gif | Bin pix/s/dead.gif | Bin pix/s/egg.gif | Bin pix/s/evil.gif | Bin pix/s/heart.gif | Bin pix/s/kiss.gif | Bin pix/s/martin.gif | Bin pix/s/mixed.gif | Bin pix/s/no.gif | Bin pix/s/sad.gif | Bin pix/s/shy.gif | Bin pix/s/sleepy.gif | Bin pix/s/smiley.gif | Bin pix/s/surprise.gif | Bin pix/s/thoughtful.gif | Bin pix/s/tongueout.gif | Bin pix/s/wideeyes.gif | Bin pix/s/wink.gif | Bin pix/s/yes.gif | Bin pix/spacer.gif | Bin pix/t/backup.gif | Bin pix/t/email.gif | Bin pix/t/emailno.gif | Bin pix/t/go.gif | Bin pix/t/groupn.gif | Bin pix/t/groups.gif | Bin pix/t/groupv.gif | Bin pix/t/left.gif | Bin pix/t/lock.gif | Bin pix/t/log.gif | Bin pix/t/message.gif | Bin pix/t/move.gif | Bin pix/t/preview.gif | Bin pix/t/restore.gif | Bin pix/t/right.gif | Bin pix/t/stop.gif | Bin pix/t/unlock.gif | Bin pix/t/user.gif | Bin pix/t/usernot.gif | Bin pix/u/f1.png | Bin pix/u/f2.png | Bin pix/webding.png | Bin .../simpletest/testportfolioplugindownload.php | 0 portfolio/flickr/lib.php | 0 portfolio/flickr/version.php | 0 question/format/examview/format.php | 0 question/format/gift/format.php | 0 question/format/learnwise/format.php | 0 question/format/qti_two/templates/choice.tpl | 0 .../format/qti_two/templates/choiceMultiple.tpl | 0 question/format/qti_two/templates/composite.tpl | 0 question/format/qti_two/templates/extendedText.tpl | 0 .../qti_two/templates/extendedText_simpleEssay.tpl | 0 question/format/qti_two/templates/imsmanifest.tpl | 0 .../format/qti_two/templates/mmchoiceMultiple.tpl | 0 .../format/qti_two/templates/notimplemented.tpl | 0 question/format/qti_two/templates/numerical.tpl | 0 question/format/qti_two/templates/textEntry.tpl | 0 question/format/xhtml/format.php | 0 question/format/xml/format.php | 0 question/type/calculated/pix/icon.gif | Bin repository/alfresco/lib.php | 0 repository/boxnet/lib.php | 0 repository/boxnet/version.php | 0 repository/coursefiles/db/access.php | 0 .../coursefiles/lang/en/repository_coursefiles.php | 0 repository/coursefiles/lib.php | 0 repository/coursefiles/pix/icon.png | Bin repository/coursefiles/version.php | 0 repository/draftfiles_ajax.php | 0 repository/draftfiles_manager.php | 0 repository/dropbox/db/access.php | 0 repository/dropbox/lang/en/repository_dropbox.php | 0 repository/dropbox/version.php | 0 repository/filepicker.php | 0 repository/flickr/lib.php | 0 repository/flickr_public/image.php | 0 repository/local/lib.php | 0 repository/merlot/db/access.php | 0 repository/merlot/lib.php | 0 repository/merlot/pix/icon.png | Bin repository/merlot/version.php | 0 repository/recent/lib.php | 0 repository/repository_ajax.php | 0 repository/repository_callback.php | 0 repository/upload/lib.php | 0 repository/upload/pix/icon.png | Bin repository/url/pix/icon.png | Bin repository/user/db/install.php | 0 repository/user/lang/en/repository_user.php | 0 repository/user/lib.php | 0 repository/user/pix/icon.png | Bin repository/user/version.php | 0 search/Zend/Exception.php | 0 theme/anomaly/pix/tab/right_last.gif | Bin theme/anomaly/pix/tab/rtlbg.gif | Bin theme/anomaly/pix/tab/tabrow1.gif | Bin theme/boxxie/pix/tab/right_last.gif | Bin theme/boxxie/pix/tab/rtlbg.gif | Bin theme/boxxie/pix/tab/tabrow1.gif | Bin theme/fusion/pix/header-bg.jpg | Bin theme/fusion/pix/header-center.jpg | Bin theme/fusion/pix/main-bg.gif | Bin theme/fusion/pix/side-bg.png | Bin theme/fusion/pix/side-start.png | Bin theme/nonzero/lib.php | 0 theme/nonzero/settings.php | 0 theme/standard/pix/tab/right_last.gif | Bin theme/standard/pix/tab/rtlbg.gif | Bin theme/standard/pix/tab/tabrow1.gif | Bin user/default/f1.jpg | Bin user/default/f2.jpg | Bin user/emailupdate.php | 0 user/filters/date.php | 0 633 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 admin/generator.php mode change 100755 => 100644 admin/langimport.php mode change 100755 => 100644 admin/process_email.php mode change 100755 => 100644 admin/report/spamcleaner/index.php mode change 100755 => 100644 admin/report/unittest/coveragefile.php mode change 100755 => 100644 admin/roles/allow.php mode change 100755 => 100644 admin/roles/assign.php mode change 100755 => 100644 admin/roles/check.php mode change 100755 => 100644 admin/roles/define.php mode change 100755 => 100644 admin/roles/manage.php mode change 100755 => 100644 admin/roles/managetabs.php mode change 100755 => 100644 admin/roles/override.php mode change 100755 => 100644 admin/uploaduser.php mode change 100755 => 100644 admin/user/user_bulk.php mode change 100755 => 100644 admin/user/user_bulk_confirm.php mode change 100755 => 100644 admin/user/user_bulk_delete.php mode change 100755 => 100644 admin/user/user_bulk_display.php mode change 100755 => 100644 admin/user/user_bulk_download.php mode change 100755 => 100644 admin/user/user_bulk_message.php mode change 100755 => 100644 auth/ldap/cli/sync_users.php mode change 100755 => 100644 auth/shibboleth/config.html mode change 100755 => 100644 backup/backupfilesedit.php mode change 100755 => 100644 backup/cc/cc2moodle.php mode change 100755 => 100644 backup/cc/entities.class.php mode change 100755 => 100644 backup/cc/entity.forum.class.php mode change 100755 => 100644 backup/cc/entity.label.class.php mode change 100755 => 100644 backup/cc/entity.quiz.class.php mode change 100755 => 100644 backup/cc/entity.resource.class.php mode change 100755 => 100644 backup/cc/includes/constants.php mode change 100755 => 100644 backup/cc/restore_cc.php mode change 100755 => 100644 backup/cc/schemas/cclibxml2validator.xsd mode change 100755 => 100644 backup/cc/schemas/config.xml mode change 100755 => 100644 backup/cc/schemas/domainProfile_0/imsccauth_v1p0.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_0/imsccauth_v1p0_constraintsDocument.scmt mode change 100755 => 100644 backup/cc/schemas/domainProfile_0/imsccauth_v1p0_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/anyElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/anyElement_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/anyElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/dataTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/elementNames.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/elementTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/rootElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/vocabTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/common/vocabValues.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/dataTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/elementNames_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/elementTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/extend/custom.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/imscc_m_definition.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/lomLoose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/lomLoose_constraintsDocument.scmt mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/lomLoose_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/rootElement_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/unique/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/vocab/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/vocabTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_1/vocabValues_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/anyElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/anyElement_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/anyElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/dataTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/elementNames.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/elementTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/rootElement.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/vocabTypes.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/common/vocabValues.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/dataTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/elementNames_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/elementTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/extend/custom.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/imscc_mR_definition.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/lomLoose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/lomLoose_constraintsDocument.scmt mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/lomLoose_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/rootElement_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/unique/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/vocab/loose.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/vocabTypes_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_2/vocabValues_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_3/imscp_extensionv1p2.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_constraintsDocument.scmt mode change 100755 => 100644 backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_def_copy.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_4/imscc_q_definition.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_4/xml.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_5/imswl_v1p0.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_5/imswl_v1p0_localised.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_6/imsdt_v1p0.xsd mode change 100755 => 100644 backup/cc/schemas/domainProfile_6/imsdt_v1p0_localised.xsd mode change 100755 => 100644 backup/cc/schemas/imscc_c1p2maeV0p15_definition.xsd mode change 100755 => 100644 backup/cc/schemas/imscp_v1p2.xsd mode change 100755 => 100644 backup/cc/schemas/imscp_v1p2_constraintsDocument.scmt mode change 100755 => 100644 backup/cc/schemas/imscp_v1p2_localised.xsd mode change 100755 => 100644 backup/cc/sheets/base.xml mode change 100755 => 100644 backup/cc/sheets/course_blocks_block.xml mode change 100755 => 100644 backup/cc/sheets/course_header.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_forum.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_label.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_quiz.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_quiz_feedback.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_quiz_question_instance.xml mode change 100755 => 100644 backup/cc/sheets/course_modules_mod_resource.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question_answer.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question_eesay.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question_multiple_choice.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question_shortanswer.xml mode change 100755 => 100644 backup/cc/sheets/course_question_categories_question_category_question_true_false.xml mode change 100755 => 100644 backup/cc/sheets/course_sections_section.xml mode change 100755 => 100644 backup/cc/sheets/course_sections_section_mods_mod.xml mode change 100755 => 100644 backup/cc/sheets/info_details_mod.xml mode change 100755 => 100644 backup/cc/sheets/info_details_mod_instance.xml mode change 100755 => 100644 backup/restorefile.php mode change 100755 => 100644 backup/restorefile_form.php mode change 100755 => 100644 backup/util/xml/parser/simpletest/fixtures/test4.xml mode change 100755 => 100644 blocks/blog_menu/block_blog_menu.php mode change 100755 => 100644 blocks/html/block_html.php mode change 100755 => 100644 blocks/mentees/block_mentees.php mode change 100755 => 100644 blocks/mentees/lang/en/block_mentees.php mode change 100755 => 100644 blocks/private_files/block_private_files.php mode change 100755 => 100644 blocks/rss_client/lang/en/block_rss_client.php mode change 100755 => 100644 blocks/section_links/config_instance.html mode change 100755 => 100644 blocks/section_links/settings.php mode change 100755 => 100644 blog/edit.php mode change 100755 => 100644 blog/index.php mode change 100755 => 100644 blog/preferences.php mode change 100755 => 100644 blog/rsslib.php mode change 100755 => 100644 course/format/scorm/config.php mode change 100755 => 100644 course/format/social/config.php mode change 100755 => 100644 course/format/topics/config.php mode change 100755 => 100644 course/format/weeks/config.php mode change 100755 => 100644 course/reset.php mode change 100755 => 100644 course/simpletest/testcourselib.php mode change 100755 => 100644 enrol/authorize/enrol_form.php mode change 100755 => 100644 enrol/authorize/version.php mode change 100755 => 100644 files/externallib.php mode change 100755 => 100644 files/filebrowser_ajax.php mode change 100755 => 100644 filter/algebra/AlgParser.pm mode change 100755 => 100644 filter/algebra/algebra2tex.pl mode change 100755 => 100644 filter/mediaplugin/mp3player.swf mode change 100755 => 100644 filter/tex/mimetex.exe mode change 100755 => 100644 grade/edit/outcome/course_form.html mode change 100755 => 100644 grade/edit/tree/functions.js mode change 100755 => 100644 grade/edit/tree/grade_form.php mode change 100755 => 100644 grade/edit/tree/lib.php mode change 100755 => 100644 grade/export/grade_export_form.php mode change 100755 => 100644 grade/export/lib.php mode change 100755 => 100644 grade/export/ods/export.php mode change 100755 => 100644 grade/export/ods/grade_export_ods.php mode change 100755 => 100644 grade/export/ods/index.php mode change 100755 => 100644 grade/export/txt/export.php mode change 100755 => 100644 grade/export/txt/grade_export_txt.php mode change 100755 => 100644 grade/export/txt/index.php mode change 100755 => 100644 grade/export/txt/version.php mode change 100755 => 100644 grade/export/xls/export.php mode change 100755 => 100644 grade/export/xls/grade_export_xls.php mode change 100755 => 100644 grade/export/xls/index.php mode change 100755 => 100644 grade/export/xml/export.php mode change 100755 => 100644 grade/export/xml/grade_export_xml.php mode change 100755 => 100644 grade/export/xml/index.php mode change 100755 => 100644 grade/import/xml/index.php mode change 100755 => 100644 install/welcome.html mode change 100755 => 100644 lang/en/blog.php mode change 100755 => 100644 lang/en/error.php mode change 100755 => 100644 lang/en/install.php mode change 100755 => 100644 lang/en/notes.php mode change 100755 => 100644 lib/accesslib.php mode change 100755 => 100644 lib/ajax/section_classes.js mode change 100755 => 100644 lib/alfresco/Service/Association.php mode change 100755 => 100644 lib/alfresco/Service/BaseObject.php mode change 100755 => 100644 lib/alfresco/Service/ChildAssociation.php mode change 100755 => 100644 lib/alfresco/Service/ContentData.php mode change 100755 => 100644 lib/alfresco/Service/Functions.php mode change 100755 => 100644 lib/alfresco/Service/Logger/Logger.php mode change 100755 => 100644 lib/alfresco/Service/Logger/LoggerConfig.php mode change 100755 => 100644 lib/alfresco/Service/NamespaceMap.php mode change 100755 => 100644 lib/alfresco/Service/Node.php mode change 100755 => 100644 lib/alfresco/Service/Repository.php mode change 100755 => 100644 lib/alfresco/Service/Session.php mode change 100755 => 100644 lib/alfresco/Service/SpacesStore.php mode change 100755 => 100644 lib/alfresco/Service/Store.php mode change 100755 => 100644 lib/alfresco/Service/Version.php mode change 100755 => 100644 lib/alfresco/Service/VersionHistory.php mode change 100755 => 100644 lib/alfresco/Service/WebService/AlfrescoWebService.php mode change 100755 => 100644 lib/alfresco/Service/WebService/WebServiceFactory.php mode change 100755 => 100644 lib/boxlib.php mode change 100755 => 100644 lib/ddl/simpletest/testddl.php mode change 100755 => 100644 lib/dml/simpletest/testdml.php mode change 100755 => 100644 lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/css/media.css mode change 100755 => 100644 lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin.js mode change 100755 => 100644 lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin_src.js mode change 100755 => 100644 lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/js/media.js mode change 100755 => 100644 lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/moodlemedia.htm mode change 100755 => 100644 lib/eventslib.php mode change 100755 => 100644 lib/flickrlib.php mode change 100755 => 100644 lib/form/selectwithlink.php mode change 100755 => 100644 lib/form/url.php mode change 100755 => 100644 lib/grade/simpletest/testgradecategory.php mode change 100755 => 100644 lib/grade/simpletest/testgradegrades.php mode change 100755 => 100644 lib/grade/simpletest/testgradeitem.php mode change 100755 => 100644 lib/grade/simpletest/testgradescale.php mode change 100755 => 100644 lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt mode change 100755 => 100644 lib/htmlpurifier/HTMLPurifier/PropertyList.php mode change 100755 => 100644 lib/htmlpurifier/HTMLPurifier/PropertyListIterator.php mode change 100755 => 100644 lib/jabber/XMPP/Exception.php mode change 100755 => 100644 lib/markdown.php mode change 100755 => 100644 lib/odbc.php mode change 100755 => 100644 lib/pear/HTTP/WebDAV/Server.php mode change 100755 => 100644 lib/pear/OLE.php mode change 100755 => 100644 lib/pear/OLE/PPS.php mode change 100755 => 100644 lib/pear/OLE/PPS/File.php mode change 100755 => 100644 lib/pear/OLE/PPS/Root.php mode change 100755 => 100644 lib/pear/PHP/runsniffer mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-cz.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-de.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-es.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-fr.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-it.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-nl.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-no.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-se.php mode change 100755 => 100644 lib/phpmailer/language/phpmailer.lang-tr.php mode change 100755 => 100644 lib/profilerlib.php mode change 100755 => 100644 lib/simpletest/testeventslib.php mode change 100755 => 100644 lib/simpletest/testmathslib.php mode change 100755 => 100644 lib/simpletest/testportfoliolib.php mode change 100755 => 100644 lib/tcpdf/README.TXT mode change 100755 => 100644 lib/tcpdf/config/tcpdf_config.php mode change 100755 => 100644 lib/tcpdf/fonts/README.TXT mode change 100755 => 100644 lib/tcpdf/fonts/freemono.php mode change 100755 => 100644 lib/tcpdf/fonts/freemonob.php mode change 100755 => 100644 lib/tcpdf/fonts/freemonobi.php mode change 100755 => 100644 lib/tcpdf/fonts/freemonoi.php mode change 100755 => 100644 lib/tcpdf/fonts/freesans.php mode change 100755 => 100644 lib/tcpdf/fonts/freesansb.php mode change 100755 => 100644 lib/tcpdf/fonts/freesansbi.php mode change 100755 => 100644 lib/tcpdf/fonts/freesansi.php mode change 100755 => 100644 lib/tcpdf/fonts/freeserif.php mode change 100755 => 100644 lib/tcpdf/fonts/freeserifb.php mode change 100755 => 100644 lib/tcpdf/fonts/freeserifbi.php mode change 100755 => 100644 lib/tcpdf/fonts/freeserifi.php mode change 100755 => 100644 lib/tcpdf/tcpdf.php mode change 100755 => 100644 lib/validateurlsyntax.php mode change 100755 => 100644 lib/zend/Zend/Amf/Adobe/Auth.php mode change 100755 => 100644 lib/zend/Zend/Amf/Adobe/DbInspector.php mode change 100755 => 100644 lib/zend/Zend/Amf/Adobe/Introspector.php mode change 100755 => 100644 lib/zend/Zend/Amf/Auth/Abstract.php mode change 100755 => 100644 lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php mode change 100755 => 100644 lib/zend/Zend/Amf/Parse/Resource/Stream.php mode change 100755 => 100644 lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Books.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Books/VolumeQuery.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Docs.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Docs/DocumentListEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Docs/DocumentListFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Docs/Query.php mode change 100755 => 100644 lib/zend/Zend/Gdata/DublinCore.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Entry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Distance.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Exposure.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/FStop.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Flash.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/FocalLength.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/ImageUniqueId.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Iso.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Make.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Model.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Tags.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Extension/Time.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Exif/Feed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo/Entry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo/Extension/GeoRssWhere.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo/Extension/GmlPoint.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo/Extension/GmlPos.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Geo/Feed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/Extension/Ccr.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/ProfileEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/ProfileFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/ProfileListEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/ProfileListFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Health/Query.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Entry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaCategory.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaContent.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaCopyright.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaCredit.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaDescription.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaGroup.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaHash.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaKeywords.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaPlayer.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaRating.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaRestriction.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaText.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaThumbnail.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Extension/MediaTitle.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Media/Feed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/AlbumEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/AlbumFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/AlbumQuery.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/CommentEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Access.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/AlbumId.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/BytesUsed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Checksum.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Client.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/CommentCount.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/CommentingEnabled.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Height.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Id.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Location.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/MaxPhotosPerAlbum.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Name.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Nickname.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/NumPhotos.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/NumPhotosRemaining.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/PhotoId.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Position.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/QuotaCurrent.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/QuotaLimit.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Rotation.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Size.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Thumbnail.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Timestamp.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/User.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Version.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Weight.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/Extension/Width.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/PhotoEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/PhotoFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/PhotoQuery.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/TagEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/UserEntry.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/UserFeed.php mode change 100755 => 100644 lib/zend/Zend/Gdata/Photos/UserQuery.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/Control.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/CountHint.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/Link.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/MediaContent.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/MediaGroup.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/MediaRating.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/Private.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/Extension/Token.php mode change 100755 => 100644 lib/zend/Zend/Gdata/YouTube/MediaEntry.php mode change 100755 => 100644 lib/zend/Zend/Http/Client/Adapter/Stream.php mode change 100755 => 100644 lib/zend/Zend/Http/Response/Stream.php mode change 100755 => 100644 lib/zend/Zend/Service/Amazon/Exception.php mode change 100755 => 100644 lib/zend/Zend/Service/Amazon/S3.php mode change 100755 => 100644 lib/zend/Zend/Service/Amazon/S3/Exception.php mode change 100755 => 100644 lib/zend/Zend/Service/Amazon/S3/Stream.php mode change 100755 => 100644 lib/zend/Zend/Service/Twitter.php mode change 100755 => 100644 lib/zend/Zend/Service/Twitter/Exception.php mode change 100755 => 100644 message/output/email/version.php mode change 100755 => 100644 message/output/jabber/version.php mode change 100755 => 100644 message/output/popup/version.php mode change 100755 => 100644 mod/assignment/pix/icon.gif mode change 100755 => 100644 mod/chat/beep.wav mode change 100755 => 100644 mod/chat/chatd.php mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/bubbles.png mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/chat.css mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/config.php mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/horizontal.png mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/input.png mode change 100755 => 100644 mod/chat/gui_ajax/theme/bubble/vertical.png mode change 100755 => 100644 mod/chat/gui_ajax/theme/compact/chat.css mode change 100755 => 100644 mod/chat/gui_ajax/theme/compact/config.php mode change 100755 => 100644 mod/chat/pix/icon.gif mode change 100755 => 100644 mod/data/css.php mode change 100755 => 100644 mod/data/edit.php mode change 100755 => 100644 mod/data/field.php mode change 100755 => 100644 mod/data/field/checkbox/field.class.php mode change 100755 => 100644 mod/data/field/checkbox/mod.html mode change 100755 => 100644 mod/data/field/date/field.class.php mode change 100755 => 100644 mod/data/field/date/mod.html mode change 100755 => 100644 mod/data/field/file/field.class.php mode change 100755 => 100644 mod/data/field/file/mod.html mode change 100755 => 100644 mod/data/field/latlong/field.class.php mode change 100755 => 100644 mod/data/field/latlong/mod.html mode change 100755 => 100644 mod/data/field/menu/field.class.php mode change 100755 => 100644 mod/data/field/menu/mod.html mode change 100755 => 100644 mod/data/field/multimenu/field.class.php mode change 100755 => 100644 mod/data/field/multimenu/mod.html mode change 100755 => 100644 mod/data/field/number/field.class.php mode change 100755 => 100644 mod/data/field/number/mod.html mode change 100755 => 100644 mod/data/field/picture/field.class.php mode change 100755 => 100644 mod/data/field/picture/mod.html mode change 100755 => 100644 mod/data/field/radiobutton/field.class.php mode change 100755 => 100644 mod/data/field/radiobutton/mod.html mode change 100755 => 100644 mod/data/field/text/field.class.php mode change 100755 => 100644 mod/data/field/text/mod.html mode change 100755 => 100644 mod/data/field/textarea/field.class.php mode change 100755 => 100644 mod/data/field/textarea/mod.html mode change 100755 => 100644 mod/data/field/url/field.class.php mode change 100755 => 100644 mod/data/field/url/mod.html mode change 100755 => 100644 mod/data/import.php mode change 100755 => 100644 mod/data/index.php mode change 100755 => 100644 mod/data/lang/en/data.php mode change 100755 => 100644 mod/data/lib.php mode change 100755 => 100644 mod/data/pix/field/checkbox.gif mode change 100755 => 100644 mod/data/pix/field/date.gif mode change 100755 => 100644 mod/data/pix/field/file.gif mode change 100755 => 100644 mod/data/pix/field/latlong.gif mode change 100755 => 100644 mod/data/pix/field/menu.gif mode change 100755 => 100644 mod/data/pix/field/multimenu.gif mode change 100755 => 100644 mod/data/pix/field/number.gif mode change 100755 => 100644 mod/data/pix/field/picture.gif mode change 100755 => 100644 mod/data/pix/field/radiobutton.gif mode change 100755 => 100644 mod/data/pix/field/text.gif mode change 100755 => 100644 mod/data/pix/field/textarea.gif mode change 100755 => 100644 mod/data/pix/field/url.gif mode change 100755 => 100644 mod/data/pix/icon.gif mode change 100755 => 100644 mod/data/tabs.php mode change 100755 => 100644 mod/data/templates.php mode change 100755 => 100644 mod/data/view.php mode change 100755 => 100644 mod/forum/pix/icon.gif mode change 100755 => 100644 mod/glossary/db/install.xml mode change 100755 => 100644 mod/glossary/formats/TEMPLATE/TEMPLATE_format.php mode change 100755 => 100644 mod/label/pix/icon.gif mode change 100755 => 100644 mod/lesson/pix/icon.gif mode change 100755 => 100644 mod/quiz/db/install.xml mode change 100755 => 100644 mod/quiz/pix/icon.gif mode change 100755 => 100644 mod/scorm/aicc.php mode change 100755 => 100644 mod/scorm/datamodel.php mode change 100755 => 100644 mod/scorm/datamodels/sequencinglib.php mode change 100755 => 100644 mod/scorm/index.php mode change 100755 => 100644 mod/scorm/lib.php mode change 100755 => 100644 mod/scorm/loadSCO.php mode change 100755 => 100644 mod/scorm/locallib.php mode change 100755 => 100644 mod/scorm/pix/browsed.gif mode change 100755 => 100644 mod/scorm/pix/completed.gif mode change 100755 => 100644 mod/scorm/pix/failed.gif mode change 100755 => 100644 mod/scorm/pix/icon.gif mode change 100755 => 100644 mod/scorm/pix/incomplete.gif mode change 100755 => 100644 mod/scorm/pix/minus.gif mode change 100755 => 100644 mod/scorm/pix/notattempted.gif mode change 100755 => 100644 mod/scorm/pix/passed.gif mode change 100755 => 100644 mod/scorm/pix/plus.gif mode change 100755 => 100644 mod/scorm/pix/popdown.gif mode change 100755 => 100644 mod/scorm/pix/popup.gif mode change 100755 => 100644 mod/scorm/pix/spacer.gif mode change 100755 => 100644 mod/scorm/player.php mode change 100755 => 100644 mod/scorm/report.php mode change 100755 => 100644 mod/scorm/view.php mode change 100755 => 100644 mod/survey/pix/icon.gif mode change 100755 => 100644 mod/workshop/pix/userplan/task-info.gif mode change 100755 => 100644 pix/a/l_breadcrumb.gif mode change 100755 => 100644 pix/adv.gif mode change 100755 => 100644 pix/b.gif mode change 100755 => 100644 pix/f/audio.gif mode change 100755 => 100644 pix/f/folder.gif mode change 100755 => 100644 pix/f/odt.gif mode change 100755 => 100644 pix/f/parent.gif mode change 100755 => 100644 pix/f/powerpoint.gif mode change 100755 => 100644 pix/f/video.gif mode change 100755 => 100644 pix/f/web.gif mode change 100755 => 100644 pix/f/xml.gif mode change 100755 => 100644 pix/f/zip.gif mode change 100755 => 100644 pix/g/f1.png mode change 100755 => 100644 pix/g/f2.png mode change 100755 => 100644 pix/help.gif mode change 100755 => 100644 pix/i/admin.gif mode change 100755 => 100644 pix/i/agg_sum.gif mode change 100755 => 100644 pix/i/all.gif mode change 100755 => 100644 pix/i/backup.gif mode change 100755 => 100644 pix/i/course.gif mode change 100755 => 100644 pix/i/db.gif mode change 100755 => 100644 pix/i/edit.gif mode change 100755 => 100644 pix/i/email.gif mode change 100755 => 100644 pix/i/feedback.gif mode change 100755 => 100644 pix/i/files.gif mode change 100755 => 100644 pix/i/grades.gif mode change 100755 => 100644 pix/i/group.gif mode change 100755 => 100644 pix/i/guest.gif mode change 100755 => 100644 pix/i/hide.gif mode change 100755 => 100644 pix/i/info.gif mode change 100755 => 100644 pix/i/key.gif mode change 100755 => 100644 pix/i/lock.gif mode change 100755 => 100644 pix/i/marked.gif mode change 100755 => 100644 pix/i/marker.gif mode change 100755 => 100644 pix/i/new.gif mode change 100755 => 100644 pix/i/news.gif mode change 100755 => 100644 pix/i/one.gif mode change 100755 => 100644 pix/i/reload.gif mode change 100755 => 100644 pix/i/report.gif mode change 100755 => 100644 pix/i/restore.gif mode change 100755 => 100644 pix/i/return.gif mode change 100755 => 100644 pix/i/roles.gif mode change 100755 => 100644 pix/i/scales.gif mode change 100755 => 100644 pix/i/search.gif mode change 100755 => 100644 pix/i/settings.gif mode change 100755 => 100644 pix/i/show.gif mode change 100755 => 100644 pix/i/stats.gif mode change 100755 => 100644 pix/i/switch.gif mode change 100755 => 100644 pix/i/unlock.gif mode change 100755 => 100644 pix/i/user.gif mode change 100755 => 100644 pix/i/users.gif mode change 100755 => 100644 pix/m/USD.gif mode change 100755 => 100644 pix/madewithmoodle.gif mode change 100755 => 100644 pix/moodlelogo-med-white.gif mode change 100755 => 100644 pix/moodlelogo-med.gif mode change 100755 => 100644 pix/moodlelogo.gif mode change 100755 => 100644 pix/movehere.gif mode change 100755 => 100644 pix/s/angry.gif mode change 100755 => 100644 pix/s/approve.gif mode change 100755 => 100644 pix/s/biggrin.gif mode change 100755 => 100644 pix/s/blackeye.gif mode change 100755 => 100644 pix/s/blush.gif mode change 100755 => 100644 pix/s/clown.gif mode change 100755 => 100644 pix/s/cool.gif mode change 100755 => 100644 pix/s/dead.gif mode change 100755 => 100644 pix/s/egg.gif mode change 100755 => 100644 pix/s/evil.gif mode change 100755 => 100644 pix/s/heart.gif mode change 100755 => 100644 pix/s/kiss.gif mode change 100755 => 100644 pix/s/martin.gif mode change 100755 => 100644 pix/s/mixed.gif mode change 100755 => 100644 pix/s/no.gif mode change 100755 => 100644 pix/s/sad.gif mode change 100755 => 100644 pix/s/shy.gif mode change 100755 => 100644 pix/s/sleepy.gif mode change 100755 => 100644 pix/s/smiley.gif mode change 100755 => 100644 pix/s/surprise.gif mode change 100755 => 100644 pix/s/thoughtful.gif mode change 100755 => 100644 pix/s/tongueout.gif mode change 100755 => 100644 pix/s/wideeyes.gif mode change 100755 => 100644 pix/s/wink.gif mode change 100755 => 100644 pix/s/yes.gif mode change 100755 => 100644 pix/spacer.gif mode change 100755 => 100644 pix/t/backup.gif mode change 100755 => 100644 pix/t/email.gif mode change 100755 => 100644 pix/t/emailno.gif mode change 100755 => 100644 pix/t/go.gif mode change 100755 => 100644 pix/t/groupn.gif mode change 100755 => 100644 pix/t/groups.gif mode change 100755 => 100644 pix/t/groupv.gif mode change 100755 => 100644 pix/t/left.gif mode change 100755 => 100644 pix/t/lock.gif mode change 100755 => 100644 pix/t/log.gif mode change 100755 => 100644 pix/t/message.gif mode change 100755 => 100644 pix/t/move.gif mode change 100755 => 100644 pix/t/preview.gif mode change 100755 => 100644 pix/t/restore.gif mode change 100755 => 100644 pix/t/right.gif mode change 100755 => 100644 pix/t/stop.gif mode change 100755 => 100644 pix/t/unlock.gif mode change 100755 => 100644 pix/t/user.gif mode change 100755 => 100644 pix/t/usernot.gif mode change 100755 => 100644 pix/u/f1.png mode change 100755 => 100644 pix/u/f2.png mode change 100755 => 100644 pix/webding.png mode change 100755 => 100644 portfolio/download/simpletest/testportfolioplugindownload.php mode change 100755 => 100644 portfolio/flickr/lib.php mode change 100755 => 100644 portfolio/flickr/version.php mode change 100755 => 100644 question/format/examview/format.php mode change 100755 => 100644 question/format/gift/format.php mode change 100755 => 100644 question/format/learnwise/format.php mode change 100755 => 100644 question/format/qti_two/templates/choice.tpl mode change 100755 => 100644 question/format/qti_two/templates/choiceMultiple.tpl mode change 100755 => 100644 question/format/qti_two/templates/composite.tpl mode change 100755 => 100644 question/format/qti_two/templates/extendedText.tpl mode change 100755 => 100644 question/format/qti_two/templates/extendedText_simpleEssay.tpl mode change 100755 => 100644 question/format/qti_two/templates/imsmanifest.tpl mode change 100755 => 100644 question/format/qti_two/templates/mmchoiceMultiple.tpl mode change 100755 => 100644 question/format/qti_two/templates/notimplemented.tpl mode change 100755 => 100644 question/format/qti_two/templates/numerical.tpl mode change 100755 => 100644 question/format/qti_two/templates/textEntry.tpl mode change 100755 => 100644 question/format/xhtml/format.php mode change 100755 => 100644 question/format/xml/format.php mode change 100755 => 100644 question/type/calculated/pix/icon.gif mode change 100755 => 100644 repository/alfresco/lib.php mode change 100755 => 100644 repository/boxnet/lib.php mode change 100755 => 100644 repository/boxnet/version.php mode change 100755 => 100644 repository/coursefiles/db/access.php mode change 100755 => 100644 repository/coursefiles/lang/en/repository_coursefiles.php mode change 100755 => 100644 repository/coursefiles/lib.php mode change 100755 => 100644 repository/coursefiles/pix/icon.png mode change 100755 => 100644 repository/coursefiles/version.php mode change 100755 => 100644 repository/draftfiles_ajax.php mode change 100755 => 100644 repository/draftfiles_manager.php mode change 100755 => 100644 repository/dropbox/db/access.php mode change 100755 => 100644 repository/dropbox/lang/en/repository_dropbox.php mode change 100755 => 100644 repository/dropbox/version.php mode change 100755 => 100644 repository/filepicker.php mode change 100755 => 100644 repository/flickr/lib.php mode change 100755 => 100644 repository/flickr_public/image.php mode change 100755 => 100644 repository/local/lib.php mode change 100755 => 100644 repository/merlot/db/access.php mode change 100755 => 100644 repository/merlot/lib.php mode change 100755 => 100644 repository/merlot/pix/icon.png mode change 100755 => 100644 repository/merlot/version.php mode change 100755 => 100644 repository/recent/lib.php mode change 100755 => 100644 repository/repository_ajax.php mode change 100755 => 100644 repository/repository_callback.php mode change 100755 => 100644 repository/upload/lib.php mode change 100755 => 100644 repository/upload/pix/icon.png mode change 100755 => 100644 repository/url/pix/icon.png mode change 100755 => 100644 repository/user/db/install.php mode change 100755 => 100644 repository/user/lang/en/repository_user.php mode change 100755 => 100644 repository/user/lib.php mode change 100755 => 100644 repository/user/pix/icon.png mode change 100755 => 100644 repository/user/version.php mode change 100755 => 100644 search/Zend/Exception.php mode change 100755 => 100644 theme/anomaly/pix/tab/right_last.gif mode change 100755 => 100644 theme/anomaly/pix/tab/rtlbg.gif mode change 100755 => 100644 theme/anomaly/pix/tab/tabrow1.gif mode change 100755 => 100644 theme/boxxie/pix/tab/right_last.gif mode change 100755 => 100644 theme/boxxie/pix/tab/rtlbg.gif mode change 100755 => 100644 theme/boxxie/pix/tab/tabrow1.gif mode change 100755 => 100644 theme/fusion/pix/header-bg.jpg mode change 100755 => 100644 theme/fusion/pix/header-center.jpg mode change 100755 => 100644 theme/fusion/pix/main-bg.gif mode change 100755 => 100644 theme/fusion/pix/side-bg.png mode change 100755 => 100644 theme/fusion/pix/side-start.png mode change 100755 => 100644 theme/nonzero/lib.php mode change 100755 => 100644 theme/nonzero/settings.php mode change 100755 => 100644 theme/standard/pix/tab/right_last.gif mode change 100755 => 100644 theme/standard/pix/tab/rtlbg.gif mode change 100755 => 100644 theme/standard/pix/tab/tabrow1.gif mode change 100755 => 100644 user/default/f1.jpg mode change 100755 => 100644 user/default/f2.jpg mode change 100755 => 100644 user/emailupdate.php mode change 100755 => 100644 user/filters/date.php diff --git a/admin/generator.php b/admin/generator.php old mode 100755 new mode 100644 diff --git a/admin/langimport.php b/admin/langimport.php old mode 100755 new mode 100644 diff --git a/admin/process_email.php b/admin/process_email.php old mode 100755 new mode 100644 diff --git a/admin/report/spamcleaner/index.php b/admin/report/spamcleaner/index.php old mode 100755 new mode 100644 diff --git a/admin/report/unittest/coveragefile.php b/admin/report/unittest/coveragefile.php old mode 100755 new mode 100644 diff --git a/admin/roles/allow.php b/admin/roles/allow.php old mode 100755 new mode 100644 diff --git a/admin/roles/assign.php b/admin/roles/assign.php old mode 100755 new mode 100644 diff --git a/admin/roles/check.php b/admin/roles/check.php old mode 100755 new mode 100644 diff --git a/admin/roles/define.php b/admin/roles/define.php old mode 100755 new mode 100644 diff --git a/admin/roles/manage.php b/admin/roles/manage.php old mode 100755 new mode 100644 diff --git a/admin/roles/managetabs.php b/admin/roles/managetabs.php old mode 100755 new mode 100644 diff --git a/admin/roles/override.php b/admin/roles/override.php old mode 100755 new mode 100644 diff --git a/admin/uploaduser.php b/admin/uploaduser.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk.php b/admin/user/user_bulk.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk_confirm.php b/admin/user/user_bulk_confirm.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk_delete.php b/admin/user/user_bulk_delete.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk_display.php b/admin/user/user_bulk_display.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk_download.php b/admin/user/user_bulk_download.php old mode 100755 new mode 100644 diff --git a/admin/user/user_bulk_message.php b/admin/user/user_bulk_message.php old mode 100755 new mode 100644 diff --git a/auth/ldap/cli/sync_users.php b/auth/ldap/cli/sync_users.php old mode 100755 new mode 100644 diff --git a/auth/shibboleth/config.html b/auth/shibboleth/config.html old mode 100755 new mode 100644 diff --git a/backup/backupfilesedit.php b/backup/backupfilesedit.php old mode 100755 new mode 100644 diff --git a/backup/cc/cc2moodle.php b/backup/cc/cc2moodle.php old mode 100755 new mode 100644 diff --git a/backup/cc/entities.class.php b/backup/cc/entities.class.php old mode 100755 new mode 100644 diff --git a/backup/cc/entity.forum.class.php b/backup/cc/entity.forum.class.php old mode 100755 new mode 100644 diff --git a/backup/cc/entity.label.class.php b/backup/cc/entity.label.class.php old mode 100755 new mode 100644 diff --git a/backup/cc/entity.quiz.class.php b/backup/cc/entity.quiz.class.php old mode 100755 new mode 100644 diff --git a/backup/cc/entity.resource.class.php b/backup/cc/entity.resource.class.php old mode 100755 new mode 100644 diff --git a/backup/cc/includes/constants.php b/backup/cc/includes/constants.php old mode 100755 new mode 100644 diff --git a/backup/cc/restore_cc.php b/backup/cc/restore_cc.php old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/cclibxml2validator.xsd b/backup/cc/schemas/cclibxml2validator.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/config.xml b/backup/cc/schemas/config.xml old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_0/imsccauth_v1p0.xsd b/backup/cc/schemas/domainProfile_0/imsccauth_v1p0.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_0/imsccauth_v1p0_constraintsDocument.scmt b/backup/cc/schemas/domainProfile_0/imsccauth_v1p0_constraintsDocument.scmt old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_0/imsccauth_v1p0_localised.xsd b/backup/cc/schemas/domainProfile_0/imsccauth_v1p0_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/anyElement.xsd b/backup/cc/schemas/domainProfile_1/anyElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/anyElement_localised.xsd b/backup/cc/schemas/domainProfile_1/anyElement_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/anyElement.xsd b/backup/cc/schemas/domainProfile_1/common/anyElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/dataTypes.xsd b/backup/cc/schemas/domainProfile_1/common/dataTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/elementNames.xsd b/backup/cc/schemas/domainProfile_1/common/elementNames.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/elementTypes.xsd b/backup/cc/schemas/domainProfile_1/common/elementTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/rootElement.xsd b/backup/cc/schemas/domainProfile_1/common/rootElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/vocabTypes.xsd b/backup/cc/schemas/domainProfile_1/common/vocabTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/common/vocabValues.xsd b/backup/cc/schemas/domainProfile_1/common/vocabValues.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/dataTypes_localised.xsd b/backup/cc/schemas/domainProfile_1/dataTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/elementNames_localised.xsd b/backup/cc/schemas/domainProfile_1/elementNames_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/elementTypes_localised.xsd b/backup/cc/schemas/domainProfile_1/elementTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/extend/custom.xsd b/backup/cc/schemas/domainProfile_1/extend/custom.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/imscc_m_definition.xsd b/backup/cc/schemas/domainProfile_1/imscc_m_definition.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/lomLoose.xsd b/backup/cc/schemas/domainProfile_1/lomLoose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/lomLoose_constraintsDocument.scmt b/backup/cc/schemas/domainProfile_1/lomLoose_constraintsDocument.scmt old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/lomLoose_localised.xsd b/backup/cc/schemas/domainProfile_1/lomLoose_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/loose.xsd b/backup/cc/schemas/domainProfile_1/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/rootElement_localised.xsd b/backup/cc/schemas/domainProfile_1/rootElement_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/unique/loose.xsd b/backup/cc/schemas/domainProfile_1/unique/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/vocab/loose.xsd b/backup/cc/schemas/domainProfile_1/vocab/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/vocabTypes_localised.xsd b/backup/cc/schemas/domainProfile_1/vocabTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_1/vocabValues_localised.xsd b/backup/cc/schemas/domainProfile_1/vocabValues_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/anyElement.xsd b/backup/cc/schemas/domainProfile_2/anyElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/anyElement_localised.xsd b/backup/cc/schemas/domainProfile_2/anyElement_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/anyElement.xsd b/backup/cc/schemas/domainProfile_2/common/anyElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/dataTypes.xsd b/backup/cc/schemas/domainProfile_2/common/dataTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/elementNames.xsd b/backup/cc/schemas/domainProfile_2/common/elementNames.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/elementTypes.xsd b/backup/cc/schemas/domainProfile_2/common/elementTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/rootElement.xsd b/backup/cc/schemas/domainProfile_2/common/rootElement.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/vocabTypes.xsd b/backup/cc/schemas/domainProfile_2/common/vocabTypes.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/common/vocabValues.xsd b/backup/cc/schemas/domainProfile_2/common/vocabValues.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/dataTypes_localised.xsd b/backup/cc/schemas/domainProfile_2/dataTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/elementNames_localised.xsd b/backup/cc/schemas/domainProfile_2/elementNames_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/elementTypes_localised.xsd b/backup/cc/schemas/domainProfile_2/elementTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/extend/custom.xsd b/backup/cc/schemas/domainProfile_2/extend/custom.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/imscc_mR_definition.xsd b/backup/cc/schemas/domainProfile_2/imscc_mR_definition.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/lomLoose.xsd b/backup/cc/schemas/domainProfile_2/lomLoose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/lomLoose_constraintsDocument.scmt b/backup/cc/schemas/domainProfile_2/lomLoose_constraintsDocument.scmt old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/lomLoose_localised.xsd b/backup/cc/schemas/domainProfile_2/lomLoose_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/loose.xsd b/backup/cc/schemas/domainProfile_2/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/rootElement_localised.xsd b/backup/cc/schemas/domainProfile_2/rootElement_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/unique/loose.xsd b/backup/cc/schemas/domainProfile_2/unique/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/vocab/loose.xsd b/backup/cc/schemas/domainProfile_2/vocab/loose.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/vocabTypes_localised.xsd b/backup/cc/schemas/domainProfile_2/vocabTypes_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_2/vocabValues_localised.xsd b/backup/cc/schemas/domainProfile_2/vocabValues_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2.xsd b/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_constraintsDocument.scmt b/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_constraintsDocument.scmt old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_localised.xsd b/backup/cc/schemas/domainProfile_3/imscp_extensionv1p2_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2.xsd b/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_def_copy.xsd b/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_def_copy.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_localised.xsd b/backup/cc/schemas/domainProfile_4/ims_qtiasiv1p2_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_4/imscc_q_definition.xsd b/backup/cc/schemas/domainProfile_4/imscc_q_definition.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_4/xml.xsd b/backup/cc/schemas/domainProfile_4/xml.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_5/imswl_v1p0.xsd b/backup/cc/schemas/domainProfile_5/imswl_v1p0.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_5/imswl_v1p0_localised.xsd b/backup/cc/schemas/domainProfile_5/imswl_v1p0_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_6/imsdt_v1p0.xsd b/backup/cc/schemas/domainProfile_6/imsdt_v1p0.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/domainProfile_6/imsdt_v1p0_localised.xsd b/backup/cc/schemas/domainProfile_6/imsdt_v1p0_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/imscc_c1p2maeV0p15_definition.xsd b/backup/cc/schemas/imscc_c1p2maeV0p15_definition.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/imscp_v1p2.xsd b/backup/cc/schemas/imscp_v1p2.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/imscp_v1p2_constraintsDocument.scmt b/backup/cc/schemas/imscp_v1p2_constraintsDocument.scmt old mode 100755 new mode 100644 diff --git a/backup/cc/schemas/imscp_v1p2_localised.xsd b/backup/cc/schemas/imscp_v1p2_localised.xsd old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/base.xml b/backup/cc/sheets/base.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_blocks_block.xml b/backup/cc/sheets/course_blocks_block.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_header.xml b/backup/cc/sheets/course_header.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_forum.xml b/backup/cc/sheets/course_modules_mod_forum.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_label.xml b/backup/cc/sheets/course_modules_mod_label.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_quiz.xml b/backup/cc/sheets/course_modules_mod_quiz.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_quiz_feedback.xml b/backup/cc/sheets/course_modules_mod_quiz_feedback.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_quiz_question_instance.xml b/backup/cc/sheets/course_modules_mod_quiz_question_instance.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_modules_mod_resource.xml b/backup/cc/sheets/course_modules_mod_resource.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories.xml b/backup/cc/sheets/course_question_categories.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category.xml b/backup/cc/sheets/course_question_categories_question_category.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question.xml b/backup/cc/sheets/course_question_categories_question_category_question.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question_answer.xml b/backup/cc/sheets/course_question_categories_question_category_question_answer.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question_eesay.xml b/backup/cc/sheets/course_question_categories_question_category_question_eesay.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question_multiple_choice.xml b/backup/cc/sheets/course_question_categories_question_category_question_multiple_choice.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question_shortanswer.xml b/backup/cc/sheets/course_question_categories_question_category_question_shortanswer.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_question_categories_question_category_question_true_false.xml b/backup/cc/sheets/course_question_categories_question_category_question_true_false.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_sections_section.xml b/backup/cc/sheets/course_sections_section.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/course_sections_section_mods_mod.xml b/backup/cc/sheets/course_sections_section_mods_mod.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/info_details_mod.xml b/backup/cc/sheets/info_details_mod.xml old mode 100755 new mode 100644 diff --git a/backup/cc/sheets/info_details_mod_instance.xml b/backup/cc/sheets/info_details_mod_instance.xml old mode 100755 new mode 100644 diff --git a/backup/restorefile.php b/backup/restorefile.php old mode 100755 new mode 100644 diff --git a/backup/restorefile_form.php b/backup/restorefile_form.php old mode 100755 new mode 100644 diff --git a/backup/util/xml/parser/simpletest/fixtures/test4.xml b/backup/util/xml/parser/simpletest/fixtures/test4.xml old mode 100755 new mode 100644 diff --git a/blocks/blog_menu/block_blog_menu.php b/blocks/blog_menu/block_blog_menu.php old mode 100755 new mode 100644 diff --git a/blocks/html/block_html.php b/blocks/html/block_html.php old mode 100755 new mode 100644 diff --git a/blocks/mentees/block_mentees.php b/blocks/mentees/block_mentees.php old mode 100755 new mode 100644 diff --git a/blocks/mentees/lang/en/block_mentees.php b/blocks/mentees/lang/en/block_mentees.php old mode 100755 new mode 100644 diff --git a/blocks/private_files/block_private_files.php b/blocks/private_files/block_private_files.php old mode 100755 new mode 100644 diff --git a/blocks/rss_client/lang/en/block_rss_client.php b/blocks/rss_client/lang/en/block_rss_client.php old mode 100755 new mode 100644 diff --git a/blocks/section_links/config_instance.html b/blocks/section_links/config_instance.html old mode 100755 new mode 100644 diff --git a/blocks/section_links/settings.php b/blocks/section_links/settings.php old mode 100755 new mode 100644 diff --git a/blog/edit.php b/blog/edit.php old mode 100755 new mode 100644 diff --git a/blog/index.php b/blog/index.php old mode 100755 new mode 100644 diff --git a/blog/preferences.php b/blog/preferences.php old mode 100755 new mode 100644 diff --git a/blog/rsslib.php b/blog/rsslib.php old mode 100755 new mode 100644 diff --git a/course/format/scorm/config.php b/course/format/scorm/config.php old mode 100755 new mode 100644 diff --git a/course/format/social/config.php b/course/format/social/config.php old mode 100755 new mode 100644 diff --git a/course/format/topics/config.php b/course/format/topics/config.php old mode 100755 new mode 100644 diff --git a/course/format/weeks/config.php b/course/format/weeks/config.php old mode 100755 new mode 100644 diff --git a/course/reset.php b/course/reset.php old mode 100755 new mode 100644 diff --git a/course/simpletest/testcourselib.php b/course/simpletest/testcourselib.php old mode 100755 new mode 100644 diff --git a/enrol/authorize/enrol_form.php b/enrol/authorize/enrol_form.php old mode 100755 new mode 100644 diff --git a/enrol/authorize/version.php b/enrol/authorize/version.php old mode 100755 new mode 100644 diff --git a/files/externallib.php b/files/externallib.php old mode 100755 new mode 100644 diff --git a/files/filebrowser_ajax.php b/files/filebrowser_ajax.php old mode 100755 new mode 100644 diff --git a/filter/algebra/AlgParser.pm b/filter/algebra/AlgParser.pm old mode 100755 new mode 100644 diff --git a/filter/algebra/algebra2tex.pl b/filter/algebra/algebra2tex.pl old mode 100755 new mode 100644 diff --git a/filter/mediaplugin/mp3player.swf b/filter/mediaplugin/mp3player.swf old mode 100755 new mode 100644 diff --git a/filter/tex/mimetex.exe b/filter/tex/mimetex.exe old mode 100755 new mode 100644 diff --git a/grade/edit/outcome/course_form.html b/grade/edit/outcome/course_form.html old mode 100755 new mode 100644 diff --git a/grade/edit/tree/functions.js b/grade/edit/tree/functions.js old mode 100755 new mode 100644 diff --git a/grade/edit/tree/grade_form.php b/grade/edit/tree/grade_form.php old mode 100755 new mode 100644 diff --git a/grade/edit/tree/lib.php b/grade/edit/tree/lib.php old mode 100755 new mode 100644 diff --git a/grade/export/grade_export_form.php b/grade/export/grade_export_form.php old mode 100755 new mode 100644 diff --git a/grade/export/lib.php b/grade/export/lib.php old mode 100755 new mode 100644 diff --git a/grade/export/ods/export.php b/grade/export/ods/export.php old mode 100755 new mode 100644 diff --git a/grade/export/ods/grade_export_ods.php b/grade/export/ods/grade_export_ods.php old mode 100755 new mode 100644 diff --git a/grade/export/ods/index.php b/grade/export/ods/index.php old mode 100755 new mode 100644 diff --git a/grade/export/txt/export.php b/grade/export/txt/export.php old mode 100755 new mode 100644 diff --git a/grade/export/txt/grade_export_txt.php b/grade/export/txt/grade_export_txt.php old mode 100755 new mode 100644 diff --git a/grade/export/txt/index.php b/grade/export/txt/index.php old mode 100755 new mode 100644 diff --git a/grade/export/txt/version.php b/grade/export/txt/version.php old mode 100755 new mode 100644 diff --git a/grade/export/xls/export.php b/grade/export/xls/export.php old mode 100755 new mode 100644 diff --git a/grade/export/xls/grade_export_xls.php b/grade/export/xls/grade_export_xls.php old mode 100755 new mode 100644 diff --git a/grade/export/xls/index.php b/grade/export/xls/index.php old mode 100755 new mode 100644 diff --git a/grade/export/xml/export.php b/grade/export/xml/export.php old mode 100755 new mode 100644 diff --git a/grade/export/xml/grade_export_xml.php b/grade/export/xml/grade_export_xml.php old mode 100755 new mode 100644 diff --git a/grade/export/xml/index.php b/grade/export/xml/index.php old mode 100755 new mode 100644 diff --git a/grade/import/xml/index.php b/grade/import/xml/index.php old mode 100755 new mode 100644 diff --git a/install/welcome.html b/install/welcome.html old mode 100755 new mode 100644 diff --git a/lang/en/blog.php b/lang/en/blog.php old mode 100755 new mode 100644 diff --git a/lang/en/error.php b/lang/en/error.php old mode 100755 new mode 100644 diff --git a/lang/en/install.php b/lang/en/install.php old mode 100755 new mode 100644 diff --git a/lang/en/notes.php b/lang/en/notes.php old mode 100755 new mode 100644 diff --git a/lib/accesslib.php b/lib/accesslib.php old mode 100755 new mode 100644 diff --git a/lib/ajax/section_classes.js b/lib/ajax/section_classes.js old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Association.php b/lib/alfresco/Service/Association.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/BaseObject.php b/lib/alfresco/Service/BaseObject.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/ChildAssociation.php b/lib/alfresco/Service/ChildAssociation.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/ContentData.php b/lib/alfresco/Service/ContentData.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Functions.php b/lib/alfresco/Service/Functions.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Logger/Logger.php b/lib/alfresco/Service/Logger/Logger.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Logger/LoggerConfig.php b/lib/alfresco/Service/Logger/LoggerConfig.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/NamespaceMap.php b/lib/alfresco/Service/NamespaceMap.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Node.php b/lib/alfresco/Service/Node.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Repository.php b/lib/alfresco/Service/Repository.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Session.php b/lib/alfresco/Service/Session.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/SpacesStore.php b/lib/alfresco/Service/SpacesStore.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Store.php b/lib/alfresco/Service/Store.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/Version.php b/lib/alfresco/Service/Version.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/VersionHistory.php b/lib/alfresco/Service/VersionHistory.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/WebService/AlfrescoWebService.php b/lib/alfresco/Service/WebService/AlfrescoWebService.php old mode 100755 new mode 100644 diff --git a/lib/alfresco/Service/WebService/WebServiceFactory.php b/lib/alfresco/Service/WebService/WebServiceFactory.php old mode 100755 new mode 100644 diff --git a/lib/boxlib.php b/lib/boxlib.php old mode 100755 new mode 100644 diff --git a/lib/ddl/simpletest/testddl.php b/lib/ddl/simpletest/testddl.php old mode 100755 new mode 100644 diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php old mode 100755 new mode 100644 diff --git a/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/css/media.css b/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/css/media.css old mode 100755 new mode 100644 diff --git a/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin.js old mode 100755 new mode 100644 diff --git a/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/editor_plugin_src.js old mode 100755 new mode 100644 diff --git a/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/js/media.js b/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/js/media.js old mode 100755 new mode 100644 diff --git a/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/moodlemedia.htm b/lib/editor/tinymce/tiny_mce/3.3.9.2/plugins/moodlemedia/moodlemedia.htm old mode 100755 new mode 100644 diff --git a/lib/eventslib.php b/lib/eventslib.php old mode 100755 new mode 100644 diff --git a/lib/flickrlib.php b/lib/flickrlib.php old mode 100755 new mode 100644 diff --git a/lib/form/selectwithlink.php b/lib/form/selectwithlink.php old mode 100755 new mode 100644 diff --git a/lib/form/url.php b/lib/form/url.php old mode 100755 new mode 100644 diff --git a/lib/grade/simpletest/testgradecategory.php b/lib/grade/simpletest/testgradecategory.php old mode 100755 new mode 100644 diff --git a/lib/grade/simpletest/testgradegrades.php b/lib/grade/simpletest/testgradegrades.php old mode 100755 new mode 100644 diff --git a/lib/grade/simpletest/testgradeitem.php b/lib/grade/simpletest/testgradeitem.php old mode 100755 new mode 100644 diff --git a/lib/grade/simpletest/testgradescale.php b/lib/grade/simpletest/testgradescale.php old mode 100755 new mode 100644 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt old mode 100755 new mode 100644 diff --git a/lib/htmlpurifier/HTMLPurifier/PropertyList.php b/lib/htmlpurifier/HTMLPurifier/PropertyList.php old mode 100755 new mode 100644 diff --git a/lib/htmlpurifier/HTMLPurifier/PropertyListIterator.php b/lib/htmlpurifier/HTMLPurifier/PropertyListIterator.php old mode 100755 new mode 100644 diff --git a/lib/jabber/XMPP/Exception.php b/lib/jabber/XMPP/Exception.php old mode 100755 new mode 100644 diff --git a/lib/markdown.php b/lib/markdown.php old mode 100755 new mode 100644 diff --git a/lib/odbc.php b/lib/odbc.php old mode 100755 new mode 100644 diff --git a/lib/pear/HTTP/WebDAV/Server.php b/lib/pear/HTTP/WebDAV/Server.php old mode 100755 new mode 100644 diff --git a/lib/pear/OLE.php b/lib/pear/OLE.php old mode 100755 new mode 100644 diff --git a/lib/pear/OLE/PPS.php b/lib/pear/OLE/PPS.php old mode 100755 new mode 100644 diff --git a/lib/pear/OLE/PPS/File.php b/lib/pear/OLE/PPS/File.php old mode 100755 new mode 100644 diff --git a/lib/pear/OLE/PPS/Root.php b/lib/pear/OLE/PPS/Root.php old mode 100755 new mode 100644 diff --git a/lib/pear/PHP/runsniffer b/lib/pear/PHP/runsniffer old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-cz.php b/lib/phpmailer/language/phpmailer.lang-cz.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-de.php b/lib/phpmailer/language/phpmailer.lang-de.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-es.php b/lib/phpmailer/language/phpmailer.lang-es.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-fr.php b/lib/phpmailer/language/phpmailer.lang-fr.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-it.php b/lib/phpmailer/language/phpmailer.lang-it.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-nl.php b/lib/phpmailer/language/phpmailer.lang-nl.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-no.php b/lib/phpmailer/language/phpmailer.lang-no.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-se.php b/lib/phpmailer/language/phpmailer.lang-se.php old mode 100755 new mode 100644 diff --git a/lib/phpmailer/language/phpmailer.lang-tr.php b/lib/phpmailer/language/phpmailer.lang-tr.php old mode 100755 new mode 100644 diff --git a/lib/profilerlib.php b/lib/profilerlib.php old mode 100755 new mode 100644 diff --git a/lib/simpletest/testeventslib.php b/lib/simpletest/testeventslib.php old mode 100755 new mode 100644 diff --git a/lib/simpletest/testmathslib.php b/lib/simpletest/testmathslib.php old mode 100755 new mode 100644 diff --git a/lib/simpletest/testportfoliolib.php b/lib/simpletest/testportfoliolib.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/README.TXT b/lib/tcpdf/README.TXT old mode 100755 new mode 100644 diff --git a/lib/tcpdf/config/tcpdf_config.php b/lib/tcpdf/config/tcpdf_config.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/README.TXT b/lib/tcpdf/fonts/README.TXT old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freemono.php b/lib/tcpdf/fonts/freemono.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freemonob.php b/lib/tcpdf/fonts/freemonob.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freemonobi.php b/lib/tcpdf/fonts/freemonobi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freemonoi.php b/lib/tcpdf/fonts/freemonoi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freesans.php b/lib/tcpdf/fonts/freesans.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freesansb.php b/lib/tcpdf/fonts/freesansb.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freesansbi.php b/lib/tcpdf/fonts/freesansbi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freesansi.php b/lib/tcpdf/fonts/freesansi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freeserif.php b/lib/tcpdf/fonts/freeserif.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freeserifb.php b/lib/tcpdf/fonts/freeserifb.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freeserifbi.php b/lib/tcpdf/fonts/freeserifbi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/fonts/freeserifi.php b/lib/tcpdf/fonts/freeserifi.php old mode 100755 new mode 100644 diff --git a/lib/tcpdf/tcpdf.php b/lib/tcpdf/tcpdf.php old mode 100755 new mode 100644 diff --git a/lib/validateurlsyntax.php b/lib/validateurlsyntax.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Adobe/Auth.php b/lib/zend/Zend/Amf/Adobe/Auth.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Adobe/DbInspector.php b/lib/zend/Zend/Amf/Adobe/DbInspector.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Adobe/Introspector.php b/lib/zend/Zend/Amf/Adobe/Introspector.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Auth/Abstract.php b/lib/zend/Zend/Amf/Auth/Abstract.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php b/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Parse/Resource/Stream.php b/lib/zend/Zend/Amf/Parse/Resource/Stream.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php b/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Books.php b/lib/zend/Zend/Gdata/Books.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Books/VolumeQuery.php b/lib/zend/Zend/Gdata/Books/VolumeQuery.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Docs.php b/lib/zend/Zend/Gdata/Docs.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Docs/DocumentListEntry.php b/lib/zend/Zend/Gdata/Docs/DocumentListEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Docs/DocumentListFeed.php b/lib/zend/Zend/Gdata/Docs/DocumentListFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Docs/Query.php b/lib/zend/Zend/Gdata/Docs/Query.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/DublinCore.php b/lib/zend/Zend/Gdata/DublinCore.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif.php b/lib/zend/Zend/Gdata/Exif.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Entry.php b/lib/zend/Zend/Gdata/Exif/Entry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Distance.php b/lib/zend/Zend/Gdata/Exif/Extension/Distance.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Exposure.php b/lib/zend/Zend/Gdata/Exif/Extension/Exposure.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/FStop.php b/lib/zend/Zend/Gdata/Exif/Extension/FStop.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Flash.php b/lib/zend/Zend/Gdata/Exif/Extension/Flash.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/FocalLength.php b/lib/zend/Zend/Gdata/Exif/Extension/FocalLength.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/ImageUniqueId.php b/lib/zend/Zend/Gdata/Exif/Extension/ImageUniqueId.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Iso.php b/lib/zend/Zend/Gdata/Exif/Extension/Iso.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Make.php b/lib/zend/Zend/Gdata/Exif/Extension/Make.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Model.php b/lib/zend/Zend/Gdata/Exif/Extension/Model.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Tags.php b/lib/zend/Zend/Gdata/Exif/Extension/Tags.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Extension/Time.php b/lib/zend/Zend/Gdata/Exif/Extension/Time.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Exif/Feed.php b/lib/zend/Zend/Gdata/Exif/Feed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo.php b/lib/zend/Zend/Gdata/Geo.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo/Entry.php b/lib/zend/Zend/Gdata/Geo/Entry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo/Extension/GeoRssWhere.php b/lib/zend/Zend/Gdata/Geo/Extension/GeoRssWhere.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo/Extension/GmlPoint.php b/lib/zend/Zend/Gdata/Geo/Extension/GmlPoint.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo/Extension/GmlPos.php b/lib/zend/Zend/Gdata/Geo/Extension/GmlPos.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Geo/Feed.php b/lib/zend/Zend/Gdata/Geo/Feed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health.php b/lib/zend/Zend/Gdata/Health.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/Extension/Ccr.php b/lib/zend/Zend/Gdata/Health/Extension/Ccr.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/ProfileEntry.php b/lib/zend/Zend/Gdata/Health/ProfileEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/ProfileFeed.php b/lib/zend/Zend/Gdata/Health/ProfileFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/ProfileListEntry.php b/lib/zend/Zend/Gdata/Health/ProfileListEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/ProfileListFeed.php b/lib/zend/Zend/Gdata/Health/ProfileListFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Health/Query.php b/lib/zend/Zend/Gdata/Health/Query.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media.php b/lib/zend/Zend/Gdata/Media.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Entry.php b/lib/zend/Zend/Gdata/Media/Entry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaCategory.php b/lib/zend/Zend/Gdata/Media/Extension/MediaCategory.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaContent.php b/lib/zend/Zend/Gdata/Media/Extension/MediaContent.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaCopyright.php b/lib/zend/Zend/Gdata/Media/Extension/MediaCopyright.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaCredit.php b/lib/zend/Zend/Gdata/Media/Extension/MediaCredit.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaDescription.php b/lib/zend/Zend/Gdata/Media/Extension/MediaDescription.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaGroup.php b/lib/zend/Zend/Gdata/Media/Extension/MediaGroup.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaHash.php b/lib/zend/Zend/Gdata/Media/Extension/MediaHash.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaKeywords.php b/lib/zend/Zend/Gdata/Media/Extension/MediaKeywords.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaPlayer.php b/lib/zend/Zend/Gdata/Media/Extension/MediaPlayer.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaRating.php b/lib/zend/Zend/Gdata/Media/Extension/MediaRating.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaRestriction.php b/lib/zend/Zend/Gdata/Media/Extension/MediaRestriction.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaText.php b/lib/zend/Zend/Gdata/Media/Extension/MediaText.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaThumbnail.php b/lib/zend/Zend/Gdata/Media/Extension/MediaThumbnail.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Extension/MediaTitle.php b/lib/zend/Zend/Gdata/Media/Extension/MediaTitle.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Media/Feed.php b/lib/zend/Zend/Gdata/Media/Feed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos.php b/lib/zend/Zend/Gdata/Photos.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/AlbumEntry.php b/lib/zend/Zend/Gdata/Photos/AlbumEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/AlbumFeed.php b/lib/zend/Zend/Gdata/Photos/AlbumFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/AlbumQuery.php b/lib/zend/Zend/Gdata/Photos/AlbumQuery.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/CommentEntry.php b/lib/zend/Zend/Gdata/Photos/CommentEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Access.php b/lib/zend/Zend/Gdata/Photos/Extension/Access.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/AlbumId.php b/lib/zend/Zend/Gdata/Photos/Extension/AlbumId.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/BytesUsed.php b/lib/zend/Zend/Gdata/Photos/Extension/BytesUsed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Checksum.php b/lib/zend/Zend/Gdata/Photos/Extension/Checksum.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Client.php b/lib/zend/Zend/Gdata/Photos/Extension/Client.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/CommentCount.php b/lib/zend/Zend/Gdata/Photos/Extension/CommentCount.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/CommentingEnabled.php b/lib/zend/Zend/Gdata/Photos/Extension/CommentingEnabled.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Height.php b/lib/zend/Zend/Gdata/Photos/Extension/Height.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Id.php b/lib/zend/Zend/Gdata/Photos/Extension/Id.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Location.php b/lib/zend/Zend/Gdata/Photos/Extension/Location.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/MaxPhotosPerAlbum.php b/lib/zend/Zend/Gdata/Photos/Extension/MaxPhotosPerAlbum.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Name.php b/lib/zend/Zend/Gdata/Photos/Extension/Name.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Nickname.php b/lib/zend/Zend/Gdata/Photos/Extension/Nickname.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/NumPhotos.php b/lib/zend/Zend/Gdata/Photos/Extension/NumPhotos.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/NumPhotosRemaining.php b/lib/zend/Zend/Gdata/Photos/Extension/NumPhotosRemaining.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/PhotoId.php b/lib/zend/Zend/Gdata/Photos/Extension/PhotoId.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Position.php b/lib/zend/Zend/Gdata/Photos/Extension/Position.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/QuotaCurrent.php b/lib/zend/Zend/Gdata/Photos/Extension/QuotaCurrent.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/QuotaLimit.php b/lib/zend/Zend/Gdata/Photos/Extension/QuotaLimit.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Rotation.php b/lib/zend/Zend/Gdata/Photos/Extension/Rotation.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Size.php b/lib/zend/Zend/Gdata/Photos/Extension/Size.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Thumbnail.php b/lib/zend/Zend/Gdata/Photos/Extension/Thumbnail.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Timestamp.php b/lib/zend/Zend/Gdata/Photos/Extension/Timestamp.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/User.php b/lib/zend/Zend/Gdata/Photos/Extension/User.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Version.php b/lib/zend/Zend/Gdata/Photos/Extension/Version.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Weight.php b/lib/zend/Zend/Gdata/Photos/Extension/Weight.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/Extension/Width.php b/lib/zend/Zend/Gdata/Photos/Extension/Width.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/PhotoEntry.php b/lib/zend/Zend/Gdata/Photos/PhotoEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/PhotoFeed.php b/lib/zend/Zend/Gdata/Photos/PhotoFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/PhotoQuery.php b/lib/zend/Zend/Gdata/Photos/PhotoQuery.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/TagEntry.php b/lib/zend/Zend/Gdata/Photos/TagEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/UserEntry.php b/lib/zend/Zend/Gdata/Photos/UserEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/UserFeed.php b/lib/zend/Zend/Gdata/Photos/UserFeed.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/Photos/UserQuery.php b/lib/zend/Zend/Gdata/Photos/UserQuery.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/Control.php b/lib/zend/Zend/Gdata/YouTube/Extension/Control.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/CountHint.php b/lib/zend/Zend/Gdata/YouTube/Extension/CountHint.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/Link.php b/lib/zend/Zend/Gdata/YouTube/Extension/Link.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/MediaContent.php b/lib/zend/Zend/Gdata/YouTube/Extension/MediaContent.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/MediaGroup.php b/lib/zend/Zend/Gdata/YouTube/Extension/MediaGroup.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/MediaRating.php b/lib/zend/Zend/Gdata/YouTube/Extension/MediaRating.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/Private.php b/lib/zend/Zend/Gdata/YouTube/Extension/Private.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/Extension/Token.php b/lib/zend/Zend/Gdata/YouTube/Extension/Token.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Gdata/YouTube/MediaEntry.php b/lib/zend/Zend/Gdata/YouTube/MediaEntry.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Http/Client/Adapter/Stream.php b/lib/zend/Zend/Http/Client/Adapter/Stream.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Http/Response/Stream.php b/lib/zend/Zend/Http/Response/Stream.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Amazon/Exception.php b/lib/zend/Zend/Service/Amazon/Exception.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Amazon/S3.php b/lib/zend/Zend/Service/Amazon/S3.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Amazon/S3/Exception.php b/lib/zend/Zend/Service/Amazon/S3/Exception.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Amazon/S3/Stream.php b/lib/zend/Zend/Service/Amazon/S3/Stream.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Twitter.php b/lib/zend/Zend/Service/Twitter.php old mode 100755 new mode 100644 diff --git a/lib/zend/Zend/Service/Twitter/Exception.php b/lib/zend/Zend/Service/Twitter/Exception.php old mode 100755 new mode 100644 diff --git a/message/output/email/version.php b/message/output/email/version.php old mode 100755 new mode 100644 diff --git a/message/output/jabber/version.php b/message/output/jabber/version.php old mode 100755 new mode 100644 diff --git a/message/output/popup/version.php b/message/output/popup/version.php old mode 100755 new mode 100644 diff --git a/mod/assignment/pix/icon.gif b/mod/assignment/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/chat/beep.wav b/mod/chat/beep.wav old mode 100755 new mode 100644 diff --git a/mod/chat/chatd.php b/mod/chat/chatd.php old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/bubbles.png b/mod/chat/gui_ajax/theme/bubble/bubbles.png old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/chat.css b/mod/chat/gui_ajax/theme/bubble/chat.css old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/config.php b/mod/chat/gui_ajax/theme/bubble/config.php old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/horizontal.png b/mod/chat/gui_ajax/theme/bubble/horizontal.png old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/input.png b/mod/chat/gui_ajax/theme/bubble/input.png old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/bubble/vertical.png b/mod/chat/gui_ajax/theme/bubble/vertical.png old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/compact/chat.css b/mod/chat/gui_ajax/theme/compact/chat.css old mode 100755 new mode 100644 diff --git a/mod/chat/gui_ajax/theme/compact/config.php b/mod/chat/gui_ajax/theme/compact/config.php old mode 100755 new mode 100644 diff --git a/mod/chat/pix/icon.gif b/mod/chat/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/data/css.php b/mod/data/css.php old mode 100755 new mode 100644 diff --git a/mod/data/edit.php b/mod/data/edit.php old mode 100755 new mode 100644 diff --git a/mod/data/field.php b/mod/data/field.php old mode 100755 new mode 100644 diff --git a/mod/data/field/checkbox/field.class.php b/mod/data/field/checkbox/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/checkbox/mod.html b/mod/data/field/checkbox/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/date/field.class.php b/mod/data/field/date/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/date/mod.html b/mod/data/field/date/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/file/field.class.php b/mod/data/field/file/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/file/mod.html b/mod/data/field/file/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/latlong/field.class.php b/mod/data/field/latlong/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/latlong/mod.html b/mod/data/field/latlong/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/menu/field.class.php b/mod/data/field/menu/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/menu/mod.html b/mod/data/field/menu/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/multimenu/field.class.php b/mod/data/field/multimenu/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/multimenu/mod.html b/mod/data/field/multimenu/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/number/field.class.php b/mod/data/field/number/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/number/mod.html b/mod/data/field/number/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/picture/field.class.php b/mod/data/field/picture/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/picture/mod.html b/mod/data/field/picture/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/radiobutton/field.class.php b/mod/data/field/radiobutton/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/radiobutton/mod.html b/mod/data/field/radiobutton/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/text/field.class.php b/mod/data/field/text/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/text/mod.html b/mod/data/field/text/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/textarea/field.class.php b/mod/data/field/textarea/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/textarea/mod.html b/mod/data/field/textarea/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/field/url/field.class.php b/mod/data/field/url/field.class.php old mode 100755 new mode 100644 diff --git a/mod/data/field/url/mod.html b/mod/data/field/url/mod.html old mode 100755 new mode 100644 diff --git a/mod/data/import.php b/mod/data/import.php old mode 100755 new mode 100644 diff --git a/mod/data/index.php b/mod/data/index.php old mode 100755 new mode 100644 diff --git a/mod/data/lang/en/data.php b/mod/data/lang/en/data.php old mode 100755 new mode 100644 diff --git a/mod/data/lib.php b/mod/data/lib.php old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/checkbox.gif b/mod/data/pix/field/checkbox.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/date.gif b/mod/data/pix/field/date.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/file.gif b/mod/data/pix/field/file.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/latlong.gif b/mod/data/pix/field/latlong.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/menu.gif b/mod/data/pix/field/menu.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/multimenu.gif b/mod/data/pix/field/multimenu.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/number.gif b/mod/data/pix/field/number.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/picture.gif b/mod/data/pix/field/picture.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/radiobutton.gif b/mod/data/pix/field/radiobutton.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/text.gif b/mod/data/pix/field/text.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/textarea.gif b/mod/data/pix/field/textarea.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/field/url.gif b/mod/data/pix/field/url.gif old mode 100755 new mode 100644 diff --git a/mod/data/pix/icon.gif b/mod/data/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/data/tabs.php b/mod/data/tabs.php old mode 100755 new mode 100644 diff --git a/mod/data/templates.php b/mod/data/templates.php old mode 100755 new mode 100644 diff --git a/mod/data/view.php b/mod/data/view.php old mode 100755 new mode 100644 diff --git a/mod/forum/pix/icon.gif b/mod/forum/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/glossary/db/install.xml b/mod/glossary/db/install.xml old mode 100755 new mode 100644 diff --git a/mod/glossary/formats/TEMPLATE/TEMPLATE_format.php b/mod/glossary/formats/TEMPLATE/TEMPLATE_format.php old mode 100755 new mode 100644 diff --git a/mod/label/pix/icon.gif b/mod/label/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/lesson/pix/icon.gif b/mod/lesson/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/quiz/db/install.xml b/mod/quiz/db/install.xml old mode 100755 new mode 100644 diff --git a/mod/quiz/pix/icon.gif b/mod/quiz/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/aicc.php b/mod/scorm/aicc.php old mode 100755 new mode 100644 diff --git a/mod/scorm/datamodel.php b/mod/scorm/datamodel.php old mode 100755 new mode 100644 diff --git a/mod/scorm/datamodels/sequencinglib.php b/mod/scorm/datamodels/sequencinglib.php old mode 100755 new mode 100644 diff --git a/mod/scorm/index.php b/mod/scorm/index.php old mode 100755 new mode 100644 diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php old mode 100755 new mode 100644 diff --git a/mod/scorm/loadSCO.php b/mod/scorm/loadSCO.php old mode 100755 new mode 100644 diff --git a/mod/scorm/locallib.php b/mod/scorm/locallib.php old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/browsed.gif b/mod/scorm/pix/browsed.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/completed.gif b/mod/scorm/pix/completed.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/failed.gif b/mod/scorm/pix/failed.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/icon.gif b/mod/scorm/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/incomplete.gif b/mod/scorm/pix/incomplete.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/minus.gif b/mod/scorm/pix/minus.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/notattempted.gif b/mod/scorm/pix/notattempted.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/passed.gif b/mod/scorm/pix/passed.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/plus.gif b/mod/scorm/pix/plus.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/popdown.gif b/mod/scorm/pix/popdown.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/popup.gif b/mod/scorm/pix/popup.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/pix/spacer.gif b/mod/scorm/pix/spacer.gif old mode 100755 new mode 100644 diff --git a/mod/scorm/player.php b/mod/scorm/player.php old mode 100755 new mode 100644 diff --git a/mod/scorm/report.php b/mod/scorm/report.php old mode 100755 new mode 100644 diff --git a/mod/scorm/view.php b/mod/scorm/view.php old mode 100755 new mode 100644 diff --git a/mod/survey/pix/icon.gif b/mod/survey/pix/icon.gif old mode 100755 new mode 100644 diff --git a/mod/workshop/pix/userplan/task-info.gif b/mod/workshop/pix/userplan/task-info.gif old mode 100755 new mode 100644 diff --git a/pix/a/l_breadcrumb.gif b/pix/a/l_breadcrumb.gif old mode 100755 new mode 100644 diff --git a/pix/adv.gif b/pix/adv.gif old mode 100755 new mode 100644 diff --git a/pix/b.gif b/pix/b.gif old mode 100755 new mode 100644 diff --git a/pix/f/audio.gif b/pix/f/audio.gif old mode 100755 new mode 100644 diff --git a/pix/f/folder.gif b/pix/f/folder.gif old mode 100755 new mode 100644 diff --git a/pix/f/odt.gif b/pix/f/odt.gif old mode 100755 new mode 100644 diff --git a/pix/f/parent.gif b/pix/f/parent.gif old mode 100755 new mode 100644 diff --git a/pix/f/powerpoint.gif b/pix/f/powerpoint.gif old mode 100755 new mode 100644 diff --git a/pix/f/video.gif b/pix/f/video.gif old mode 100755 new mode 100644 diff --git a/pix/f/web.gif b/pix/f/web.gif old mode 100755 new mode 100644 diff --git a/pix/f/xml.gif b/pix/f/xml.gif old mode 100755 new mode 100644 diff --git a/pix/f/zip.gif b/pix/f/zip.gif old mode 100755 new mode 100644 diff --git a/pix/g/f1.png b/pix/g/f1.png old mode 100755 new mode 100644 diff --git a/pix/g/f2.png b/pix/g/f2.png old mode 100755 new mode 100644 diff --git a/pix/help.gif b/pix/help.gif old mode 100755 new mode 100644 diff --git a/pix/i/admin.gif b/pix/i/admin.gif old mode 100755 new mode 100644 diff --git a/pix/i/agg_sum.gif b/pix/i/agg_sum.gif old mode 100755 new mode 100644 diff --git a/pix/i/all.gif b/pix/i/all.gif old mode 100755 new mode 100644 diff --git a/pix/i/backup.gif b/pix/i/backup.gif old mode 100755 new mode 100644 diff --git a/pix/i/course.gif b/pix/i/course.gif old mode 100755 new mode 100644 diff --git a/pix/i/db.gif b/pix/i/db.gif old mode 100755 new mode 100644 diff --git a/pix/i/edit.gif b/pix/i/edit.gif old mode 100755 new mode 100644 diff --git a/pix/i/email.gif b/pix/i/email.gif old mode 100755 new mode 100644 diff --git a/pix/i/feedback.gif b/pix/i/feedback.gif old mode 100755 new mode 100644 diff --git a/pix/i/files.gif b/pix/i/files.gif old mode 100755 new mode 100644 diff --git a/pix/i/grades.gif b/pix/i/grades.gif old mode 100755 new mode 100644 diff --git a/pix/i/group.gif b/pix/i/group.gif old mode 100755 new mode 100644 diff --git a/pix/i/guest.gif b/pix/i/guest.gif old mode 100755 new mode 100644 diff --git a/pix/i/hide.gif b/pix/i/hide.gif old mode 100755 new mode 100644 diff --git a/pix/i/info.gif b/pix/i/info.gif old mode 100755 new mode 100644 diff --git a/pix/i/key.gif b/pix/i/key.gif old mode 100755 new mode 100644 diff --git a/pix/i/lock.gif b/pix/i/lock.gif old mode 100755 new mode 100644 diff --git a/pix/i/marked.gif b/pix/i/marked.gif old mode 100755 new mode 100644 diff --git a/pix/i/marker.gif b/pix/i/marker.gif old mode 100755 new mode 100644 diff --git a/pix/i/new.gif b/pix/i/new.gif old mode 100755 new mode 100644 diff --git a/pix/i/news.gif b/pix/i/news.gif old mode 100755 new mode 100644 diff --git a/pix/i/one.gif b/pix/i/one.gif old mode 100755 new mode 100644 diff --git a/pix/i/reload.gif b/pix/i/reload.gif old mode 100755 new mode 100644 diff --git a/pix/i/report.gif b/pix/i/report.gif old mode 100755 new mode 100644 diff --git a/pix/i/restore.gif b/pix/i/restore.gif old mode 100755 new mode 100644 diff --git a/pix/i/return.gif b/pix/i/return.gif old mode 100755 new mode 100644 diff --git a/pix/i/roles.gif b/pix/i/roles.gif old mode 100755 new mode 100644 diff --git a/pix/i/scales.gif b/pix/i/scales.gif old mode 100755 new mode 100644 diff --git a/pix/i/search.gif b/pix/i/search.gif old mode 100755 new mode 100644 diff --git a/pix/i/settings.gif b/pix/i/settings.gif old mode 100755 new mode 100644 diff --git a/pix/i/show.gif b/pix/i/show.gif old mode 100755 new mode 100644 diff --git a/pix/i/stats.gif b/pix/i/stats.gif old mode 100755 new mode 100644 diff --git a/pix/i/switch.gif b/pix/i/switch.gif old mode 100755 new mode 100644 diff --git a/pix/i/unlock.gif b/pix/i/unlock.gif old mode 100755 new mode 100644 diff --git a/pix/i/user.gif b/pix/i/user.gif old mode 100755 new mode 100644 diff --git a/pix/i/users.gif b/pix/i/users.gif old mode 100755 new mode 100644 diff --git a/pix/m/USD.gif b/pix/m/USD.gif old mode 100755 new mode 100644 diff --git a/pix/madewithmoodle.gif b/pix/madewithmoodle.gif old mode 100755 new mode 100644 diff --git a/pix/moodlelogo-med-white.gif b/pix/moodlelogo-med-white.gif old mode 100755 new mode 100644 diff --git a/pix/moodlelogo-med.gif b/pix/moodlelogo-med.gif old mode 100755 new mode 100644 diff --git a/pix/moodlelogo.gif b/pix/moodlelogo.gif old mode 100755 new mode 100644 diff --git a/pix/movehere.gif b/pix/movehere.gif old mode 100755 new mode 100644 diff --git a/pix/s/angry.gif b/pix/s/angry.gif old mode 100755 new mode 100644 diff --git a/pix/s/approve.gif b/pix/s/approve.gif old mode 100755 new mode 100644 diff --git a/pix/s/biggrin.gif b/pix/s/biggrin.gif old mode 100755 new mode 100644 diff --git a/pix/s/blackeye.gif b/pix/s/blackeye.gif old mode 100755 new mode 100644 diff --git a/pix/s/blush.gif b/pix/s/blush.gif old mode 100755 new mode 100644 diff --git a/pix/s/clown.gif b/pix/s/clown.gif old mode 100755 new mode 100644 diff --git a/pix/s/cool.gif b/pix/s/cool.gif old mode 100755 new mode 100644 diff --git a/pix/s/dead.gif b/pix/s/dead.gif old mode 100755 new mode 100644 diff --git a/pix/s/egg.gif b/pix/s/egg.gif old mode 100755 new mode 100644 diff --git a/pix/s/evil.gif b/pix/s/evil.gif old mode 100755 new mode 100644 diff --git a/pix/s/heart.gif b/pix/s/heart.gif old mode 100755 new mode 100644 diff --git a/pix/s/kiss.gif b/pix/s/kiss.gif old mode 100755 new mode 100644 diff --git a/pix/s/martin.gif b/pix/s/martin.gif old mode 100755 new mode 100644 diff --git a/pix/s/mixed.gif b/pix/s/mixed.gif old mode 100755 new mode 100644 diff --git a/pix/s/no.gif b/pix/s/no.gif old mode 100755 new mode 100644 diff --git a/pix/s/sad.gif b/pix/s/sad.gif old mode 100755 new mode 100644 diff --git a/pix/s/shy.gif b/pix/s/shy.gif old mode 100755 new mode 100644 diff --git a/pix/s/sleepy.gif b/pix/s/sleepy.gif old mode 100755 new mode 100644 diff --git a/pix/s/smiley.gif b/pix/s/smiley.gif old mode 100755 new mode 100644 diff --git a/pix/s/surprise.gif b/pix/s/surprise.gif old mode 100755 new mode 100644 diff --git a/pix/s/thoughtful.gif b/pix/s/thoughtful.gif old mode 100755 new mode 100644 diff --git a/pix/s/tongueout.gif b/pix/s/tongueout.gif old mode 100755 new mode 100644 diff --git a/pix/s/wideeyes.gif b/pix/s/wideeyes.gif old mode 100755 new mode 100644 diff --git a/pix/s/wink.gif b/pix/s/wink.gif old mode 100755 new mode 100644 diff --git a/pix/s/yes.gif b/pix/s/yes.gif old mode 100755 new mode 100644 diff --git a/pix/spacer.gif b/pix/spacer.gif old mode 100755 new mode 100644 diff --git a/pix/t/backup.gif b/pix/t/backup.gif old mode 100755 new mode 100644 diff --git a/pix/t/email.gif b/pix/t/email.gif old mode 100755 new mode 100644 diff --git a/pix/t/emailno.gif b/pix/t/emailno.gif old mode 100755 new mode 100644 diff --git a/pix/t/go.gif b/pix/t/go.gif old mode 100755 new mode 100644 diff --git a/pix/t/groupn.gif b/pix/t/groupn.gif old mode 100755 new mode 100644 diff --git a/pix/t/groups.gif b/pix/t/groups.gif old mode 100755 new mode 100644 diff --git a/pix/t/groupv.gif b/pix/t/groupv.gif old mode 100755 new mode 100644 diff --git a/pix/t/left.gif b/pix/t/left.gif old mode 100755 new mode 100644 diff --git a/pix/t/lock.gif b/pix/t/lock.gif old mode 100755 new mode 100644 diff --git a/pix/t/log.gif b/pix/t/log.gif old mode 100755 new mode 100644 diff --git a/pix/t/message.gif b/pix/t/message.gif old mode 100755 new mode 100644 diff --git a/pix/t/move.gif b/pix/t/move.gif old mode 100755 new mode 100644 diff --git a/pix/t/preview.gif b/pix/t/preview.gif old mode 100755 new mode 100644 diff --git a/pix/t/restore.gif b/pix/t/restore.gif old mode 100755 new mode 100644 diff --git a/pix/t/right.gif b/pix/t/right.gif old mode 100755 new mode 100644 diff --git a/pix/t/stop.gif b/pix/t/stop.gif old mode 100755 new mode 100644 diff --git a/pix/t/unlock.gif b/pix/t/unlock.gif old mode 100755 new mode 100644 diff --git a/pix/t/user.gif b/pix/t/user.gif old mode 100755 new mode 100644 diff --git a/pix/t/usernot.gif b/pix/t/usernot.gif old mode 100755 new mode 100644 diff --git a/pix/u/f1.png b/pix/u/f1.png old mode 100755 new mode 100644 diff --git a/pix/u/f2.png b/pix/u/f2.png old mode 100755 new mode 100644 diff --git a/pix/webding.png b/pix/webding.png old mode 100755 new mode 100644 diff --git a/portfolio/download/simpletest/testportfolioplugindownload.php b/portfolio/download/simpletest/testportfolioplugindownload.php old mode 100755 new mode 100644 diff --git a/portfolio/flickr/lib.php b/portfolio/flickr/lib.php old mode 100755 new mode 100644 diff --git a/portfolio/flickr/version.php b/portfolio/flickr/version.php old mode 100755 new mode 100644 diff --git a/question/format/examview/format.php b/question/format/examview/format.php old mode 100755 new mode 100644 diff --git a/question/format/gift/format.php b/question/format/gift/format.php old mode 100755 new mode 100644 diff --git a/question/format/learnwise/format.php b/question/format/learnwise/format.php old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/choice.tpl b/question/format/qti_two/templates/choice.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/choiceMultiple.tpl b/question/format/qti_two/templates/choiceMultiple.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/composite.tpl b/question/format/qti_two/templates/composite.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/extendedText.tpl b/question/format/qti_two/templates/extendedText.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/extendedText_simpleEssay.tpl b/question/format/qti_two/templates/extendedText_simpleEssay.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/imsmanifest.tpl b/question/format/qti_two/templates/imsmanifest.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/mmchoiceMultiple.tpl b/question/format/qti_two/templates/mmchoiceMultiple.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/notimplemented.tpl b/question/format/qti_two/templates/notimplemented.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/numerical.tpl b/question/format/qti_two/templates/numerical.tpl old mode 100755 new mode 100644 diff --git a/question/format/qti_two/templates/textEntry.tpl b/question/format/qti_two/templates/textEntry.tpl old mode 100755 new mode 100644 diff --git a/question/format/xhtml/format.php b/question/format/xhtml/format.php old mode 100755 new mode 100644 diff --git a/question/format/xml/format.php b/question/format/xml/format.php old mode 100755 new mode 100644 diff --git a/question/type/calculated/pix/icon.gif b/question/type/calculated/pix/icon.gif old mode 100755 new mode 100644 diff --git a/repository/alfresco/lib.php b/repository/alfresco/lib.php old mode 100755 new mode 100644 diff --git a/repository/boxnet/lib.php b/repository/boxnet/lib.php old mode 100755 new mode 100644 diff --git a/repository/boxnet/version.php b/repository/boxnet/version.php old mode 100755 new mode 100644 diff --git a/repository/coursefiles/db/access.php b/repository/coursefiles/db/access.php old mode 100755 new mode 100644 diff --git a/repository/coursefiles/lang/en/repository_coursefiles.php b/repository/coursefiles/lang/en/repository_coursefiles.php old mode 100755 new mode 100644 diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php old mode 100755 new mode 100644 diff --git a/repository/coursefiles/pix/icon.png b/repository/coursefiles/pix/icon.png old mode 100755 new mode 100644 diff --git a/repository/coursefiles/version.php b/repository/coursefiles/version.php old mode 100755 new mode 100644 diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php old mode 100755 new mode 100644 diff --git a/repository/draftfiles_manager.php b/repository/draftfiles_manager.php old mode 100755 new mode 100644 diff --git a/repository/dropbox/db/access.php b/repository/dropbox/db/access.php old mode 100755 new mode 100644 diff --git a/repository/dropbox/lang/en/repository_dropbox.php b/repository/dropbox/lang/en/repository_dropbox.php old mode 100755 new mode 100644 diff --git a/repository/dropbox/version.php b/repository/dropbox/version.php old mode 100755 new mode 100644 diff --git a/repository/filepicker.php b/repository/filepicker.php old mode 100755 new mode 100644 diff --git a/repository/flickr/lib.php b/repository/flickr/lib.php old mode 100755 new mode 100644 diff --git a/repository/flickr_public/image.php b/repository/flickr_public/image.php old mode 100755 new mode 100644 diff --git a/repository/local/lib.php b/repository/local/lib.php old mode 100755 new mode 100644 diff --git a/repository/merlot/db/access.php b/repository/merlot/db/access.php old mode 100755 new mode 100644 diff --git a/repository/merlot/lib.php b/repository/merlot/lib.php old mode 100755 new mode 100644 diff --git a/repository/merlot/pix/icon.png b/repository/merlot/pix/icon.png old mode 100755 new mode 100644 diff --git a/repository/merlot/version.php b/repository/merlot/version.php old mode 100755 new mode 100644 diff --git a/repository/recent/lib.php b/repository/recent/lib.php old mode 100755 new mode 100644 diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php old mode 100755 new mode 100644 diff --git a/repository/repository_callback.php b/repository/repository_callback.php old mode 100755 new mode 100644 diff --git a/repository/upload/lib.php b/repository/upload/lib.php old mode 100755 new mode 100644 diff --git a/repository/upload/pix/icon.png b/repository/upload/pix/icon.png old mode 100755 new mode 100644 diff --git a/repository/url/pix/icon.png b/repository/url/pix/icon.png old mode 100755 new mode 100644 diff --git a/repository/user/db/install.php b/repository/user/db/install.php old mode 100755 new mode 100644 diff --git a/repository/user/lang/en/repository_user.php b/repository/user/lang/en/repository_user.php old mode 100755 new mode 100644 diff --git a/repository/user/lib.php b/repository/user/lib.php old mode 100755 new mode 100644 diff --git a/repository/user/pix/icon.png b/repository/user/pix/icon.png old mode 100755 new mode 100644 diff --git a/repository/user/version.php b/repository/user/version.php old mode 100755 new mode 100644 diff --git a/search/Zend/Exception.php b/search/Zend/Exception.php old mode 100755 new mode 100644 diff --git a/theme/anomaly/pix/tab/right_last.gif b/theme/anomaly/pix/tab/right_last.gif old mode 100755 new mode 100644 diff --git a/theme/anomaly/pix/tab/rtlbg.gif b/theme/anomaly/pix/tab/rtlbg.gif old mode 100755 new mode 100644 diff --git a/theme/anomaly/pix/tab/tabrow1.gif b/theme/anomaly/pix/tab/tabrow1.gif old mode 100755 new mode 100644 diff --git a/theme/boxxie/pix/tab/right_last.gif b/theme/boxxie/pix/tab/right_last.gif old mode 100755 new mode 100644 diff --git a/theme/boxxie/pix/tab/rtlbg.gif b/theme/boxxie/pix/tab/rtlbg.gif old mode 100755 new mode 100644 diff --git a/theme/boxxie/pix/tab/tabrow1.gif b/theme/boxxie/pix/tab/tabrow1.gif old mode 100755 new mode 100644 diff --git a/theme/fusion/pix/header-bg.jpg b/theme/fusion/pix/header-bg.jpg old mode 100755 new mode 100644 diff --git a/theme/fusion/pix/header-center.jpg b/theme/fusion/pix/header-center.jpg old mode 100755 new mode 100644 diff --git a/theme/fusion/pix/main-bg.gif b/theme/fusion/pix/main-bg.gif old mode 100755 new mode 100644 diff --git a/theme/fusion/pix/side-bg.png b/theme/fusion/pix/side-bg.png old mode 100755 new mode 100644 diff --git a/theme/fusion/pix/side-start.png b/theme/fusion/pix/side-start.png old mode 100755 new mode 100644 diff --git a/theme/nonzero/lib.php b/theme/nonzero/lib.php old mode 100755 new mode 100644 diff --git a/theme/nonzero/settings.php b/theme/nonzero/settings.php old mode 100755 new mode 100644 diff --git a/theme/standard/pix/tab/right_last.gif b/theme/standard/pix/tab/right_last.gif old mode 100755 new mode 100644 diff --git a/theme/standard/pix/tab/rtlbg.gif b/theme/standard/pix/tab/rtlbg.gif old mode 100755 new mode 100644 diff --git a/theme/standard/pix/tab/tabrow1.gif b/theme/standard/pix/tab/tabrow1.gif old mode 100755 new mode 100644 diff --git a/user/default/f1.jpg b/user/default/f1.jpg old mode 100755 new mode 100644 diff --git a/user/default/f2.jpg b/user/default/f2.jpg old mode 100755 new mode 100644 diff --git a/user/emailupdate.php b/user/emailupdate.php old mode 100755 new mode 100644 diff --git a/user/filters/date.php b/user/filters/date.php old mode 100755 new mode 100644 From faceca9176370f64bb6db9e6b910fba479f2a498 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 1 Mar 2011 17:22:00 +0100 Subject: [PATCH 037/369] MDL-26564 fix reversed password policy check --- admin/uploaduser.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/uploaduser.php b/admin/uploaduser.php index c2be9f1a67a..4fcd9b2f5c1 100755 --- a/admin/uploaduser.php +++ b/admin/uploaduser.php @@ -538,7 +538,7 @@ if ($formdata = $mform2->is_cancelled()) { } else if (!empty($user->password)) { if ($updatepasswords) { $errmsg = null; - $weak = check_password_policy($user->password, $errmsg); + $weak = !check_password_policy($user->password, $errmsg); if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) { if ($weak) { $weakpasswords++; @@ -644,7 +644,7 @@ if ($formdata = $mform2->is_cancelled()) { } } else { $errmsg = null; - $weak = check_password_policy($user->password, $errmsg); + $weak = !check_password_policy($user->password, $errmsg); if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) { if ($weak) { $weakpasswords++; From 2197b642b3cd66cc6661ee41b6fbff884c0d18e5 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 1 Mar 2011 17:29:52 +0100 Subject: [PATCH 038/369] MDL-26564 print password when changed --- admin/uploaduser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/uploaduser.php b/admin/uploaduser.php index 4fcd9b2f5c1..1861a5d1547 100755 --- a/admin/uploaduser.php +++ b/admin/uploaduser.php @@ -550,6 +550,7 @@ if ($formdata = $mform2->is_cancelled()) { } unset_user_preference('create_password', $existinguser); // no need to create password any more $existinguser->password = hash_internal_user_password($user->password); + $upt->track('password', $user->password, 'normal', false); } else { // do not print password when not changed $upt->track('password', '', 'normal', false); From 0b15b43b3ed2f05aa7c84b6551d67255e1faff9c Mon Sep 17 00:00:00 2001 From: Aaron Barnes Date: Thu, 17 Feb 2011 16:56:26 +1300 Subject: [PATCH 039/369] MDL-26190 completion blocks: Show messages rather than hiding the block --- blocks/completionstatus/block_completionstatus.php | 4 +++- blocks/selfcompletion/block_selfcompletion.php | 2 ++ blocks/selfcompletion/lang/en/block_selfcompletion.php | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/blocks/completionstatus/block_completionstatus.php b/blocks/completionstatus/block_completionstatus.php index 7a8e17b5624..0d7d1043652 100644 --- a/blocks/completionstatus/block_completionstatus.php +++ b/blocks/completionstatus/block_completionstatus.php @@ -49,6 +49,7 @@ class block_completionstatus extends block_base { // Don't display if completion isn't enabled! if (!$this->page->course->enablecompletion) { + $this->content->text = get_string('completionnotenabled', 'block_completionstatus'); return $this->content; } @@ -58,6 +59,7 @@ class block_completionstatus extends block_base { // Check if this course has any criteria if (empty($completions)) { + $this->content->text = get_string('nocriteria', 'block_completionstatus'); return $this->content; } @@ -157,7 +159,7 @@ class block_completionstatus extends block_base { // Is course complete? $coursecomplete = $info->is_course_complete($USER->id); - + // Load course completion $params = array( 'userid' => $USER->id, diff --git a/blocks/selfcompletion/block_selfcompletion.php b/blocks/selfcompletion/block_selfcompletion.php index f08eef57a7f..a5a7da9620d 100644 --- a/blocks/selfcompletion/block_selfcompletion.php +++ b/blocks/selfcompletion/block_selfcompletion.php @@ -54,6 +54,7 @@ class block_selfcompletion extends block_base { // Don't display if completion isn't enabled! if (!$this->page->course->enablecompletion) { + $this->content->text = get_string('completionnotenabled', 'block_selfcompletion'); return $this->content; } @@ -68,6 +69,7 @@ class block_selfcompletion extends block_base { // Check if self completion is one of this course's criteria if (empty($completion)) { + $this->content->text = get_string('selfcompletionnotenabled', 'block_selfcompletion'); return $this->content; } diff --git a/blocks/selfcompletion/lang/en/block_selfcompletion.php b/blocks/selfcompletion/lang/en/block_selfcompletion.php index 7b066a11f88..45775d854ef 100644 --- a/blocks/selfcompletion/lang/en/block_selfcompletion.php +++ b/blocks/selfcompletion/lang/en/block_selfcompletion.php @@ -26,3 +26,5 @@ $string['selfcompletion'] = 'Self completion'; $string['pluginname'] = 'Self completion'; $string['completecourse'] = 'Complete course'; +$string['completionnotenabled'] = 'Course completion is not enabled'; +$string['selfcompletionnotenabled'] = 'The self completion criteria has not been enabled for this course'; From 84fed015d8bc83e327876a655b92c59a03967de1 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 2 Mar 2011 09:09:06 +0100 Subject: [PATCH 040/369] Revert "gradebook MDL-26228 moved scroll bar css from standard theme into base" This reverts commit 54c3b90ec6ded5c746b3904872a003ed9da82e7a. --- theme/base/style/grade.css | 2 +- theme/standard/style/grade.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/base/style/grade.css b/theme/base/style/grade.css index 52f098f5042..593f08a585e 100644 --- a/theme/base/style/grade.css +++ b/theme/base/style/grade.css @@ -15,7 +15,7 @@ #grade-aggregation-help code {display: block;margin-top: 7px;} .gradeexportlink {padding: 2em;text-align: center;} -.gradetreebox {margin-top:10px;overflow-x:auto;overflow-y:hidden;} +.gradetreebox {margin-top:10px;} .gradetreebox table {font-size: 0.8em;width: 100%;} .gradetreebox td.colspan, .gradetreebox tr.category .cell {background-color: #DDD;} diff --git a/theme/standard/style/grade.css b/theme/standard/style/grade.css index 5b901c0f78e..1f9c2dfef39 100644 --- a/theme/standard/style/grade.css +++ b/theme/standard/style/grade.css @@ -18,7 +18,7 @@ td.grade div.overridden {background-color: #DDDDDD;} .path-grade-report-grader .graderreportoverlay {background-color:#EEEEEE;border:1px solid black;padding:10px;} .path-grade-edit-tree .moving {background-color: #E8EEF7;} -.path-grade-edit-tree .gradetreebox {width:70%;padding-bottom:15px;} +.path-grade-edit-tree .gradetreebox {width:70%;padding-bottom:15px;overflow-x:auto;overflow-y:hidden;} .path-grade-edit-scale .scale_options, #page-admin-grade-edit-scale-index .scale_options {font-size: 0.8em;} From 48fe5c6cf923999b2052fc76848da1024c6d09a5 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Thu, 3 Mar 2011 18:26:24 +0100 Subject: [PATCH 041/369] weekly release --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 7287adaf4fe..67c36bab5b7 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011022100.01; // YYYYMMDD = date of the last version bump +$version = 2011030300.00; // YYYYMMDD = date of the last version bump // XX = daily increments -$release = '2.0.2+ (Build: 20110223)'; // Human-friendly version name +$release = '2.0.2+ (Build: 20110303)'; // Human-friendly version name From 98529b009b872d6ac6d905201d17441a1f6b2aee Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Wed, 2 Mar 2011 10:33:14 +0800 Subject: [PATCH 042/369] backup MDL-26572 made restore store null instead of 0 --- backup/moodle2/restore_stepslib.php | 35 +++++++++---------- .../plan/restore_structure_step.class.php | 8 +++-- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index eace0149591..7708d33e994 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -148,14 +148,14 @@ class restore_gradebook_structure_step extends restore_structure_step { //manual grade items store category id in categoryid if ($data->itemtype=='manual') { - $data->categoryid = $this->get_mappingid('grade_category', $data->categoryid); + $data->categoryid = $this->get_mappingid('grade_category', $data->categoryid, NULL); } //course and category grade items store their category id in iteminstance else if ($data->itemtype=='course' || $data->itemtype=='category') { - $data->iteminstance = $this->get_mappingid('grade_category', $data->iteminstance); + $data->iteminstance = $this->get_mappingid('grade_category', $data->iteminstance, NULL); } - $data->scaleid = $this->get_mappingid('scale', $data->scaleid); - $data->outcomeid = $this->get_mappingid('outcome', $data->outcomeid); + $data->scaleid = $this->get_mappingid('scale', $data->scaleid, NULL); + $data->outcomeid = $this->get_mappingid('outcome', $data->outcomeid, NULL); $data->locktime = $this->apply_date_offset($data->locktime); $data->timecreated = $this->apply_date_offset($data->timecreated); @@ -164,23 +164,19 @@ class restore_gradebook_structure_step extends restore_structure_step { $coursecategory = $newitemid = null; //course grade item should already exist so updating instead of inserting if($data->itemtype=='course') { - //get the ID of the already created grade item $gi = new stdclass(); $gi->courseid = $this->get_courseid(); - $gi->itemtype = $data->itemtype; - if ($data->itemtype=='course') { - //need to get the id of the grade_category that was automatically created for the course - $category = new stdclass(); - $category->courseid = $this->get_courseid(); - $category->parent = null; - //course category fullname starts out as ? but may be edited - //$category->fullname = '?'; - $coursecategory = $DB->get_record('grade_categories', (array)$category); - $gi->iteminstance = $coursecategory->id; - } + //need to get the id of the grade_category that was automatically created for the course + $category = new stdclass(); + $category->courseid = $this->get_courseid(); + $category->parent = null; + //course category fullname starts out as ? but may be edited + //$category->fullname = '?'; + $coursecategory = $DB->get_record('grade_categories', (array)$category); + $gi->iteminstance = $coursecategory->id; $existinggradeitem = $DB->get_record('grade_items', (array)$gi); if (!empty($existinggradeitem)) { @@ -208,8 +204,8 @@ class restore_gradebook_structure_step extends restore_structure_step { $data->itemid = $this->get_new_parentid('grade_item'); - $data->userid = $this->get_mappingid('user', $data->userid); - $data->usermodified = $this->get_mappingid('user', $data->usermodified); + $data->userid = $this->get_mappingid('user', $data->userid, NULL); + $data->usermodified = $this->get_mappingid('user', $data->usermodified, NULL); $data->locktime = $this->apply_date_offset($data->locktime); // TODO: Ask, all the rest of locktime/exported... work with time... to be rolled? $data->overridden = $this->apply_date_offset($data->overridden); @@ -337,6 +333,9 @@ class restore_gradebook_structure_step extends restore_structure_step { } } $rs->close(); + + //Restore marks items as needing update. Update everything now. + grade_regrade_final_grades($this->get_courseid()); } } diff --git a/backup/util/plan/restore_structure_step.class.php b/backup/util/plan/restore_structure_step.class.php index 970605e2906..927f71c7f01 100644 --- a/backup/util/plan/restore_structure_step.class.php +++ b/backup/util/plan/restore_structure_step.class.php @@ -196,11 +196,13 @@ abstract class restore_structure_step extends restore_step { /** * Return the new id of a mapping for the given itemname - * + * @param string $itemname the type of item. For example 'scale' or 'outcome' + * @param int $oldid the item ID from the backup + * @param $ifnotfound what to return if $oldid wasnt found */ - public function get_mappingid($itemname, $oldid) { + public function get_mappingid($itemname, $oldid, $ifnotfound = false) { $mapping = $this->get_mapping($itemname, $oldid); - return $mapping ? $mapping->newitemid : false; + return $mapping ? $mapping->newitemid : $ifnotfound; } /** From 3d673fc4740f4a2c361590f8600b93ecdcabc1fb Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 25 Feb 2011 23:39:42 +0100 Subject: [PATCH 043/369] MDL-26609 Admins are warned if they try to install or upgrade to unstable version The commit introduces four new constants that can be used to declare a maturity level of Moodle core and, in the future, of extension plugins. If the administrator is about to install or upgrade Moodle to a version that is not considered as production-ready yet, a warning is displayed before any change in the database. --- admin/cli/install.php | 30 +++++++++++++++++++++++++++--- admin/cli/upgrade.php | 32 +++++++++++++++++++++++++++++--- admin/index.php | 20 ++++++++++++++++++-- lang/en/admin.php | 7 +++++++ lib/setuplib.php | 8 ++++++++ theme/standard/style/admin.css | 5 ++++- version.php | 9 ++++++--- 7 files changed, 99 insertions(+), 12 deletions(-) diff --git a/admin/cli/install.php b/admin/cli/install.php index 3378948d7c3..0631be1c869 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -70,6 +70,8 @@ Options: problem encountered. --agree-license Indicates agreement with software license, required in non-interactive mode. +--allow-unstable Install even if the version is not marked as stable yet, + required in non-interactive mode. -h, --help Print out this help Example: @@ -136,9 +138,6 @@ $CFG->early_install_lang = true; $parts = explode('/', str_replace('\\', '/', dirname(dirname(__FILE__)))); $CFG->admin = array_pop($parts); -require($CFG->dirroot.'/version.php'); -$CFG->target_release = $release; - //point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else //the problem is that we need specific version of quickforms and hacked excel files :-( ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path')); @@ -154,6 +153,9 @@ require_once($CFG->libdir.'/deprecatedlib.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/componentlib.class.php'); +require($CFG->dirroot.'/version.php'); +$CFG->target_release = $release; + //Database types $databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'), 'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'), @@ -193,6 +195,7 @@ list($options, $unrecognized) = cli_get_params( 'adminpass' => '', 'non-interactive' => false, 'agree-license' => false, + 'allow-unstable' => false, 'help' => false ), array( @@ -402,6 +405,27 @@ $CFG->langotherroot = $CFG->dataroot.'/lang'; $CFG->langlocalroot = $CFG->dataroot.'/lang'; get_string_manager(true); +// make sure we are installing stable release or require a confirmation +if (isset($maturity)) { + if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) { + $maturitylevel = get_string('maturity'.$maturity, 'admin'); + + if ($interactive) { + cli_separator(); + cli_heading(get_string('notice')); + echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL; + echo get_string('continue') . PHP_LOL; + $prompt = get_string('cliyesnoprompt', 'admin'); + $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin'))); + if ($input == get_string('clianswerno', 'admin')) { + exit(1); + } + } else { + cli_error(get_string('maturitycorewarning', 'admin')); + } + } +} + // ask for db type - show only drivers available if ($interactive) { $options['dbtype'] = strtolower($options['dbtype']); diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 142f2d30514..0057426d39e 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -40,8 +40,16 @@ require_once($CFG->libdir.'/environmentlib.php'); // now get cli options -list($options, $unrecognized) = cli_get_params(array('non-interactive'=>false, 'help'=>false), - array('h'=>'help')); +list($options, $unrecognized) = cli_get_params( + array( + 'non-interactive' => false, + 'allow-unstable' => false, + 'help' => false + ), + array( + 'h' => 'help' + ) +); $interactive = empty($options['non-interactive']); @@ -59,6 +67,8 @@ Site defaults may be changed via local/defaults.php. Options: --non-interactive No interactive questions or confirmations +--allow-unstable Upgrade even if the version is not marked as stable yet, + required in non-interactive mode. -h, --help Print out this help Example: @@ -73,7 +83,7 @@ if (empty($CFG->version)) { cli_error(get_string('missingconfigversion', 'debug')); } -require("$CFG->dirroot/version.php"); // defines $version and $release +require("$CFG->dirroot/version.php"); // defines $version, $release and $maturity $CFG->target_release = $release; // used during installation and upgrades if ($version < $CFG->version) { @@ -93,6 +103,22 @@ if (!check_moodle_environment($version, $environment_results, false, ENV_SELECT_ exit(1); } +// make sure we are upgrading to a stable release or display a warning +if (isset($maturity)) { + if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) { + $maturitylevel = get_string('maturity'.$maturity, 'admin'); + + if ($interactive) { + cli_separator(); + cli_heading(get_string('notice')); + echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL; + cli_separator(); + } else { + cli_error(get_string('maturitycorewarning', 'admin', $maturitylevel)); + } + } +} + if ($interactive) { echo html_to_text(get_string('upgradesure', 'admin', $newversion))."\n"; $prompt = get_string('cliyesnoprompt', 'admin'); diff --git a/admin/index.php b/admin/index.php index 14b6f243321..09f79472d30 100644 --- a/admin/index.php +++ b/admin/index.php @@ -86,7 +86,7 @@ if (!isset($CFG->version)) { $version = null; $release = null; -require("$CFG->dirroot/version.php"); // defines $version and $release +require("$CFG->dirroot/version.php"); // defines $version, $release and $maturity $CFG->target_release = $release; // used during installation and upgrades if (!$version or !$release) { @@ -135,9 +135,18 @@ if (!core_tables_exist()) { $PAGE->set_cacheable(false); echo $OUTPUT->header(); echo $OUTPUT->heading("Moodle $release"); + + if (isset($maturity)) { + // main version.php declares moodle code maturity + if ($maturity < MATURITY_STABLE) { + $maturitylevel = get_string('maturity'.$maturity, 'admin'); + echo $OUTPUT->box(get_string('maturitycorewarning', 'admin', $maturitylevel), 'generalbox maturitywarning'); + } + } + $releasenoteslink = get_string('releasenoteslink', 'admin', 'http://docs.moodle.org/en/Release_Notes'); $releasenoteslink = str_replace('target="_blank"', 'onclick="this.target=\'_blank\'"', $releasenoteslink); // extremely ugly validation hack - echo $OUTPUT->box($releasenoteslink, 'generalbox boxaligncenter boxwidthwide'); + echo $OUTPUT->box($releasenoteslink, 'generalbox releasenoteslink'); require_once($CFG->libdir.'/environmentlib.php'); if (!check_moodle_environment($release, $environment_results, true, ENV_SELECT_RELEASE)) { @@ -194,6 +203,13 @@ if ($version > $CFG->version) { // upgrade $PAGE->set_heading($stradministration); $PAGE->set_cacheable(false); echo $OUTPUT->header(); + if (isset($maturity)) { + // main version.php declares moodle code maturity + if ($maturity < MATURITY_STABLE) { + $maturitylevel = get_string('maturity'.$maturity, 'admin'); + echo $OUTPUT->box(get_string('maturitycorewarning', 'admin', $maturitylevel), 'generalbox maturitywarning'); + } + } $continueurl = new moodle_url('index.php', array('confirmupgrade' => 1)); $cancelurl = new moodle_url('index.php'); echo $OUTPUT->confirm(get_string('upgradesure', 'admin', $a->newversion), $continueurl, $cancelurl); diff --git a/lang/en/admin.php b/lang/en/admin.php index d11e5ff52d9..178c85c3d24 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -680,6 +680,13 @@ $string['maintinprogress'] = 'Maintenance is in progress...'; $string['managelang'] = 'Manage'; $string['managelicenses'] = 'Manage licences'; $string['manageqtypes'] = 'Manage question types'; +$string['maturity50'] = 'Alpha'; +$string['maturity100'] = 'Beta'; +$string['maturity150'] = 'Release candidate'; +$string['maturity200'] = 'Stable version'; +$string['maturitycorewarning'] = 'You are going to install or upgrade Moodle to a version marked as "{$a}" +that is not considered as production-ready yet. Please make sure this is intentional +and that you are using correct checkout of Moodle source code.'; $string['maxbytes'] = 'Maximum uploaded file size'; $string['maxconsecutiveidentchars'] = 'Consecutive identical characters'; $string['maxeditingtime'] = 'Maximum time to edit posts'; diff --git a/lib/setuplib.php b/lib/setuplib.php index 12c543d6528..c4b07ee06d1 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -53,6 +53,14 @@ define('MEMORY_EXTRA', -3); /** Extremely large memory limit - not recommended for standard scripts */ define('MEMORY_HUGE', -4); +/** + * Software maturity levels used by the core and plugins + */ +define('MATURITY_ALPHA', 50); // internals can be tested using white box techniques +define('MATURITY_BETA', 100); // feature complete, ready for preview and testing +define('MATURITY_RC', 150); // tested, will be released unless there are fatal bugs +define('MATURITY_STABLE', 200); // ready for production deployment + /** * Simple class. It is usually used instead of stdClass because it looks * more familiar to Java developers ;-) Do not use for type checking of diff --git a/theme/standard/style/admin.css b/theme/standard/style/admin.css index 36b5694eb60..7beb53b6c84 100644 --- a/theme/standard/style/admin.css +++ b/theme/standard/style/admin.css @@ -23,6 +23,9 @@ #page-admin-index .adminerror, #page-admin-index .adminwarning {margin:20px;} +#page-admin-index .maturitywarning {margin-left:auto;margin-right:auto;text-align:center;width:60%;background-color:#ffd3d9;} +#page-admin-index .releasenoteslink {margin-left:auto;margin-right:auto;text-align:center;width:60%;} + #page-admin-enrol .enrolplugintable {width:700px;margin:1em auto;} #page-admin-report-capability-index #settingsform h2, @@ -144,4 +147,4 @@ table.flexible .r1 {background-color: #FAFAFA;} */ #page-admin-webservice-service_users .missingcaps {color: #ff6600;font-size: 90%;} #page-admin-setting-webservicetokens .missingcaps {color: #ff6600;font-size: 90%;} -#page-admin-webservice-service_functions .functiondesc {font-size: 90%;} \ No newline at end of file +#page-admin-webservice-service_functions .functiondesc {font-size: 90%;} diff --git a/version.php b/version.php index 67c36bab5b7..cf98cffa610 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,10 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011030300.00; // YYYYMMDD = date of the last version bump - // XX = daily increments -$release = '2.0.2+ (Build: 20110303)'; // Human-friendly version name +$version = 2011030300.00; // YYYYMMDD = date of the last version bump + // XX = daily increments + +$release = '2.0.2+ (Build: 20110303)'; // Human-friendly version name + +$maturity = MATURITY_STABLE; // this version's maturity level From dc41abd8082797cfedf92ff15b0c0fc4a7bc4e2c Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 3 Mar 2011 16:54:04 +0100 Subject: [PATCH 044/369] MDL-26609 Provide a link to a docs page for more help with Moodle versions and their maturity Thanks Martin Dougiamas for this suggestion. --- admin/cli/install.php | 1 + admin/cli/upgrade.php | 1 + admin/index.php | 12 +++++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/admin/cli/install.php b/admin/cli/install.php index 0631be1c869..0acea3d326c 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -414,6 +414,7 @@ if (isset($maturity)) { cli_separator(); cli_heading(get_string('notice')); echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL; + echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL; echo get_string('continue') . PHP_LOL; $prompt = get_string('cliyesnoprompt', 'admin'); $input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin'))); diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 0057426d39e..8bd8b204fa3 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -112,6 +112,7 @@ if (isset($maturity)) { cli_separator(); cli_heading(get_string('notice')); echo get_string('maturitycorewarning', 'admin', $maturitylevel) . PHP_EOL; + echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL; cli_separator(); } else { cli_error(get_string('maturitycorewarning', 'admin', $maturitylevel)); diff --git a/admin/index.php b/admin/index.php index 09f79472d30..ddc0cbad385 100644 --- a/admin/index.php +++ b/admin/index.php @@ -140,7 +140,10 @@ if (!core_tables_exist()) { // main version.php declares moodle code maturity if ($maturity < MATURITY_STABLE) { $maturitylevel = get_string('maturity'.$maturity, 'admin'); - echo $OUTPUT->box(get_string('maturitycorewarning', 'admin', $maturitylevel), 'generalbox maturitywarning'); + echo $OUTPUT->box( + $OUTPUT->container(get_string('maturitycorewarning', 'admin', $maturitylevel)) . + $OUTPUT->container($OUTPUT->doc_link('admin/versions', get_string('morehelp'))), + 'generalbox maturitywarning'); } } @@ -207,8 +210,11 @@ if ($version > $CFG->version) { // upgrade // main version.php declares moodle code maturity if ($maturity < MATURITY_STABLE) { $maturitylevel = get_string('maturity'.$maturity, 'admin'); - echo $OUTPUT->box(get_string('maturitycorewarning', 'admin', $maturitylevel), 'generalbox maturitywarning'); - } + echo $OUTPUT->box( + $OUTPUT->container(get_string('maturitycorewarning', 'admin', $maturitylevel)) . + $OUTPUT->container($OUTPUT->doc_link('admin/versions', get_string('morehelp'))), + 'generalbox maturitywarning'); +} } $continueurl = new moodle_url('index.php', array('confirmupgrade' => 1)); $cancelurl = new moodle_url('index.php'); From 1a4d6a5b605c0b28fa1298f56f48fe80b4ee4b23 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 3 Mar 2011 17:16:11 +0100 Subject: [PATCH 045/369] MDL-26609 Display information about the current version during the upgrade As Eloy Lafuente noticed in the tracker discussion, we display the information about the current version in the browser window title but not at the screen itself. The patch fixes that by displaying the information in the page heading instead of the page title. Eloy's original idea to put the information into the grey message box would require a change of [upgradesure,core_admin] string because unfortunately it does not expect $a as an object but as a plain string. --- admin/cli/upgrade.php | 8 ++++++++ admin/index.php | 9 ++++----- lang/en/moodle.php | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 8bd8b204fa3..7e145f2ec9a 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -90,6 +90,7 @@ if ($version < $CFG->version) { cli_error(get_string('downgradedcore', 'error')); } +$oldversion = "$CFG->release ($CFG->version)"; $newversion = "$release ($version)"; // test environment first @@ -103,6 +104,13 @@ if (!check_moodle_environment($version, $environment_results, false, ENV_SELECT_ exit(1); } +if ($interactive) { + $a = new stdClass(); + $a->oldversion = $oldversion; + $a->newversion = $newversion; + echo cli_heading(get_string('databasechecking', '', $a)) . PHP_EOL; +} + // make sure we are upgrading to a stable release or display a warning if (isset($maturity)) { if (($maturity < MATURITY_STABLE) and !$options['allow-unstable']) { diff --git a/admin/index.php b/admin/index.php index ddc0cbad385..f40ad17512a 100644 --- a/admin/index.php +++ b/admin/index.php @@ -130,8 +130,8 @@ if (!core_tables_exist()) { if (empty($confirmrelease)) { $strcurrentrelease = get_string('currentrelease'); $PAGE->navbar->add($strcurrentrelease); - $PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release); - $PAGE->set_heading($strinstallation); + $PAGE->set_title($strinstallation); + $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release); $PAGE->set_cacheable(false); echo $OUTPUT->header(); echo $OUTPUT->heading("Moodle $release"); @@ -201,9 +201,8 @@ if ($version > $CFG->version) { // upgrade $strdatabasechecking = get_string('databasechecking', '', $a); if (empty($confirmupgrade)) { - $PAGE->navbar->add($strdatabasechecking); - $PAGE->set_title($strdatabasechecking); - $PAGE->set_heading($stradministration); + $PAGE->set_title($stradministration); + $PAGE->set_heading($strdatabasechecking); $PAGE->set_cacheable(false); echo $OUTPUT->header(); if (isset($maturity)) { diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 7c9d27dff65..1958e418b98 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -386,7 +386,7 @@ $string['currentlyselectedusers'] = 'Currently selected users'; $string['currentpicture'] = 'Current picture'; $string['currentrelease'] = 'Current release information'; $string['currentversion'] = 'Current version'; -$string['databasechecking'] = 'Upgrading Moodle database from version {$a->oldversion} to {$a->newversion}...'; +$string['databasechecking'] = 'Upgrading Moodle database from version {$a->oldversion} to {$a->newversion}'; $string['databaseperformance'] = 'Database performance'; $string['databasesetup'] = 'Setting up database'; $string['databasesuccess'] = 'Database was successfully upgraded'; From ea118bed0c289b6e39592133d8d3e0e56abff0b9 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 3 Mar 2011 15:35:50 +0100 Subject: [PATCH 046/369] MDL-20562 Do not use a capability name as a navigation node title Ideally all reports should use their pluginname in the navigation tree. In this particular case, the patch fixes two issues: using the capability name as the report title in the navigation and incorrect pluginname defined for coursereport_log. --- course/report/log/lang/en/coursereport_log.php | 2 +- course/report/log/lib.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/course/report/log/lang/en/coursereport_log.php b/course/report/log/lang/en/coursereport_log.php index 3113eea5502..dc374083dd8 100644 --- a/course/report/log/lang/en/coursereport_log.php +++ b/course/report/log/lang/en/coursereport_log.php @@ -27,4 +27,4 @@ $string['loglive'] = 'Live logs'; $string['log:view'] = 'View course logs'; $string['log:viewlive'] = 'View live logs'; $string['log:viewtoday'] = 'View today\'s logs'; -$string['pluginname'] = 'Live logs'; +$string['pluginname'] = 'Logs'; diff --git a/course/report/log/lib.php b/course/report/log/lib.php index e12de536482..96cbdc70c9a 100644 --- a/course/report/log/lib.php +++ b/course/report/log/lib.php @@ -534,6 +534,6 @@ function log_report_extend_navigation($navigation, $course, $context) { global $CFG, $OUTPUT; if (has_capability('coursereport/log:view', $context)) { $url = new moodle_url('/course/report/log/index.php', array('id'=>$course->id)); - $navigation->add(get_string('log:view', 'coursereport_log'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '')); + $navigation->add(get_string('pluginname', 'coursereport_log'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '')); } } From 0c5e812ba7c43856b5193f03b75a3f7a3d51d686 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Fri, 4 Mar 2011 15:44:20 +0800 Subject: [PATCH 047/369] MDL-26392, nwiki and creole format wiki pages should support file attachments --- mod/wiki/edit_form.php | 28 +++--- mod/wiki/lang/en/wiki.php | 8 +- mod/wiki/locallib.php | 116 +++++++------------------ mod/wiki/pagelib.php | 14 +-- mod/wiki/parser/markups/wikimarkup.php | 21 ++++- mod/wiki/parser/parser.php | 4 +- 6 files changed, 82 insertions(+), 109 deletions(-) diff --git a/mod/wiki/edit_form.php b/mod/wiki/edit_form.php index 17f6d14e3d5..054555901f9 100644 --- a/mod/wiki/edit_form.php +++ b/mod/wiki/edit_form.php @@ -80,20 +80,20 @@ class mod_wiki_edit_form extends moodleform { $mform->addElement('hidden', 'contentformat'); $mform->setDefault('contentformat', $format); -// if ($format != 'html') { -// //uploads -// $mform->addElement('header', 'attachments_tags', get_string('attachments', 'wiki')); -// $mform->addElement('filemanager', 'attachments', get_string('attachments', 'wiki'), null, page_wiki_edit::$attachmentoptions); -// $fileinfo = array( -// 'contextid'=>$contextid, -// 'component'=>'mod_wiki', -// 'filearea'=>$filearea, -// 'itemid'=>$fileitemid, -// ); -// -// $mform->addElement('wikifiletable', 'deleteuploads', get_string('wikifiletable', 'wiki'), null, $fileinfo, $format); -// $mform->addElement('submit', 'editoption', get_string('upload', 'wiki'), array('id' => 'tags')); -// } + if ($format != 'html') { + //uploads + $mform->addElement('header', 'attachments_tags', get_string('uploadtitle', 'wiki')); + $mform->addElement('filemanager', 'attachments', '', null, page_wiki_edit::$attachmentoptions); + $fileinfo = array( + 'contextid'=>$contextid, + 'component'=>'mod_wiki', + 'filearea'=>$filearea, + 'itemid'=>$fileitemid, + ); + + //$mform->addElement('wikifiletable', 'deleteuploads', get_string('wikifiletable', 'wiki'), null, $fileinfo, $format); + //$mform->addElement('submit', 'editoption', get_string('upload', 'wiki'), array('id' => 'tags')); + } if (!empty($CFG->usetags)) { $mform->addElement('header', 'tagshdr', get_string('tags', 'tag')); diff --git a/mod/wiki/lang/en/wiki.php b/mod/wiki/lang/en/wiki.php index 5a2069cae2b..a12e3d594d2 100644 --- a/mod/wiki/lang/en/wiki.php +++ b/mod/wiki/lang/en/wiki.php @@ -68,12 +68,16 @@ To create a new page, type the new page name enclosed in double square brackets, $string['formatcreole'] = 'Creole format'; $string['formatcreole_help'] = 'Creole is a common wiki markup language with an edit toolbar for inserting appropriate markup. -To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]].'; +To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]]. + +To insert image, attach the image files in file manager, then reference the file name using creole markup language.'; $string['formatcreole_link'] = 'mod/wiki/creole'; $string['formatnwiki'] = 'NWiki format'; $string['formatnwiki_help'] = 'Nwiki is the Mediawiki-like markup language used in the contributed Nwiki module. -To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]].'; +To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]]. + +To insert image, attach the image files in file manager, then reference the file name using nwiki markup language.'; $string['formatnwiki_link'] = 'mod/wiki/nwiki'; $string['history'] = 'History'; $string['history_help'] = 'The history lists links to previous versions of the page.'; diff --git a/mod/wiki/locallib.php b/mod/wiki/locallib.php index 91feed29b3a..5a284dbcc8c 100644 --- a/mod/wiki/locallib.php +++ b/mod/wiki/locallib.php @@ -578,7 +578,23 @@ function wiki_parse_content($markup, $pagecontent, $options = array()) { $cm = get_coursemodule_from_instance("wiki", $subwiki->wikiid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); - $parser_options = array('link_callback' => '/mod/wiki/locallib.php:wiki_parser_link', 'link_callback_args' => array('swid' => $options['swid']), 'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table', 'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path', 'real_path_callback_args' => array('context' => $context, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'pageid' => $options['pageid']), 'pageid' => $options['pageid'], 'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']), 'printable' => (isset($options['printable']) && $options['printable'])); + $parser_options = array('link_callback' => '/mod/wiki/locallib.php:wiki_parser_link', + 'link_callback_args' => array('swid' => $options['swid']), + 'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table', + 'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path', + 'real_path_callback_args' => array( + 'context' => $context, + 'component' => 'mod_wiki', + 'filearea' => 'attachments', + 'subwikiid'=> $subwiki->id, + 'pageid' => $options['pageid'] + ), + 'preview' => !empty($options['preview']) ? true : false, + 'itemid' => !empty($options['itemid']) ? $options['itemid'] : null, + 'pageid' => $options['pageid'], + 'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']), + 'printable' => (isset($options['printable']) && $options['printable']) + ); return wiki_parser_proxy::parse($pagecontent, $markup, $parser_options); } @@ -661,7 +677,7 @@ function wiki_parser_table($table) { /** * Returns an absolute path link, unless there is no such link. * - * @param string url Link's URL + * @param string url Link's URL or filename * @param stdClass context filearea params * @param string filearea * @param int fileareaid @@ -669,13 +685,26 @@ function wiki_parser_table($table) { * @return File full path */ -function wiki_parser_real_path($url, $context, $filearea, $fileareaid) { +function wiki_parser_real_path($url, $context, $component, $filearea, $swid) { global $CFG; if (preg_match("/^(?:http|ftp)s?\:\/\//", $url)) { return $url; } else { - return "{$CFG->wwwroot}/pluginfile.php/{$context->id}/$filearea/$fileareaid/$url"; + if ($context->contextlevel == CONTEXT_USER) { + // when preview wiki page, files are in draft area + $file = 'draftfile.php'; + } else if ($context->contextlevel == CONTEXT_MODULE) { + $file = 'pluginfile.php'; + } else { + $file = 'brokenfile.php#'; + } + if (!$CFG->slasharguments) { + $file = $file . '?file='; + } + $baseurl = "$CFG->wwwroot/$file/{$context->id}/$component/$filearea/$swid/"; + // it is a file in current file area + return $baseurl . $url; } } @@ -995,85 +1024,6 @@ function wiki_delete_old_locks() { $DB->delete_records_select('wiki_locks', "lockedat < ?", array(time() - 3600)); } -/** - * File processing - */ - -/** - * Uploads files to permanent disk space. - * - * @param int draftitemid Draft space ID - * @param int contextid - * - * @return array of files that have not been inserted. - */ - -function wiki_process_attachments($draftitemid, $deleteuploads, $contextid, $filearea, $itemid, $options = null) { - global $CFG, $USER; - - if (empty($options)) { - $options = page_wiki_edit::$attachmentoptions; - } - - $errors = array(); - - $usercontext = get_context_instance(CONTEXT_USER, $USER->id); - $fs = get_file_storage(); - - $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id'); - - foreach ($oldfiles as $file) { - if (in_array($file->get_pathnamehash(), $deleteuploads)) { - $file->delete(); - } - } - - $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); - $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id'); - - $file_record = array('contextid' => $contextid, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'itemid' => $itemid); - //more or less a merge... - $newhashes = array(); - foreach ($draftfiles as $file) { - $newhash = sha1("/$contextid/mod_wiki/attachments/$itemid" . $file->get_filepath() . $file->get_filename()); - $newhashes[$newhash] = $file; - } - - $filecount = 0; - foreach ($oldfiles as $file) { - $oldhash = $file->get_pathnamehash(); - if (!$file->is_directory() && isset($newhashes[$oldhash])) { - //repeated file: ERROR!!! - unset($newhashes[$oldhash]); - $errors[] = $file; - } - - if (!$file->is_directory()) { - $filecount++; - } - } - - foreach ($newhashes as $file) { - if ($file->get_filepath() !== '/' or $file->is_directory()) { - continue; - } - - if ($options['maxfiles'] and $options['maxfiles'] <= $filecount) { - break; - } - - if (!$file->is_directory()) { - $filecount++; - $fs->create_file_from_storedfile($file_record, $file); - } - } - - //delete all draft files - $fs->delete_area_files($usercontext->id, 'user', 'draft', $draftitemid); - - return $errors; -} - function wiki_get_comment($commentid){ global $DB; return $DB->get_record('comments', array('id' => $commentid)); diff --git a/mod/wiki/pagelib.php b/mod/wiki/pagelib.php index f49545eab25..d438765d581 100644 --- a/mod/wiki/pagelib.php +++ b/mod/wiki/pagelib.php @@ -367,7 +367,7 @@ class page_wiki_edit extends page_wiki { function __construct($wiki, $subwiki, $cm) { global $CFG, $PAGE; parent::__construct($wiki, $subwiki, $cm); - self::$attachmentoptions = array('subdirs' => false, 'maxfiles' => - 1, 'maxbytes' => $CFG->maxbytes, 'accepted_types' => '*'); + self::$attachmentoptions = array('subdirs' => false, 'maxfiles' => - 1, 'maxbytes' => $CFG->maxbytes, 'accepted_types' => 'image'); $PAGE->requires->js_init_call('M.mod_wiki.renew_lock', null, true); $PAGE->requires->yui2_lib('connection'); } @@ -540,9 +540,9 @@ class page_wiki_edit extends page_wiki { $data = file_prepare_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $context, 'mod_wiki', 'attachments', $this->subwiki->id); break; default: - //$draftitemid = file_get_submitted_draft_itemid('attachments'); - //file_prepare_draft_area($draftitemid, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); - //$data->attachments = $draftitemid; + $draftitemid = file_get_submitted_draft_itemid('attachments'); + file_prepare_draft_area($draftitemid, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); + $data->attachments = $draftitemid; } if ($version->contentformat != 'html') { @@ -588,7 +588,6 @@ class page_wiki_edit extends page_wiki { if ($this->upload) { file_save_draft_area_files($this->attachments, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); return null; - //return wiki_process_attachments($this->attachments, $this->deleteuploads, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); } } } @@ -1034,12 +1033,13 @@ class page_wiki_preview extends page_wiki_edit { $form = new mod_wiki_edit_form($url, $params); - $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true); + $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true, 'preview'=>true); if ($data = $form->get_data()) { if (isset($data->newcontent)) { // wiki fromat $text = $data->newcontent; + $options['itemid'] = $data->attachments; } else { // html format $text = $data->newcontent_editor['text']; @@ -1047,7 +1047,7 @@ class page_wiki_preview extends page_wiki_edit { $parseroutput = wiki_parse_content($data->contentformat, $text, $options); $this->set_newcontent($text); echo $OUTPUT->notification(get_string('previewwarning', 'wiki'), 'notifyproblem wiki_info'); - $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true)); + $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true, 'filter'=>false)); echo $OUTPUT->box($content, 'generalbox wiki_previewbox'); $content = $this->newcontent; } diff --git a/mod/wiki/parser/markups/wikimarkup.php b/mod/wiki/parser/markups/wikimarkup.php index 30976db0c6a..a748710074e 100644 --- a/mod/wiki/parser/markups/wikimarkup.php +++ b/mod/wiki/parser/markups/wikimarkup.php @@ -25,6 +25,10 @@ abstract class wiki_markup_parser extends generic_parser { //header & ToC protected $toc = array(); + /** @var boolean parse content for preview*/ + protected $preview = false; + /** @var int if preview, itemid will be required to generate file url */ + protected $itemid = null; /** * function wiki_parser_link_callback($link = "") @@ -143,6 +147,10 @@ abstract class wiki_markup_parser extends generic_parser { $this->printable = true; } break; + case 'preview': + $this->preview = $options['preview']; + $this->itemid = $options['itemid']; + break; } } } @@ -324,7 +332,18 @@ abstract class wiki_markup_parser extends generic_parser { } protected function real_path($url) { - $callbackargs = array_merge(array($url), $this->realpathcallbackargs); + global $USER; + if ($this->preview) { + // when preview wiki page, images are in draft area + $callbackargs = array(); + $callbackargs[] = $url; + $callbackargs[] = get_context_instance(CONTEXT_USER, $USER->id); + $callbackargs[] = 'user'; + $callbackargs[] = 'draft'; + $callbackargs[] = $this->itemid; + } else { + $callbackargs = array_merge(array($url), $this->realpathcallbackargs); + } return call_user_func_array($this->realpathcallback, $callbackargs); } diff --git a/mod/wiki/parser/parser.php b/mod/wiki/parser/parser.php index b8af04df213..122061ccd05 100644 --- a/mod/wiki/parser/parser.php +++ b/mod/wiki/parser/parser.php @@ -139,8 +139,8 @@ abstract class generic_parser { /** * Initialize options */ - - protected function set_options($options) {} + protected function set_options($options) { + } /** * Block processing function & callbacks From 3479ba4d4887b227933c3fb88e65653cba1158ab Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Fri, 18 Feb 2011 01:08:58 +0100 Subject: [PATCH 048/369] MDL-26458 sqlsrv - limit impl using scrollable sets --- lib/dml/sqlsrv_native_moodle_database.php | 125 +++------------------- 1 file changed, 15 insertions(+), 110 deletions(-) diff --git a/lib/dml/sqlsrv_native_moodle_database.php b/lib/dml/sqlsrv_native_moodle_database.php index ac6e42aaf3d..a319935d06b 100644 --- a/lib/dml/sqlsrv_native_moodle_database.php +++ b/lib/dml/sqlsrv_native_moodle_database.php @@ -347,13 +347,18 @@ class sqlsrv_native_moodle_database extends moodle_database { * @param mixed $params array of params for binding. If NULL, they are ignored. * @param mixed $sql_query_type - Type of operation * @param mixed $free_result - Default true, transaction query will be freed. + * @param mixed $scrollable - Default false, to use for quickly seeking to target records */ - private function do_query($sql, $params, $sql_query_type, $free_result = true) { + private function do_query($sql, $params, $sql_query_type, $free_result = true, $scrollable = false) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); $sql = $this->emulate_bound_params($sql, $params); $this->query_start($sql, $params, $sql_query_type); - $result = sqlsrv_query($this->sqlsrv, $sql); + if (!$scrollable) { // Only supporting next row + $result = sqlsrv_query($this->sqlsrv, $sql); + } else { // Suporting absolute/relative rows + $result = sqlsrv_query($this->sqlsrv, $sql, array(), array('Scrollable' => SQLSRV_CURSOR_STATIC)); + } if ($result === false) { // TODO do something with error or just use if DEV or DEBUG? @@ -756,118 +761,18 @@ class sqlsrv_native_moodle_database extends moodle_database { $limitnum = max(0, $limitnum); if ($limitfrom or $limitnum) { - $sql = $this->limit_to_top_n($sql, $limitfrom, $limitnum); - } - $result = $this->do_query($sql, $params, SQL_QUERY_SELECT, false); - return $this->create_recordset($result); - } - - /** - * Perform a emulation for LIMIT(offset, limit) - * - * @param string $sql - * @param int $offset - * @param int $limit - * @return string sql - */ - private function limit_to_top_n($sql, $offset, $limit) { - // If there is no limit we can return immediately - if ($limit < 1 && $offset < 1) { - return $sql; - } - - // Make sure they are at least 0 - $limit = max(0, (int)$limit); - $offset = max(0, (int)$offset); - // This is an sqlserver bigint - -1 and will be used as a value - // for top when essentially we want everything. - // This needs to be a string so that it doesn't get malformed. - $bigint = '9223372036854775806'; - - // If limit is 0 set it to BITINT - 1 - if (empty($limit)) { - $limit = $bigint; - } else { - $limit = $offset + $limit; - } - - // Set up defaults for the next bit. - $columns = '*'; // Default to all columns - $columnnames = '*'; // As above - $firstcolumn = 'id'; // The default first column is id - $orderby = ''; // The order by of the main query - - // We need to do a couple of maintenance tasks on the columns seeing as - // they are going to be wrapped in a sub select. - // - // 1. Collect the first column to use for an order by if there isn't an - // explicit order by within the query. - // 2. Give all constant columns a proper alias, this is required because - // of the subselect. - if (preg_match('#^(\s*SELECT\s+)(DISTINCT\s+)?(.*?)(\sFROM\s)#is', $sql, $columnmatches)) { - // Make sure we have some columns - if (!empty($columnmatches[3])) { - $columns = explode(',', $columnmatches[3]); - $firstcolumn = null; - $constantcount = 0; - foreach ($columns as $key=>$column) { - // Trim, trim, trim, except during Movember. - $column = trim($column); - if (preg_match('#\sAS\s+(\w+)\s*$#si', $column, $matches)) { - // Make sure we use the column alias if available. - $column = $matches[1]; - } else if (preg_match("#^('[^']*'|\d+)$#", $column)) { - // Give constants an alias in the main query and use the - // alias for the new outer queries. - $constantcount++; - $column = 'constant_'.$constantcount; - $columns[$key] .= ' AS '.$column; - } - - // Store the first column for later abuse. - if ($firstcolumn === null) { - $firstcolumn = $column; - } - } - // Glue things back together - $columns = join(', ', $columns); - // Switch out the fixed main columns (added constant aliases). - $sql = str_replace($columnmatches[0], $columnmatches[1].$columnmatches[2].$columns.$columnmatches[4], $sql); + if ($limitnum >= 1) { // Only apply TOP clause if we have any limitnum (limitfrom offset is handled later) + $fetch = $limitfrom + $limitnum; + $sql = preg_replace('/^([\s(])*SELECT([\s]+(DISTINCT|ALL))?(?!\s*TOP\s*\()/i', + "\\1SELECT\\2 TOP $fetch", $sql); } } + $result = $this->do_query($sql, $params, SQL_QUERY_SELECT, false, (bool)$limitfrom); - // Collect the orderby from the main query to use in the row number order by. - if (preg_match('#\sORDER\s+BY\s+([^)]+?)(GROUP\s+BY|$)#i', $sql, $matches)) { - // We need to remove it from the main query as well. - $sql = str_replace($matches[0], ' '.$matches[2], $sql); - $orderby = $matches[1]; - } else { - // Default orderby to the first column. - $orderby = $firstcolumn; + if ($limitfrom) { // Skip $limitfrom records + sqlsrv_fetch($result, SQLSRV_SCROLL_ABSOLUTE, $limitfrom - 1); } - // Remove any table aliases from the order by. - $orderby = preg_replace('#[^\s,]*\.([^\s,]*)#', '$1', $orderby); - - // If the orderby is all tables everything will break, default to id. - if ($orderby == '*') { - $orderby = 'id'; - } - - // Now we need to build the queries up so that we collect a row count field and then sort on it. - // To do this we need to nest the query twice. The first nesting selects all the rows from the - // query and then proceeds to use OVER to generate a row number. - // The second nesting we limit by selecting where rownumber between offset and limit - // In both cases we will select the original query fields using q.* this is important - // as there can be any number of crafty things going on. It does however mean that we - // end up with the first field being sqlsrvrownumber however sqlsrv_native_moodle_recordset - // strips that off during processing if it exists. - // Build the inner outer query. - $sql = "SELECT TOP $bigint ROW_NUMBER() OVER(ORDER BY $orderby) AS sqlsrvrownumber, q.* FROM ($sql) AS q"; - // Build the outer most query. - $sql = "SELECT q.* FROM ($sql) AS q WHERE q.sqlsrvrownumber > $offset AND q.sqlsrvrownumber <= $limit"; - - // Return the now mangled query for use. - return $sql; + return $this->create_recordset($result); } /** From de6aaa7295ab763439a3a21b91d85a997763ce26 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 4 Mar 2011 11:21:27 +0100 Subject: [PATCH 049/369] MDL-26683 workshop: fixed typos in code comments --- mod/workshop/db/access.php | 6 +++--- mod/workshop/eval/best/lib.php | 2 +- mod/workshop/form/accumulative/db/upgradelib.php | 2 +- mod/workshop/form/comments/db/upgradelib.php | 2 +- mod/workshop/form/numerrors/db/upgradelib.php | 2 +- mod/workshop/form/numerrors/lib.php | 2 +- mod/workshop/form/rubric/db/upgradelib.php | 4 ++-- mod/workshop/locallib.php | 6 +++--- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mod/workshop/db/access.php b/mod/workshop/db/access.php index 1e292b1097e..32d17636533 100644 --- a/mod/workshop/db/access.php +++ b/mod/workshop/db/access.php @@ -42,7 +42,7 @@ $capabilities = array( ) ), - // Ability to change the current phase (stage) of the workshop, it est for example + // Ability to change the current phase (stage) of the workshop, for example // allow submitting, start assessment period, close workshop etc. 'mod/workshop:switchphase' => array( 'captype' => 'write', @@ -110,7 +110,7 @@ $capabilities = array( ) ), - // Ability to publish submissions, it est make them available when workshop is closed + // Ability to publish submissions, i.e. make them available when workshop is closed 'mod/workshop:publishsubmissions' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, @@ -134,7 +134,7 @@ $capabilities = array( ) ), - // Ability to identify the reviewer of the given submission (ie the owner of the assessment) + // Ability to identify the reviewer of the given submission (i.e. the owner of the assessment) 'mod/workshop:viewreviewernames' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, diff --git a/mod/workshop/eval/best/lib.php b/mod/workshop/eval/best/lib.php index 813235a4276..0857396756c 100644 --- a/mod/workshop/eval/best/lib.php +++ b/mod/workshop/eval/best/lib.php @@ -178,7 +178,7 @@ class workshop_best_evaluation implements workshop_evaluation { $distances[$asid] = $this->assessments_distance($assessment, $average, $diminfo, $settings); } - // identify the best assessments - it est those with the shortest distance from the best assessment + // identify the best assessments - that is those with the shortest distance from the best assessment $bestids = array_keys($distances, min($distances)); // for every assessment, calculate its distance from the nearest best assessment diff --git a/mod/workshop/form/accumulative/db/upgradelib.php b/mod/workshop/form/accumulative/db/upgradelib.php index 1e7237ec86d..aa73a523635 100644 --- a/mod/workshop/form/accumulative/db/upgradelib.php +++ b/mod/workshop/form/accumulative/db/upgradelib.php @@ -63,7 +63,7 @@ function workshopform_accumulative_upgrade_legacy() { // refetch them from DB so that this function can be called during recovery $newelementids = workshop_upgrade_element_id_mappings('accumulative'); - // migrate all grades for these elements (it est the values that reviewers put into forms) + // migrate all grades for these elements (i.e. the values that reviewers put into forms) echo $OUTPUT->notification('Copying assessment form grades', 'notifysuccess'); $sql = "SELECT * FROM {workshop_grades_old} diff --git a/mod/workshop/form/comments/db/upgradelib.php b/mod/workshop/form/comments/db/upgradelib.php index ee45f2ad142..f870422c688 100644 --- a/mod/workshop/form/comments/db/upgradelib.php +++ b/mod/workshop/form/comments/db/upgradelib.php @@ -60,7 +60,7 @@ function workshopform_comments_upgrade_legacy() { // now we need to reload the legacy element ids $newelementids = workshop_upgrade_element_id_mappings('comments'); - // migrate all comments for these elements (it est the values that reviewers put into forms) + // migrate all comments for these elements (i.e. the values that reviewers put into forms) echo $OUTPUT->notification('Copying assessment form comments', 'notifysuccess'); $sql = "SELECT * FROM {workshop_grades_old} diff --git a/mod/workshop/form/numerrors/db/upgradelib.php b/mod/workshop/form/numerrors/db/upgradelib.php index e27d61e303d..364e9e080bf 100644 --- a/mod/workshop/form/numerrors/db/upgradelib.php +++ b/mod/workshop/form/numerrors/db/upgradelib.php @@ -83,7 +83,7 @@ function workshopform_numerrors_upgrade_legacy() { // refetch them from DB so that this function can be called during recovery $newelementids = workshop_upgrade_element_id_mappings('numerrors'); - // migrate all grades for these elements (it est the values that reviewers put into forms) + // migrate all grades for these elements (i.e. the values that reviewers put into forms) echo $OUTPUT->notification('Copying assessment form grades', 'notifysuccess'); $sql = "SELECT * FROM {workshop_grades_old} diff --git a/mod/workshop/form/numerrors/lib.php b/mod/workshop/form/numerrors/lib.php index f43d17592f1..123160b3bf2 100644 --- a/mod/workshop/form/numerrors/lib.php +++ b/mod/workshop/form/numerrors/lib.php @@ -556,7 +556,7 @@ class workshop_numerrors_strategy implements workshop_strategy { if (empty($grades)) { return null; } - $sumerrors = 0; // sum of the weighted errors (ie the negative responses) + $sumerrors = 0; // sum of the weighted errors (i.e. the negative responses) foreach ($grades as $grade) { if (grade_floats_different($grade->grade, 1.00000)) { // negative reviewer's response diff --git a/mod/workshop/form/rubric/db/upgradelib.php b/mod/workshop/form/rubric/db/upgradelib.php index 50c4fbde447..c41a4ac5db0 100644 --- a/mod/workshop/form/rubric/db/upgradelib.php +++ b/mod/workshop/form/rubric/db/upgradelib.php @@ -92,7 +92,7 @@ function workshopform_rubric_upgrade_legacy_criterion() { // reload the mappings - this must be reloaded to that we can run this during recovery $newelementids = workshop_upgrade_element_id_mappings('rubric_levels'); - // migrate all grades for these elements (it est the values that reviewers put into forms) + // migrate all grades for these elements (i.e. the values that reviewers put into forms) echo $OUTPUT->notification('Copying criterion assessment form grades', 'notifysuccess'); $sql = "SELECT * FROM {workshop_grades_old} @@ -199,7 +199,7 @@ function workshopform_rubric_upgrade_legacy_rubric() { unset($oldweights); unset($element); - // migrate all grades for these elements (it est the values that reviewers put into forms) + // migrate all grades for these elements (i.e. the values that reviewers put into forms) echo $OUTPUT->notification('Copying rubric assessment form grades', 'notifysuccess'); $sql = "SELECT * FROM {workshop_grades_old} diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 0f943af9c35..e3aba61762a 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -458,7 +458,7 @@ class workshop { } /** - * Returns the list of all allocations (it est assigned assessments) in the workshop + * Returns the list of all allocations (i.e. assigned assessments) in the workshop * * Assessments of example submissions are ignored * @@ -721,7 +721,7 @@ class workshop { * Returns the list of all assessments in the workshop with some data added * * Fetches data from {workshop_assessments} and adds some useful information from other - * tables. The returned object does not contain textual fields (ie comments) to prevent memory + * tables. The returned object does not contain textual fields (i.e. comments) to prevent memory * lack issues. * * @return array [assessmentid] => assessment stdclass @@ -2397,7 +2397,7 @@ class workshop_user_plan implements renderable { */ abstract class workshop_submission_base { - /** @var bool is the submission anonymous (ie contains author information) */ + /** @var bool is the submission anonymous (i.e. contains author information) */ protected $anonymous; /* @var array of columns from workshop_submissions that are assigned as properties */ From 757bade1f608182c4c1a0789c2cef1bda00b620c Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 4 Mar 2011 13:12:31 +0100 Subject: [PATCH 050/369] MDL-26684 workshop: fixed missing href attribute in the link to the own submission This was caused by incorrect construction of workshop_submission_summary. Instead of direct initiation, the helper method should be used. The helper adds a property 'url' needed to render 'href' later. --- mod/workshop/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/workshop/view.php b/mod/workshop/view.php index a13f97fa4a6..55d349c12fc 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -409,7 +409,7 @@ case workshop::PHASE_EVALUATION: print_collapsible_region_start('', 'workshop-viewlet-ownsubmission', get_string('yoursubmission', 'workshop')); echo $output->box_start('generalbox ownsubmission'); if ($submission = $workshop->get_submission_by_author($USER->id)) { - echo $output->render(new workshop_submission_summary($submission, true)); + echo $output->render($workshop->prepare_submission_summary($submission, true)); } else { echo $output->container(get_string('noyoursubmission', 'workshop')); } From e13d02f544bd0708590ca2e591a94a992135f67c Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 4 Mar 2011 13:16:36 +0100 Subject: [PATCH 051/369] MDL-26535 workshop: new capability to control the anonymity of published submissions Re-using 'mod/workshop:viewauthornames' would not be a happy option here because teacher would have to change local overrides every time when they were closing or re-opening the workshop (if they wanted anonymous assessment but non-anonymous hall of fame). --- mod/workshop/db/access.php | 12 ++++++++++++ mod/workshop/lang/en/workshop.php | 1 + mod/workshop/version.php | 2 +- mod/workshop/view.php | 3 ++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/mod/workshop/db/access.php b/mod/workshop/db/access.php index 32d17636533..5b23e6410dd 100644 --- a/mod/workshop/db/access.php +++ b/mod/workshop/db/access.php @@ -170,6 +170,18 @@ $capabilities = array( ) ), + // Ability to view the authors of published submissions. + 'mod/workshop:viewauthorpublished' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ) + ), + // Ability to always view the assessments of other users' work and the calculated grades, regardless the phase. // Applies to the user's group only or - if the user is allowed to access all groups - applies to any assessment 'mod/workshop:viewallassessments' => array( diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index b1fb16fb142..d68a95cccc4 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -254,6 +254,7 @@ $string['workshop:view'] = 'View workshop'; $string['workshop:viewallassessments'] = 'View all assessments'; $string['workshop:viewallsubmissions'] = 'View all submissions'; $string['workshop:viewauthornames'] = 'View author names'; +$string['workshop:viewauthorpublished'] = 'View authors of published submissions'; $string['workshop:viewpublishedsubmissions'] = 'View published submissions'; $string['workshop:viewreviewernames'] = 'View reviewer names'; $string['yoursubmission'] = 'Your submission'; diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 11348c1c9f6..54bdc72312d 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -29,6 +29,6 @@ defined('MOODLE_INTERNAL') || die(); -$module->version = 2011021100; +$module->version = 2011030400; $module->requires = 2011020900; // Requires this Moodle version //$module->cron = 60; diff --git a/mod/workshop/view.php b/mod/workshop/view.php index 55d349c12fc..ab478863b2b 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -492,11 +492,12 @@ case workshop::PHASE_CLOSED: print_collapsible_region_end(); } if (has_capability('mod/workshop:viewpublishedsubmissions', $workshop->context)) { + $shownames = has_capability('mod/workshop:viewauthorpublished', $workshop->context); if ($submissions = $workshop->get_published_submissions()) { print_collapsible_region_start('', 'workshop-viewlet-publicsubmissions', get_string('publishedsubmissions', 'workshop')); foreach ($submissions as $submission) { echo $output->box_start('generalbox submission-summary'); - echo $output->render($workshop->prepare_submission_summary($submission, true)); + echo $output->render($workshop->prepare_submission_summary($submission, $shownames)); echo $output->box_end(); } print_collapsible_region_end(); From f07704d2a21b91895a1c115c6604ad310b0e603c Mon Sep 17 00:00:00 2001 From: sam marshall Date: Mon, 28 Feb 2011 15:31:23 +0000 Subject: [PATCH 052/369] lib MDL-26625 Add session size info to perfdebug block --- lib/moodlelib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index e1d5a6e3f9d..656bc35c676 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -9300,6 +9300,11 @@ function get_performance_info() { $info['txt'] .= "serverload: {$info['serverload']} "; } + // Display size of session + $info['sessionsize'] = display_size(strlen(session_encode())); + $info['html'] .= 'Session: ' . $info['sessionsize'] . ' '; + $info['txt'] .= "Session: {$info['sessionsize']} "; + /* if (isset($rcache->hits) && isset($rcache->misses)) { $info['rcachehits'] = $rcache->hits; $info['rcachemisses'] = $rcache->misses; From b031caf8586fa45c03c37750b5e4a23d6c48b306 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Mon, 28 Feb 2011 11:19:58 +0000 Subject: [PATCH 053/369] lib MDL-26423 Added support for ->allowid option in format_text --- lib/simpletest/testweblib.php | 26 ++++++++++++++++++++++++++ lib/weblib.php | 30 ++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lib/simpletest/testweblib.php b/lib/simpletest/testweblib.php index 4af49a1d431..eb5467d99b7 100644 --- a/lib/simpletest/testweblib.php +++ b/lib/simpletest/testweblib.php @@ -143,6 +143,32 @@ class web_test extends UnitTestCase { $this->assertEqual('lala xx', clean_text($text, FORMAT_MOODLE)); $this->assertEqual('lala xx', clean_text($text, FORMAT_HTML)); } + + /** + * Tests the 'allowid' option for format_text. + */ + public function test_format_text_allowid() { + global $CFG; + + // This test relates only to html purifier, so switch to it if not in use + $oldcfg = $CFG->enablehtmlpurifier; + $CFG->enablehtmlpurifier = true; + + // Start off by not allowing ids (default) + $options = array( + 'nocache' => true + ); + $result = format_text('
Frog
', FORMAT_HTML, $options); + $this->assertEqual('
Frog
', $result); + + // Now allow ids + $options['allowid'] = true; + $result = format_text('
Frog
', FORMAT_HTML, $options); + $this->assertEqual('
Frog
', $result); + + // Switch config back + $CFG->enablehtmlpurifier = $oldcfg; + } } diff --git a/lib/weblib.php b/lib/weblib.php index 85ef74756a7..4abc493b62d 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -958,6 +958,8 @@ function format_text_menu() { * context : The context that will be used for filtering. * overflowdiv : If set to true the formatted text will be encased in a div * with the class no-overflow before being returned. Default false. + * allowid : If true then id attributes will not be removed, even when + * using htmlpurifier. Default false. * * * @todo Finish documenting this function @@ -1069,7 +1071,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ switch ($format) { case FORMAT_HTML: if (!$options['noclean']) { - $text = clean_text($text, FORMAT_HTML); + $text = clean_text($text, FORMAT_HTML, $options); } $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_HTML)); break; @@ -1092,7 +1094,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ case FORMAT_MARKDOWN: $text = markdown_to_html($text); if (!$options['noclean']) { - $text = clean_text($text, FORMAT_HTML); + $text = clean_text($text, FORMAT_HTML, $options); } $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_MARKDOWN)); break; @@ -1100,7 +1102,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ default: // FORMAT_MOODLE or anything else $text = text_to_html($text, null, $options['para'], $options['newlines']); if (!$options['noclean']) { - $text = clean_text($text, FORMAT_HTML); + $text = clean_text($text, FORMAT_HTML, $options); } $text = $filtermanager->filter_text($text, $context, array('originalformat' => $format)); break; @@ -1445,9 +1447,11 @@ function trusttext_active() { * * @param string $text The text to be cleaned * @param int $format deprecated parameter, should always contain FORMAT_HTML or FORMAT_MOODLE + * @param array $options Array of options; currently only option supported is 'allowid' (if true, + * does not remove id attributes when cleaning) * @return string The cleaned up text */ -function clean_text($text, $format = FORMAT_HTML) { +function clean_text($text, $format = FORMAT_HTML, $options = array()) { global $ALLOWED_TAGS, $CFG; if (empty($text) or is_numeric($text)) { @@ -1464,7 +1468,7 @@ function clean_text($text, $format = FORMAT_HTML) { } if (!empty($CFG->enablehtmlpurifier)) { - $text = purify_html($text); + $text = purify_html($text, $options); } else { /// Fix non standard entity notations $text = fix_non_standard_entities($text); @@ -1492,16 +1496,19 @@ function clean_text($text, $format = FORMAT_HTML) { * * @global object * @param string $text The (X)HTML string to purify + * @param array $options Array of options; currently only option supported is 'allowid' (if set, + * does not remove id attributes when cleaning) */ -function purify_html($text) { +function purify_html($text, $options = array()) { global $CFG; // this can not be done only once because we sometimes need to reset the cache $cachedir = $CFG->dataroot.'/cache/htmlpurifier'; check_dir_exists($cachedir); - static $purifier = false; - if ($purifier === false) { + $type = !empty($options['allowid']) ? 'allowid' : 'normal'; + static $purifiers = array(); + if (empty($purifiers[$type])) { require_once $CFG->libdir.'/htmlpurifier/HTMLPurifier.safe-includes.php'; $config = HTMLPurifier_Config::createDefault(); @@ -1522,6 +1529,10 @@ function purify_html($text) { $config->set('HTML.SafeEmbed', true); } + if ($type === 'allowid') { + $config->set('Attr.EnableID', true); + } + $def = $config->getHTMLDefinition(true); $def->addElement('nolink', 'Block', 'Flow', array()); // skip our filters inside $def->addElement('tex', 'Inline', 'Inline', array()); // tex syntax, equivalent to $$xx$$ @@ -1530,6 +1541,9 @@ function purify_html($text) { $def->addAttribute('span', 'xxxlang', 'CDATA'); // current problematic multilang $purifier = new HTMLPurifier($config); + $purifiers[$type] = $purifier; + } else { + $purifier = $purifiers[$type]; } $multilang = (strpos($text, 'class="multilang"') !== false); From 89213d00419a600f54c560fd19733cf0389e37b3 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Tue, 1 Mar 2011 14:30:45 +0000 Subject: [PATCH 054/369] backup MDL-26606 Backup should allow themes to have course data; also fix course theme restore --- backup/moodle2/backup_plan_builder.class.php | 1 + backup/moodle2/backup_stepslib.php | 4 ++ backup/moodle2/backup_theme_plugin.class.php | 60 +++++++++++++++++++ backup/moodle2/restore_plan_builder.class.php | 2 + backup/moodle2/restore_stepslib.php | 6 +- backup/moodle2/restore_theme_plugin.class.php | 29 +++++++++ backup/util/dbops/backup_plan_dbops.class.php | 39 ++++++++++++ 7 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 backup/moodle2/backup_theme_plugin.class.php create mode 100644 backup/moodle2/restore_theme_plugin.class.php diff --git a/backup/moodle2/backup_plan_builder.class.php b/backup/moodle2/backup_plan_builder.class.php index 89c8654534f..4c9e87619d0 100644 --- a/backup/moodle2/backup_plan_builder.class.php +++ b/backup/moodle2/backup_plan_builder.class.php @@ -35,6 +35,7 @@ require_once($CFG->dirroot . '/backup/moodle2/backup_xml_transformer.class.php') require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_format_plugin.class.php'); +require_once($CFG->dirroot . '/backup/moodle2/backup_theme_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_subplugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_settingslib.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_stepslib.php'); diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index 6b4dbf34355..051a409c906 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -412,6 +412,10 @@ class backup_course_structure_step extends backup_structure_step { // attach format plugin structure to $course element, only one allowed $this->add_plugin_structure('format', $course, false); + // attach theme plugin structure to $course element; multiple themes can + // save course data (in case of user theme, legacy theme, etc) + $this->add_plugin_structure('theme', $course, true); + // Build the tree $course->add_child($category); diff --git a/backup/moodle2/backup_theme_plugin.class.php b/backup/moodle2/backup_theme_plugin.class.php new file mode 100644 index 00000000000..2fd75919635 --- /dev/null +++ b/backup/moodle2/backup_theme_plugin.class.php @@ -0,0 +1,60 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 onwards The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Base class for theme backup plugins. + * + * NOTE: When you back up a course, it runs backup for ALL themes - not just + * the currently selected one. + * + * That means that if, for example, a course was once in theme A, and theme A + * had some data settings, but it is then changed to theme B, the data settings + * will still be included in the backup and restore. With the restored course, + * if you ever change it back to theme A, the settings will be ready. + * + * It also means that other themes which are not the one set up for the course, + * but might be seen by some users (eg user themes, session themes, mnet themes) + * can store data. + * + * If this behaviour is not desired for a particular theme's data, the subclass + * can call is_current_theme('myname') to check. + */ +abstract class backup_theme_plugin extends backup_plugin { + + // Stores current theme for course. Lazily initialised. + protected $theme; + + /** + * Checks if an expected theme is actually the current theme for the course. + * @param string $expected Name of theme you are expecting e.g. 'standard' + * @return bool True if that theme is the current course theme + */ + protected function is_current_theme($expected) { + if (!$this->theme) { + $this->theme = backup_plan_dbops::get_theme_from_courseid( + $this->task->get_courseid()); + } + return $this->theme === $expected; + } +} diff --git a/backup/moodle2/restore_plan_builder.class.php b/backup/moodle2/restore_plan_builder.class.php index f685d3833b5..122b05e7b96 100644 --- a/backup/moodle2/restore_plan_builder.class.php +++ b/backup/moodle2/restore_plan_builder.class.php @@ -34,9 +34,11 @@ require_once($CFG->dirroot . '/backup/moodle2/restore_default_block_task.class.p require_once($CFG->dirroot . '/backup/moodle2/restore_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/restore_qtype_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/restore_format_plugin.class.php'); +require_once($CFG->dirroot . '/backup/moodle2/restore_theme_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/backup_format_plugin.class.php'); +require_once($CFG->dirroot . '/backup/moodle2/backup_theme_plugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/restore_subplugin.class.php'); require_once($CFG->dirroot . '/backup/moodle2/restore_settingslib.php'); require_once($CFG->dirroot . '/backup/moodle2/restore_stepslib.php'); diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index eace0149591..1e5ac90f8cd 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -1008,6 +1008,9 @@ class restore_course_structure_step extends restore_structure_step { // Apply for 'format' plugins optional paths at course level $this->add_plugin_structure('format', $course); + // Apply for 'theme' plugins optional paths at course level + $this->add_plugin_structure('theme', $course); + return array($course, $category, $tag, $allowed_module); } @@ -1052,8 +1055,9 @@ class restore_course_structure_step extends restore_structure_step { if (!array_key_exists($data->lang, $languages)) { $data->lang = ''; } + $themes = get_list_of_themes(); // Get themes for quick search later - if (!in_array($data->theme, $themes) || empty($CFG->allowcoursethemes)) { + if (!array_key_exists($data->theme, $themes) || empty($CFG->allowcoursethemes)) { $data->theme = ''; } diff --git a/backup/moodle2/restore_theme_plugin.class.php b/backup/moodle2/restore_theme_plugin.class.php new file mode 100644 index 00000000000..84931947dd5 --- /dev/null +++ b/backup/moodle2/restore_theme_plugin.class.php @@ -0,0 +1,29 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +/** + * Restore for course plugin: theme. + * + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class restore_theme_plugin extends restore_plugin { + // Use default parent behaviour +} diff --git a/backup/util/dbops/backup_plan_dbops.class.php b/backup/util/dbops/backup_plan_dbops.class.php index fe5d9415880..3d620f5b27d 100644 --- a/backup/util/dbops/backup_plan_dbops.class.php +++ b/backup/util/dbops/backup_plan_dbops.class.php @@ -128,6 +128,45 @@ abstract class backup_plan_dbops extends backup_dbops { return $DB->get_field('course', 'format', array('id' => $courseid)); } + /** + * Given a course id, returns its theme. This can either be the course + * theme or (if not specified in course) the category, site theme. + * + * User, session, and inherited-from-mnet themes cannot have backed-up + * per course data. This is course-related data so it must be in a course + * theme specified as part of the course structure + * @param int $courseid + * @return string Name of course theme + * @see moodle_page#resolve_theme() + */ + public static function get_theme_from_courseid($courseid) { + global $DB, $CFG; + + // Course theme first + if (!empty($CFG->allowcoursethemes)) { + $theme = $DB->get_field('course', 'theme', array('id' => $courseid)); + if ($theme) { + return $theme; + } + } + + // Category themes in reverse order + if (!empty($CFG->allowcategorythemes)) { + $catid = $DB->get_field('course', 'category', array('id' => $courseid)); + while($catid) { + $category = $DB->get_record('course_categories', array('id'=>$catid), + 'theme,parent', MUST_EXIST); + if ($category->theme) { + return $category->theme; + } + $catid = $category->parent; + } + } + + // Finally use site theme + return $CFG->theme; + } + /** * Return the wwwroot of the $CFG->mnet_localhost_id host * caching it along the request From 7fedc2c25e8e9b5c4548d0989c33ff50918ed746 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Wed, 23 Feb 2011 22:33:17 +0800 Subject: [PATCH 055/369] lib MDL-26458 adding unit tests to test cursors. -added test with limits and order by with table aliases to test_get_records_sql() -added test_recordset_locks_delete() and test_recordset_locks_update() - added out of range limits test to test_get_records_sql() --- lib/dml/simpletest/testdml.php | 100 +++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index ab7107e04f1..8c8857261e1 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -1015,6 +1015,19 @@ class dml_test extends UnitTestCase { $inskey6 = $DB->insert_record($tablename, array('course' => 1)); $inskey7 = $DB->insert_record($tablename, array('course' => 0)); + $table2 = $this->get_test_table("2"); + $tablename2 = $table2->getName(); + $table2->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table2->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); + $table2->add_field('nametext', XMLDB_TYPE_TEXT, 'small', null, null, null, null); + $table2->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $dbman->create_table($table2); + + $DB->insert_record($tablename2, array('course'=>3, 'nametext'=>'badabing')); + $DB->insert_record($tablename2, array('course'=>4, 'nametext'=>'badabang')); + $DB->insert_record($tablename2, array('course'=>5, 'nametext'=>'badabung')); + $DB->insert_record($tablename2, array('course'=>6, 'nametext'=>'badabong')); + $records = $DB->get_records_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3)); $this->assertEqual(2, count($records)); $this->assertEqual($inskey1, reset($records)->id); @@ -1068,6 +1081,28 @@ class dml_test extends UnitTestCase { $this->assertEqual($inskey3, reset($records)->id); $this->assertEqual($inskey2, end($records)->id); + // test 2 tables with aliases and limits with order bys + $sql = "SELECT t1.id, t1.course AS cid, t2.nametext FROM {{$tablename}} t1, {{$tablename2}} t2 + WHERE t2.course=t1.course ORDER BY t1.course, ". $DB->sql_compare_text('t2.nametext'); + $records = $DB->get_records_sql($sql, null, 2, 2); // Skip courses 3 and 6, get 4 and 5 + $this->assertEqual(2, count($records)); + $this->assertEqual('5', end($records)->cid); + $this->assertEqual('4', reset($records)->cid); + + // test 2 tables with aliases and limits with order bys (limit which is out of range) + $records = $DB->get_records_sql($sql, null, 2, 21098765432109876543210); // Skip course {3,6}, get {4,5} + $this->assertEqual(2, count($records)); + $this->assertEqual('5', end($records)->cid); + $this->assertEqual('4', reset($records)->cid); + + // test 2 tables with aliases and limits with order bys (limit which is out of range) + $records = $DB->get_records_sql($sql, null, 21098765432109876543210, 2); // Skip all courses + $this->assertEqual(0, count($records)); + + // test 2 tables with aliases and limits with order bys (limit which is out of range) + $records = $DB->get_records_sql($sql, null, 21098765432109876543210, 21098765432109876543210); // Skip all courses + $this->assertEqual(0, count($records)); + // TODO: Test limits in queries having DISTINCT clauses // note: fetching nulls, empties, LOBs already tested by test_update_record() no needed here @@ -2040,6 +2075,7 @@ class dml_test extends UnitTestCase { $record = $DB->get_record($tablename, array('course' => 2)); $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB update (full contents output disabled)'); $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB update (full contents output disabled)'); + } public function test_set_field() { @@ -2401,6 +2437,70 @@ class dml_test extends UnitTestCase { $this->assertTrue($DB->record_exists_sql("SELECT * FROM {{$tablename}} WHERE course = ?", array(3))); } + public function test_recordset_locks_delete() { + $DB = $this->tdb; + $dbman = $DB->get_manager(); + + //Setup + $table = $this->get_test_table(); + $tablename = $table->getName(); + + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $dbman->create_table($table); + + $DB->insert_record($tablename, array('course' => 1)); + $DB->insert_record($tablename, array('course' => 2)); + $DB->insert_record($tablename, array('course' => 3)); + $DB->insert_record($tablename, array('course' => 4)); + $DB->insert_record($tablename, array('course' => 5)); + $DB->insert_record($tablename, array('course' => 6)); + + // Test against db write locking while on an open recordset + $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4} + foreach ($rs as $record) { + $cid = $record->course; + $DB->delete_records($tablename, array('course' => $cid)); + $this->assertFalse($DB->record_exists($tablename, array('course' => $cid))); + } + $rs->close(); + + $this->assertEqual(4, $DB->count_records($tablename, array())); + } + + public function test_recordset_locks_update() { + $DB = $this->tdb; + $dbman = $DB->get_manager(); + + //Setup + $table = $this->get_test_table(); + $tablename = $table->getName(); + + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('course', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0'); + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $dbman->create_table($table); + + $DB->insert_record($tablename, array('course' => 1)); + $DB->insert_record($tablename, array('course' => 2)); + $DB->insert_record($tablename, array('course' => 3)); + $DB->insert_record($tablename, array('course' => 4)); + $DB->insert_record($tablename, array('course' => 5)); + $DB->insert_record($tablename, array('course' => 6)); + + // Test against db write locking while on an open recordset + $rs = $DB->get_recordset($tablename, array(), null, 'course', 2, 2); // get courses = {3,4} + foreach ($rs as $record) { + $cid = $record->course; + $DB->set_field($tablename, 'course', 10, array('course' => $cid)); + $this->assertFalse($DB->record_exists($tablename, array('course' => $cid))); + } + $rs->close(); + + $this->assertEqual(2, $DB->count_records($tablename, array('course' => 10))); + } + public function test_delete_records() { $DB = $this->tdb; $dbman = $DB->get_manager(); From 0357171e6859097bc3737bc0127e11e5bcbe13ef Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 4 Mar 2011 17:20:12 +0000 Subject: [PATCH 056/369] MDL-26324 overall feedback problem when quiz changed to being graded out of 0 --- mod/quiz/mod_form.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/mod/quiz/mod_form.php b/mod/quiz/mod_form.php index fa892be4d61..0da3ec6db03 100644 --- a/mod/quiz/mod_form.php +++ b/mod/quiz/mod_form.php @@ -344,17 +344,26 @@ class mod_quiz_mod_form extends moodleform_mod { foreach ($this->_feedbacks as $feedback){ $draftid = file_get_submitted_draft_itemid('feedbacktext['.$key.']'); $default_values['feedbacktext['.$key.']']['text'] = file_prepare_draft_area( - $draftid, // draftid - $this->context->id, // context - 'mod_quiz', // component + $draftid, // draftid + $this->context->id, // context + 'mod_quiz', // component 'feedback', // filarea - !empty($feedback->id)?(int)$feedback->id:null, // itemid + !empty($feedback->id) ? (int) $feedback->id : null, // itemid null, - $feedback->feedbacktext // text + $feedback->feedbacktext // text ); $default_values['feedbacktext['.$key.']']['format'] = $feedback->feedbacktextformat; $default_values['feedbacktext['.$key.']']['itemid'] = $draftid; + if ($default_values['grade'] == 0) { + // When a quiz is un-graded, there can only be one lot of + // feedback. If the quiz previously had a maximum grade and + // several lots of feedback, we must now avoid putting text + // into input boxes that are disabled, but which the + // validation will insist are blank. + break; + } + if ($feedback->mingrade > 0) { $default_values['feedbackboundaries['.$key.']'] = (100.0 * $feedback->mingrade / $default_values['grade']) . '%'; } From 165b7bd987866f60446cc2c315c376ad001dec9a Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Fri, 4 Mar 2011 19:45:43 +0100 Subject: [PATCH 057/369] MDL-25388 restore - confusing options restoring 1-activity --- backup/util/ui/renderer.php | 18 +++++++++++++----- backup/util/ui/restore_ui_components.php | 8 +++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/backup/util/ui/renderer.php b/backup/util/ui/renderer.php index f8ab57bc5f8..e07bc0bb06c 100644 --- a/backup/util/ui/renderer.php +++ b/backup/util/ui/renderer.php @@ -181,7 +181,7 @@ class core_backup_renderer extends plugin_renderer_base { $hasrestoreoption = false; $html = html_writer::start_tag('div', array('class'=>'backup-course-selector backup-restore')); - if (!empty($categories) && ($categories->get_count() > 0 || $categories->get_search())) { + if ($details->type == backup::TYPE_1COURSE && !empty($categories) && ($categories->get_count() > 0 || $categories->get_search())) { // New course $hasrestoreoption = true; $html .= $form; @@ -194,7 +194,7 @@ class core_backup_renderer extends plugin_renderer_base { $html .= html_writer::end_tag('form'); } - if (!empty($currentcourse)) { + if ($details->type == backup::TYPE_1COURSE && !empty($currentcourse)) { // Current course $hasrestoreoption = true; $html .= $form; @@ -214,9 +214,17 @@ class core_backup_renderer extends plugin_renderer_base { $html .= $form; $html .= html_writer::start_tag('div', array('class'=>'bcs-existing-course backup-section')); $html .= $this->output->heading(get_string('restoretoexistingcourse', 'backup'), 2, array('class'=>'header')); - $html .= $this->backup_detail_input(get_string('restoretoexistingcourseadding', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_ADDING, array('checked'=>'checked')); - $html .= $this->backup_detail_input(get_string('restoretoexistingcoursedeleting', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_DELETING); - $html .= $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses)); + if ($details->type == backup::TYPE_1COURSE) { + $html .= $this->backup_detail_input(get_string('restoretoexistingcourseadding', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_ADDING, array('checked'=>'checked')); + $html .= $this->backup_detail_input(get_string('restoretoexistingcoursedeleting', 'backup'), 'radio', 'target', backup::TARGET_EXISTING_DELETING); + $html .= $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses)); + } else { + // We only allow restore adding to existing for now. Enforce it here. + $html .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'target', 'value'=>backup::TARGET_EXISTING_ADDING)); + $courses->invalidate_results(); // Clean list of courses + $courses->set_include_currentcourse(); // Show current course in the list + $html .= $this->backup_detail_pair(get_string('selectacourse', 'backup'), $this->render($courses)); + } $html .= $this->backup_detail_pair('', html_writer::empty_tag('input', array('type'=>'submit', 'value'=>get_string('continue')))); $html .= html_writer::end_tag('div'); $html .= html_writer::end_tag('form'); diff --git a/backup/util/ui/restore_ui_components.php b/backup/util/ui/restore_ui_components.php index 5243c1d881b..056f7a1b06f 100644 --- a/backup/util/ui/restore_ui_components.php +++ b/backup/util/ui/restore_ui_components.php @@ -132,6 +132,7 @@ abstract class restore_search_base implements renderable { */ final public function invalidate_results() { $this->results = null; + $this->totalcount = null; } /** * Adds a required capability which all results will be checked against @@ -217,6 +218,7 @@ class restore_course_search extends restore_search_base { static $VAR_SEARCH = 'search'; protected $currentcourseid = null; + protected $includecurrentcourse; /** * @param array $config @@ -226,6 +228,7 @@ class restore_course_search extends restore_search_base { parent::__construct($config); $this->require_capability('moodle/restore:restorecourse'); $this->currentcourseid = $currentcouseid; + $this->includecurrentcourse = false; } /** * @@ -246,7 +249,7 @@ class restore_course_search extends restore_search_base { $where = " WHERE (".$DB->sql_like('c.fullname', ':fullnamesearch', false)." OR ".$DB->sql_like('c.shortname', ':shortnamesearch', false).") AND c.id <> :siteid"; $orderby = " ORDER BY c.sortorder"; - if ($this->currentcourseid !== null) { + if ($this->currentcourseid !== null && !$this->includecurrentcourse) { $where .= " AND c.id <> :currentcourseid"; $params['currentcourseid'] = $this->currentcourseid; } @@ -260,6 +263,9 @@ class restore_course_search extends restore_search_base { public function get_varsearch() { return self::$VAR_SEARCH; } + public function set_include_currentcourse() { + $this->includecurrentcourse = true; + } } /** From b302591de88462529927a3e0ad2701da29425d18 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Sat, 5 Mar 2011 15:19:49 +0000 Subject: [PATCH 058/369] MDL-26636 fix typo in language string. Thanks to Luis de Vasconcelos. --- mod/quiz/lang/en/quiz.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index 353cc162f86..a57bb93a027 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -89,7 +89,7 @@ $string['aon'] = 'AON format'; $string['areyousureremoveselected'] = 'Are you sure you want to remove all the selected questions?'; $string['asshownoneditscreen'] = 'As shown on the edit screen'; $string['attempt'] = 'Attempt {$a}'; -$string['attemptalreadyclosed'] = 'This attempt has already be finished.'; +$string['attemptalreadyclosed'] = 'This attempt has already been finished.'; $string['attemptclosed'] = 'Attempt has not closed yet'; $string['attemptduration'] = 'Time taken'; $string['attemptedon'] = 'Attempted on'; From 231ec773234a45dc20b3625d01a46bfef2776e23 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Sat, 5 Mar 2011 16:33:24 +0000 Subject: [PATCH 059/369] MDL-26520 random tf questions that had not been answered were shown as answered on the summary page. This was a regression from MDL-26236 thanks to some brain-dead PHP behaviour. --- question/type/random/questiontype.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/question/type/random/questiontype.php b/question/type/random/questiontype.php index 72c5aaba309..0ecefd45778 100644 --- a/question/type/random/questiontype.php +++ b/question/type/random/questiontype.php @@ -260,6 +260,12 @@ class random_qtype extends default_questiontype { $wrappedquestion->qtype = 'missingtype'; } $state->responses[''] = substr($state->responses[''], strlen('random' . $questionid . '-')); + if ($state->responses[''] === false) { + // In PHP, if $response === $prefix, then + // substr($response, strlen($prefix)) returns false, not '', + // which is stupid, and caused MDL-26520. Fix up that case here. + $state->responses[''] = ''; + } } if (!$QTYPES[$wrappedquestion->qtype] From 4a6f461830bf1d671a7a90c64b010aba280ac599 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Sat, 5 Mar 2011 19:27:32 +0000 Subject: [PATCH 060/369] MDL-26685 each attempt builds on last did not work when quiz_attemts.id and question_attempts.id were not equal. --- mod/quiz/startattempt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/quiz/startattempt.php b/mod/quiz/startattempt.php index 145ed5f115e..099480de086 100644 --- a/mod/quiz/startattempt.php +++ b/mod/quiz/startattempt.php @@ -74,7 +74,7 @@ if ($lastattempt && !$lastattempt->timefinish) { /// Get number for the next or unfinished attempt if ($lastattempt && !$lastattempt->preview && !$quizobj->is_preview_user()) { - $lastattemptid = $lastattempt->id; + $lastattemptid = $lastattempt->uniqueid; $attemptnumber = $lastattempt->attempt + 1; } else { $lastattempt = false; From 209442ce2445c973c8589fdf564a7bea34c47900 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Sat, 5 Mar 2011 19:51:38 +0000 Subject: [PATCH 061/369] MDL-26517 HTML tags visible in the response history table and quiz reports. --- question/type/essay/questiontype.php | 10 ++++++++++ question/type/questiontype.php | 6 ++++-- question/type/shortanswer/questiontype.php | 8 ++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/question/type/essay/questiontype.php b/question/type/essay/questiontype.php index 102b26f1bc2..6cb505f1329 100644 --- a/question/type/essay/questiontype.php +++ b/question/type/essay/questiontype.php @@ -127,6 +127,16 @@ class question_essay_qtype extends default_questiontype { return true; } + /** + * @param string response is a response. + * @return formatted response + */ + function format_response($response, $format) { + $safeformatoptions = new stdClass(); + $safeformatoptions->para = false; + return format_text($response, FORMAT_MOODLE, $safeformatoptions); + } + /** * Runs all the code required to set up and save an essay question for testing purposes. * Alternate DB table prefix may be used to facilitate data deletion. diff --git a/question/type/questiontype.php b/question/type/questiontype.php index 11843cdbf4d..defbe1bf00f 100644 --- a/question/type/questiontype.php +++ b/question/type/questiontype.php @@ -1348,13 +1348,15 @@ class default_questiontype { } return $toreturn; } + /** * @param string response is a response. * @return formatted response */ - function format_response($response, $format){ - return s($response); + function format_response($response, $format) { + return $this->format_text($response, $format); } + /** * Renders the question for printing and returns the LaTeX source produced * diff --git a/question/type/shortanswer/questiontype.php b/question/type/shortanswer/questiontype.php index 1388f5e4970..66ed308122a 100644 --- a/question/type/shortanswer/questiontype.php +++ b/question/type/shortanswer/questiontype.php @@ -223,6 +223,14 @@ class question_shortanswer_qtype extends default_questiontype { return preg_match($regexp, trim($string)); } + /** + * @param string response is a response. + * @return formatted response + */ + function format_response($response, $format){ + return s($response); + } + /* * Override the parent class method, to remove escaping from asterisks. */ From 8f63ab1f447b1b5943286783a86ca9c1e34c65fa Mon Sep 17 00:00:00 2001 From: ppichet Date: Wed, 16 Feb 2011 16:18:52 -0500 Subject: [PATCH 062/369] MDL-26445 question -fix numerical unit grade fix unit penalty grading and display Signed-off-by: ppichet --- question/type/numerical/questiontype.php | 4 ++-- question/type/shortanswer/questiontype.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/numerical/questiontype.php b/question/type/numerical/questiontype.php index ebc37b8d067..ef0b1f09a3c 100644 --- a/question/type/numerical/questiontype.php +++ b/question/type/numerical/questiontype.php @@ -608,7 +608,7 @@ class question_numerical_qtype extends question_shortanswer_qtype { if($question->options->unitgradingtype == 1){ $raw_unitpenalty = $question->options->unitpenalty * $rawgrade ; }else { - $raw_unitpenalty = $question->options->unitpenalty * $question->maxgrade; + $raw_unitpenalty = $question->options->unitpenalty ; } $state->options->raw_unitpenalty = $raw_unitpenalty ; } @@ -818,7 +818,7 @@ class question_numerical_qtype extends question_shortanswer_qtype { if($question->options->unitgradingtype == 1){ $raw_unitpenalty = $question->options->unitpenalty * $state->raw_grade ; }else { - $raw_unitpenalty = $question->options->unitpenalty * $question->maxgrade; + $raw_unitpenalty = $question->options->unitpenalty ; } $state->raw_grade -= $raw_unitpenalty ; } diff --git a/question/type/shortanswer/questiontype.php b/question/type/shortanswer/questiontype.php index 1388f5e4970..191d090fa3e 100644 --- a/question/type/shortanswer/questiontype.php +++ b/question/type/shortanswer/questiontype.php @@ -318,7 +318,7 @@ class question_shortanswer_qtype extends default_questiontype { // waiting for the new question engine code for a permanent one if(isset($state->options->raw_unitpenalty) && $state->options->raw_unitpenalty > 0.0 ){ echo ' '; - print_string('unitappliedpenalty','qtype_numerical',question_format_grade($cmoptions, $state->options->raw_unitpenalty )); + print_string('unitappliedpenalty','qtype_numerical',question_format_grade($cmoptions, $state->options->raw_unitpenalty * $question->maxgrade )); } if ($cmoptions->penaltyscheme) { // print details of grade adjustment due to penalties From 25bd5c75ab0606c3886e72124e5b7858287feff1 Mon Sep 17 00:00:00 2001 From: andyjdavis Date: Wed, 16 Feb 2011 15:48:59 +0800 Subject: [PATCH 063/369] message MDL-26433 refactored the constants in messaging --- message/discussion.php | 3 +- message/index.php | 38 ++++++++------- message/lib.php | 90 ++++++++++++++++-------------------- message/search.html | 2 +- message/search_advanced.html | 2 +- 5 files changed, 63 insertions(+), 72 deletions(-) diff --git a/message/discussion.php b/message/discussion.php index 29298db1227..32a1f4645e4 100644 --- a/message/discussion.php +++ b/message/discussion.php @@ -27,10 +27,11 @@ require('../config.php'); require('lib.php'); + //the same URL params as in 1.9 $userid = required_param('id', PARAM_INT); $noframesjs = optional_param('noframesjs', 0, PARAM_BOOL); - $params = array('id'=>$userid); + $params = array('user2'=>$userid); if (!empty($noframesjs)) { $params['noframesjs'] = $noframesjs; } diff --git a/message/index.php b/message/index.php index e5f49156654..69102822674 100644 --- a/message/index.php +++ b/message/index.php @@ -37,21 +37,21 @@ if (empty($CFG->messaging)) { print_error('disabled', 'message'); } -//VIEW_PARAM is the preferred URL parameter but we'll still accept usergroup in case its referenced externally -$usergroup = optional_param('usergroup', VIEW_UNREAD_MESSAGES, PARAM_ALPHANUMEXT); -$viewing = optional_param(VIEW_PARAM, $usergroup, PARAM_ALPHANUMEXT); +//'viewing' is the preferred URL parameter but we'll still accept usergroup in case its referenced externally +$usergroup = optional_param('usergroup', MESSAGE_VIEW_UNREAD_MESSAGES, PARAM_ALPHANUMEXT); +$viewing = optional_param('viewing', $usergroup, PARAM_ALPHANUMEXT); $history = optional_param('history', MESSAGE_HISTORY_SHORT, PARAM_INT); $search = optional_param('search', '', PARAM_CLEAN); //TODO: use PARAM_RAW, but make sure we use s() and p() properly //the same param as 1.9 and the param we have been logging. Use this parameter. -$user1id = optional_param(MESSAGE_USER1_PARAM, $USER->id, PARAM_INT); +$user1id = optional_param('user1', $USER->id, PARAM_INT); //2.0 shipped using this param. Retaining it only for compatibility. It should be removed. $user1id = optional_param('user', $user1id, PARAM_INT); //the same param as 1.9 and the param we have been logging. Use this parameter. -$user2id = optional_param(MESSAGE_USER2_PARAM, 0, PARAM_INT); -//2.0 shipped using this param. Retaining it only for compatibility. It should be removed. +$user2id = optional_param('user2', 0, PARAM_INT); +//The class send_form supplies the receiving user id as 'id' $user2id = optional_param('id', $user2id, PARAM_INT); $addcontact = optional_param('addcontact', 0, PARAM_INT); // adding a contact @@ -68,15 +68,15 @@ $page = optional_param('page', 0, PARAM_INT); $url = new moodle_url('/message/index.php'); if ($user2id !== 0) { - $url->param('id', $user2id); + $url->param('user2', $user2id); } if ($user2id !== 0) { //Switch view back to contacts if: //1) theyve searched and selected a user //2) they've viewed recent messages or notifications and clicked through to a user - if ($viewing == VIEW_SEARCH || $viewing == VIEW_SEARCH || $viewing == VIEW_RECENT_NOTIFICATIONS) { - $viewing = VIEW_CONTACTS; + if ($viewing == MESSAGE_VIEW_SEARCH || $viewing == MESSAGE_VIEW_SEARCH || $viewing == MESSAGE_VIEW_RECENT_NOTIFICATIONS) { + $viewing = MESSAGE_VIEW_CONTACTS; } } $url->param('viewing', $viewing); @@ -91,7 +91,7 @@ $context = get_context_instance(CONTEXT_SYSTEM); $user1 = null; $currentuser = true; -$showcontactactionlinks = SHOW_ACTION_LINKS_IN_CONTACT_LIST; +$showcontactactionlinks = true; if ($user1id != $USER->id) { $user1 = $DB->get_record('user', array('id' => $user1id)); if (!$user1) { @@ -122,7 +122,7 @@ if ($user1->id != $USER->id && (!empty($user2) && $user2->id != $USER->id) && !h if ($addcontact and confirm_sesskey()) { add_to_log(SITEID, 'message', 'add contact', 'index.php?user1='.$addcontact.'&user2='.$USER->id, $addcontact); message_add_contact($addcontact); - redirect($CFG->wwwroot . '/message/index.php?'.VIEW_PARAM.'=contacts&id='.$addcontact); + redirect($CFG->wwwroot . '/message/index.php?viewing=contacts&id='.$addcontact); } if ($removecontact and confirm_sesskey()) { add_to_log(SITEID, 'message', 'remove contact', 'index.php?user1='.$removecontact.'&user2='.$USER->id, $removecontact); @@ -140,7 +140,6 @@ if ($unblockcontact and confirm_sesskey()) { //was a message sent? Do NOT allow someone looking at someone else's messages to send them. $messageerror = null; if ($currentuser && !empty($user2) && has_capability('moodle/site:sendmessage', $context)) { - // Check that the user is not blocking us!! if ($contact = $DB->get_record('message_contacts', array('userid' => $user2->id, 'contactid' => $user1->id))) { if ($contact->blocked and !has_capability('moodle/site:readallmessages', $context)) { @@ -167,13 +166,12 @@ if ($currentuser && !empty($user2) && has_capability('moodle/site:sendmessage', if (!confirm_sesskey()) { print_error('invalidsesskey'); } - $messageid = message_post_message($user1, $user2, $data->message, FORMAT_MOODLE); if (!empty($messageid)) { //including the id of the user sending the message in the logged URL so the URL works for admins //note message ID may be misleading as the message may potentially get a different ID when moved from message to message_read add_to_log(SITEID, 'message', 'write', 'index.php?user='.$user1->id.'&id='.$user2->id.'&history=1#m'.$messageid, $user1->id); - redirect($CFG->wwwroot . '/message/index.php?'.VIEW_PARAM.'='.$viewing.'&id='.$user2->id); + redirect($CFG->wwwroot . '/message/index.php?viewing='.$viewing.'&id='.$user2->id); } } } @@ -206,16 +204,16 @@ if (!empty($user2)) { if ($countunread>0) { //mark the messages we're going to display as read message_mark_messages_read($user1->id, $user2->id); - if($viewing == VIEW_UNREAD_MESSAGES) { + if($viewing == MESSAGE_VIEW_UNREAD_MESSAGES) { $viewingnewmessages = true; } } } $countunreadtotal = message_count_unread_messages($user1); -if ($countunreadtotal == 0 && $viewing == VIEW_UNREAD_MESSAGES && empty($user2)) { +if ($countunreadtotal == 0 && $viewing == MESSAGE_VIEW_UNREAD_MESSAGES && empty($user2)) { //default to showing the search - $viewing = VIEW_SEARCH; + $viewing = MESSAGE_VIEW_SEARCH; } $blockedusers = message_get_blocked_users($user1, $user2); @@ -298,11 +296,11 @@ echo html_writer::start_tag('div', array('class' => 'messagearea mdl-align')); } echo html_writer::end_tag('div'); } - } else if ($viewing == VIEW_SEARCH) { + } else if ($viewing == MESSAGE_VIEW_SEARCH) { message_print_search($advancedsearch, $user1); - } else if ($viewing == VIEW_RECENT_CONVERSATIONS) { + } else if ($viewing == MESSAGE_VIEW_RECENT_CONVERSATIONS) { message_print_recent_conversations($user1); - } else if ($viewing == VIEW_RECENT_NOTIFICATIONS) { + } else if ($viewing == MESSAGE_VIEW_RECENT_NOTIFICATIONS) { message_print_recent_notifications($user1); } echo html_writer::end_tag('div'); diff --git a/message/lib.php b/message/lib.php index c2cb7af8bc3..c0524b99356 100644 --- a/message/lib.php +++ b/message/lib.php @@ -25,7 +25,6 @@ require_once($CFG->libdir.'/eventslib.php'); - define ('MESSAGE_SHORTLENGTH', 300); //$PAGE isnt set if we're being loaded by cron which doesnt display popups anyway @@ -38,32 +37,16 @@ define ('MESSAGE_DISCUSSION_HEIGHT',500); define ('MESSAGE_SHORTVIEW_LIMIT', 8);//the maximum number of messages to show on the short message history -define ('CONTACT_ID','id'); - define('MESSAGE_HISTORY_SHORT',0); define('MESSAGE_HISTORY_ALL',1); -//some constants used as function arguments. Just to make function calls a bit more understandable -define('IS_CONTACT',true); -define('IS_NOT_CONTACT',false); - -define('IS_BLOCKED',true); -define('IS_NOT_BLOCKED',false); - -define('VIEW_PARAM','viewing'); - -define('VIEW_UNREAD_MESSAGES','unread'); -define('VIEW_RECENT_CONVERSATIONS','recentconversations'); -define('VIEW_RECENT_NOTIFICATIONS','recentnotifications'); -define('VIEW_CONTACTS','contacts'); -define('VIEW_BLOCKED','blockedusers'); -define('VIEW_COURSE','course_'); -define('VIEW_SEARCH','search'); - -define('MESSAGE_USER1_PARAM','user1'); -define('MESSAGE_USER2_PARAM','user2'); - -define('SHOW_ACTION_LINKS_IN_CONTACT_LIST', true); +define('MESSAGE_VIEW_UNREAD_MESSAGES','unread'); +define('MESSAGE_VIEW_RECENT_CONVERSATIONS','recentconversations'); +define('MESSAGE_VIEW_RECENT_NOTIFICATIONS','recentnotifications'); +define('MESSAGE_VIEW_CONTACTS','contacts'); +define('MESSAGE_VIEW_BLOCKED','blockedusers'); +define('MESSAGE_VIEW_COURSE','course_'); +define('MESSAGE_VIEW_SEARCH','search'); define('MESSAGE_SEARCH_MAX_RESULTS', 200); @@ -84,7 +67,7 @@ if (!isset($CFG->message_offline_time)) { * Print the selector that allows the user to view their contacts, course participants, their recent * conversations etc * @param int $countunreadtotal how many unread messages does the user have? -* @param int $viewing What is the user viewing? ie VIEW_UNREAD_MESSAGES, VIEW_SEARCH etc +* @param int $viewing What is the user viewing? ie MESSAGE_VIEW_UNREAD_MESSAGES, MESSAGE_VIEW_SEARCH etc * @param object $user1 the user whose messages are being viewed * @param object $user2 the user $user1 is talking to * @param array $blockedusers an array of users blocked by $user1 @@ -101,13 +84,13 @@ function message_print_contact_selector($countunreadtotal, $viewing, $user1, $us echo html_writer::start_tag('div', array('class' => 'contactselector mdl-align')); //if 0 unread messages and they've requested unread messages then show contacts - if ($countunreadtotal == 0 && $viewing == VIEW_UNREAD_MESSAGES) { - $viewing = VIEW_CONTACTS; + if ($countunreadtotal == 0 && $viewing == MESSAGE_VIEW_UNREAD_MESSAGES) { + $viewing = MESSAGE_VIEW_CONTACTS; } //if they have no blocked users and they've requested blocked users switch them over to contacts - if (count($blockedusers) == 0 && $viewing == VIEW_BLOCKED) { - $viewing = VIEW_CONTACTS; + if (count($blockedusers) == 0 && $viewing == MESSAGE_VIEW_BLOCKED) { + $viewing = MESSAGE_VIEW_CONTACTS; } $onlyactivecourses = true; @@ -121,13 +104,13 @@ function message_print_contact_selector($countunreadtotal, $viewing, $user1, $us message_print_usergroup_selector($viewing, $courses, $coursecontexts, $countunreadtotal, count($blockedusers), $strunreadmessages); - if ($viewing == VIEW_UNREAD_MESSAGES) { + if ($viewing == MESSAGE_VIEW_UNREAD_MESSAGES) { message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $PAGE->url, 1, $showcontactactionlinks,$strunreadmessages, $user2); - } else if ($viewing == VIEW_CONTACTS || $viewing == VIEW_SEARCH || $viewing == VIEW_RECENT_CONVERSATIONS || $viewing == VIEW_RECENT_NOTIFICATIONS) { + } else if ($viewing == MESSAGE_VIEW_CONTACTS || $viewing == MESSAGE_VIEW_SEARCH || $viewing == MESSAGE_VIEW_RECENT_CONVERSATIONS || $viewing == MESSAGE_VIEW_RECENT_NOTIFICATIONS) { message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $PAGE->url, 0, $showcontactactionlinks, $strunreadmessages, $user2); - } else if ($viewing == VIEW_BLOCKED) { + } else if ($viewing == MESSAGE_VIEW_BLOCKED) { message_print_blocked_users($blockedusers, $PAGE->url, $showcontactactionlinks, null, $user2); - } else if (substr($viewing, 0, 7) == VIEW_COURSE) { + } else if (substr($viewing, 0, 7) == MESSAGE_VIEW_COURSE) { $courseidtoshow = intval(substr($viewing, 7)); if (!empty($courseidtoshow) @@ -144,11 +127,11 @@ function message_print_contact_selector($countunreadtotal, $viewing, $user1, $us echo html_writer::start_tag('form', array('action' => 'index.php','method' => 'GET')); echo html_writer::start_tag('fieldset'); $managebuttonclass = 'visible'; - if ($viewing == VIEW_SEARCH) { + if ($viewing == MESSAGE_VIEW_SEARCH) { $managebuttonclass = 'hiddenelement'; } $strmanagecontacts = get_string('search','message'); - echo html_writer::empty_tag('input', array('type' => 'hidden','name' => VIEW_PARAM,'value' => VIEW_SEARCH)); + echo html_writer::empty_tag('input', array('type' => 'hidden','name' => 'viewing','value' => MESSAGE_VIEW_SEARCH)); echo html_writer::empty_tag('input', array('type' => 'submit','value' => $strmanagecontacts,'class' => $managebuttonclass)); echo html_writer::end_tag('fieldset'); echo html_writer::end_tag('form'); @@ -270,8 +253,10 @@ function message_print_blocked_users($blockedusers, $contactselecturl=null, $sho echo html_writer::tag('td', get_string('blockedusers', 'message', $countblocked), array('colspan' => 3, 'class' => 'heading')); echo html_writer::end_tag('tr'); + $isuserblocked = true; + $isusercontact = false; foreach ($blockedusers as $blockeduser) { - message_print_contactlist_user($blockeduser, IS_NOT_CONTACT, IS_BLOCKED, $contactselecturl, $showactionlinks, $user2); + message_print_contactlist_user($blockeduser, $isusercontact, $isuserblocked, $contactselecturl, $showactionlinks, $user2); } } @@ -377,6 +362,7 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ $countonlinecontacts = count($onlinecontacts); $countofflinecontacts = count($offlinecontacts); $countstrangers = count($strangers); + $isuserblocked = null; if ($countonlinecontacts + $countofflinecontacts == 0) { echo html_writer::tag('div', get_string('contactlistempty', 'message'), array('class' => 'heading')); @@ -395,9 +381,11 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ message_print_heading(get_string('onlinecontacts', 'message', $countonlinecontacts)); } + $isuserblocked = false; + $isusercontact = true; foreach ($onlinecontacts as $contact) { if ($minmessages == 0 || $contact->messagecount >= $minmessages) { - message_print_contactlist_user($contact, IS_CONTACT, IS_NOT_BLOCKED, $contactselecturl, $showactionlinks, $user2); + message_print_contactlist_user($contact, $isusercontact, $isuserblocked, $contactselecturl, $showactionlinks, $user2); } } } @@ -409,9 +397,11 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ message_print_heading(get_string('offlinecontacts', 'message', $countofflinecontacts)); } + $isuserblocked = false; + $isusercontact = true; foreach ($offlinecontacts as $contact) { if ($minmessages == 0 || $contact->messagecount >= $minmessages) { - message_print_contactlist_user($contact, IS_CONTACT, IS_NOT_BLOCKED, $contactselecturl, $showactionlinks, $user2); + message_print_contactlist_user($contact, $isusercontact, $isuserblocked, $contactselecturl, $showactionlinks, $user2); } } @@ -421,9 +411,11 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ if ($countstrangers) { message_print_heading(get_string('incomingcontacts', 'message', $countstrangers)); + $isuserblocked = false; + $isusercontact = false; foreach ($strangers as $stranger) { if ($minmessages == 0 || $stranger->messagecount >= $minmessages) { - message_print_contactlist_user($stranger, IS_NOT_CONTACT, IS_NOT_BLOCKED, $contactselecturl, $showactionlinks, $user2); + message_print_contactlist_user($stranger, $isusercontact, $isuserblocked, $contactselecturl, $showactionlinks, $user2); } } } @@ -438,7 +430,7 @@ function message_print_contacts($onlinecontacts, $offlinecontacts, $strangers, $ /** * Print a select box allowing the user to choose to view new messages, course participants etc. * Called by message_print_contact_selector() -* @param int $viewing What page is the user viewing ie VIEW_UNREAD_MESSAGES, VIEW_RECENT_CONVERSATIONS etc +* @param int $viewing What page is the user viewing ie MESSAGE_VIEW_UNREAD_MESSAGES, MESSAGE_VIEW_RECENT_CONVERSATIONS etc * @param array $courses array of course objects. The courses the user is enrolled in. * @param array $coursecontexts array of course contexts. Keyed on course id. * @param int $countunreadtotal how many unread messages does the user have? @@ -451,14 +443,14 @@ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $ $textlib = textlib_get_instance(); // going to use textlib services if ($countunreadtotal>0) { //if there are unread messages - $options[VIEW_UNREAD_MESSAGES] = $strunreadmessages; + $options[MESSAGE_VIEW_UNREAD_MESSAGES] = $strunreadmessages; } $str = get_string('mycontacts', 'message'); - $options[VIEW_CONTACTS] = $str; + $options[MESSAGE_VIEW_CONTACTS] = $str; - $options[VIEW_RECENT_CONVERSATIONS] = get_string('mostrecentconversations', 'message'); - $options[VIEW_RECENT_NOTIFICATIONS] = get_string('mostrecentnotifications', 'message'); + $options[MESSAGE_VIEW_RECENT_CONVERSATIONS] = get_string('mostrecentconversations', 'message'); + $options[MESSAGE_VIEW_RECENT_NOTIFICATIONS] = get_string('mostrecentnotifications', 'message'); if (!empty($courses)) { $courses_options = array(); @@ -467,9 +459,9 @@ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $ if (has_capability('moodle/course:viewparticipants', $coursecontexts[$course->id])) { //Not using short_text() as we want the end of the course name. Not the beginning. if ($textlib->strlen($course->shortname) > MESSAGE_MAX_COURSE_NAME_LENGTH) { - $courses_options[VIEW_COURSE.$course->id] = '...'.$textlib->substr($course->shortname, -MESSAGE_MAX_COURSE_NAME_LENGTH); + $courses_options[MESSAGE_VIEW_COURSE.$course->id] = '...'.$textlib->substr($course->shortname, -MESSAGE_MAX_COURSE_NAME_LENGTH); } else { - $courses_options[VIEW_COURSE.$course->id] = $course->shortname; + $courses_options[MESSAGE_VIEW_COURSE.$course->id] = $course->shortname; } } } @@ -481,12 +473,12 @@ function message_print_usergroup_selector($viewing, $courses, $coursecontexts, $ if ($countblocked>0) { $str = get_string('blockedusers','message', $countblocked); - $options[VIEW_BLOCKED] = $str; + $options[MESSAGE_VIEW_BLOCKED] = $str; } echo html_writer::start_tag('form', array('id' => 'usergroupform','method' => 'get','action' => '')); echo html_writer::start_tag('fieldset'); - echo html_writer::select($options, VIEW_PARAM, $viewing, false, array('id' => VIEW_PARAM,'onchange' => 'this.form.submit()')); + echo html_writer::select($options, 'viewing', $viewing, false, array('id' => 'viewing','onchange' => 'this.form.submit()')); echo html_writer::end_tag('fieldset'); echo html_writer::end_tag('form'); } @@ -2039,7 +2031,7 @@ function message_print_contactlist_user($contact, $incontactlist = true, $isbloc $link = $action = null; if (!empty($selectcontacturl)) { - $link = new moodle_url($selectcontacturl.'&'.CONTACT_ID.'='.$contact->id); + $link = new moodle_url($selectcontacturl.'&user2='.$contact->id); } else { //can $selectcontacturl be removed and maybe the be removed and hardcoded? $link = new moodle_url("/message/index.php?id=$contact->id"); diff --git a/message/search.html b/message/search.html index edbe0557943..7adedc29f15 100644 --- a/message/search.html +++ b/message/search.html @@ -6,7 +6,7 @@ - + diff --git a/message/search_advanced.html b/message/search_advanced.html index e6fffc8212f..1eac7dd1594 100644 --- a/message/search_advanced.html +++ b/message/search_advanced.html @@ -2,7 +2,7 @@
- + From 69c3d39a9c0d00661f0d204c4a08485b18aeb321 Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Mon, 7 Mar 2011 09:54:33 +1300 Subject: [PATCH 064/369] AICC MDL-26672 fix for handling of value = 0 --- mod/scorm/aicc.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/scorm/aicc.php b/mod/scorm/aicc.php index 86b3de42019..ed08cf40094 100644 --- a/mod/scorm/aicc.php +++ b/mod/scorm/aicc.php @@ -93,7 +93,7 @@ if ($sco = scorm_get_sco($scoid)) { $userdata->course_id = $sco->identifier; $userdata->datafromlms = isset($sco->datafromlms)?$sco->datafromlms:''; - $userdata->mastery_score = isset($sco->mastery_score)?$sco->mastery_score:''; + $userdata->mastery_score = isset($sco->mastery_score) && is_numeric($sco->mastery_score)?trim($sco->mastery_score):''; $userdata->max_time_allowed = isset($sco->max_time_allowed)?$sco->max_time_allowed:''; $userdata->time_limit_action = isset($sco->time_limit_action)?$sco->time_limit_action:''; @@ -278,9 +278,9 @@ } if ($mode == 'normal') { if ($sco = scorm_get_sco($scoid)) { - if (!empty($sco->mastery_score)) { - if (!empty($score)) { - if ($score >= $sco->mastery_score) { + if (isset($sco->mastery_score) && is_numeric($sco->mastery_score)) { + if ($score != '') { // $score is correctly initialized w/ an empty string, see above + if ($score >= trim($sco->mastery_score)) { $lessonstatus = 'passed'; } else { $lessonstatus = 'failed'; From d67c20b8735885864b95bba2167aba9c96f8e1d0 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 4 Mar 2011 13:51:28 +0100 Subject: [PATCH 065/369] MDL-26535 workshop: fixed availability of published and assessed submissions While working on the new capability to view authors of published submissions, I realized that published submissions are correctly listed (implemented in 00bc77ee) but they can't be viewed by submission.php. This patch fixes submission.php so that it allows to view published submissions. Also, I noticed that when the workshop is closed, the submissions that were assessed by the user are not listed (as they were in the previous phases) but submission.php provides access to them correctly. So I added a code that lists assessed submissions in the closed phase. --- mod/workshop/styles.css | 6 ++++++ mod/workshop/submission.php | 15 ++++++++++++++- mod/workshop/view.php | 31 +++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mod/workshop/styles.css b/mod/workshop/styles.css index 3c6548315a3..22c48513451 100644 --- a/mod/workshop/styles.css +++ b/mod/workshop/styles.css @@ -12,6 +12,12 @@ margin: 0.75em auto; } +.path-mod-workshop #workshop-viewlet-assignedassessments div.singlebutton, +.path-mod-workshop #workshop-viewlet-allexamples div.singlebutton, +.path-mod-workshop #workshop-viewlet-examples div.singlebutton { + text-align: left; +} + /** * Submission - one line summary display */ diff --git a/mod/workshop/submission.php b/mod/workshop/submission.php index a0766e6d112..81b5e9a8226 100644 --- a/mod/workshop/submission.php +++ b/mod/workshop/submission.php @@ -72,6 +72,9 @@ $canoverride = (($workshop->phase == workshop::PHASE_EVALUATION) and has_capa $userassessment = $workshop->get_assessment_of_submission_by_user($submission->id, $USER->id); $isreviewer = !empty($userassessment); $editable = ($cansubmit and $ownsubmission); +$ispublished = ($workshop->phase == workshop::PHASE_CLOSED + and $submission->published == 1 + and has_capability('mod/workshop:viewpublishedsubmissions', $workshop->context)); if (empty($submission->id) and !$workshop->creating_submission_allowed()) { $editable = false; @@ -93,8 +96,13 @@ if ($editable and $workshop->useexamples and $workshop->examplesmode == workshop } $edit = ($editable and $edit); +$seenaspublished = false; // is the submission seen as a published submission? + if ($submission->id and ($ownsubmission or $canviewall or $isreviewer)) { // ok you can go +} elseif ($submission->id and $ispublished) { + // ok you can go + $seenaspublished = true; } elseif (is_null($submission->id) and $cansubmit) { // ok you can go } else { @@ -238,7 +246,12 @@ if ($edit) { // else display the submission if ($submission->id) { - echo $output->render($workshop->prepare_submission($submission, has_capability('mod/workshop:viewauthornames', $workshop->context))); + if ($seenaspublished) { + $showauthor = has_capability('mod/workshop:viewauthorpublished', $workshop->context); + } else { + $showauthor = has_capability('mod/workshop:viewauthornames', $workshop->context); + } + echo $output->render($workshop->prepare_submission($submission, $showauthor)); } else { echo $output->box(get_string('noyoursubmission', 'workshop')); } diff --git a/mod/workshop/view.php b/mod/workshop/view.php index ab478863b2b..2cd32a0062f 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -503,6 +503,37 @@ case workshop::PHASE_CLOSED: print_collapsible_region_end(); } } + if ($assessments = $workshop->get_assessments_by_reviewer($USER->id)) { + print_collapsible_region_start('', 'workshop-viewlet-assignedassessments', get_string('assignedassessments', 'workshop')); + $shownames = has_capability('mod/workshop:viewauthornames', $PAGE->context); + foreach ($assessments as $assessment) { + $submission = new stdclass(); + $submission->id = $assessment->submissionid; + $submission->title = $assessment->submissiontitle; + $submission->timecreated = $assessment->submissioncreated; + $submission->timemodified = $assessment->submissionmodified; + $submission->authorid = $assessment->authorid; + $submission->authorfirstname = $assessment->authorfirstname; + $submission->authorlastname = $assessment->authorlastname; + $submission->authorpicture = $assessment->authorpicture; + $submission->authorimagealt = $assessment->authorimagealt; + $submission->authoremail = $assessment->authoremail; + + if (is_null($assessment->grade)) { + $class = ' notgraded'; + $submission->status = 'notgraded'; + $buttontext = get_string('assess', 'workshop'); + } else { + $class = ' graded'; + $submission->status = 'graded'; + $buttontext = get_string('reassess', 'workshop'); + } + echo $output->box_start('generalbox assessment-summary' . $class); + echo $output->render($workshop->prepare_submission_summary($submission, $shownames)); + echo $output->box_end(); + } + print_collapsible_region_end(); + } break; default: } From 4b43b1074f112a39a745f28affceb6fa0fd2e04b Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 7 Mar 2011 00:16:25 +0100 Subject: [PATCH 066/369] backup MDL-26572 add new param to plugin and subplugin functions --- backup/moodle2/restore_plugin.class.php | 7 +++++-- backup/moodle2/restore_subplugin.class.php | 7 +++++-- backup/util/plan/restore_structure_step.class.php | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/backup/moodle2/restore_plugin.class.php b/backup/moodle2/restore_plugin.class.php index 8103adaeeec..02039876352 100644 --- a/backup/moodle2/restore_plugin.class.php +++ b/backup/moodle2/restore_plugin.class.php @@ -174,9 +174,12 @@ abstract class restore_plugin { /** * Return the new id of a mapping for the given itemname * + * @param string $itemname the type of item + * @param int $oldid the item ID from the backup + * @param mixed $ifnotfound what to return if $oldid wasnt found. Defaults to false */ - protected function get_mappingid($itemname, $oldid) { - return $this->step->get_mappingid($itemname, $oldid); + protected function get_mappingid($itemname, $oldid, $ifnotfound = false) { + return $this->step->get_mappingid($itemname, $oldid, $ifnotfound); } /** diff --git a/backup/moodle2/restore_subplugin.class.php b/backup/moodle2/restore_subplugin.class.php index d22a0d9c1f8..8972e358405 100644 --- a/backup/moodle2/restore_subplugin.class.php +++ b/backup/moodle2/restore_subplugin.class.php @@ -123,9 +123,12 @@ abstract class restore_subplugin { /** * Return the new id of a mapping for the given itemname * + * @param string $itemname the type of item + * @param int $oldid the item ID from the backup + * @param mixed $ifnotfound what to return if $oldid wasnt found. Defaults to false */ - protected function get_mappingid($itemname, $oldid) { - return $this->step->get_mappingid($itemname, $oldid); + protected function get_mappingid($itemname, $oldid, $ifnotfound = false) { + return $this->step->get_mappingid($itemname, $oldid, $ifnotfound); } /** diff --git a/backup/util/plan/restore_structure_step.class.php b/backup/util/plan/restore_structure_step.class.php index 927f71c7f01..ae648bc4911 100644 --- a/backup/util/plan/restore_structure_step.class.php +++ b/backup/util/plan/restore_structure_step.class.php @@ -196,9 +196,10 @@ abstract class restore_structure_step extends restore_step { /** * Return the new id of a mapping for the given itemname - * @param string $itemname the type of item. For example 'scale' or 'outcome' + * + * @param string $itemname the type of item * @param int $oldid the item ID from the backup - * @param $ifnotfound what to return if $oldid wasnt found + * @param mixed $ifnotfound what to return if $oldid wasnt found. Defaults to false */ public function get_mappingid($itemname, $oldid, $ifnotfound = false) { $mapping = $this->get_mapping($itemname, $oldid); From 71575a152cea82c647375e36c2397cb2619d1182 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 7 Mar 2011 11:57:38 +0000 Subject: [PATCH 067/369] MDL-26517 display responses in reports by converting to plain text. Following Eloy's testing, that seems to be the only safe way. It is also consistent with what has been done in Moodle 2.1. --- question/type/essay/questiontype.php | 2 +- question/type/questiontype.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/essay/questiontype.php b/question/type/essay/questiontype.php index 6cb505f1329..0bfc86ae5a5 100644 --- a/question/type/essay/questiontype.php +++ b/question/type/essay/questiontype.php @@ -134,7 +134,7 @@ class question_essay_qtype extends default_questiontype { function format_response($response, $format) { $safeformatoptions = new stdClass(); $safeformatoptions->para = false; - return format_text($response, FORMAT_MOODLE, $safeformatoptions); + return s(html_to_text(format_text($response, FORMAT_MOODLE, $safeformatoptions), 0, false)); } /** diff --git a/question/type/questiontype.php b/question/type/questiontype.php index defbe1bf00f..e5dacab5ab7 100644 --- a/question/type/questiontype.php +++ b/question/type/questiontype.php @@ -1354,7 +1354,7 @@ class default_questiontype { * @return formatted response */ function format_response($response, $format) { - return $this->format_text($response, $format); + return s(html_to_text($this->format_text($response, $format), 0, false)); } /** From 2fb0b3bd3bf03b1024fbce2e1f3377dfe5a3e1db Mon Sep 17 00:00:00 2001 From: Mary Evans Date: Mon, 7 Mar 2011 09:27:30 -0800 Subject: [PATCH 068/369] Edited theme/nonzero/style/core.css via GitHub --- theme/nonzero/style/core.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/theme/nonzero/style/core.css b/theme/nonzero/style/core.css index e458e659b04..ce6172554ed 100644 --- a/theme/nonzero/style/core.css +++ b/theme/nonzero/style/core.css @@ -157,3 +157,6 @@ a:active { .course-content .main .content { background: #fff; } + +/** Custom CSS **/ +[[setting:customcss]] \ No newline at end of file From 2150d1580f7ecac1e737340586406e9b6d0866a0 Mon Sep 17 00:00:00 2001 From: Mary Evans Date: Mon, 7 Mar 2011 15:01:21 -0800 Subject: [PATCH 069/369] Added Custom CSS Settings - Fix for MDL-26700 --- theme/nonzero/style/core.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/theme/nonzero/style/core.css b/theme/nonzero/style/core.css index e458e659b04..ce6172554ed 100644 --- a/theme/nonzero/style/core.css +++ b/theme/nonzero/style/core.css @@ -157,3 +157,6 @@ a:active { .course-content .main .content { background: #fff; } + +/** Custom CSS **/ +[[setting:customcss]] \ No newline at end of file From 23c799459d66f49b662c80c526c09753af84c384 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 8 Mar 2011 10:11:07 +0100 Subject: [PATCH 070/369] Revert "MDL-26392, nwiki and creole format wiki pages should support file attachments" This reverts commit 0c5e812ba7c43856b5193f03b75a3f7a3d51d686 because UI is going to be reimplemented. --- mod/wiki/edit_form.php | 28 +++--- mod/wiki/lang/en/wiki.php | 8 +- mod/wiki/locallib.php | 116 ++++++++++++++++++------- mod/wiki/pagelib.php | 14 +-- mod/wiki/parser/markups/wikimarkup.php | 21 +---- mod/wiki/parser/parser.php | 4 +- 6 files changed, 109 insertions(+), 82 deletions(-) diff --git a/mod/wiki/edit_form.php b/mod/wiki/edit_form.php index 054555901f9..17f6d14e3d5 100644 --- a/mod/wiki/edit_form.php +++ b/mod/wiki/edit_form.php @@ -80,20 +80,20 @@ class mod_wiki_edit_form extends moodleform { $mform->addElement('hidden', 'contentformat'); $mform->setDefault('contentformat', $format); - if ($format != 'html') { - //uploads - $mform->addElement('header', 'attachments_tags', get_string('uploadtitle', 'wiki')); - $mform->addElement('filemanager', 'attachments', '', null, page_wiki_edit::$attachmentoptions); - $fileinfo = array( - 'contextid'=>$contextid, - 'component'=>'mod_wiki', - 'filearea'=>$filearea, - 'itemid'=>$fileitemid, - ); - - //$mform->addElement('wikifiletable', 'deleteuploads', get_string('wikifiletable', 'wiki'), null, $fileinfo, $format); - //$mform->addElement('submit', 'editoption', get_string('upload', 'wiki'), array('id' => 'tags')); - } +// if ($format != 'html') { +// //uploads +// $mform->addElement('header', 'attachments_tags', get_string('attachments', 'wiki')); +// $mform->addElement('filemanager', 'attachments', get_string('attachments', 'wiki'), null, page_wiki_edit::$attachmentoptions); +// $fileinfo = array( +// 'contextid'=>$contextid, +// 'component'=>'mod_wiki', +// 'filearea'=>$filearea, +// 'itemid'=>$fileitemid, +// ); +// +// $mform->addElement('wikifiletable', 'deleteuploads', get_string('wikifiletable', 'wiki'), null, $fileinfo, $format); +// $mform->addElement('submit', 'editoption', get_string('upload', 'wiki'), array('id' => 'tags')); +// } if (!empty($CFG->usetags)) { $mform->addElement('header', 'tagshdr', get_string('tags', 'tag')); diff --git a/mod/wiki/lang/en/wiki.php b/mod/wiki/lang/en/wiki.php index a12e3d594d2..5a2069cae2b 100644 --- a/mod/wiki/lang/en/wiki.php +++ b/mod/wiki/lang/en/wiki.php @@ -68,16 +68,12 @@ To create a new page, type the new page name enclosed in double square brackets, $string['formatcreole'] = 'Creole format'; $string['formatcreole_help'] = 'Creole is a common wiki markup language with an edit toolbar for inserting appropriate markup. -To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]]. - -To insert image, attach the image files in file manager, then reference the file name using creole markup language.'; +To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]].'; $string['formatcreole_link'] = 'mod/wiki/creole'; $string['formatnwiki'] = 'NWiki format'; $string['formatnwiki_help'] = 'Nwiki is the Mediawiki-like markup language used in the contributed Nwiki module. -To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]]. - -To insert image, attach the image files in file manager, then reference the file name using nwiki markup language.'; +To create a new page, type the new page name enclosed in double square brackets, for example [[Page 2]].'; $string['formatnwiki_link'] = 'mod/wiki/nwiki'; $string['history'] = 'History'; $string['history_help'] = 'The history lists links to previous versions of the page.'; diff --git a/mod/wiki/locallib.php b/mod/wiki/locallib.php index 5a284dbcc8c..91feed29b3a 100644 --- a/mod/wiki/locallib.php +++ b/mod/wiki/locallib.php @@ -578,23 +578,7 @@ function wiki_parse_content($markup, $pagecontent, $options = array()) { $cm = get_coursemodule_from_instance("wiki", $subwiki->wikiid); $context = get_context_instance(CONTEXT_MODULE, $cm->id); - $parser_options = array('link_callback' => '/mod/wiki/locallib.php:wiki_parser_link', - 'link_callback_args' => array('swid' => $options['swid']), - 'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table', - 'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path', - 'real_path_callback_args' => array( - 'context' => $context, - 'component' => 'mod_wiki', - 'filearea' => 'attachments', - 'subwikiid'=> $subwiki->id, - 'pageid' => $options['pageid'] - ), - 'preview' => !empty($options['preview']) ? true : false, - 'itemid' => !empty($options['itemid']) ? $options['itemid'] : null, - 'pageid' => $options['pageid'], - 'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']), - 'printable' => (isset($options['printable']) && $options['printable']) - ); + $parser_options = array('link_callback' => '/mod/wiki/locallib.php:wiki_parser_link', 'link_callback_args' => array('swid' => $options['swid']), 'table_callback' => '/mod/wiki/locallib.php:wiki_parser_table', 'real_path_callback' => '/mod/wiki/locallib.php:wiki_parser_real_path', 'real_path_callback_args' => array('context' => $context, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'pageid' => $options['pageid']), 'pageid' => $options['pageid'], 'pretty_print' => (isset($options['pretty_print']) && $options['pretty_print']), 'printable' => (isset($options['printable']) && $options['printable'])); return wiki_parser_proxy::parse($pagecontent, $markup, $parser_options); } @@ -677,7 +661,7 @@ function wiki_parser_table($table) { /** * Returns an absolute path link, unless there is no such link. * - * @param string url Link's URL or filename + * @param string url Link's URL * @param stdClass context filearea params * @param string filearea * @param int fileareaid @@ -685,26 +669,13 @@ function wiki_parser_table($table) { * @return File full path */ -function wiki_parser_real_path($url, $context, $component, $filearea, $swid) { +function wiki_parser_real_path($url, $context, $filearea, $fileareaid) { global $CFG; if (preg_match("/^(?:http|ftp)s?\:\/\//", $url)) { return $url; } else { - if ($context->contextlevel == CONTEXT_USER) { - // when preview wiki page, files are in draft area - $file = 'draftfile.php'; - } else if ($context->contextlevel == CONTEXT_MODULE) { - $file = 'pluginfile.php'; - } else { - $file = 'brokenfile.php#'; - } - if (!$CFG->slasharguments) { - $file = $file . '?file='; - } - $baseurl = "$CFG->wwwroot/$file/{$context->id}/$component/$filearea/$swid/"; - // it is a file in current file area - return $baseurl . $url; + return "{$CFG->wwwroot}/pluginfile.php/{$context->id}/$filearea/$fileareaid/$url"; } } @@ -1024,6 +995,85 @@ function wiki_delete_old_locks() { $DB->delete_records_select('wiki_locks', "lockedat < ?", array(time() - 3600)); } +/** + * File processing + */ + +/** + * Uploads files to permanent disk space. + * + * @param int draftitemid Draft space ID + * @param int contextid + * + * @return array of files that have not been inserted. + */ + +function wiki_process_attachments($draftitemid, $deleteuploads, $contextid, $filearea, $itemid, $options = null) { + global $CFG, $USER; + + if (empty($options)) { + $options = page_wiki_edit::$attachmentoptions; + } + + $errors = array(); + + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $fs = get_file_storage(); + + $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id'); + + foreach ($oldfiles as $file) { + if (in_array($file->get_pathnamehash(), $deleteuploads)) { + $file->delete(); + } + } + + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); + $oldfiles = $fs->get_area_files($contextid, 'mod_wiki', 'attachments', $itemid, 'id'); + + $file_record = array('contextid' => $contextid, 'component' => 'mod_wiki', 'filearea' => 'attachments', 'itemid' => $itemid); + //more or less a merge... + $newhashes = array(); + foreach ($draftfiles as $file) { + $newhash = sha1("/$contextid/mod_wiki/attachments/$itemid" . $file->get_filepath() . $file->get_filename()); + $newhashes[$newhash] = $file; + } + + $filecount = 0; + foreach ($oldfiles as $file) { + $oldhash = $file->get_pathnamehash(); + if (!$file->is_directory() && isset($newhashes[$oldhash])) { + //repeated file: ERROR!!! + unset($newhashes[$oldhash]); + $errors[] = $file; + } + + if (!$file->is_directory()) { + $filecount++; + } + } + + foreach ($newhashes as $file) { + if ($file->get_filepath() !== '/' or $file->is_directory()) { + continue; + } + + if ($options['maxfiles'] and $options['maxfiles'] <= $filecount) { + break; + } + + if (!$file->is_directory()) { + $filecount++; + $fs->create_file_from_storedfile($file_record, $file); + } + } + + //delete all draft files + $fs->delete_area_files($usercontext->id, 'user', 'draft', $draftitemid); + + return $errors; +} + function wiki_get_comment($commentid){ global $DB; return $DB->get_record('comments', array('id' => $commentid)); diff --git a/mod/wiki/pagelib.php b/mod/wiki/pagelib.php index d438765d581..f49545eab25 100644 --- a/mod/wiki/pagelib.php +++ b/mod/wiki/pagelib.php @@ -367,7 +367,7 @@ class page_wiki_edit extends page_wiki { function __construct($wiki, $subwiki, $cm) { global $CFG, $PAGE; parent::__construct($wiki, $subwiki, $cm); - self::$attachmentoptions = array('subdirs' => false, 'maxfiles' => - 1, 'maxbytes' => $CFG->maxbytes, 'accepted_types' => 'image'); + self::$attachmentoptions = array('subdirs' => false, 'maxfiles' => - 1, 'maxbytes' => $CFG->maxbytes, 'accepted_types' => '*'); $PAGE->requires->js_init_call('M.mod_wiki.renew_lock', null, true); $PAGE->requires->yui2_lib('connection'); } @@ -540,9 +540,9 @@ class page_wiki_edit extends page_wiki { $data = file_prepare_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $context, 'mod_wiki', 'attachments', $this->subwiki->id); break; default: - $draftitemid = file_get_submitted_draft_itemid('attachments'); - file_prepare_draft_area($draftitemid, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); - $data->attachments = $draftitemid; + //$draftitemid = file_get_submitted_draft_itemid('attachments'); + //file_prepare_draft_area($draftitemid, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); + //$data->attachments = $draftitemid; } if ($version->contentformat != 'html') { @@ -588,6 +588,7 @@ class page_wiki_edit extends page_wiki { if ($this->upload) { file_save_draft_area_files($this->attachments, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); return null; + //return wiki_process_attachments($this->attachments, $this->deleteuploads, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); } } } @@ -1033,13 +1034,12 @@ class page_wiki_preview extends page_wiki_edit { $form = new mod_wiki_edit_form($url, $params); - $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true, 'preview'=>true); + $options = array('swid' => $this->page->subwikiid, 'pageid' => $this->page->id, 'pretty_print' => true); if ($data = $form->get_data()) { if (isset($data->newcontent)) { // wiki fromat $text = $data->newcontent; - $options['itemid'] = $data->attachments; } else { // html format $text = $data->newcontent_editor['text']; @@ -1047,7 +1047,7 @@ class page_wiki_preview extends page_wiki_edit { $parseroutput = wiki_parse_content($data->contentformat, $text, $options); $this->set_newcontent($text); echo $OUTPUT->notification(get_string('previewwarning', 'wiki'), 'notifyproblem wiki_info'); - $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true, 'filter'=>false)); + $content = format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true)); echo $OUTPUT->box($content, 'generalbox wiki_previewbox'); $content = $this->newcontent; } diff --git a/mod/wiki/parser/markups/wikimarkup.php b/mod/wiki/parser/markups/wikimarkup.php index a748710074e..30976db0c6a 100644 --- a/mod/wiki/parser/markups/wikimarkup.php +++ b/mod/wiki/parser/markups/wikimarkup.php @@ -25,10 +25,6 @@ abstract class wiki_markup_parser extends generic_parser { //header & ToC protected $toc = array(); - /** @var boolean parse content for preview*/ - protected $preview = false; - /** @var int if preview, itemid will be required to generate file url */ - protected $itemid = null; /** * function wiki_parser_link_callback($link = "") @@ -147,10 +143,6 @@ abstract class wiki_markup_parser extends generic_parser { $this->printable = true; } break; - case 'preview': - $this->preview = $options['preview']; - $this->itemid = $options['itemid']; - break; } } } @@ -332,18 +324,7 @@ abstract class wiki_markup_parser extends generic_parser { } protected function real_path($url) { - global $USER; - if ($this->preview) { - // when preview wiki page, images are in draft area - $callbackargs = array(); - $callbackargs[] = $url; - $callbackargs[] = get_context_instance(CONTEXT_USER, $USER->id); - $callbackargs[] = 'user'; - $callbackargs[] = 'draft'; - $callbackargs[] = $this->itemid; - } else { - $callbackargs = array_merge(array($url), $this->realpathcallbackargs); - } + $callbackargs = array_merge(array($url), $this->realpathcallbackargs); return call_user_func_array($this->realpathcallback, $callbackargs); } diff --git a/mod/wiki/parser/parser.php b/mod/wiki/parser/parser.php index 122061ccd05..b8af04df213 100644 --- a/mod/wiki/parser/parser.php +++ b/mod/wiki/parser/parser.php @@ -139,8 +139,8 @@ abstract class generic_parser { /** * Initialize options */ - protected function set_options($options) { - } + + protected function set_options($options) {} /** * Block processing function & callbacks From ed66022935843752b78fbfbc6db6e3839864c039 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 8 Mar 2011 10:31:16 +0100 Subject: [PATCH 071/369] MDL-26625 do not look for session size if session not started --- lib/moodlelib.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 656bc35c676..ab586af5cf3 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -9300,10 +9300,12 @@ function get_performance_info() { $info['txt'] .= "serverload: {$info['serverload']} "; } - // Display size of session - $info['sessionsize'] = display_size(strlen(session_encode())); - $info['html'] .= 'Session: ' . $info['sessionsize'] . ' '; - $info['txt'] .= "Session: {$info['sessionsize']} "; + // Display size of session if session started + if (session_id()) { + $info['sessionsize'] = display_size(strlen(session_encode())); + $info['html'] .= 'Session: ' . $info['sessionsize'] . ' '; + $info['txt'] .= "Session: {$info['sessionsize']} "; + } /* if (isset($rcache->hits) && isset($rcache->misses)) { $info['rcachehits'] = $rcache->hits; From 7e0218e79f0fc50aa8f4e5c1a53f1ffcc2c301c3 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 8 Mar 2011 10:43:48 +0000 Subject: [PATCH 072/369] MDL-26724 notice from numerical qtype when no answer is given. --- question/type/numerical/display.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/numerical/display.html b/question/type/numerical/display.html index 12d678d507e..b8b9704e904 100644 --- a/question/type/numerical/display.html +++ b/question/type/numerical/display.html @@ -63,9 +63,9 @@ ?> size=""/> responses['unit'] != '') echo $feedbackimgunit; if ($options->feedback && $question->options->unitgradingtype == 1 && ! $valid_numerical_unit && ! $answerasterisk ){ - if ( $empty_unit) { + if (!empty($empty_unit)) { print_string('unitmandatory', 'qtype_numerical'); - }else { + } else { if(isset($question->options->units) && count($question->options->units) > 0){ $found = 0 ; $valid_unit_found = 0 ; From d93cafeaa1b1d93a19cad75e7683bd031546cc07 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 8 Mar 2011 17:48:05 +0000 Subject: [PATCH 073/369] MDL-26733 avoid possible notice in admin/user.php. --- admin/user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/user.php b/admin/user.php index d2ad915cece..2827ccfb07d 100644 --- a/admin/user.php +++ b/admin/user.php @@ -180,7 +180,7 @@ } foreach ($users as $key => $user) { - if (!empty($user->country)) { + if (isset($countries[$user->country])) { $users[$key]->country = $countries[$user->country]; } } From 8d22e342a97fec39ab8b7650e7d0ba91fca5827e Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Mon, 21 Feb 2011 14:51:39 +0800 Subject: [PATCH 074/369] user MDL-24724 added email to user course profile --- user/view.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/user/view.php b/user/view.php index 1cd701bb6d3..c77ba7c11e6 100644 --- a/user/view.php +++ b/user/view.php @@ -236,6 +236,15 @@ echo ''; echo '

'; +//checks were performed above that ensure that if we've got to here either the user +//is viewing their own profile ($USER->id == $user->id) or $user is enrolled in the course +if ($currentuser + or $user->maildisplay == 1 //allow everyone to see email address + or ($user->maildisplay == 2 && is_enrolled($coursecontext, $USER)) //fellow course members can see email. Already know $user is enrolled + or has_capability('moodle/course:useremail', $coursecontext)) { + print_row(get_string("email").":", obfuscate_mailto($user->email, '')); +} + // Show last time this user accessed this course if (!isset($hiddenfields['lastaccess'])) { if ($lastaccess = $DB->get_record('user_lastaccess', array('userid'=>$user->id, 'courseid'=>$course->id))) { From 48c235941f959692f5eb7a48ffcd93a149f8d7d9 Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Wed, 9 Mar 2011 15:55:25 +0800 Subject: [PATCH 075/369] gradebook MDL-26228 moved scrollbar css from standard theme into base --- theme/base/style/grade.css | 2 +- theme/standard/style/grade.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theme/base/style/grade.css b/theme/base/style/grade.css index 593f08a585e..52f098f5042 100644 --- a/theme/base/style/grade.css +++ b/theme/base/style/grade.css @@ -15,7 +15,7 @@ #grade-aggregation-help code {display: block;margin-top: 7px;} .gradeexportlink {padding: 2em;text-align: center;} -.gradetreebox {margin-top:10px;} +.gradetreebox {margin-top:10px;overflow-x:auto;overflow-y:hidden;} .gradetreebox table {font-size: 0.8em;width: 100%;} .gradetreebox td.colspan, .gradetreebox tr.category .cell {background-color: #DDD;} diff --git a/theme/standard/style/grade.css b/theme/standard/style/grade.css index 1f9c2dfef39..5b901c0f78e 100644 --- a/theme/standard/style/grade.css +++ b/theme/standard/style/grade.css @@ -18,7 +18,7 @@ td.grade div.overridden {background-color: #DDDDDD;} .path-grade-report-grader .graderreportoverlay {background-color:#EEEEEE;border:1px solid black;padding:10px;} .path-grade-edit-tree .moving {background-color: #E8EEF7;} -.path-grade-edit-tree .gradetreebox {width:70%;padding-bottom:15px;overflow-x:auto;overflow-y:hidden;} +.path-grade-edit-tree .gradetreebox {width:70%;padding-bottom:15px;} .path-grade-edit-scale .scale_options, #page-admin-grade-edit-scale-index .scale_options {font-size: 0.8em;} From c09604234acc7d006fc3a0411ff9f5714bd82508 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 9 Mar 2011 09:07:01 +0100 Subject: [PATCH 076/369] weekly release --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index cf98cffa610..265ab74a9c4 100644 --- a/version.php +++ b/version.php @@ -30,9 +30,9 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011030300.00; // YYYYMMDD = date of the last version bump +$version = 2011030900.00; // YYYYMMDD = date of the last version bump // XX = daily increments -$release = '2.0.2+ (Build: 20110303)'; // Human-friendly version name +$release = '2.0.2+ (Build: 20110309)'; // Human-friendly version name $maturity = MATURITY_STABLE; // this version's maturity level From a6b53a7cbeed048068c908c01cea44147c37e559 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Wed, 9 Mar 2011 15:16:02 +0800 Subject: [PATCH 077/369] FILEPICKER MDL-26583 filepicker should use core language string not string from modules --- lib/outputrequirementslib.php | 2 +- repository/filepicker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index a9d5127d138..93f21fd034c 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -411,7 +411,7 @@ class page_requirements_manager { array('saving', 'repository'), array('search', 'repository'), array('searching', 'repository'), array('size', 'repository'), array('submit', 'repository'), array('sync', 'repository'), array('title', 'repository'), array('upload', 'repository'), array('uploading', 'repository'), array('xhtmlerror', 'repository'), - array('xhtml', 'quiz'), array('cancel'), array('chooselicense', 'repository'), array('author', 'repository'), + array('cancel'), array('chooselicense', 'repository'), array('author', 'repository'), array('ok', 'moodle'), array('error', 'moodle'), array('info', 'moodle'), array('norepositoriesavailable', 'repository'), array('norepositoriesexternalavailable', 'repository'), array('nofilesattached', 'repository'), array('filepicker', 'repository'), array('nofilesavailable', 'repository') diff --git a/repository/filepicker.js b/repository/filepicker.js index 68c7ad77a31..6f30b238e2c 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -812,7 +812,7 @@ M.core_filepicker.init = function(Y, options) { try { panel.set('innerHTML', str); } catch(e) { - alert(e.toString()+M.str.quiz.xhtml); + alert(M.str.repository.xhtmlerror); } // register buttons // process login action From c4a88609fe02fb60e81f742ce8cf6f328dde0879 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Wed, 9 Mar 2011 17:04:09 +0800 Subject: [PATCH 078/369] MDL-26594 renamed named param causing oracle reserved word error. - thanks to Luca Mazzola --- lib/completionlib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/completionlib.php b/lib/completionlib.php index 2dcf40fcbcd..a747101b6cf 100644 --- a/lib/completionlib.php +++ b/lib/completionlib.php @@ -989,10 +989,10 @@ class completion_info { $sql = "SELECT u.id "; $sql .= $tracked->sql; - $sql .= ' AND u.id = :user'; + $sql .= ' AND u.id = :userid'; $params = $tracked->data; - $params['user'] = (int)$userid; + $params['userid'] = (int)$userid; return $DB->record_exists_sql($sql, $params); } From ca8f828cb507d7dfdc702d67ff34340be881e35f Mon Sep 17 00:00:00 2001 From: stabijoh Date: Wed, 9 Mar 2011 08:01:27 -0500 Subject: [PATCH 079/369] MDL-24743 fix for Magazine theme forced font size --- theme/magazine/style/core.css | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/theme/magazine/style/core.css b/theme/magazine/style/core.css index ccc1ffc1c0f..451da66b8e7 100644 --- a/theme/magazine/style/core.css +++ b/theme/magazine/style/core.css @@ -273,13 +273,12 @@ div.johndocsleft { /** breadcrumb image replacement **/ div#jcontrols_button span.arrow.sep { - font-size: 1px; + font-size: .01em; color: #fafafa; background: url([[pix:theme|breadcrumb_separator_arrow_2_dots]]) no-repeat; - background-position: 50% 9px; + background-position: 50% 7px; display: inline-block; width: 16px; - line-height: 40px; } /** Block styles **/ From cea5d97b4cb9d795ff71ef594f0a9e59010c26d5 Mon Sep 17 00:00:00 2001 From: stabijoh Date: Wed, 9 Mar 2011 09:35:42 -0500 Subject: [PATCH 080/369] Additional fix for MDL-25786, use of #header in theme Magazine --- theme/magazine/layout/frontpage.php | 2 +- theme/magazine/layout/general.php | 2 +- theme/magazine/style/core.css | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/theme/magazine/layout/frontpage.php b/theme/magazine/layout/frontpage.php index 6a7ecdbcac5..163306797e2 100644 --- a/theme/magazine/layout/frontpage.php +++ b/theme/magazine/layout/frontpage.php @@ -37,7 +37,7 @@ echo $OUTPUT->doctype() ?>
-
'; - foreach($this->columns as $column => $index) { + foreach ($this->columns as $column => $index) { $icon_hide = ''; $icon_sort = ''; - if($this->is_collapsible) { - if(!empty($this->sess->collapse[$column])) { + if ($this->is_collapsible) { + if (!empty($this->sess->collapse[$column])) { // some headers contain < br/> tags, do not include in title $icon_hide = ' '.get_string('show').''; - } - else if($this->headers[$index] !== NULL) { + } else if($this->headers[$index] !== NULL) { // some headers contain < br/> tags, do not include in title $icon_hide = ' '.get_string('hide').''; } @@ -1068,34 +1056,31 @@ class flexible_table { $primary_sort_column = ''; $primary_sort_order = ''; - if(reset($this->sess->sortby)) { + if (reset($this->sess->sortby)) { $primary_sort_column = key($this->sess->sortby); $primary_sort_order = current($this->sess->sortby); } - switch($column) { + switch ($column) { case 'fullname': - if($this->is_sortable($column)) { + if ($this->is_sortable($column)) { $icon_sort_first = $icon_sort_last = ''; - if($primary_sort_column == 'firstname') { + if ($primary_sort_column == 'firstname') { $lsortorder = get_string('asc'); - if($primary_sort_order == SORT_ASC) { + if ($primary_sort_order == SORT_ASC) { $icon_sort_first = ' '.get_string('asc').''; $fsortorder = get_string('asc'); - } - else { + } else { $icon_sort_first = ' '.get_string('desc').''; $fsortorder = get_string('desc'); } - } - else if($primary_sort_column == 'lastname') { + } else if($primary_sort_column == 'lastname') { $fsortorder = get_string('asc'); - if($primary_sort_order == SORT_ASC) { + if ($primary_sort_order == SORT_ASC) { $icon_sort_last = ' '.get_string('asc').''; $lsortorder = get_string('asc'); - } - else { + } else { $icon_sort_last = ' '.get_string('desc').''; $lsortorder = get_string('desc'); } @@ -1126,13 +1111,12 @@ class flexible_table { break; default: - if($this->is_sortable($column)) { - if($primary_sort_column == $column) { - if($primary_sort_order == SORT_ASC) { + if ($this->is_sortable($column)) { + if ($primary_sort_column == $column) { + if ($primary_sort_order == SORT_ASC) { $icon_sort = ' '.get_string('asc').''; $localsortorder = get_string('asc'); - } - else { + } else { $icon_sort = ' '.get_string('desc').''; $localsortorder = get_string('desc'); } @@ -1143,13 +1127,11 @@ class flexible_table { } } - if($this->headers[$index] === NULL) { + if ($this->headers[$index] === NULL) { echo ''; - } - else if(!empty($this->sess->collapse[$column])) { + } else if(!empty($this->sess->collapse[$column])) { echo ''; - } - else { + } else { // took out nowrap for accessibility, might need replacement if (!is_array($this->column_style[$column])) { // $usestyles = array('white-space:nowrap'); @@ -1168,19 +1150,19 @@ class flexible_table { /** * This function is not part of the public api. */ - function start_html(){ + function start_html() { global $OUTPUT; // Do we need to print initial bars? $this->print_initials_bar(); // Paging bar - if($this->use_pages) { + if ($this->use_pages) { $pagingbar = new paging_bar($this->totalrows, $this->currpage, $this->pagesize, $this->baseurl); $pagingbar->pagevar = $this->request[TABLE_VAR_PAGE]; echo $OUTPUT->render($pagingbar); } - if(in_array(TABLE_P_TOP, $this->showdownloadbuttonsat)) { + if (in_array(TABLE_P_TOP, $this->showdownloadbuttonsat)) { echo $this->download_buttons(); } @@ -1198,12 +1180,12 @@ class flexible_table { * @return type? */ function make_styles_string(&$styles) { - if(empty($styles)) { + if (empty($styles)) { return ''; } $string = ' style="'; - foreach($styles as $property => $value) { + foreach ($styles as $property => $value) { $string .= $property.':'.$value.';'; } $string .= '"'; @@ -1216,12 +1198,12 @@ class flexible_table { * @return type? */ function make_attributes_string(&$attributes) { - if(empty($attributes)) { + if (empty($attributes)) { return ''; } $string = ' '; - foreach($attributes as $attr => $value) { + foreach ($attributes as $attr => $value) { $string .= ($attr.'="'.$value.'" '); } @@ -1229,12 +1211,13 @@ class flexible_table { } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_sql extends flexible_table{ +class table_sql extends flexible_table { public $countsql = NULL; public $countparams = NULL; @@ -1256,12 +1239,11 @@ class table_sql extends flexible_table{ */ public $is_collapsible = true; - /** * @param string $uniqueid a string identifying this table.Used as a key in * session vars. */ - function table_sql($uniqueid){ + function table_sql($uniqueid) { parent::flexible_table($uniqueid); // some sensible defaults $this->set_attribute('cellspacing', '0'); @@ -1274,16 +1256,15 @@ class table_sql extends flexible_table{ * method or if other_cols returns NULL then put the data straight into the * table. */ - function build_table(){ - if ($this->rawdata){ - foreach($this->rawdata as $row){ + function build_table() { + if ($this->rawdata) { + foreach ($this->rawdata as $row) { $formattedrow = $this->format_row($row); $this->add_data_keyed($formattedrow); } } } - /** * This is only needed if you want to use different sql to count rows. * Used for example when perhaps all db JOINS are not needed when counting @@ -1293,7 +1274,7 @@ class table_sql extends flexible_table{ * We need to count rows returned by the db seperately to the query itself * as we need to know how many pages of data we have to display. */ - function set_count_sql($sql, array $params = NULL){ + function set_count_sql($sql, array $params = NULL) { $this->countsql = $sql; $this->countparams = $params; } @@ -1304,7 +1285,7 @@ class table_sql extends flexible_table{ * Of course you can use sub-queries, JOINS etc. by putting them in the * appropriate clause of the query. */ - function set_sql($fields, $from, $where, array $params = NULL){ + function set_sql($fields, $from, $where, array $params = NULL) { $this->sql = new stdClass(); $this->sql->fields = $fields; $this->sql->from = $from; @@ -1319,10 +1300,10 @@ class table_sql extends flexible_table{ * @param boolean $useinitialsbar do you want to use the initials bar. Bar * will only be used if there is a fullname column defined for the table. */ - function query_db($pagesize, $useinitialsbar=true){ + function query_db($pagesize, $useinitialsbar=true) { global $DB; if (!$this->is_downloading()) { - if ($this->countsql === NULL){ + if ($this->countsql === NULL) { $this->countsql = 'SELECT COUNT(1) FROM '.$this->sql->from.' WHERE '.$this->sql->where; } if ($useinitialsbar && !$this->is_downloading()) { @@ -1357,14 +1338,13 @@ class table_sql extends flexible_table{ } } - /** * Convenience method to call a number of methods for you to display the * table. */ - function out($pagesize, $useinitialsbar, $downloadhelpbutton=''){ + function out($pagesize, $useinitialsbar, $downloadhelpbutton='') { global $DB; - if (!$this->columns){ + if (!$this->columns) { $onerow = $DB->get_record_sql("SELECT {$this->sql->fields} FROM {$this->sql->from} WHERE {$this->sql->where}", $this->sql->params); //if columns is not set then define columns as the keys of the rows returned //from the db. @@ -1378,12 +1358,13 @@ class table_sql extends flexible_table{ } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_default_export_format_parent{ +class table_default_export_format_parent { /** * @var flexible_table or child class reference pointing to table class * object from which to export data. @@ -1395,21 +1376,23 @@ class table_default_export_format_parent{ * started yet. */ var $documentstarted = false; - function table_default_export_format_parent(&$table){ + function table_default_export_format_parent(&$table) { $this->table =& $table; } - function set_table(&$table){ + function set_table(&$table) { $this->table =& $table; } function add_data($row) { return false; } + function add_seperator() { return false; } - function document_started(){ + + function document_started() { return $this->documentstarted; } /** @@ -1417,19 +1400,20 @@ class table_default_export_format_parent{ * the text as safe HTML or as plain text dependent on what is appropriate * for the download format. The default removes all tags. */ - function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL){ + function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { //use some whitespace to indicate where there was some line spacing. $text = str_replace(array('

', "\n", "\r"), ' ', $text); return strip_tags($text); } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_spreadsheet_export_format_parent extends table_default_export_format_parent{ +class table_spreadsheet_export_format_parent extends table_default_export_format_parent { var $rownum; var $workbook; var $worksheet; @@ -1450,9 +1434,10 @@ class table_spreadsheet_export_format_parent extends table_default_export_format /** * This method will be overridden in the child class. */ - function define_workbook(){ + function define_workbook() { } - function start_document($filename){ + + function start_document($filename) { $filename = $filename.'.'.$this->fileextension; $this->define_workbook(); // format types @@ -1465,11 +1450,13 @@ class table_spreadsheet_export_format_parent extends table_default_export_format $this->workbook->send($filename); $this->documentstarted = true; } - function start_table($sheettitle){ + + function start_table($sheettitle) { $this->worksheet =& $this->workbook->add_worksheet($sheettitle); $this->rownum=0; } - function output_headers($headers){ + + function output_headers($headers) { $colnum = 0; foreach ($headers as $item) { $this->worksheet->write($this->rownum,$colnum,$item,$this->formatheaders); @@ -1477,37 +1464,41 @@ class table_spreadsheet_export_format_parent extends table_default_export_format } $this->rownum++; } - function add_data($row){ + + function add_data($row) { $colnum = 0; - foreach($row as $item){ + foreach ($row as $item) { $this->worksheet->write($this->rownum,$colnum,$item,$this->formatnormal); $colnum++; } $this->rownum++; return true; } + function add_seperator() { $this->rownum++; return true; } - function finish_table(){ + function finish_table() { } - function finish_document(){ + + function finish_document() { $this->workbook->close(); exit; } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_excel_export_format extends table_spreadsheet_export_format_parent{ +class table_excel_export_format extends table_spreadsheet_export_format_parent { var $fileextension = 'xls'; - function define_workbook(){ + function define_workbook() { global $CFG; require_once("$CFG->libdir/excellib.class.php"); // Creating a workbook @@ -1516,14 +1507,15 @@ class table_excel_export_format extends table_spreadsheet_export_format_parent{ } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_ods_export_format extends table_spreadsheet_export_format_parent{ +class table_ods_export_format extends table_spreadsheet_export_format_parent { var $fileextension = 'ods'; - function define_workbook(){ + function define_workbook() { global $CFG; require_once("$CFG->libdir/odslib.class.php"); // Creating a workbook @@ -1531,6 +1523,7 @@ class table_ods_export_format extends table_spreadsheet_export_format_parent{ } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} @@ -1585,35 +1578,38 @@ class table_text_export_format_parent extends table_default_export_format_parent } } + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_tsv_export_format extends table_text_export_format_parent{ +class table_tsv_export_format extends table_text_export_format_parent { protected $seperator = "\t"; protected $mimetype = 'text/tab-separated-values'; protected $ext = '.txt'; } -/** - * @package moodlecore - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class table_csv_export_format extends table_text_export_format_parent{ - protected $seperator = ","; - protected $mimetype = 'text/csv'; - protected $ext = '.csv'; -} /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class table_xhtml_export_format extends table_default_export_format_parent{ - function start_document($filename){ +class table_csv_export_format extends table_text_export_format_parent { + protected $seperator = ","; + protected $mimetype = 'text/csv'; + protected $ext = '.csv'; +} + + +/** + * @package moodlecore + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class table_xhtml_export_format extends table_default_export_format_parent { + function start_document($filename) { header("Content-Type: application/download\n"); header("Content-Disposition: attachment; filename=\"$filename.html\""); header("Expires: 0"); @@ -1666,7 +1662,7 @@ table { margin:auto; } -h1, h2{ +h1, h2 { text-align:center; } .bold { @@ -1675,8 +1671,6 @@ font-weight:bold; .mdl-align { text-align:center; } - - /*]]>*/$filename @@ -1684,41 +1678,46 @@ font-weight:bold; EOF; $this->documentstarted = true; } - function start_table($sheettitle){ + + function start_table($sheettitle) { $this->table->sortable(false); $this->table->collapsible(false); echo "

{$sheettitle}

"; $this->table->start_html(); } - - function output_headers($headers){ + function output_headers($headers) { $this->table->print_headers(); } - function add_data($row){ + + function add_data($row) { $this->table->print_row($row); return true; } + function add_seperator() { $this->table->print_row(NULL); return true; } - function finish_table(){ + + function finish_table() { $this->table->finish_html(); } - function finish_document(){ + + function finish_document() { echo "\n"; exit; } - function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL){ - if (is_null($options)){ + + function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { + if (is_null($options)) { $options = new stdClass; } //some sensible defaults - if (!isset($options->para)){ + if (!isset($options->para)) { $options->para = false; } - if (!isset($options->newlines)){ + if (!isset($options->newlines)) { $options->newlines = false; } if (!isset($options->smiley)) { From 4b7079c100a014e62e224518a307469ac62dfe34 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:31:23 +0000 Subject: [PATCH 205/369] MDL-26425 tablelib clean up constant definitions. --- lib/tablelib.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 0202b624f44..7c196ddf63d 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -25,23 +25,24 @@ defined('MOODLE_INTERNAL') || die(); -/** TABLE_VAR_SORT = 1 */ +/**#@+ + * These constants relate to the table's handling of URL parameters. + */ define('TABLE_VAR_SORT', 1); -/** TABLE_VAR_HIDE = 2 */ define('TABLE_VAR_HIDE', 2); -/** TABLE_VAR_SHOW = 3 */ define('TABLE_VAR_SHOW', 3); -/** TABLE_VAR_IFIRST = 4 */ define('TABLE_VAR_IFIRST', 4); -/** TABLE_VAR_ILAST = 5 */ define('TABLE_VAR_ILAST', 5); -/** TABLE_VAR_PAGE = 6 */ define('TABLE_VAR_PAGE', 6); +/**#@-*/ -/** TABLE_P_TOP = 1 */ -define('TABLE_P_TOP', 1); -/** TABLE_P_BOTTOM = 2 */ -define('TABLE_P_BOTTOM', 2); +/**#@+ + * Constants that indicate whether the paging bar for the table + * appears above or below the table. + */ +define('TABLE_P_TOP', 1); +define('TABLE_P_BOTTOM', 2); +/**#@-*/ /** From a49c17b42493e7b07ecbae0dbc35901cda87e239 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:33:31 +0000 Subject: [PATCH 206/369] MDL-26425 tablelib rename constructors to PHP5 __construct and add depreacted functions with the old name so that legacy code does not break. --- lib/tablelib.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 7c196ddf63d..bae9504c11c 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -119,7 +119,7 @@ class flexible_table { * @param int $uniqueid * @todo Document properly */ - function flexible_table($uniqueid) { + function __construct($uniqueid) { $this->uniqueid = $uniqueid; $this->request = array( TABLE_VAR_SORT => 'tsort', @@ -131,6 +131,17 @@ class flexible_table { ); } + /** + * Backwards-compatible constructor, so that legacy code subclassing + * flexible_table does not break. + * @deprecated since Moodle 2.0. Will be removed in Moodle 2.1. + */ + function flexible_table($uniqueid) { + debugging('Please update your code to user PHP5-style parent::__construct(...), ' . + 'not parent::flexible_table(...).'); + $this->__construct($uniqueid); + } + /** * Call this to pass the download type. Use : * $download = optional_param('download', '', PARAM_ALPHA); @@ -1244,13 +1255,24 @@ class table_sql extends flexible_table { * @param string $uniqueid a string identifying this table.Used as a key in * session vars. */ - function table_sql($uniqueid) { - parent::flexible_table($uniqueid); + function __construct($uniqueid) { + parent::__construct($uniqueid); // some sensible defaults $this->set_attribute('cellspacing', '0'); $this->set_attribute('class', 'generaltable generalbox'); } + /** + * Backwards-compatible constructor, so that legacy code subclassing + * table_sql does not break. + * @deprecated since Moodle 2.0. Will be removed in Moodle 2.1. + */ + function table_sql($uniqueid) { + debugging('Please update your code to user PHP5-style parent::__construct(...), ' . + 'not parent::table_sql(...).'); + $this->__construct($uniqueid); + } + /** * Take the data returned from the db_query and go through all the rows * processing each col using either col_{columnname} method or other_cols From 59f392b3f0f4a4df55c019c3a112d0752e347c59 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:37:40 +0000 Subject: [PATCH 207/369] MDL-26425 tablelib clean up setup and URL handling code. Note that this change removes ->reseturl, This was supposed to be a way to reset all the session stuff relating to a table automatically in some situations, but from using Moodle and reading the code, I don't beleive it was working. The code was horrible and not easily fixible, and has been broken for years, so I just removed it. --- lib/tablelib.php | 122 ++++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 85 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index bae9504c11c..6df00292920 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -360,16 +360,11 @@ class flexible_table { } /** - * Sets $this->reseturl to the given $url, and $this->baseurl to the given $url plus ? or & - * @param string $url the url with params needed to call up this page + * Sets $this->baseurl. + * @param moodle_url|string $url the url with params needed to call up this page */ function define_baseurl($url) { - $this->reseturl = $url; - if (!strpos($url, '?')) { - $this->baseurl = $url.'?'; - } else { - $this->baseurl = $url.'&'; - } + $this->baseurl = new moodle_url($url); } /** @@ -425,14 +420,15 @@ class flexible_table { $this->sess = &$SESSION->flextable[$this->uniqueid]; - if (!empty($_GET[$this->request[TABLE_VAR_SHOW]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_SHOW]]])) { - // Show this column - $this->sess->collapse[$_GET[$this->request[TABLE_VAR_SHOW]]] = false; - } else if(!empty($_GET[$this->request[TABLE_VAR_HIDE]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_HIDE]]])) { - // Hide this column - $this->sess->collapse[$_GET[$this->request[TABLE_VAR_HIDE]]] = true; - if (array_key_exists($_GET[$this->request[TABLE_VAR_HIDE]], $this->sess->sortby)) { - unset($this->sess->sortby[$_GET[$this->request[TABLE_VAR_HIDE]]]); + if (($showcol = optional_param($this->request[TABLE_VAR_SHOW], '', PARAM_ALPHANUMEXT)) && + isset($this->columns[$showcol])) { + $this->sess->collapse[$showcol] = false; + + } else if (($hidecol = optional_param($this->request[TABLE_VAR_SHOW], '', PARAM_ALPHANUMEXT)) && + isset($this->columns[$hidecol])) { + $this->sess->collapse[$hidecol] = true; + if (array_key_exists($hidecol, $this->sess->sortby)) { + unset($this->sess->sortby[$hidecol]); } } @@ -443,29 +439,22 @@ class flexible_table { } } - if ( - !empty($_GET[$this->request[TABLE_VAR_SORT]]) && $this->is_sortable($_GET[$this->request[TABLE_VAR_SORT]]) && - (isset($this->columns[$_GET[$this->request[TABLE_VAR_SORT]]]) || - (($_GET[$this->request[TABLE_VAR_SORT]] == 'firstname' || $_GET[$this->request[TABLE_VAR_SORT]] == 'lastname') && isset($this->columns['fullname'])) - )) - { - if (empty($this->sess->collapse[$_GET[$this->request[TABLE_VAR_SORT]]])) { - if (array_key_exists($_GET[$this->request[TABLE_VAR_SORT]], $this->sess->sortby)) { - // This key already exists somewhere. Change its sortorder and bring it to the top. - $sortorder = $this->sess->sortby[$_GET[$this->request[TABLE_VAR_SORT]]] == SORT_ASC ? SORT_DESC : SORT_ASC; - unset($this->sess->sortby[$_GET[$this->request[TABLE_VAR_SORT]]]); - $this->sess->sortby = array_merge(array($_GET[$this->request[TABLE_VAR_SORT]] => $sortorder), $this->sess->sortby); - } else { - // Key doesn't exist, so just add it to the beginning of the array, ascending order - $this->sess->sortby = array_merge(array($_GET[$this->request[TABLE_VAR_SORT]] => SORT_ASC), $this->sess->sortby); - } - // Finally, make sure that no more than $this->maxsortkeys are present into the array - if (!empty($this->maxsortkeys) && ($sortkeys = count($this->sess->sortby)) > $this->maxsortkeys) { - while ($sortkeys-- > $this->maxsortkeys) { - array_pop($this->sess->sortby); - } - } + if (($sortcol = optional_param($this->request[TABLE_VAR_SORT], '', PARAM_ALPHANUMEXT)) && + $this->is_sortable($sortcol) && empty($this->sess->collapse[$sortcol]) && + (isset($this->columns[$sortcol]) || in_array($sortcol, array('firstname', 'lastname')) && isset($this->columns['fullname']))) { + + if (array_key_exists($sortcol, $this->sess->sortby)) { + // This key already exists somewhere. Change its sortorder and bring it to the top. + $sortorder = $this->sess->sortby[$sortcol] == SORT_ASC ? SORT_DESC : SORT_ASC; + unset($this->sess->sortby[$sortcol]); + $this->sess->sortby = array_merge(array($sortcol => $sortorder), $this->sess->sortby); + } else { + // Key doesn't exist, so just add it to the beginning of the array, ascending order + $this->sess->sortby = array_merge(array($sortcol => SORT_ASC), $this->sess->sortby); } + + // Finally, make sure that no more than $this->maxsortkeys are present into the array + $this->sess->sortby = array_slice($this->sess->sortby, 0, $this->maxsortkeys); } // If we didn't sort just now, then use the default sort order if one is defined and the column exists @@ -473,67 +462,30 @@ class flexible_table { $this->sess->sortby = array ($this->sort_default_column => ($this->sort_default_order == SORT_DESC ? SORT_DESC : SORT_ASC)); } - if (isset($_GET[$this->request[TABLE_VAR_ILAST]])) { - if (empty($_GET[$this->request[TABLE_VAR_ILAST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_ILAST]]))) { - $this->sess->i_last = $_GET[$this->request[TABLE_VAR_ILAST]]; - } + $ilast = optional_param($this->request[TABLE_VAR_ILAST], null, PARAM_RAW); + if (!is_null($ilast) && ($ilast ==='' || strpos(get_string('alphabet', 'langconfig'), $ilast) !== false)) { + $this->sess->i_last = $ilast; } - if (isset($_GET[$this->request[TABLE_VAR_IFIRST]])) { - if (empty($_GET[$this->request[TABLE_VAR_IFIRST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_IFIRST]]))) { - $this->sess->i_first = $_GET[$this->request[TABLE_VAR_IFIRST]]; - } + $ifirst = optional_param($this->request[TABLE_VAR_IFIRST], null, PARAM_RAW); + if (!is_null($ifirst) && ($ifirst === '' || strpos(get_string('alphabet', 'langconfig'), $ifirst) !== false)) { + $this->sess->i_first = $ifirst; } if (empty($this->baseurl)) { - $getcopy = $_GET; - unset($getcopy[$this->request[TABLE_VAR_SHOW]]); - unset($getcopy[$this->request[TABLE_VAR_HIDE]]); - unset($getcopy[$this->request[TABLE_VAR_SORT]]); - unset($getcopy[$this->request[TABLE_VAR_IFIRST]]); - unset($getcopy[$this->request[TABLE_VAR_ILAST]]); - unset($getcopy[$this->request[TABLE_VAR_PAGE]]); - - $strippedurl = strip_querystring(qualified_me()); - - if (!empty($getcopy)) { - $first = false; - $querystring = ''; - foreach ($getcopy as $var => $val) { - if (!$first) { - $first = true; - $querystring .= '?'.$var.'='.$val; - } else { - $querystring .= '&'.$var.'='.$val; - } - } - $this->reseturl = $strippedurl.$querystring; - $querystring .= '&'; - } else { - $this->reseturl = $strippedurl; - $querystring = '?'; - } - - $this->baseurl = strip_querystring(qualified_me()) . $querystring; - } - - // If it's "the first time" we 've been here, forget the previous initials filters - if (qualified_me() == $this->reseturl) { - $this->sess->i_first = ''; - $this->sess->i_last = ''; + debugging('You should set baseurl when using flexible_table.'); + global $PAGE; + $this->baseurl = $PAGE->url; } $this->currpage = optional_param($this->request[TABLE_VAR_PAGE], 0, PARAM_INT); $this->setup = true; - /// Always introduce the "flexible" class for the table if not specified - /// No attributes, add flexible class + // Always introduce the "flexible" class for the table if not specified if (empty($this->attributes)) { $this->attributes['class'] = 'flexible'; - /// No classes, add flexible class } else if (!isset($this->attributes['class'])) { $this->attributes['class'] = 'flexible'; - /// No flexible class in passed classes, add flexible class } else if (!in_array('flexible', explode(' ', $this->attributes['class']))) { $this->attributes['class'] = trim('flexible ' . $this->attributes['class']); } From e81eed542c3d005a745103b6a33b6bab3d0ac41b Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:42:33 +0000 Subject: [PATCH 208/369] MDL-26425 tablelib better validation of the sort code, also some cleanup. You may think that the extra validation is unnecessary, since the sort fields are already validated when the URL parameters are parsed, however that overlooks an important point. There may be other options that affect which columns are in the SQL, for example the quiz show individual question grades setting. These other options can cause a column that was in the table, and being sorted on, to disappear. Therefore, it is necessary to re-validate the sort columns when they are used, to make sure they are still present, otherwise you can get ORDER BY sql that refers to non-existant columns, which then causes DB errors. --- lib/tablelib.php | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 6df00292920..c31a1ed65af 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -549,6 +549,18 @@ class flexible_table { return array(); } + foreach ($this->sess->sortby as $column => $notused) { + if (isset($this->columns[$column])) { + continue; // This column is OK. + } + if (in_array($column, array('firstname', 'lastname')) && + isset($this->columns['fullname'])) { + continue; // This column is OK. + } + // This column is not OK. + unset($this->sess->sortby[$column]); + } + return $this->sess->sortby; } @@ -573,7 +585,7 @@ class flexible_table { } /** - * @return array - sql where, params array + * @return string sql to add to where statement. */ function get_sql_where() { global $DB; @@ -1304,8 +1316,15 @@ class table_sql extends flexible_table { // Fetch the attempts $sort = $this->get_sql_sort(); - $sort = $sort?" ORDER BY {$sort}":''; - $sql = "SELECT {$this->sql->fields} FROM {$this->sql->from} WHERE {$this->sql->where}{$sort}"; + if ($sort) { + $sort = "ORDER BY $sort"; + } + $sql = "SELECT + {$this->sql->fields} + FROM {$this->sql->from} + WHERE {$this->sql->where} + {$sort}"; + if (!$this->is_downloading()) { $this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size()); } else { From abf72969a440f525761a6e152a2e29aa0a3db164 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:46:48 +0000 Subject: [PATCH 209/369] MDL-26425 tablelib change col_username to use html_writer and moodle_url. --- lib/tablelib.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index c31a1ed65af..8981db438d6 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -730,13 +730,12 @@ class flexible_table { global $COURSE, $CFG; if (!$this->download) { - if ($COURSE->id == SITEID) { - return ''. - fullname($row).''; - } else { - return ''.fullname($row).''; + $profileurl = new moodle_url('/user/profile.php', array('id' => $row->{$this->useridfield})); + if ($COURSE->id != SITEID) { + $profileurl->param('course', $COURSE->id); } + return html_writer::link($profileurl, fullname($row)); + } else { return fullname($row); } @@ -910,7 +909,6 @@ class flexible_table { * This function is not part of the public api. */ function download_buttons() { - global $OUTPUT; if ($this->is_downloadable() && !$this->is_downloading()) { $downloadoptions = $this->get_download_menu(); $html = ''; From b08fb128c847deb6246744fcbb6a7d5068502a28 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:47:54 +0000 Subject: [PATCH 210/369] MDL-26425 tablelib ability for table_sql to add a class to the row based on the data. --- lib/tablelib.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 8981db438d6..6cfaa96cdc0 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -1245,11 +1245,21 @@ class table_sql extends flexible_table { if ($this->rawdata) { foreach ($this->rawdata as $row) { $formattedrow = $this->format_row($row); - $this->add_data_keyed($formattedrow); + $this->add_data_keyed($formattedrow, + $this->get_row_class($row)); } } } + /** + * Get any extra classes names to add to this row in the HTML. + * @param $row array the data for this row. + * @return string added to the class="" attribute of the tr. + */ + function get_row_class($row) { + return ''; + } + /** * This is only needed if you want to use different sql to count rows. * Used for example when perhaps all db JOINS are not needed when counting From 6f0d3480c75cad8fd7824704ddaa136f3a44d06c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 11:55:12 +0000 Subject: [PATCH 211/369] MDL-26425 tablelib change print_initials_bar to remove duplication, and to use html_writer. --- lib/tablelib.php | 56 +++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 6cfaa96cdc0..8fe68328ae5 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -815,50 +815,52 @@ class flexible_table { return $this->sess->i_last; } + protected function print_one_initials_bar($alpha, $current, $class, $title, $urlvar) { + echo html_writer::start_tag('div', array('class' => 'initialbar ' . $class)) . + $title . ' : '; + if ($current) { + echo html_writer::link($this->baseurl->out(false, array($urlvar => '')), get_string('all')); + } else { + echo html_writer::tag('strong', get_string('all')); + } + + foreach ($alpha as $letter) { + if ($letter === $current) { + echo html_writer::tag('strong', $letter); + } else { + echo html_writer::link($this->baseurl->out(false, array($urlvar => $letter)), $letter); + } + } + + echo html_writer::end_tag('div'); + } + /** * This function is not part of the public api. */ function print_initials_bar() { - if ((!empty($this->sess->i_last) || !empty($this->sess->i_first) || $this->use_initials) + if ((!empty($this->sess->i_last) || !empty($this->sess->i_first) ||$this->use_initials) && isset($this->columns['fullname'])) { - $strall = get_string('all'); $alpha = explode(',', get_string('alphabet', 'langconfig')); // Bar of first initials - - echo '
'.get_string('firstname').' : '; if (!empty($this->sess->i_first)) { - echo ''.$strall.''; + $ifirst = $this->sess->i_first; } else { - echo ''.$strall.''; + $ifirst = ''; } - foreach ($alpha as $letter) { - if (isset($this->sess->i_first) && $letter == $this->sess->i_first) { - echo ' '.$letter.''; - } else { - echo ' '.$letter.''; - } - } - echo '
'; + $this->print_one_initials_bar($alpha, $ifirst, 'firstinitial', + get_string('firstname'), $this->request[TABLE_VAR_IFIRST]); // Bar of last initials - - echo '
'.get_string('lastname').' : '; if (!empty($this->sess->i_last)) { - echo ''.$strall.''; + $ilast = $this->sess->i_last; } else { - echo ''.$strall.''; + $ilast = ''; } - foreach ($alpha as $letter) { - if (isset($this->sess->i_last) && $letter == $this->sess->i_last) { - echo ' '.$letter.''; - } else { - echo ' '.$letter.''; - } - } - echo '
'; - + $this->print_one_initials_bar($alpha, $ilast, 'lastinitial', + get_string('lastname'), $this->request[TABLE_VAR_ILAST]); } } From 76dc1e2527b7b682e332c84cb2d38e84f47755d2 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 12:00:30 +0000 Subject: [PATCH 212/369] MDL-26425 tablelib use html_writer when outputting rows and headers. This includes refactoring to extract methods like sort_icon and show_hide_link which I think makes the code easier to read. Note also the change to make_styles_string that makes it usable with html_writer. (Perhpas we need a css_writer classe ;-)) --- lib/tablelib.php | 207 ++++++++++++++++++++++++----------------------- 1 file changed, 105 insertions(+), 102 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 8fe68328ae5..5ff2066c9f7 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -954,31 +954,36 @@ class flexible_table { $rowclasses[] = $classname; } - echo '
'; + echo html_writer::start_tag('tr', array('class', implode(' ', $rowclasses))); // If we have a separator, print it if ($row === NULL) { $colcount = count($this->columns); - echo ''; + echo html_writer::tag('td', html_writer::tag('div', '', + array('class' => 'tabledivider')), array('colspan' => $colcount)); + } else { $colbyindex = array_flip($this->columns); foreach ($row as $index => $data) { $column = $colbyindex[$index]; - echo ''; + + echo html_writer::tag('td', $content, array( + 'class' => 'cell c' . $index . $this->column_class[$column], + 'style' => $this->make_styles_string($this->column_style[$column]))); } } - echo ''; + echo html_writer::end_tag('tr'); $suppress_enabled = array_sum($this->column_suppress); if ($suppress_enabled) { @@ -994,40 +999,54 @@ class flexible_table { if (!$this->started_output) { //no data has been added to the table. $this->print_nothing_to_display(); + } else { - echo '
`YsmcZ3{XP%Nd03*b>66Wd8Hh^wsw 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%0Do(@fzzp3rJJ6&T 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 literal 0 HcmV?d00001 diff --git a/lib/flowplayer/flowplayer.audio-3.2.2.swf b/lib/flowplayer/flowplayer.audio-3.2.2.swf new file mode 100644 index 0000000000000000000000000000000000000000..16aef5c70c6e876ccd9d3eb74e61e7525c78830c GIT binary patch literal 3972 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 v`bm;>=iRql;oNrTf80e)I{5A@8t%N~-n;L-?Vc 600) { + if (newwidth > 500) { obj.setStyle('width', newwidth + 'px'); } else { - obj.setStyle('width', '600px'); + obj.setStyle('width', '500px'); } var headerheight = get_htmlelement_size('page-header', 'height'); var footerheight = get_htmlelement_size('page-footer', 'height'); - var newheight = parseInt(YAHOO.util.Dom.getViewportHeight()) - footerheight - headerheight - 20; + var newheight = parseInt(YAHOO.util.Dom.getViewportHeight()) - footerheight - headerheight - 100; if (newheight < 400) { newheight = 400; } @@ -1534,71 +1529,163 @@ M.form.init_smartselect = function(Y, id, options) { }); }; -M.util.init_flvflowplayer = function (id, playerpath, fileurl) { - $f(id, playerpath, { - plugins: { - controls: { - autoHide: true +/** List of flv players to be loaded */ +M.util.video_players = []; +/** List of mp3 players to be loaded */ +M.util.audio_players = []; + +/** + * Add video player + * @param id element id + * @param fileurl media url + * @param width + * @param height + * @param autosize true means detect size from media + */ +M.util.add_video_player = function (id, fileurl, width, height, autosize) { + M.util.video_players.push({id: id, fileurl: fileurl, width: width, height: height, autosize: autosize, resized: false}); +}; + +/** + * Add audio player. + * @param id + * @param fileurl + * @param small + */ +M.util.add_audio_player = function (id, fileurl, small) { + M.util.audio_players.push({id: id, fileurl: fileurl, small: small}); +}; + +/** + * Initialise all audio and video player, must be called from page footer. + */ +M.util.load_flowplayer = function() { + if (M.util.video_players.length == 0 && M.util.audio_players.length == 0) { + return; + } + if (typeof(flowplayer) == 'undefined') { + var loaded = false; + + var embed_function = function() { + if (loaded || typeof(flowplayer) == 'undefined') { + return; + } + loaded = true; + + var controls = { + autoHide: true + } + /* TODO: add CSS color overrides for the flv flow player */ + + for(var i=0; i 0 && video.height > 0) { + var src = {src: M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.7.swf', width: video.width, height: video.height}; + } else { + var src = M.cfg.wwwroot + '/lib/flowplayer/flowplayer-3.2.7.swf'; } - }, - clip: { - url: fileurl, - autoPlay: false, - autoBuffering: true + flowplayer(video.id, src, { + plugins: {controls: controls}, + clip: { + url: video.fileurl, autoPlay: false, autoBuffering: true, scaling: 'fit', mvideo: video, + onMetaData: function(clip) { + if (clip.mvideo.autosize && !clip.mvideo.resized) { + clip.mvideo.resized = true; + //alert("metadata!!! "+clip.width+' '+clip.height+' '+JSON.stringify(clip.metaData)); + if (typeof(clip.metaData.width) == 'undefined' || typeof(clip.metaData.height) == 'undefined') { + // bad luck, we have to guess - we may not get metadata at all + var width = clip.width; + var height = clip.height; + } else { + var width = clip.metaData.width; + var height = clip.metaData.height; + } + var minwidth = 300; // controls are messed up in smaller objects + if (width < minwidth) { + height = (height * minwidth) / width; + width = minwidth; + } + + var object = this._api(); + object.width = width; + object.height = height; + } + } + } + }); + } + if (M.util.audio_players.length == 0) { + return; + } + var controls = { + autoHide: false, + fullscreen: false, + next: false, + previous: false, + scrubber: true, + play: true, + pause: true, + volume: true, + mute: false, + backgroundGradient: [0.5,0,0.3] + }; + + var rule; + for (var j=0; j < document.styleSheets.length; j++) { + if (typeof (document.styleSheets[j].rules) != 'undefined') { + var allrules = document.styleSheets[j].rules; + } else if (typeof (document.styleSheets[j].cssRules) != 'undefined') { + var allrules = document.styleSheets[j].cssRules; + } else { + // why?? + continue; + } + for(var i=0; i$value) { if (in_array($key, $configurable)) { diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 3231669c206..a5f8c10955c 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -279,6 +279,9 @@ class core_renderer extends renderer_base { $output .= ''; } + // flow player embedding support + $this->page->requires->js_function_call('M.util.load_flowplayer'); + $this->page->requires->js_function_call('setTimeout', array('fix_column_widths()', 20)); $focus = $this->page->focuscontrol; @@ -2464,22 +2467,6 @@ EOD; return $this->page->theme->larrow; } - /** - * Returns the colours of the small MP3 player - * @return string - */ - public function filter_mediaplugin_colors() { - return $this->page->theme->filter_mediaplugin_colors; - } - - /** - * Returns the colours of the big MP3 player - * @return string - */ - public function resource_mp3player_colors() { - return $this->page->theme->resource_mp3player_colors; - } - /** * Returns the custom menu if one has been set * diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index a9d5127d138..63835b190a0 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -287,6 +287,7 @@ class page_requirements_manager { 'loadingicon' => $renderer->pix_url('i/loading_small', 'moodle')->out(false), 'themerev' => theme_get_revision(), 'theme' => $page->theme->name, + 'jsrev' => ((empty($CFG->cachejs) or empty($CFG->jsrev)) ? -1 : $CFG->jsrev), ); if (debugging('', DEBUG_DEVELOPER)) { $this->M_cfg['developerdebug'] = true; diff --git a/lib/resourcelib.php b/lib/resourcelib.php index 82c5eb6c531..a2efe25d5c5 100644 --- a/lib/resourcelib.php +++ b/lib/resourcelib.php @@ -146,7 +146,12 @@ function resourcelib_guess_url_mimetype($fullurl) { global $CFG; require_once("$CFG->libdir/filelib.php"); - if (preg_match("|^(.*)/[a-z]*file.php(\?file=)?(/[^&\?]*)|", $fullurl, $matches)) { + if ($fullurl instanceof moodle_url) { + $fullurl = $fullurl->out(false); + } + + $matches = null; + if (preg_match("|^(.*)/[a-z]*file.php(\?file=)?(/[^&\?#]*)|", $fullurl, $matches)) { // remove the special moodle file serving hacks so that the *file.php is ignored $fullurl = $matches[1].$matches[3]; } @@ -165,10 +170,38 @@ function resourcelib_guess_url_mimetype($fullurl) { } else { // ok, this finally looks like a real file - return mimeinfo('type', $fullurl); + $parts = explode('?', $fullurl); + $url = reset($parts); + return mimeinfo('type', $url); } } +/** + * Looks for the extension. + * + * @param string $fullurl + * @return string file extension + */ +function resourcelib_get_extension($fullurl) { + + if ($fullurl instanceof moodle_url) { + $fullurl = $fullurl->out(false); + } + + $matches = null; + if (preg_match("|^(.*)/[a-z]*file.php(\?file=)?(/.*)|", $fullurl, $matches)) { + // remove the special moodle file serving hacks so that the *file.php is ignored + $fullurl = $matches[1].$matches[3]; + } + + $matches = null; + if (preg_match('/^[^#\?]+\.([a-z0-9]+)([#\?].*)?$/i', $fullurl, $matches)) { + return strtolower($matches[1]); + } + + return ''; +} + /** * Returns image embedding html. * @param string $fullurl @@ -192,46 +225,21 @@ function resourcelib_embed_image($fullurl, $title) { * @return string html */ function resourcelib_embed_mp3($fullurl, $title, $clicktoopen) { - global $CFG, $OUTPUT, $PAGE; - $c = $OUTPUT->resource_mp3player_colors(); // You can set this up in your theme/xxx/config.php - $colors = explode('&', $c); - $playercolors = array(); - foreach ($colors as $color) { - $color = explode('=', $color); - $playercolors[$color[0]] = $color[1]; + if ($fullurl instanceof moodle_url) { + $fullurl = $fullurl->out(false); } - $id = 'filter_mp3_'.time(); //we need something unique because it might be stored in text cache + $id = 'resource_mp3_'.time(); //we need something unique because it might be stored in text cache - $playerpath = $CFG->wwwroot .'/filter/mediaplugin/mp3player.swf'; - $audioplayerpath = $CFG->wwwroot .'/filter/mediaplugin/flowplayer.audio.swf'; + // note: size is specified in theme, it can be made as wide as necessary, but the height can not be changed - $code = << - - - -OET; - $PAGE->requires->js('/lib/flowplayer.js'); - $code .= $PAGE->requires->js_function_call('M.util.init_mp3flowplayer', array('id'=>$id, 'playerpath'=>$playerpath, 'audioplayerpath'=>$audioplayerpath, 'fileurl'=>$fullurl, 'color'=>$playercolors)); + $output = '
'; + $output .= html_writer::tag('span', $clicktoopen, array('id'=>$id, 'class'=>'resourcemediaplugin resourcemediaplugin_mp3', 'title'=>$title)); + $output .= html_writer::script(js_writer::function_call('M.util.add_audio_player', array($id, $fullurl, false))); + $output .= '
'; - return $code; + return $output; } /** @@ -244,29 +252,29 @@ OET; function resourcelib_embed_flashvideo($fullurl, $title, $clicktoopen) { global $CFG, $PAGE; - $id = 'filter_flv_'.time(); //we need something unique because it might be stored in text cache + if ($fullurl instanceof moodle_url) { + $fullurl = $fullurl->out(false); + } - $playerpath = $CFG->wwwroot .'/filter/mediaplugin/flvplayer.swf'; + $id = 'resource_flv_'.time(); //we need something unique because it might be stored in text cache - $code = << - - - -EOT; + //note: nobody should be adding any dimensions to themes!!! - $PAGE->requires->js('/lib/flowplayer.js'); - $code .= $PAGE->requires->js_function_call('M.util.init_flvflowplayer', array('id'=>$id, 'playerpath'=>$playerpath, 'fileurl'=>$fullurl)); - return $code; + if (preg_match('/\?d=([\d]{1,4}%?)x([\d]{1,4}%?)/', $fullurl, $matches)) { + $width = $matches[1]; + $height = $matches[2]; + $autosize = false; + } else { + $width = 400; + $height = 300; + $autosize = true; + } + $output = '
'; + $output .= html_writer::tag('span', $clicktoopen, array('id'=>$id, 'class'=>'resourcemediaplugin resourcemediaplugin_flv', 'title'=>$title)); + $output .= html_writer::script(js_writer::function_call('M.util.add_video_player', array($id, $fullurl, $width, $height, $autosize))); + $output .= '
'; + + return $output; } /** @@ -406,11 +414,12 @@ EOT; function resourcelib_embed_real($fullurl, $title, $clicktoopen) { $code = << - + + $clicktoopen @@ -436,13 +445,15 @@ function resourcelib_embed_pdf($fullurl, $title, $clicktoopen) { $code = << - + $clicktoopen EOT; - //$PAGE->requires->js_init_call('M.util.init_maximised_embed', array('resourceobject'), true); + + // the size is hardcoded in the boject obove intentionally because it is adjusted by the following function on-the-fly + $PAGE->requires->js_init_call('M.util.init_maximised_embed', array('resourceobject'), true); return $code; } @@ -458,6 +469,10 @@ EOT; function resourcelib_embed_general($fullurl, $title, $clicktoopen, $mimetype) { global $CFG, $PAGE; + if ($fullurl instanceof moodle_url) { + $fullurl = $fullurl->out(); + } + $iframe = false; // IE can not embed stuff properly if stored on different server // that is why we use iframe instead, unfortunately this tag does not validate @@ -481,7 +496,7 @@ EOT; } else { $code = << - + $clicktoopen @@ -489,6 +504,7 @@ EOT; EOT; } + // the size is hardcoded in the boject obove intentionally because it is adjusted by the following function on-the-fly $PAGE->requires->js_init_call('M.util.init_maximised_embed', array('resourceobject'), true); return $code; diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 47dadd93077..eb8ec851090 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -85,11 +85,11 @@ - mp3player - - - - + flowplayer + Flowplayer + GPL + 3.2.7 + 3 overlib diff --git a/lib/ufo.js b/lib/ufo.js deleted file mode 100644 index ad8f28cd8d0..00000000000 --- a/lib/ufo.js +++ /dev/null @@ -1,340 +0,0 @@ -/* Unobtrusive Flash Objects (UFO) v3.22 - Copyright 2005-2007 Bobby van der Sluis - This software is licensed under the CC-GNU LGPL - -- - Modified by Guy Thomas - - made more IE friendly by using better on DOM loaded check - -*/ - -var UFO = { - req: ["movie", "width", "height", "majorversion", "build"], - opt: ["play", "loop", "menu", "quality", "scale", "salign", "wmode", "bgcolor", "base", "flashvars", "devicefont", "allowscriptaccess", "seamlesstabbing", "allowfullscreen", "allownetworking"], - optAtt: ["id", "name", "align"], - optExc: ["swliveconnect"], - ximovie: "ufo.swf", - xiwidth: "215", - xiheight: "138", - ua: navigator.userAgent.toLowerCase(), - pluginType: "", - fv: [0,0], - foList: [], - - create: function(FO, id) { - if (!UFO.uaHas("w3cdom") || UFO.uaHas("ieMac")) return; - UFO.getFlashVersion(); - UFO.foList[id] = UFO.updateFO(FO); - UFO.createCSS("#" + id, "visibility:hidden;"); - UFO.domLoad(id); - }, - - updateFO: function(FO) { - if (typeof FO.xi != "undefined" && FO.xi == "true") { - if (typeof FO.ximovie == "undefined") FO.ximovie = UFO.ximovie; - if (typeof FO.xiwidth == "undefined") FO.xiwidth = UFO.xiwidth; - if (typeof FO.xiheight == "undefined") FO.xiheight = UFO.xiheight; - } - FO.mainCalled = false; - return FO; - }, - - domLoad: function(id) { - onDOMComplete(window, function(){UFO.main(id);}); - }, - - main: function(id) { - var _fo = UFO.foList[id]; - if (_fo.mainCalled) return; - UFO.foList[id].mainCalled = true; - document.getElementById(id).style.visibility = "hidden"; - if (UFO.hasRequired(id)) { - if (UFO.hasFlashVersion(parseInt(_fo.majorversion, 10), parseInt(_fo.build, 10))) { - if (typeof _fo.setcontainercss != "undefined" && _fo.setcontainercss == "true") UFO.setContainerCSS(id); - UFO.writeSWF(id); - } - else if (_fo.xi == "true" && UFO.hasFlashVersion(6, 65)) { - UFO.createDialog(id); - } - } - document.getElementById(id).style.visibility = "visible"; - }, - - createCSS: function(selector, declaration) { - var _h = document.getElementsByTagName("head")[0]; - var _s = UFO.createElement("style"); - if (!UFO.uaHas("ieWin")) _s.appendChild(document.createTextNode(selector + " {" + declaration + "}")); // bugs in IE/Win - _s.setAttribute("type", "text/css"); - _s.setAttribute("media", "screen"); - _h.appendChild(_s); - if (UFO.uaHas("ieWin") && document.styleSheets && document.styleSheets.length > 0) { - var _ls = document.styleSheets[document.styleSheets.length - 1]; - if (typeof _ls.addRule == "object") _ls.addRule(selector, declaration); - } - }, - - setContainerCSS: function(id) { - var _fo = UFO.foList[id]; - var _w = /%/.test(_fo.width) ? "" : "px"; - var _h = /%/.test(_fo.height) ? "" : "px"; - UFO.createCSS("#" + id, "width:" + _fo.width + _w +"; height:" + _fo.height + _h +";"); - if (_fo.width == "100%") { - UFO.createCSS("body", "margin-left:0; margin-right:0; padding-left:0; padding-right:0;"); - } - if (_fo.height == "100%") { - UFO.createCSS("html", "height:100%; overflow:hidden;"); - UFO.createCSS("body", "margin-top:0; margin-bottom:0; padding-top:0; padding-bottom:0; height:100%;"); - } - }, - - createElement: function(el) { - return (UFO.uaHas("xml") && typeof document.createElementNS != "undefined") ? document.createElementNS("http://www.w3.org/1999/xhtml", el) : document.createElement(el); - }, - - createObjParam: function(el, aName, aValue) { - var _p = UFO.createElement("param"); - _p.setAttribute("name", aName); - _p.setAttribute("value", aValue); - el.appendChild(_p); - }, - - uaHas: function(ft) { - var _u = UFO.ua; - switch(ft) { - case "w3cdom": - return (typeof document.getElementById != "undefined" && typeof document.getElementsByTagName != "undefined" && (typeof document.createElement != "undefined" || typeof document.createElementNS != "undefined")); - case "xml": - var _m = document.getElementsByTagName("meta"); - var _l = _m.length; - for (var i = 0; i < _l; i++) { - if (/content-type/i.test(_m[i].getAttribute("http-equiv")) && /xml/i.test(_m[i].getAttribute("content"))) return true; - } - return false; - case "ieMac": - return /msie/.test(_u) && !/opera/.test(_u) && /mac/.test(_u); - case "ieWin": - return /msie/.test(_u) && !/opera/.test(_u) && /win/.test(_u); - case "gecko": - return /gecko/.test(_u) && !/applewebkit/.test(_u); - case "opera": - return /opera/.test(_u); - case "safari": - return /applewebkit/.test(_u); - default: - return false; - } - }, - - getFlashVersion: function() { - if (UFO.fv[0] != 0) return; - if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") { - UFO.pluginType = "npapi"; - var _d = navigator.plugins["Shockwave Flash"].description; - if (typeof _d != "undefined") { - _d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); - var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10); - var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0; - UFO.fv = [_m, _r]; - } - } - else if (window.ActiveXObject) { - UFO.pluginType = "ax"; - try { // avoid fp 6 crashes - var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); - } - catch(e) { - try { - var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); - UFO.fv = [6, 0]; - _a.AllowScriptAccess = "always"; // throws if fp < 6.47 - } - catch(e) { - if (UFO.fv[0] == 6) return; - } - try { - var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); - } - catch(e) {} - } - if (typeof _a == "object") { - var _d = _a.GetVariable("$version"); // bugs in fp 6.21/6.23 - if (typeof _d != "undefined") { - _d = _d.replace(/^\S+\s+(.*)$/, "$1").split(","); - UFO.fv = [parseInt(_d[0], 10), parseInt(_d[2], 10)]; - } - } - } - }, - - hasRequired: function(id) { - var _l = UFO.req.length; - for (var i = 0; i < _l; i++) { - if (typeof UFO.foList[id][UFO.req[i]] == "undefined") return false; - } - return true; - }, - - hasFlashVersion: function(major, release) { - return (UFO.fv[0] > major || (UFO.fv[0] == major && UFO.fv[1] >= release)) ? true : false; - }, - - writeSWF: function(id) { - var _fo = UFO.foList[id]; - var _e = document.getElementById(id); - if (UFO.pluginType == "npapi") { - if (UFO.uaHas("gecko") || UFO.uaHas("xml")) { - while(_e.hasChildNodes()) { - _e.removeChild(_e.firstChild); - } - var _obj = UFO.createElement("object"); - _obj.setAttribute("type", "application/x-shockwave-flash"); - _obj.setAttribute("data", _fo.movie); - _obj.setAttribute("width", _fo.width); - _obj.setAttribute("height", _fo.height); - var _l = UFO.optAtt.length; - for (var i = 0; i < _l; i++) { - if (typeof _fo[UFO.optAtt[i]] != "undefined") _obj.setAttribute(UFO.optAtt[i], _fo[UFO.optAtt[i]]); - } - var _o = UFO.opt.concat(UFO.optExc); - var _l = _o.length; - for (var i = 0; i < _l; i++) { - if (typeof _fo[_o[i]] != "undefined") UFO.createObjParam(_obj, _o[i], _fo[_o[i]]); - } - _e.appendChild(_obj); - } - else { - var _emb = ""; - var _o = UFO.opt.concat(UFO.optAtt).concat(UFO.optExc); - var _l = _o.length; - for (var i = 0; i < _l; i++) { - if (typeof _fo[_o[i]] != "undefined") _emb += ' ' + _o[i] + '="' + _fo[_o[i]] + '"'; - } - _e.innerHTML = ''; - } - } - else if (UFO.pluginType == "ax") { - var _objAtt = ""; - var _l = UFO.optAtt.length; - for (var i = 0; i < _l; i++) { - if (typeof _fo[UFO.optAtt[i]] != "undefined") _objAtt += ' ' + UFO.optAtt[i] + '="' + _fo[UFO.optAtt[i]] + '"'; - } - var _objPar = ""; - var _l = UFO.opt.length; - for (var i = 0; i < _l; i++) { - if (typeof _fo[UFO.opt[i]] != "undefined") _objPar += ''; - } - var _p = window.location.protocol == "https:" ? "https:" : "http:"; - _e.innerHTML = '' + _objPar + ''; - } - }, - - createDialog: function(id) { - var _fo = UFO.foList[id]; - UFO.createCSS("html", "height:100%; overflow:hidden;"); - UFO.createCSS("body", "height:100%; overflow:hidden;"); - UFO.createCSS("#xi-con", "position:absolute; left:0; top:0; z-index:1000; width:100%; height:100%; background-color:#fff; filter:alpha(opacity:75); opacity:0.75;"); - UFO.createCSS("#xi-dia", "position:absolute; left:50%; top:50%; margin-left: -" + Math.round(parseInt(_fo.xiwidth, 10) / 2) + "px; margin-top: -" + Math.round(parseInt(_fo.xiheight, 10) / 2) + "px; width:" + _fo.xiwidth + "px; height:" + _fo.xiheight + "px;"); - var _b = document.getElementsByTagName("body")[0]; - var _c = UFO.createElement("div"); - _c.setAttribute("id", "xi-con"); - var _d = UFO.createElement("div"); - _d.setAttribute("id", "xi-dia"); - _c.appendChild(_d); - _b.appendChild(_c); - var _mmu = window.location; - if (UFO.uaHas("xml") && UFO.uaHas("safari")) { - var _mmd = document.getElementsByTagName("title")[0].firstChild.nodeValue = document.getElementsByTagName("title")[0].firstChild.nodeValue.slice(0, 47) + " - Flash Player Installation"; - } - else { - var _mmd = document.title = document.title.slice(0, 47) + " - Flash Player Installation"; - } - var _mmp = UFO.pluginType == "ax" ? "ActiveX" : "PlugIn"; - var _uc = typeof _fo.xiurlcancel != "undefined" ? "&xiUrlCancel=" + _fo.xiurlcancel : ""; - var _uf = typeof _fo.xiurlfailed != "undefined" ? "&xiUrlFailed=" + _fo.xiurlfailed : ""; - UFO.foList["xi-dia"] = { movie:_fo.ximovie, width:_fo.xiwidth, height:_fo.xiheight, majorversion:"6", build:"65", flashvars:"MMredirectURL=" + _mmu + "&MMplayerType=" + _mmp + "&MMdoctitle=" + _mmd + _uc + _uf }; - UFO.writeSWF("xi-dia"); - }, - - expressInstallCallback: function() { - var _b = document.getElementsByTagName("body")[0]; - var _c = document.getElementById("xi-con"); - _b.removeChild(_c); - UFO.createCSS("body", "height:auto; overflow:auto;"); - UFO.createCSS("html", "height:auto; overflow:auto;"); - }, - - cleanupIELeaks: function() { - var _o = document.getElementsByTagName("object"); - var _l = _o.length; - for (var i = 0; i < _l; i++) { - _o[i].style.display = "none"; - for (var x in _o[i]) { - if (typeof _o[i][x] == "function") { - _o[i][x] = null; - } - } - } - } - -}; - -if (typeof window.attachEvent != "undefined" && UFO.uaHas("ieWin")) { - window.attachEvent("onunload", UFO.cleanupIELeaks); -} - -/* - * - * DOMComplete - Load Event - * - * Author: Diego Perini (diego.perini@gmail.com) - * Updated: 28/06/2007 - * Version: 0.99.8 - * http://javascript.nwbox.com/DOMComplete/ - * Modified: By Guy Thomas 07/02/2008 - * Changed to scroll temporary node instead of actual document - */ -function onDOMComplete(w, f) { - var d = w.document, done = false; - //create temporary node to check scroll left ( see http://www.hedgerwow.com/360/dhtml/ie-dom-ondocumentready.html) - var tempNode = document.createElement('document:ready'); - wait(); - if ((/WebKit|KHTML|MSIE/i).test(navigator.userAgent)) { - poll(); - } - function load(e) { - if (!done) { - tempNode = null; - done = true; stop(); f(e); - } - } - - function has(p) { return typeof d[p] != 'undefined'; } - - function poll() { - if (d.body !== null && d.getElementsByTagName) { - // please see http://javascript.nwbox.com/IEContentLoaded/ for the IE improvement part of DOMComplete - // GT modified to use tempNode.doScroll('left') to check DOM loaded (instead of actually scrolling the page) - if (has('fileSize')) { try { tempNode.doScroll('left'); load('documentready'); } catch (e) { } } - if (has('readyState') && (/loaded|complete/).test(d.readyState)) { load('readyState'); } - } - if (!done) { setTimeout(poll, 10); } - } - - function stop() { - if (typeof d.removeEventListener == 'function') { - d.removeEventListener('DOMContentLoaded', load, false); - } - } - - function wait() { - if (typeof d.addEventListener == 'function') { - d.addEventListener('DOMContentLoaded', load, false); - } - var oldonload = w.onload; - w.onload = function (e) { - if (typeof oldonload == 'function') { - oldonload(); - } - load(e || this.event); - }; - } -} diff --git a/lib/weblib.php b/lib/weblib.php index 4abc493b62d..c57de8649ea 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -1018,7 +1018,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ if (is_object($options['context'])) { $context = $options['context']; } else { - $context = get_context_instance_by_id($context); + $context = get_context_instance_by_id($options['context']); } } else if ($courseid_do_not_use) { // legacy courseid @@ -1073,7 +1073,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ if (!$options['noclean']) { $text = clean_text($text, FORMAT_HTML, $options); } - $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_HTML)); + $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_HTML, 'noclean' => $options['noclean'])); break; case FORMAT_PLAIN: @@ -1096,7 +1096,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ if (!$options['noclean']) { $text = clean_text($text, FORMAT_HTML, $options); } - $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_MARKDOWN)); + $text = $filtermanager->filter_text($text, $context, array('originalformat' => FORMAT_MARKDOWN, 'noclean' => $options['noclean'])); break; default: // FORMAT_MOODLE or anything else @@ -1104,7 +1104,7 @@ function format_text($text, $format = FORMAT_MOODLE, $options = NULL, $courseid_ if (!$options['noclean']) { $text = clean_text($text, FORMAT_HTML, $options); } - $text = $filtermanager->filter_text($text, $context, array('originalformat' => $format)); + $text = $filtermanager->filter_text($text, $context, array('originalformat' => $format, 'noclean' => $options['noclean'])); break; } if ($options['filter']) { @@ -3277,28 +3277,3 @@ function print_password_policy() { } return $message; } - -function create_ufo_inline($id, $args) { - global $CFG; - // must not use $PAGE, $THEME, $COURSE etc. because the result is cached! - // unfortunately this ufo.js can not be cached properly because we do not have access to current $CFG either - $jsoutput = html_writer::script('', $CFG->wwwroot.'/lib/ufo.js'); - $jsoutput .= html_writer::script(js_writer::function_call('M.util.create_UFO_object', array($id, $args))); - return $jsoutput; -} - -function create_flowplayer($id, $fileurl, $type='flv', $color='#000000') { - global $CFG; - - $playerpath = $CFG->wwwroot.'/filter/mediaplugin/'.$type.'player.swf'; - $jsoutput = html_writer::script('', $CFG->wwwroot.'/lib/flowplayer.js'); - - if ($type == 'flv') { - $jsoutput .= html_writer::script(js_writer::function_call('M.util.init_flvflowplayer', array($id, $playerpath, $fileurl))); - } else if ($type == 'mp3') { - $audioplayerpath = $CFG->wwwroot .'/filter/mediaplugin/flowplayer.audio.swf'; - $jsoutput .= html_writer::script(js_writer::function_call('M.util.init_mp3flowplayerplugin', array($id, $playerpath, $audioplayerpath, $fileurl, $color))); - } - - return $jsoutput; -} diff --git a/mod/lesson/locallib.php b/mod/lesson/locallib.php index f5213307a7d..060afeff719 100644 --- a/mod/lesson/locallib.php +++ b/mod/lesson/locallib.php @@ -603,6 +603,8 @@ function lesson_get_media_html($lesson, $context) { $mimetype = resourcelib_guess_url_mimetype($url); + $extension = resourcelib_get_extension($url->out(false)); + // find the correct type and print it out if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image $code = resourcelib_embed_image($url, $title); @@ -611,7 +613,7 @@ function lesson_get_media_html($lesson, $context) { // MP3 audio file $code = resourcelib_embed_mp3($url, $title, $clicktoopen); - } else if ($mimetype == 'video/x-flv') { + } else if ($mimetype == 'video/x-flv' or $extension === 'f4v') { // Flash video file $code = resourcelib_embed_flashvideo($url, $title, $clicktoopen); diff --git a/mod/lesson/styles.css b/mod/lesson/styles.css index 00fc038fc4a..99028da116e 100644 --- a/mod/lesson/styles.css +++ b/mod/lesson/styles.css @@ -23,6 +23,8 @@ .path-mod-lesson .progress_bar_token {height: 20px;width: 5px;padding: 0;margin: 0;} .path-mod-lesson .edit_pages_box .addlinks {margin:0;margin-bottom:1em;} +.path-mod-lesson .resourcecontent {text-align: center;} + /** * Style for view.php **/ diff --git a/mod/resource/locallib.php b/mod/resource/locallib.php index 8de90261222..55f6ef81a84 100644 --- a/mod/resource/locallib.php +++ b/mod/resource/locallib.php @@ -73,38 +73,40 @@ function resource_display_embed($resource, $cm, $course, $file) { $mimetype = $file->get_mimetype(); $title = $resource->name; + $extension = resourcelib_get_extension($file->get_filename()); + if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image $code = resourcelib_embed_image($fullurl, $title); - } else if ($mimetype == 'application/pdf') { + } else if ($mimetype === 'application/pdf') { // PDF document $code = resourcelib_embed_pdf($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'audio/mp3') { + } else if ($mimetype === 'audio/mp3') { // MP3 audio file $code = resourcelib_embed_mp3($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'video/x-flv') { + } else if ($mimetype === 'video/x-flv' or $extension === 'f4v') { // Flash video file $code = resourcelib_embed_flashvideo($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'application/x-shockwave-flash') { + } else if ($mimetype === 'application/x-shockwave-flash') { // Flash file $code = resourcelib_embed_flash($fullurl, $title, $clicktoopen); - } else if (substr($mimetype, 0, 10) == 'video/x-ms') { + } else if (substr($mimetype, 0, 10) === 'video/x-ms') { // Windows Media Player file $code = resourcelib_embed_mediaplayer($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'video/quicktime') { + } else if ($mimetype === 'video/quicktime') { // Quicktime file $code = resourcelib_embed_quicktime($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'video/mpeg') { + } else if ($mimetype === 'video/mpeg') { // Mpeg file $code = resourcelib_embed_mpeg($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'audio/x-pn-realaudio') { + } else if ($mimetype === 'audio/x-pn-realaudio') { // RealMedia file $code = resourcelib_embed_real($fullurl, $title, $clicktoopen); @@ -363,7 +365,7 @@ function resource_get_final_display_type($resource) { static $download = array('application/zip', 'application/x-tar', 'application/g-zip'); // binary formats static $embed = array('image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', // images 'application/x-shockwave-flash', 'video/x-flv', 'video/x-ms-wm', // video formats - 'video/quicktime', 'video/mpeg', + 'video/quicktime', 'video/mpeg', 'video/mp4', 'audio/mp3', 'audio/x-realaudio-plugin', 'x-realaudio-plugin', // audio formats 'application/pdf', 'text/html', ); diff --git a/mod/resource/styles.css b/mod/resource/styles.css index 0e4b5774de2..b92c6ef647b 100644 --- a/mod/resource/styles.css +++ b/mod/resource/styles.css @@ -1,11 +1 @@ -.path-mod-resource .popupnotice {text-align:center;margin:40px;} - -.resourcecontent object {height:600px;width:800px;} -.resourcecontent.resourcepdf object{height: 800px;width: 100%;} - -.resourcecontent .resourcemediaplugin_mp3 object {height:25px; } -.path-mod-resource .resourcemediaplugin_mp3 {width: 800px;margin:10px auto;} -.resourcecontent.resourcemp3 object#nonjsmp3plugin {height:25px;} - -.ie .resourcecontent .resourcemediaplugin_mp3 object {height:34px;} - +.path-mod-resource .resourcecontent {text-align: center;} diff --git a/mod/url/lang/en/url.php b/mod/url/lang/en/url.php index 42a94ce4780..5dc4f4cc6e3 100644 --- a/mod/url/lang/en/url.php +++ b/mod/url/lang/en/url.php @@ -24,7 +24,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['clicktoopen'] = 'Click {$a} link to open URL.'; +$string['clicktoopen'] = 'Click {$a} link to open resource.'; $string['configdisplayoptions'] = 'Select all options that should be available, existing settings are not modified. Hold CTRL key to select multiple fields.'; $string['configframesize'] = 'When a web page or an uploaded file is displayed within a frame, this value is the height (in pixels) of the top frame (which contains the navigation).'; $string['configrolesinparams'] = 'Enable if you want to include localized role names in list of available parameter variables.'; diff --git a/mod/url/locallib.php b/mod/url/locallib.php index 0e57a658bc0..b4e600ce4b8 100644 --- a/mod/url/locallib.php +++ b/mod/url/locallib.php @@ -234,6 +234,8 @@ function url_display_embed($url, $cm, $course) { $link = html_writer::tag('a', $fullurl, array('href'=>str_replace('&', '&', $fullurl))); $clicktoopen = get_string('clicktoopen', 'url', $link); + $extension = resourcelib_get_extension($url->externalurl); + if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image $code = resourcelib_embed_image($fullurl, $title); @@ -241,7 +243,7 @@ function url_display_embed($url, $cm, $course) { // MP3 audio file $code = resourcelib_embed_mp3($fullurl, $title, $clicktoopen); - } else if ($mimetype == 'video/x-flv') { + } else if ($mimetype == 'video/x-flv' or $extension === 'f4v') { // Flash video file $code = resourcelib_embed_flashvideo($fullurl, $title, $clicktoopen); @@ -305,7 +307,7 @@ function url_get_final_display_type($url) { 'application/pdf', 'text/html'); // these are known to cause trouble for external links, sorry static $embed = array('image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', // images 'application/x-shockwave-flash', 'video/x-flv', 'video/x-ms-wm', // video formats - 'video/quicktime', 'video/mpeg', + 'video/quicktime', 'video/mpeg', 'video/mp4', 'audio/mp3', 'audio/x-realaudio-plugin', 'x-realaudio-plugin', // audio formats, ); diff --git a/mod/url/styles.css b/mod/url/styles.css new file mode 100644 index 00000000000..38d1abfcceb --- /dev/null +++ b/mod/url/styles.css @@ -0,0 +1 @@ +.path-mod-url .resourcecontent {text-align: center;} diff --git a/theme/anomaly/config.php b/theme/anomaly/config.php index ac2f64c531d..e9ff5f51ee8 100644 --- a/theme/anomaly/config.php +++ b/theme/anomaly/config.php @@ -23,20 +23,6 @@ $THEME->parents = array('base'); // TODO: new themes can not be based on standa $THEME->parents_exclude_sheets = array('base'=>array('styles_moz')); -$THEME->resource_mp3player_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'font=Arial&fontColour=3333FF&buffer=10&waitForPlay=no&autoPlay=yes'; -/// With this you can control the colours of the "big" MP3 player -/// that is used for MP3 resources. - - -$THEME->filter_mediaplugin_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'waitForPlay=yes'; -/// ...And this controls the small embedded player - $THEME->layouts = array( // Most pages - if we encounter an unknown or a missing page type, this one is used. 'base' => array( diff --git a/theme/arialist/config.php b/theme/arialist/config.php index 818985e78d2..f8c5942b93c 100644 --- a/theme/arialist/config.php +++ b/theme/arialist/config.php @@ -190,8 +190,6 @@ $THEME->csspostprocess = 'arialist_process_css'; // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - //////////////////////////////////////////////////// // Used to control the colours used in the small // media player for the filters @@ -258,10 +256,4 @@ $THEME->rarrow = '⟩'; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// - $THEME->editor_sheets = array('editor'); \ No newline at end of file diff --git a/theme/base/style/core.css b/theme/base/style/core.css index eaf5e8e3fe7..5de56412340 100644 --- a/theme/base/style/core.css +++ b/theme/base/style/core.css @@ -674,14 +674,6 @@ body.tag .managelink {padding: 5px;} */ .ie.dir-rtl .mform .fitem .felement {margin-right:0;text-align:right;float:right;} -/** - * Filters - */ -.jsenabled .mediaplugin.mediaplugin_mp3 object {height:15px;width:100px; } -.jsenabled .mediaplugin.mediaplugin_flv object {height:600px;width:800px;} - -.ie .mediaplugin.mediaplugin_mp3 object{height:20px;} - /** * Fix for broken YUI images in the menunav component */ @@ -704,3 +696,6 @@ body.tag .managelink {padding: 5px;} .mod-indent-14 {margin-left:280px;} .mod-indent-15, .mod-indent-huge {margin-left:300px;} + +/* Resourcelib mp3 player size: only width could be changed here, height hardcoded in JS */ +.resourcecontent .resourcemediaplugin_mp3 object {height:25px; width: 600px} \ No newline at end of file diff --git a/theme/binarius/config.php b/theme/binarius/config.php index 59808d35ada..08b47c3a6ec 100644 --- a/theme/binarius/config.php +++ b/theme/binarius/config.php @@ -190,13 +190,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -258,10 +251,4 @@ $THEME->layouts = array( // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// - $THEME->editor_sheets = array('editor'); \ No newline at end of file diff --git a/theme/boxxie/config.php b/theme/boxxie/config.php index 0102183c1fc..ab3a0c0ce44 100644 --- a/theme/boxxie/config.php +++ b/theme/boxxie/config.php @@ -164,13 +164,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -232,8 +225,3 @@ $THEME->layouts = array( // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/brick/config.php b/theme/brick/config.php index 2d465cdf193..3d5a6fe6981 100644 --- a/theme/brick/config.php +++ b/theme/brick/config.php @@ -18,7 +18,7 @@ /** * Configuration for Moodle's brick theme. * - * DO NOT MODIFY THIS THEME! + * DO NOT MODIFY THIS THEME! * COPY IT FIRST, THEN RENAME THE COPY AND MODIFY IT INSTEAD. * * For full information about creating Moodle themes, see: @@ -33,7 +33,7 @@ $THEME->name = 'brick'; //////////////////////////////////////////////////// // Name of the theme. Most likely the name of -// the directory in which this file resides. +// the directory in which this file resides. //////////////////////////////////////////////////// @@ -44,11 +44,11 @@ $THEME->parents = array( ///////////////////////////////////////////////////// // Which existing theme(s) in the /theme/ directory -// do you want this theme to extend. A theme can -// extend any number of themes. Rather than -// creating an entirely new theme and copying all -// of the CSS, you can simply create a new theme, -// extend the theme you like and just add the +// do you want this theme to extend. A theme can +// extend any number of themes. Rather than +// creating an entirely new theme and copying all +// of the CSS, you can simply create a new theme, +// extend the theme you like and just add the // changes you want to your theme. //////////////////////////////////////////////////// @@ -61,7 +61,7 @@ $THEME->sheets = array( ); //////////////////////////////////////////////////// -// Name of the stylesheet(s) you've including in +// Name of the stylesheet(s) you've including in // this theme's /styles/ directory. //////////////////////////////////////////////////// @@ -85,7 +85,7 @@ $THEME->enable_dock = true; // $THEME->editor_sheets //////////////////////////////////////////////////// -// An array of stylesheets to include within the +// An array of stylesheets to include within the // body of the editor. //////////////////////////////////////////////////// @@ -167,7 +167,7 @@ $THEME->layouts = array( 'regions' => array('side-post'), 'defaultregion' => 'side-post', ), - + ); /////////////////////////////////////////////////////////////// @@ -181,23 +181,16 @@ $THEME->layouts = array( //$THEME->csspostprocess = 'arialist_process_css'; //////////////////////////////////////////////////// -// Allows the user to provide the name of a function -// that all CSS should be passed to before being +// Allows the user to provide the name of a function +// that all CSS should be passed to before being // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// // An array containing the names of JavaScript files -// located in /javascript/ to include in the theme. +// located in /javascript/ to include in the theme. // (gets included in the head) //////////////////////////////////////////////////// @@ -210,7 +203,7 @@ $THEME->layouts = array( //$THEME->larrow = '⟨'; //////////////////////////////////////////////////// -// Overrides the left arrow image used throughout +// Overrides the left arrow image used throughout // Moodle //////////////////////////////////////////////////// @@ -243,22 +236,17 @@ $THEME->layouts = array( // $THEME->plugins_exclude_sheets //////////////////////////////////////////////////// -// An array of plugin sheets to ignore and not +// An array of plugin sheets to ignore and not // include. //////////////////////////////////////////////////// // $THEME->renderfactory //////////////////////////////////////////////////// -// Sets a custom render factory to use with the +// Sets a custom render factory to use with the // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// $THEME->csspostprocess = 'brick_process_css'; //$THEME->rendererfactory = 'theme_overridden_renderer_factory'; - + diff --git a/theme/canvas/config.php b/theme/canvas/config.php index 68b0353c6f6..e3dbaa4084d 100644 --- a/theme/canvas/config.php +++ b/theme/canvas/config.php @@ -218,13 +218,6 @@ $THEME->hidefromselector = true; // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -273,10 +266,4 @@ $THEME->hidefromselector = true; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// - $THEME->editor_sheets = array('editor'); \ No newline at end of file diff --git a/theme/formal_white/config.php b/theme/formal_white/config.php index 02d00c26522..707470c173b 100644 --- a/theme/formal_white/config.php +++ b/theme/formal_white/config.php @@ -58,20 +58,6 @@ $THEME->parents_exclude_sheets = array( ), ); -$THEME->resource_mp3player_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'font=Arial&fontColour=3333FF&buffer=10&waitForPlay=no&autoPlay=yes'; -/// With this you can control the colours of the "big" MP3 player -/// that is used for MP3 resources. - - -$THEME->filter_mediaplugin_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'waitForPlay=yes'; -/// ...And this controls the small embedded player - $THEME->layouts = array( // Most pages - if we encounter an unknown or a missing page type, this one is used. 'base' => array( diff --git a/theme/formfactor/config.php b/theme/formfactor/config.php index e39d2ab1abc..2b026d0c646 100644 --- a/theme/formfactor/config.php +++ b/theme/formfactor/config.php @@ -170,13 +170,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -238,10 +231,4 @@ $THEME->layouts = array( // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// - $THEME->editor_sheets = array('editor'); \ No newline at end of file diff --git a/theme/fusion/config.php b/theme/fusion/config.php index 4262e773ce9..90e34421137 100644 --- a/theme/fusion/config.php +++ b/theme/fusion/config.php @@ -191,13 +191,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -259,9 +252,4 @@ $THEME->rarrow = '⟩'; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// $THEME->csspostprocess = 'fusion_process_css'; \ No newline at end of file diff --git a/theme/leatherbound/config.php b/theme/leatherbound/config.php index fe39c6c2d0d..53acc3aae50 100644 --- a/theme/leatherbound/config.php +++ b/theme/leatherbound/config.php @@ -179,13 +179,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -247,8 +240,3 @@ $THEME->layouts = array( // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/magazine/config.php b/theme/magazine/config.php index 706cf9ffa90..9d64097430e 100644 --- a/theme/magazine/config.php +++ b/theme/magazine/config.php @@ -143,13 +143,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -211,9 +204,4 @@ $THEME->layouts = array( // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// $THEME->csspostprocess = 'magazine_process_css'; \ No newline at end of file diff --git a/theme/nimble/config.php b/theme/nimble/config.php index 1f9f380f5f0..48ff3ea5c87 100644 --- a/theme/nimble/config.php +++ b/theme/nimble/config.php @@ -57,7 +57,7 @@ $THEME->sheets = array( 'core', 'pagelayout', 'colors', - 'menu', + 'menu', ); //////////////////////////////////////////////////// @@ -191,13 +191,6 @@ $THEME->layouts = array( // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -259,10 +252,4 @@ $THEME->rarrow = '⟩'; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// - $THEME->csspostprocess = 'nimble_process_css'; diff --git a/theme/nonzero/config.php b/theme/nonzero/config.php index c46e3033bca..e274f93f501 100644 --- a/theme/nonzero/config.php +++ b/theme/nonzero/config.php @@ -190,13 +190,6 @@ $THEME->csspostprocess = 'nonzero_process_css'; // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -258,8 +251,3 @@ $THEME->csspostprocess = 'nonzero_process_css'; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/overlay/config.php b/theme/overlay/config.php index 686e96c7284..358fd539623 100644 --- a/theme/overlay/config.php +++ b/theme/overlay/config.php @@ -18,7 +18,7 @@ /** * Configuration for Moodle's overlay theme. * - * DO NOT MODIFY THIS THEME! + * DO NOT MODIFY THIS THEME! * COPY IT FIRST, THEN RENAME THE COPY AND MODIFY IT INSTEAD. * * For full information about creating Moodle themes, see: @@ -33,7 +33,7 @@ $THEME->name = 'overlay'; //////////////////////////////////////////////////// // Name of the theme. Most likely the name of -// the directory in which this file resides. +// the directory in which this file resides. //////////////////////////////////////////////////// @@ -44,11 +44,11 @@ $THEME->parents = array( ///////////////////////////////////////////////////// // Which existing theme(s) in the /theme/ directory -// do you want this theme to extend. A theme can -// extend any number of themes. Rather than -// creating an entirely new theme and copying all -// of the CSS, you can simply create a new theme, -// extend the theme you like and just add the +// do you want this theme to extend. A theme can +// extend any number of themes. Rather than +// creating an entirely new theme and copying all +// of the CSS, you can simply create a new theme, +// extend the theme you like and just add the // changes you want to your theme. //////////////////////////////////////////////////// @@ -60,7 +60,7 @@ $THEME->sheets = array( ); //////////////////////////////////////////////////// -// Name of the stylesheet(s) you've including in +// Name of the stylesheet(s) you've including in // this theme's /styles/ directory. //////////////////////////////////////////////////// @@ -84,7 +84,7 @@ $THEME->enable_dock = true; $THEME->editor_sheets = array('editor'); //////////////////////////////////////////////////// -// An array of stylesheets to include within the +// An array of stylesheets to include within the // body of the editor. //////////////////////////////////////////////////// @@ -180,23 +180,16 @@ $THEME->layouts = array( $THEME->csspostprocess = 'overlay_process_css'; //////////////////////////////////////////////////// -// Allows the user to provide the name of a function -// that all CSS should be passed to before being +// Allows the user to provide the name of a function +// that all CSS should be passed to before being // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// // An array containing the names of JavaScript files -// located in /javascript/ to include in the theme. +// located in /javascript/ to include in the theme. // (gets included in the head) //////////////////////////////////////////////////// @@ -209,7 +202,7 @@ $THEME->csspostprocess = 'overlay_process_css'; // $THEME->larrow //////////////////////////////////////////////////// -// Overrides the left arrow image used throughout +// Overrides the left arrow image used throughout // Moodle //////////////////////////////////////////////////// @@ -242,19 +235,14 @@ $THEME->csspostprocess = 'overlay_process_css'; // $THEME->plugins_exclude_sheets //////////////////////////////////////////////////// -// An array of plugin sheets to ignore and not +// An array of plugin sheets to ignore and not // include. //////////////////////////////////////////////////// // $THEME->renderfactory //////////////////////////////////////////////////// -// Sets a custom render factory to use with the +// Sets a custom render factory to use with the // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/serenity/config.php b/theme/serenity/config.php index 1665ddcf367..e4c16af787f 100644 --- a/theme/serenity/config.php +++ b/theme/serenity/config.php @@ -4,7 +4,7 @@ $THEME->name = 'serenity'; //////////////////////////////////////////////////// // Name of the theme. Most likely the name of -// the directory in which this file resides. +// the directory in which this file resides. //////////////////////////////////////////////////// @@ -12,11 +12,11 @@ $THEME->parents = array('canvas','base'); ///////////////////////////////////////////////////// // Which existing theme(s) in the /theme/ directory -// do you want this theme to extend. A theme can -// extend any number of themes. Rather than -// creating an entirely new theme and copying all -// of the CSS, you can simply create a new theme, -// extend the theme you like and just add the +// do you want this theme to extend. A theme can +// extend any number of themes. Rather than +// creating an entirely new theme and copying all +// of the CSS, you can simply create a new theme, +// extend the theme you like and just add the // changes you want to your theme. //////////////////////////////////////////////////// @@ -24,7 +24,7 @@ $THEME->parents = array('canvas','base'); $THEME->sheets = array('core'); //////////////////////////////////////////////////// -// Name of the stylesheet(s) you've including in +// Name of the stylesheet(s) you've including in // this theme's /styles/ directory. //////////////////////////////////////////////////// @@ -39,53 +39,46 @@ $THEME->enable_dock = true; $THEME->editor_sheets = array('editor'); //////////////////////////////////////////////////// -// An array of stylesheets to include within the +// An array of stylesheets to include within the // body of the editor. //////////////////////////////////////////////////// // $THEME->csspostprocess - + //////////////////////////////////////////////////// -// Allows the user to provide the name of a function -// that all CSS should be passed to before being +// Allows the user to provide the name of a function +// that all CSS should be passed to before being // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - -// $THEME->javascripts +// $THEME->javascripts //////////////////////////////////////////////////// // An array containing the names of JavaScript files -// located in /javascript/ to include in the theme. +// located in /javascript/ to include in the theme. // (gets included in the head) //////////////////////////////////////////////////// -// $THEME->javascripts_footer +// $THEME->javascripts_footer //////////////////////////////////////////////////// // As above but will be included in the page footer. //////////////////////////////////////////////////// -// $THEME->larrow +// $THEME->larrow //////////////////////////////////////////////////// -// Overrides the left arrow image used throughout +// Overrides the left arrow image used throughout // Moodle //////////////////////////////////////////////////// -// $THEME->rarrow +// $THEME->rarrow //////////////////////////////////////////////////// // Overrides the right arrow image used throughout Moodle //////////////////////////////////////////////////// -// $THEME->layouts +// $THEME->layouts //////////////////////////////////////////////////// // An array setting the layouts for the theme @@ -98,7 +91,7 @@ $THEME->editor_sheets = array('editor'); // the themes parents //////////////////////////////////////////////////// -// $THEME->parents_exclude_sheets +// $THEME->parents_exclude_sheets //////////////////////////////////////////////////// // An array of stylesheets not to inherit from the @@ -108,19 +101,14 @@ $THEME->editor_sheets = array('editor'); // $THEME->plugins_exclude_sheets //////////////////////////////////////////////////// -// An array of plugin sheets to ignore and not +// An array of plugin sheets to ignore and not // include. //////////////////////////////////////////////////// // $THEME->renderfactory //////////////////////////////////////////////////// -// Sets a custom render factory to use with the +// Sets a custom render factory to use with the // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/sky_high/config.php b/theme/sky_high/config.php index 2c190bc5308..c8c2474d52f 100644 --- a/theme/sky_high/config.php +++ b/theme/sky_high/config.php @@ -189,13 +189,6 @@ $THEME->csspostprocess = 'sky_high_process_css'; // delivered. //////////////////////////////////////////////////// -// $THEME->filter_mediaplugin_colors - -//////////////////////////////////////////////////// -// Used to control the colours used in the small -// media player for the filters -//////////////////////////////////////////////////// - // $THEME->javascripts //////////////////////////////////////////////////// @@ -257,8 +250,3 @@ $THEME->csspostprocess = 'sky_high_process_css'; // theme, used when working with custom renderers. //////////////////////////////////////////////////// -// $THEME->resource_mp3player_colors - -//////////////////////////////////////////////////// -// Controls the colours for the MP3 player -//////////////////////////////////////////////////// diff --git a/theme/standard/style/core.css b/theme/standard/style/core.css index cbc6375aa43..e2c0c405f3e 100644 --- a/theme/standard/style/core.css +++ b/theme/standard/style/core.css @@ -2,7 +2,7 @@ html, body#tinymce {background-color:#FAFAFA;} body {font-family:Arial, Verdana, Helvetica, sans-serif;padding: 4px;} body.lang-vi {font-family:Arial, Verdana, Helvetica, sans-serif !important;} -/** +/** * Links */ a {text-decoration:none;color:#0000FF;} @@ -15,7 +15,7 @@ a:hover {text-decoration:underline;color:#FF0000;} .homelink a {color: #000;text-decoration: none;border-top: 1px solid #cecece;border-bottom: 2px solid #4a4a4a;border-left: 1px solid #cecece;border-right: 2px solid #4a4a4a;} .homelink a:hover {text-decoration: none;border-bottom: 1px solid #cecece;border-top: 2px solid #4a4a4a;border-right: 1px solid #cecece;border-left: 2px solid #4a4a4a;} -/** +/** * Headings */ h1.main, @@ -92,13 +92,13 @@ table.formtable tbody th {background-color: transparent;background-image: none;} .mod_introbox {border-color:#DDDDDD;} -/** +/** * Docs */ #doc-contents h1 {font-size: 0.9em;} #doc-contents ul {font-size: 0.8em;} -/** +/** * Login */ #page-login-index #content {font-size: 0.85em;} @@ -219,10 +219,6 @@ form.popupform label {margin-right: 0.5em;} /** * Filters */ -.mediaplugin {display:block;clear:both;margin-top:5px;margin-bottom:5px;} -.mediaplugin_mp3, -.mediaplugin_swf, -.mediaplugin_flv {display:inline;clear:none;margin:0px;margin-left:0.5em;} .texrender {border:0px;vertical-align:middle;} /** @@ -282,7 +278,7 @@ h2.tag-heading {text-align:center;margin-left:auto;margin-right:auto;width:95%;} .tag .managelink {text-align:right;} table#tag-management-list {margin: 10px auto;width: 80%;} -/** +/** * Overriding base */ #page-header .headermain {font-size:1.5em;} From 181991e791a13a3c383234718c26c499e31d3df1 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 12 Mar 2011 19:04:26 +0100 Subject: [PATCH 104/369] MDL-26621 respect email privacy settings on the main user profile and fix missing context --- lib/enrollib.php | 41 +++++++++++++++++++++++++++++++++++++++++ user/profile.php | 9 ++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/enrollib.php b/lib/enrollib.php index 5c338b5008f..96a70f00ea8 100644 --- a/lib/enrollib.php +++ b/lib/enrollib.php @@ -220,6 +220,47 @@ function enrol_check_plugins($user) { unset($inprogress[$user->id]); // Unset the flag } +/** + * Do these two students share any course? + * + * The courses has to be visible and enrolments has to be active, + * timestart and timeend restrictions are ignored. + * + * @param stdClass|int $user1 + * @param stdClass|int $user2 + * @return bool + */ +function enrol_sharing_course($user1, $user2) { + global $DB, $CFG; + + $user1 = !empty($user1->id) ? $user1->id : $user1; + $user2 = !empty($user2->id) ? $user2->id : $user2; + + if (empty($user1) or empty($user2)) { + return false; + } + + if (!$plugins = explode(',', $CFG->enrol_plugins_enabled)) { + return false; + } + + list($plugins, $params) = $DB->get_in_or_equal($plugins, SQL_PARAMS_NAMED, 'ee00'); + $params['enabled'] = ENROL_INSTANCE_ENABLED; + $params['active1'] = ENROL_USER_ACTIVE; + $params['active2'] = ENROL_USER_ACTIVE; + $params['user1'] = $user1; + $params['user2'] = $user2; + + $sql = "SELECT DISTINCT 'x' + FROM {enrol} e + JOIN {user_enrolments} ue1 ON (ue1.enrolid = e.id AND ue1.status = :active1 AND ue1.userid = :user1) + JOIN {user_enrolments} ue2 ON (ue1.enrolid = e.id AND ue1.status = :active2 AND ue2.userid = :user2) + JOIN {course} c ON (c.id = e.courseid AND c.visible = 1) + WHERE e.status = :enabled AND e.enrol $plugins"; + + return $DB->record_exists_sql($sql, $params); +} + /** * This function adds necessary enrol plugins UI into the course edit form. * diff --git a/user/profile.php b/user/profile.php index a3730515c9e..8559d197853 100644 --- a/user/profile.php +++ b/user/profile.php @@ -63,8 +63,10 @@ if (!$currentuser && !empty($CFG->forceloginforprofiles) && !has_capability('moodle/user:viewdetails', $context) && !has_coursecontact_role($userid)) { + // Course managers can be browsed at site level. If not forceloginforprofiles, allow access (bug #4366) $struser = get_string('user'); + $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM)); $PAGE->set_title("$SITE->shortname: $struser"); // Do not leak the name $PAGE->set_heading("$SITE->shortname: $struser"); $PAGE->set_url('/user/profile.php', array('id'=>$userid)); @@ -247,9 +249,10 @@ if (has_capability('moodle/user:viewhiddendetails', $context)) { } } -if ($user->maildisplay == 1 - or ($user->maildisplay == 2 && !isguestuser()) - or has_capability('moodle/course:useremail', $context)) { +if ($currentuser + or $user->maildisplay == 1 + or has_capability('moodle/course:useremail', $context) + or ($user->maildisplay == 2 and enrol_sharing_course($user, $USER))) { print_row(get_string("email").":", obfuscate_mailto($user->email, '')); } From ee69d85a1fb5ab788b40c4fd2abaee2ab553c917 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 13 Mar 2011 10:14:20 +0100 Subject: [PATCH 105/369] MDL-26634 LDAP NTLM SSO Multiple subnet separator is not specified and people use a wrong one Credit goes to Inaki Arenaza. --- auth/ldap/lang/en/auth_ldap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/ldap/lang/en/auth_ldap.php b/auth/ldap/lang/en/auth_ldap.php index a6e4ff600f4..7962513b9ca 100644 --- a/auth/ldap/lang/en/auth_ldap.php +++ b/auth/ldap/lang/en/auth_ldap.php @@ -101,7 +101,7 @@ $string['auth_ntlmsso_enabled'] = 'Set to yes to attempt Single Sign On with the $string['auth_ntlmsso_enabled_key'] = 'Enable'; $string['auth_ntlmsso_ie_fastpath'] = 'Set to yes to enable the NTLM SSO fast path (bypasses certain steps and only works if the client\'s browser is MS Internet Explorer).'; $string['auth_ntlmsso_ie_fastpath_key'] = 'MS IE fast path?'; -$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask'; +$string['auth_ntlmsso_subnet'] = 'If set, it will only attempt SSO with clients in this subnet. Format: xxx.xxx.xxx.xxx/bitmask. Separate multiple subnets with \',\' (comma).'; $string['auth_ntlmsso_subnet_key'] = 'Subnet'; $string['auth_ntlmsso_type_key'] = 'Authentication type'; $string['auth_ntlmsso_type'] = 'The authentication method configured in the web server to authenticate the users (if in doubt, choose NTLM)'; From b399e435924ea074250a6fb0bc4fcf731e513cda Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 13 Mar 2011 10:46:41 +0100 Subject: [PATCH 106/369] MDL-26480 IIS redirect bug workaround Credit goes to Zenger Sergey --- lib/weblib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/weblib.php b/lib/weblib.php index 4abc493b62d..66febe84f67 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -2468,6 +2468,11 @@ function redirect($url, $message='', $delay=-1) { $encodedurl = preg_replace('/^.*href="([^"]*)".*$/', "\\1", clean_text('')); if ($delay == 0 && !$debugdisableredirect && !headers_sent()) { + // workaround for IIS bug http://support.microsoft.com/kb/q176113/ + if (session_id()) { + session_get_instance()->write_close(); + } + //302 might not work for POST requests, 303 is ignored by obsolete clients. @header($_SERVER['SERVER_PROTOCOL'] . ' 303 See Other'); @header('Location: '.$url); From f7f0909ce57ccd17524700c220d42c55e0078f4e Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 13 Mar 2011 15:09:23 +0100 Subject: [PATCH 107/369] PULL-442 multiple TeX related fixes Prevent moodle_url error, cleanup entity encoding and decoding, disable tex source view when TeX and Algebra plugins disabled, localise TeX source popup and prevent phishing attempts, fix executable permission of Algebra pearl script, prevent image error in tex debug when Tex/Ghostscript not configured properly, fix copyright blocks and phpdocs, improve coding style, fix wrong source display link in Algebra filter. --- filter/algebra/algebra2tex.pl | 0 filter/algebra/filter.php | 18 ++--- filter/tex/db/upgrade.php | 42 ++++++++++ filter/tex/displaytex.php | 59 +++++++++++--- filter/tex/filter.php | 125 +++++++++++++++++------------- filter/tex/filtersettings.php | 23 ++++++ filter/tex/lang/en/filter_tex.php | 9 ++- filter/tex/lib.php | 24 ++++++ filter/tex/pix.php | 2 +- filter/tex/texdebug.php | 43 +++++++--- filter/tex/version.php | 2 +- 11 files changed, 251 insertions(+), 96 deletions(-) mode change 100644 => 100755 filter/algebra/algebra2tex.pl create mode 100644 filter/tex/db/upgrade.php diff --git a/filter/algebra/algebra2tex.pl b/filter/algebra/algebra2tex.pl old mode 100644 new mode 100755 diff --git a/filter/algebra/filter.php b/filter/algebra/filter.php index f5ff02809d7..a6fc6a28a3a 100644 --- a/filter/algebra/filter.php +++ b/filter/algebra/filter.php @@ -50,15 +50,11 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig global $CFG, $OUTPUT; $output = ""; - $origtex = $tex; $style = 'style="border:0px; vertical-align:'.$align.';'; + $title = ''; if ($tex) { - $tex = str_replace('&','&',$tex); - $tex = str_replace('<','<',$tex); - $tex = str_replace('>','>',$tex); - $tex = str_replace('"','"',$tex); - $tex = str_replace("\'",''',$tex); - $title = "title=\"$tex\""; + $tex = html_entity_decode($tex, ENT_QUOTES, 'UTF-8'); + $title = 'title="'.s($tex).'"'; } if ($height) { $style .= " height:{$height}px;"; @@ -69,7 +65,7 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig $style .= '"'; $anchorcontents = ''; if ($imagefile) { - $anchorcontents .= "\"".s($origtex)."\"slasharguments) { // Use this method if possible for better caching $anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php/$imagefile"; } else { @@ -77,12 +73,12 @@ function filter_algebra_image($imagefile, $tex= "", $height="", $width="", $alig } $anchorcontents .= "\" $style />"; - $link = $action = null; if (!file_exists("$CFG->dataroot/filter/algebra/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { $link = '/filter/algebra/algebradebug.php'; + $action = null; } else { - $link = '/filter/algebra/displaytex.php?'.urlencode($tex); - $action = new popup_action('click', $link, 'popup', array('height'=>300,'width'=>240)); + $link = new moodle_url('/filter/tex/displaytex.php', array('texexp'=>$tex)); + $action = new popup_action('click', $link, 'popup', array('width'=>320,'height'=>240)); //TODO: the popups do not work when text caching is enabled!! } $output .= $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX')); diff --git a/filter/tex/db/upgrade.php b/filter/tex/db/upgrade.php new file mode 100644 index 00000000000..db046016414 --- /dev/null +++ b/filter/tex/db/upgrade.php @@ -0,0 +1,42 @@ +. + +/** + * TeX filter upgrade code. + * + * @package filter + * @subpackage tex + * @copyright 2011 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * @param int $oldversion the version we are upgrading from + * @return bool result + */ +function xmldb_filter_tex_upgrade($oldversion) { + global $CFG, $DB, $OUTPUT; + + if ($oldversion < 2011031301) { + // clear caches + require_once("$CFG->dirroot/filter/tex/lib.php"); + filter_tex_updatedcallback(null); + + upgrade_plugin_savepoint(true, 2011031301, 'filter', 'tex'); + } + + return true; +} diff --git a/filter/tex/displaytex.php b/filter/tex/displaytex.php index be70dc7b5bf..ddc6ee6fa82 100644 --- a/filter/tex/displaytex.php +++ b/filter/tex/displaytex.php @@ -1,20 +1,55 @@ . - require_once('../../config.php'); +/** + * This script displays tex source code, it is used also from the algebra filter. + * + * @package filter + * @subpackage tex + * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu + * Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +define('NO_MOODLE_COOKIES', true); // Because it interferes with caching + +require('../../config.php'); + +if (!filter_is_enabled('filter/tex') and !filter_is_enabled('filter/algebra')) { + print_error('filternotenabled'); +} + +$texexp = optional_param('texexp', '', PARAM_RAW); + +$title = get_string('source', 'filter_tex') - $texexp = urldecode($_SERVER['QUERY_STRING']); - // entities are usually encoded twice, first in HTML editor then in tex/filter.php - $texexp = html_entity_decode(html_entity_decode($texexp)); - // encode all entities (saves non-ISO) - $texexp = htmlentities($texexp,ENT_COMPAT,'utf-8'); ?> + - TeX Source - + <?php echo $title; ?> + - - + +
+
+
:
+
+
+
- \ No newline at end of file + diff --git a/filter/tex/filter.php b/filter/tex/filter.php index 78a831ec895..ddff02c2f10 100644 --- a/filter/tex/filter.php +++ b/filter/tex/filter.php @@ -1,5 +1,4 @@ ... tags to gif images using + * mimetex.cgi obtained from http: *www.forkosh.com/mimetex.html authored by + * John Forkosh john@forkosh.com. Several binaries of this areincluded with + * this distribution. + * Note that there may be patent restrictions on the production of gif images + * in Canada and some parts of Western Europe and Japan until July 2004. + * * @package filter * @subpackage tex * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu @@ -24,27 +32,24 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -//------------------------------------------------------------------------- -// NOTE: This Moodle text filter converts TeX expressions delimited -// by either $$...$$ or by ... tags to gif images using -// mimetex.cgi obtained from http://www.forkosh.com/mimetex.html authored by -// John Forkosh john@forkosh.com. Several binaries of this areincluded with -// this distribution. -// Note that there may be patent restrictions on the production of gif images -// in Canada and some parts of Western Europe and Japan until July 2004. -//------------------------------------------------------------------------- -///////////////////////////////////////////////////////////////////////////// -// To activate this filter, add a line like this to your // -// list of filters in your Filter configuration: // -// // -// filter/tex/filter.php // -///////////////////////////////////////////////////////////////////////////// +defined('MOODLE_INTERNAL') || die; -function filter_text_image($imagefile, $tex= "", $height="", $width="", $align="middle", $alt='') { +/** + * Create TeX image link. + * + * @param string $imagefile name of file + * @param string $tex TeX notation (html entities already decoded) + * @param int $height O means automatic + * @param int $width O means automatic + * @param string $align + * @param string $alt + * @return string HTML markup + */ +function filter_text_image($imagefile, $tex, $height, $width, $align, $alt) { global $CFG, $OUTPUT; - if ($alt==='') { - $alt = s($tex); + if (!$imagefile) { + throw new coding_exception('image file argument empty in filter_text_image()'); } // Work out any necessary inline style. @@ -65,47 +70,46 @@ function filter_text_image($imagefile, $tex= "", $height="", $width="", $align=" } // Prepare the title attribute. - if ($tex) { - $tex = str_replace('&','&',$tex); - $tex = str_replace('<','<',$tex); - $tex = str_replace('>','>',$tex); - $tex = str_replace('"','"',$tex); - $tex = str_replace("\'",''',$tex); - // Note that we retain the title tag as TeX format rather than using - // the alt text, even if supplied. The alt text is intended for blind - // users (to provide a text equivalent to the equation) while the title - // is there as a convenience for sighted users who want to see the TeX - // code. - $title = "title=\"$tex\""; + // Note that we retain the title tag as TeX format rather than using + // the alt text, even if supplied. The alt text is intended for blind + // users (to provide a text equivalent to the equation) while the title + // is there as a convenience for sighted users who want to see the TeX + // code. + $title = 'title="'.s($tex).'"'; + + if ($alt === '') { + $alt = s($tex); + } else { + $alt = s(html_entity_decode($tex, ENT_QUOTES, 'UTF-8')); } // Build the output. - $output = ""; - if ($imagefile) { - $anchorcontents = "\"$alt\"slasharguments) { // Use this method if possible for better caching - $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile"; - } else { - $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile"; - } - $anchorcontents .= "\" $style/>"; - - $link = $action = null; - if (!file_exists("$CFG->dataroot/filter/tex/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { - $link = '/filter/tex/texdebug.php'; - } else { - $link = '/filter/tex/displaytex.php?'.urlencode($tex); - $action = new popup_action('click', $link, 'popup', array('height'=>300,'width'=>240)); - } - $output .= $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX')); + $anchorcontents = "\"$alt\"slasharguments) { // Use this method if possible for better caching + $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile"; } else { - $output .= "Error: must pass URL or course"; + $anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile"; } + $anchorcontents .= "\" $style/>"; + + if (!file_exists("$CFG->dataroot/filter/tex/$imagefile") && has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { + $link = '/filter/tex/texdebug.php'; + $action = null; + } else { + $link = new moodle_url('/filter/tex/displaytex.php', array('texexp'=>$tex)); + $action = new popup_action('click', $link, 'popup', array('width'=>320,'height'=>240)); + } + $output = $OUTPUT->action_link($link, $anchorcontents, $action, array('title'=>'TeX')); //TODO: the popups do not work when text caching is enabled!! + return $output; } + +/** + * TeX filtering class. + */ class filter_tex extends moodle_text_filter { - function filter ($text, array $options = array()) { + function filter($text, array $options = array()) { global $CFG, $DB; @@ -132,9 +136,9 @@ class filter_tex extends moodle_text_filter { # } $text .= ' '; preg_match_all('/\$(\$\$+?)([^\$])/s',$text,$matches); - for ($i=0;$i TeX expression @@ -159,8 +163,17 @@ class filter_tex extends moodle_text_filter { $align = "text-top"; $texexp = preg_replace('/^align=top /','',$texexp); } + + // decode entities encoded by editor, luckily there is very little chance of double decoding + $texexp = html_entity_decode($texexp, ENT_QUOTES, 'UTF-8'); + + if ($texexp === '') { + contninue; + } + $md5 = md5($texexp); - if (! $texcache = $DB->get_record("cache_filters", array("filter"=>"tex", "md5key"=>$md5))) { + if (!$DB->record_exists("cache_filters", array("filter"=>"tex", "md5key"=>$md5))) { + $texcache = new stdClass(); $texcache->filter = 'tex'; $texcache->version = 1; $texcache->md5key = $md5; @@ -169,7 +182,7 @@ class filter_tex extends moodle_text_filter { $DB->insert_record("cache_filters", $texcache, false); } $filename = $md5 . ".{$CFG->filter_tex_convertformat}"; - $text = str_replace( $matches[0][$i], filter_text_image($filename, $texexp, '', '', $align, $alt), $text); + $text = str_replace( $matches[0][$i], filter_text_image($filename, $texexp, 0, 0, $align, $alt), $text); } return $text; } diff --git a/filter/tex/filtersettings.php b/filter/tex/filtersettings.php index 29ca17d511e..c0244e88bb1 100644 --- a/filter/tex/filtersettings.php +++ b/filter/tex/filtersettings.php @@ -1,4 +1,27 @@ . + +/** + * TeX filter settings + * + * @package filter + * @subpackage tex + * @copyright 2007 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; diff --git a/filter/tex/lang/en/filter_tex.php b/filter/tex/lang/en/filter_tex.php index f7166ed7773..8290d7b6cda 100644 --- a/filter/tex/lang/en/filter_tex.php +++ b/filter/tex/lang/en/filter_tex.php @@ -1,5 +1,4 @@ . + +/** + * TeX filter library functions. + * + * @package filter + * @subpackage tex + * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu + * Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die(); diff --git a/filter/tex/pix.php b/filter/tex/pix.php index 45b1b79b673..deb43d58938 100644 --- a/filter/tex/pix.php +++ b/filter/tex/pix.php @@ -42,7 +42,7 @@ define('NO_MOODLE_COOKIES', true); // Because it interferes with caching $latex = new latex(); $density = $CFG->filter_tex_density; $background = $CFG->filter_tex_latexbackground; - $texexp = html_entity_decode($texcache->rawtext); + $texexp = $texcache->rawtext; // the entities are now decoded before inserting to DB $latex_path = $latex->render($texexp, $md5, 12, $density, $background); if ($latex_path) { copy($latex_path, $pathname); diff --git a/filter/tex/texdebug.php b/filter/tex/texdebug.php index a53f2ee8822..35f1afb4642 100644 --- a/filter/tex/texdebug.php +++ b/filter/tex/texdebug.php @@ -1,7 +1,30 @@ . + +/** + * This function fetches math. images from the data directory + * If not, it obtains the corresponding TeX expression from the cache_tex db table + * and uses mimeTeX to create the image file + * + * @package filter + * @subpackage tex + * @copyright 2004 Zbigniew Fiedorowicz fiedorow@math.ohio-state.edu + * Originally based on code provided by Bruno Vernier bruno@vsbeducation.ca + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require_once("../../config.php"); @@ -19,7 +42,6 @@ require_login(); require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $USER->id); /// Required cap to run this. MDL-18552 - $query = urldecode($_SERVER['QUERY_STRING']); $output = ''; // look up in cache if required @@ -99,10 +121,7 @@ header("Content-type: text/html; charset=utf-8"); echo "
\n";
         if ($texexp) {
-            $texexp = str_replace('<', '<', $texexp);
-            $texexp = str_replace('>', '>', $texexp);
-            $texexp = str_replace('"', '"', $texexp);
-            echo "$texexp\n\n";
+            echo s($texexp)."\n\n";
         } else {
             echo "No text output available\n\n";
         }
@@ -237,10 +256,12 @@
         $output .= execute($cmd);
 
         if (!$graphic) {
-            echo($output);
-        } else {
+            echo $output;
+        } else if (file_exists($img)){
             send_file($img, "$md5.{$CFG->filter_tex_convertformat}");
-         }
+        } else {
+            echo "Error creating image, see command execution output for more details.";
+        }
     }
 
     function execute($cmd) {
diff --git a/filter/tex/version.php b/filter/tex/version.php
index d7ceba5cdd0..9c5df143a09 100644
--- a/filter/tex/version.php
+++ b/filter/tex/version.php
@@ -26,4 +26,4 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2010073000;
+$plugin->version = 2011031301;

From 69542fb3af642d8612032a4bed748dd52d4eb8de Mon Sep 17 00:00:00 2001
From: Petr Skoda 
Date: Sun, 13 Mar 2011 17:08:50 +0100
Subject: [PATCH 108/369] MDL-26698 use https for help ajax loginhttps pages

---
 lib/outputrenderers.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php
index 3231669c206..c237cc49388 100644
--- a/lib/outputrenderers.php
+++ b/lib/outputrenderers.php
@@ -1648,8 +1648,8 @@ class core_renderer extends renderer_base {
             $output .= $helpicon->linktext;
         }
 
-        // now create the link around it
-        $url = new moodle_url('/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->helpidentifier, 'lang'=>current_language()));
+        // now create the link around it - we need https on loginhttps pages
+        $url = new moodle_url($CFG->httpswwwroot.'/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->helpidentifier, 'lang'=>current_language()));
 
         // note: this title is displayed only if JS is disabled, otherwise the link will have the new ajax tooltip
         $title = get_string('helpprefix2', '', trim($helpicon->title, ". \t"));
@@ -1712,8 +1712,8 @@ class core_renderer extends renderer_base {
             $output .= $helpicon->linktext;
         }
 
-        // now create the link around it
-        $url = new moodle_url('/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->identifier, 'lang'=>current_language()));
+        // now create the link around it - we need https on loginhttps pages
+        $url = new moodle_url($CFG->httpswwwroot.'/help.php', array('component' => $helpicon->component, 'identifier' => $helpicon->identifier, 'lang'=>current_language()));
 
         // note: this title is displayed only if JS is disabled, otherwise the link will have the new ajax tooltip
         $title = get_string('helpprefix2', '', trim($title, ". \t"));

From 8dc0b786d07e59621f4123671b74c76b99802d79 Mon Sep 17 00:00:00 2001
From: AMOS bot 
Date: Sun, 13 Mar 2011 19:36:56 +0100
Subject: [PATCH 109/369] Automatic installer lang files (20110313)

---
 install/lang/de_kids/langconfig.php | 33 +++++++++++++++++++++++++++++
 install/lang/pl/admin.php           |  5 +++++
 install/lang/pl/install.php         |  8 +++++++
 3 files changed, 46 insertions(+)
 create mode 100644 install/lang/de_kids/langconfig.php

diff --git a/install/lang/de_kids/langconfig.php b/install/lang/de_kids/langconfig.php
new file mode 100644
index 00000000000..1ebd9f78b9e
--- /dev/null
+++ b/install/lang/de_kids/langconfig.php
@@ -0,0 +1,33 @@
+.
+
+/**
+ * Automatically generated strings for Moodle installer
+ *
+ * Do not edit this file manually! It contains just a subset of strings
+ * needed during the very first steps of installation. This file was
+ * generated automatically by export-installer.php (which is part of AMOS
+ * {@link http://docs.moodle.org/en/Development:Languages/AMOS}) using the
+ * list of strings defined in /install/stringnames.txt.
+ *
+ * @package   installer
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['parentlanguage'] = 'de_du';
+$string['thisdirection'] = '';
+$string['thislanguage'] = 'Deutsch - Kids';
diff --git a/install/lang/pl/admin.php b/install/lang/pl/admin.php
index 1f5ef1cbd71..f3d7407d437 100644
--- a/install/lang/pl/admin.php
+++ b/install/lang/pl/admin.php
@@ -28,10 +28,15 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+$string['clianswerno'] = 'n';
+$string['cliansweryes'] = 't';
 $string['cliincorrectvalueerror'] = 'Błąd, niepoprawna wartość "{$a->value}" dla "{$a->option}"';
 $string['cliincorrectvalueretry'] = 'Nieprawidłowa wartość, spróbuj ponownie';
 $string['clitypevalue'] = 'typ wartości';
 $string['clitypevaluedefault'] = 'typ wartości, naciśnij Enter, aby użyć wartości domyślnej ({$a})';
+$string['cliunknowoption'] = 'Nieznana opcja:
+  {$a}
+Proszę użyć pomocy.';
 $string['cliyesnoprompt'] = 'wpisz y (czyli tak) lub n (czyli nie)';
 $string['environmentrequireinstall'] = 'jest niezbędnę, żeby było zainstalowane/włączone';
 $string['environmentrequireversion'] = 'wersja {$a->needed} jest niezbędna a ty używasz wersji {$a->current}';
diff --git a/install/lang/pl/install.php b/install/lang/pl/install.php
index 5e2ea90c237..c41f37dca5b 100644
--- a/install/lang/pl/install.php
+++ b/install/lang/pl/install.php
@@ -32,12 +32,14 @@ $string['admindirname'] = 'Katalog admin';
 $string['availablelangs'] = 'Dostępne paczki językowe';
 $string['chooselanguagehead'] = 'Wybierz język';
 $string['chooselanguagesub'] = 'Proszę wybrać język TYLKO do instalacji. Stronę i języki dla użytkowników będzie można wybrać na następnym ekranie.';
+$string['clialreadyinstalled'] = 'Plik config.php już istnieje, użyj admin/cli/upgrade.php jeśli chcesz uaktualnić witrynę.';
 $string['databasehost'] = 'Host bazy danych';
 $string['databasename'] = 'Nazwa bazy danych';
 $string['dataroot'] = 'Katalog z danymi';
 $string['dbprefix'] = 'Prefiks tabel';
 $string['dirroot'] = 'Katalog Moodle';
 $string['environmenthead'] = 'Sprawdzam środowisko (ustawienia) ...';
+$string['errorsinenvironment'] = 'Kontrola środowiska zakończona niepowodzeniem!';
 $string['installation'] = 'Instalacja';
 $string['langdownloaderror'] = 'Niestety język "{$a}" nie może zostać pobrany. Proces instalacji będzie kontynuowany w języku angielskim.';
 $string['memorylimithelp'] = '

Limit pamięci PHP dla Twojego serwera jest ustawiony obecnie na {$a}.

@@ -54,7 +56,13 @@ Pozwoli to Moodle ustawić samoczynnie limit pamięci.
php_value memory_limit 40M

Jednakże na niektórych serwerach będzie uniemożliwiało to poprawne działanie wszystkich stron PHP (ujrzysz błędy na wyświetlanych stronach), wtedy będziesz musiał usunąć plik .htaccess.

'; +$string['paths'] = 'Ścieżki'; +$string['pathserrcreatedataroot'] = 'Katalog danych ({$a->dataroot}) nie może zostać utworzony przez instalator.'; +$string['pathshead'] = 'Potwierdź ścieżki'; +$string['pathsrodataroot'] = 'Główny katalog danych nie ma uprawnień do zapisu. '; $string['pathsroparentdataroot'] = 'Nadrzędny katalog ({$a->parent}) jest tylko do odczytu. Katalog danych ({$a->dataroot}) nie może zostać utworzony przez instalator. '; +$string['pathssubdirroot'] = 'Pełna ścieżka do katalogu z instalacją Moodle.'; +$string['pathsunsecuredataroot'] = 'Lokalizacja głównego katalogu danych nie jest bezpieczna'; $string['pathswrongadmindir'] = 'Katalog admin nie istnieje'; $string['phpextension'] = '{$a} rozszerzenie PHP'; $string['phpversion'] = 'Wersja PHP'; From c3b5e8290bd231dd80d4562834f6e108a390320d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 14 Mar 2011 00:51:42 +0100 Subject: [PATCH 110/369] MDL-25352 fix multiple issues in admin/replace.php Make sure admins know things can go wrong, MSSQL and Oracle were never working, fix block_html config saving issue, skip a lot more tables because the data there is serialised() or can not be changed in case of config tables, more warnings and checkbox confirmation. --- admin/replace.php | 37 ++++++++++++++++--------------------- blocks/html/lib.php | 21 +++++++++++++++++++++ lib/adminlib.php | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/admin/replace.php b/admin/replace.php index e77070b11d9..f1a1c7a830c 100644 --- a/admin/replace.php +++ b/admin/replace.php @@ -11,23 +11,32 @@ admin_externalpage_setup('replace'); $search = optional_param('search', '', PARAM_RAW); $replace = optional_param('replace', '', PARAM_RAW); +$sure = optional_param('sure', 0, PARAM_BOOL); ################################################################### echo $OUTPUT->header(); echo $OUTPUT->heading('Search and replace text throughout the whole database'); +if ($DB->get_dbfamily() !== 'mysql' and $DB->get_dbfamily() !== 'postgres') { + //TODO: add $DB->text_replace() to DML drivers + echo $OUTPUT->notification('Sorry, this feature is implemented only for MySQL and PostgreSQL databases.'); + echo $OUTPUT->footer(); + die; +} -if (!data_submitted() or !$search or !$replace or !confirm_sesskey()) { /// Print a form +if (!data_submitted() or !$search or !$replace or !confirm_sesskey() or !$sure) { /// Print a form + echo $OUTPUT->notification('This script is not supported, always make complete backup before proceeding!
This operations can not be rewerted!'); echo $OUTPUT->box_start(); echo '
'; - echo '
'; + echo '
'; echo ''; - echo 'Search whole database for:
'; - echo 'Replace with this string:
'; - echo '
'; - echo ''; + echo '
(usually previous server URL)
'; + echo '
(usually new server URL)
'; + echo '
'; + echo '
'; + echo '
'; echo '
'; echo $OUTPUT->box_end(); echo $OUTPUT->footer(); @@ -35,23 +44,9 @@ if (!data_submitted() or !$search or !$replace or !confirm_sesskey()) { /// Pr } echo $OUTPUT->box_start(); - -if (!db_replace($search, $replace)) { - print_error('erroroccur', debug); -} - +db_replace($search, $replace); echo $OUTPUT->box_end(); -/// Try to replace some well-known serialised contents (html blocks) -echo $OUTPUT->notification('Replacing in html blocks...'); -$instances = $DB->get_recordset('block_instances', array('blockname' => 'html')); -foreach ($instances as $instance) { - $blockobject = block_instance('html', $instance); - $blockobject->config->text = str_replace($search, $replace, $blockobject->config->text); - $blockobject->instance_config_commit(); -} -$instances->close(); - /// Rebuild course cache which might be incorrect now echo $OUTPUT->notification('Rebuilding course cache...', 'notifysuccess'); rebuild_course_cache(); diff --git a/blocks/html/lib.php b/blocks/html/lib.php index 69452162a19..4d8fc11b228 100644 --- a/blocks/html/lib.php +++ b/blocks/html/lib.php @@ -59,3 +59,24 @@ function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $a session_get_instance()->write_close(); send_stored_file($file, 60*60, 0, $forcedownload); } + +/** + * Perform global search replace such as when migrating site to new URL. + * @param $search + * @param $replace + * @return void + */ +function block_html_global_db_replace($search, $replace) { + global $DB; + + $instances = $DB->get_recordset('block_instances', array('blockname' => 'html')); + foreach ($instances as $instance) { + // TODO: intentionally hardcoded until MDL-26800 is fixed + $config = unserialize(base64_decode($instance->configdata)); + if (isset($config->text) and is_string($config->text)) { + $config->text = str_replace($search, $replace, $config->text); + $DB->set_field('block_instances', 'configdata', base64_encode(serialize($config)), array('id' => $instance->id)); + } + } + $instances->close(); +} \ No newline at end of file diff --git a/lib/adminlib.php b/lib/adminlib.php index 8e38044b0e6..f249aa35ff4 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -5967,10 +5967,14 @@ function any_new_admin_settings($node) { * @return bool success or fail */ function db_replace($search, $replace) { + global $DB, $CFG, $OUTPUT; - global $DB, $CFG; + // TODO: this is horrible hack, we should do whitelisting and each plugin should be responsible for proper replacing... + $skiptables = array('config', 'config_plugins', 'config_log', 'upgrade_log', + 'filter_config', 'sessions', 'events_queue', 'repository_instance_config', + 'block_instances', 'block_pinned_old', 'block_instance_old', ''); - /// Turn off time limits, sometimes upgrades can be slow. + // Turn off time limits, sometimes upgrades can be slow. @set_time_limit(0); if (!$tables = $DB->get_tables() ) { // No tables yet at all. @@ -5978,7 +5982,7 @@ function db_replace($search, $replace) { } foreach ($tables as $table) { - if (in_array($table, array('config'))) { // Don't process these + if (in_array($table, $skiptables)) { // Don't process these continue; } @@ -5986,6 +5990,7 @@ function db_replace($search, $replace) { $DB->set_debug(true); foreach ($columns as $column => $data) { if (in_array($data->meta_type, array('C', 'X'))) { // Text stuff only + //TODO: this should be definitively moved to DML driver to do the actual replace, this is not going to work for MSSQL and Oracle... $DB->execute("UPDATE {".$table."} SET $column = REPLACE($column, ?, ?)", array($search, $replace)); } } @@ -5993,6 +5998,31 @@ function db_replace($search, $replace) { } } + // delete modinfo caches + rebuild_course_cache(0, true); + + // TODO: we should ask all plugins to do the search&replace, for now let's do only blocks... + $blocks = get_plugin_list('block'); + foreach ($blocks as $blockname=>$fullblock) { + if ($blockname === 'NEWBLOCK') { // Someone has unzipped the template, ignore it + continue; + } + + if (!is_readable($fullblock.'/lib.php')) { + continue; + } + + $function = 'block_'.$blockname.'_global_db_replace'; + include_once($fullblock.'/lib.php'); + if (!function_exists($function)) { + continue; + } + + echo $OUTPUT->notification("Replacing in $blockname blocks...", 'notifysuccess'); + $function($search, $replace); + echo $OUTPUT->notification("...finished", 'notifysuccess'); + } + return true; } From 008011875ce19de7a8c414510832b37a041e8c68 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 14 Mar 2011 01:12:38 +0100 Subject: [PATCH 111/369] MDL-25352 fix tiny typo --- admin/replace.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/replace.php b/admin/replace.php index f1a1c7a830c..8217876de04 100644 --- a/admin/replace.php +++ b/admin/replace.php @@ -26,7 +26,7 @@ if ($DB->get_dbfamily() !== 'mysql' and $DB->get_dbfamily() !== 'postgres') { } if (!data_submitted() or !$search or !$replace or !confirm_sesskey() or !$sure) { /// Print a form - echo $OUTPUT->notification('This script is not supported, always make complete backup before proceeding!
This operations can not be rewerted!'); + echo $OUTPUT->notification('This script is not supported, always make complete backup before proceeding!
This operation can not be reverted!'); echo $OUTPUT->box_start(); echo '
'; From 2848b97948aa6d6e289b1ec447ba55ad1a5e3c67 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Mon, 14 Mar 2011 17:04:06 +0800 Subject: [PATCH 112/369] MDL-24877, do not display all courses in course category tree if there are too many courses in moodle --- admin/settings/server.php | 2 ++ index.php | 14 +++++++++++++- lang/en/admin.php | 2 ++ lang/en/moodle.php | 1 + version.php | 2 +- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/admin/settings/server.php b/admin/settings/server.php index 7f6647fec2e..807bf75f8e9 100644 --- a/admin/settings/server.php +++ b/admin/settings/server.php @@ -227,6 +227,8 @@ $ADMIN->add('server', new admin_externalpage('phpinfo', get_string('phpinfo'), " // "performance" settingpage $temp = new admin_settingpage('performance', get_string('performance', 'admin')); +$temp->add(new admin_setting_configtext('numcoursesincombo', get_string('numcoursesincombo', 'admin'), get_string('numcoursesincombo_help', 'admin'), 500)); + $temp->add(new admin_setting_configselect('extramemorylimit', get_string('extramemorylimit', 'admin'), get_string('configextramemorylimit', 'admin'), '512M', // if this option is set to 0, default 128M will be used diff --git a/index.php b/index.php index 8aa5b3a3e15..7c3472d464b 100644 --- a/index.php +++ b/index.php @@ -206,7 +206,19 @@ echo html_writer::tag('a', get_string('skipa', 'access', moodle_strtolower(get_string('courses'))), array('href'=>'#skipcourses', 'class'=>'skip-block')); echo $OUTPUT->heading(get_string('courses'), 2, 'headingblock header'); $renderer = $PAGE->get_renderer('core','course'); - echo $renderer->course_category_tree(get_course_category_tree()); + // if there are too many courses, budiling course category tree could be slow, + // users should go to course index page to see the whole list. + $coursecount = $DB->count_records('course'); + if (empty($CFG->numcoursesincombo)) { + // if $CFG->numcoursesincombo hasn't been set, use default value 500 + $CFG->numcoursesincombo = 500; + } + if ($coursecount > $CFG->numcoursesincombo) { + $link = new moodle_url('/course/'); + echo $OUTPUT->notification(get_string('maxnumcoursesincombo', 'moodle', array('link'=>$link->out(), 'maxnumofcourses'=>$CFG->numcoursesincombo, 'numberofcourses'=>$coursecount))); + } else { + echo $renderer->course_category_tree(get_course_category_tree()); + } print_course_search('', false, 'short'); echo html_writer::tag('span', '', array('class'=>'skip-block-to', 'id'=>'skipcourses')); break; diff --git a/lang/en/admin.php b/lang/en/admin.php index 178c85c3d24..915cb7a9bfd 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -764,6 +764,8 @@ $string['numberofmissingstrings'] = 'Number of missing strings: {$a}'; $string['numberofstrings'] = 'Total number of strings: {$a->strings}
Missing: {$a->missing} ({$a->missingpercent} %)'; $string['numquestions'] = 'No. questions'; $string['numquestionsandhidden'] = '{$a->numquestions} (+{$a->numhidden} hidden)'; +$string['numcoursesincombo'] = 'Maximum number of courses in combo list'; +$string['numcoursesincombo_help'] = 'The combo list doesn\'t work well with large numbers of courses. When the total number of courses in the site is higher than this setting then a link to the dedicated course listing will be shown instead of trying to display all the courses on the front page.'; $string['opensslrecommended'] = 'Installing the optional OpenSSL library is highly recommended -- it enables Moodle Networking functionality.'; $string['opentogoogle'] = 'Open to Google'; $string['optionalmaintenancemessage'] = 'Optional maintenance message'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 1958e418b98..faa6d9cbbb4 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -980,6 +980,7 @@ $string['maximumupload'] = 'Maximum upload size'; $string['maximumupload_help'] = 'This setting determines the largest size of file that can be uploaded to the course, limited by the site-wide setting set by an administrator. Activity modules also include a maximum upload size setting for further restricting the file size.'; $string['maxsize'] = 'Max size: {$a}'; $string['maxfilesize'] = 'Maximum size for new files: {$a}'; +$string['maxnumcoursesincombo'] = 'Browse
{$a->numberofcourses} courses.'; $string['memberincourse'] = 'People in the course'; $string['messagebody'] = 'Message body'; $string['messagedselectedusers'] = 'Selected users have been messaged and the recipient list has been reset.'; diff --git a/version.php b/version.php index 265ab74a9c4..94425af0da4 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011030900.00; // YYYYMMDD = date of the last version bump +$version = 2011031400.00; // YYYYMMDD = date of the last version bump // XX = daily increments $release = '2.0.2+ (Build: 20110309)'; // Human-friendly version name From 3718dfc771b46000154d29878058cfef89031611 Mon Sep 17 00:00:00 2001 From: Kordan Date: Mon, 24 Jan 2011 18:52:56 +0100 Subject: [PATCH 113/369] theme-formal_white MDL-26300, MDL-25628 , MDL-25520 FW last version --- theme/formal_white/config.php | 2 +- theme/formal_white/pix/hgradient.jpg | Bin 0 -> 18986 bytes theme/formal_white/pix/roundcorner/body_l.jpg | Bin 15826 -> 15843 bytes theme/formal_white/pix/roundcorner/body_r.jpg | Bin 15825 -> 15847 bytes theme/formal_white/pix/roundcorner/footer.jpg | Bin 15873 -> 15889 bytes .../formal_white/pix/roundcorner/footer_l.jpg | Bin 16187 -> 16557 bytes .../formal_white/pix/roundcorner/footer_r.jpg | Bin 16129 -> 16535 bytes theme/formal_white/pix/roundcorner/header.jpg | Bin 15830 -> 15847 bytes .../formal_white/pix/roundcorner/header_l.jpg | Bin 16181 -> 16560 bytes .../formal_white/pix/roundcorner/header_r.jpg | Bin 16154 -> 16553 bytes theme/formal_white/style/base.css | 18 ++- theme/formal_white/style/course.css | 119 ++++++++++++++++++ theme/formal_white/style/formalwhite.css | 25 ++-- theme/formal_white/style/general.css | 3 +- 14 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 theme/formal_white/pix/hgradient.jpg create mode 100644 theme/formal_white/style/course.css diff --git a/theme/formal_white/config.php b/theme/formal_white/config.php index 02d00c26522..f2fb140bf01 100644 --- a/theme/formal_white/config.php +++ b/theme/formal_white/config.php @@ -46,7 +46,7 @@ $THEME->parents = array('canvas','base'); // changes you want to your theme. //////////////////////////////////////////////////// -$THEME->sheets = array('dock','base','general','fw_corners','formalwhite','settings'); +$THEME->sheets = array('dock','base','general','fw_corners','formalwhite','settings','course'); //////////////////////////////////////////////////// // Name of the stylesheet(s) you've including in // this theme's /styles/ directory. diff --git a/theme/formal_white/pix/hgradient.jpg b/theme/formal_white/pix/hgradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..64c352d588757bfefb01ebf4d37fde1699c93b38 GIT binary patch literal 18986 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 NpGjM5ZI$`|CIEMErl3_Y$ z&uS`!{I#3(vr#4FKg0i<|KBPc3&_YX$uG{xFHkVnGhncA^7Lh4VE_Sk872k>CLjch zse;7>+;~29s_h87wP6n9!VSwOlyBa|Y%Znf2$W<4D}WHJKuQoSmc)?Hkit;8nNKd6 zSvCwP#0ZrFDKPmXxMz zXqalCn`CNerfXrElAN4oWNDFNY&?0A>M!CHZcs}lPNAjxY@!ry{-G{Tq$7Oh%U^^AW+PCXh)XxAucM%pi{IaxfcgbIPw&h$<#Fdj`dNh$0Z%Do!7wiV?^O M*I<6su>Jo{0Le4JAOHXW delta 744 zcmaD}eX)9iIAh*Ki5UV0RtDx)2Br#zW>%(_R)%I150o=nY_?!DV{(~M|J2(q{;O`h ziArPeS0nGIQzm-B6=q#0WzCYcx{C0UwHUZ(nsIE6>lQi)UO zt3I13g`0Ua#EEpIyJmy1fv$nMu7PO?EDp2{j3(dG)WIq)sWpKpCrm!8b%rQ~oA+vm z2-fE_FoGfi32<;RGBBfwF|o1;FfuTLq6z^RnT=UYEd7GbP5oTmEnIhx~u8 zx_ABmsz12@r%P=4{|jH1Oh3b^vi$$e|8Et}1!UxxQy!~AqGZP6fFV_9~ccAjsM?b;9+KDWD;ZsrG@(k zH1_E#W!#!k4;1HMWCChp5K9f684Tt!gSfmx8U0`$BZwz$H#6F9raeTp0TY`&gUE{i j3=q{Io~-Jlm-_q=^^8Ei?j)WsD+D(=&YQ|q|NkZcH|N(Q delta 810 zcmbPO(^xY>oUv-6#0&ugD+6;Y15*VYbD?^Kk2g(^;Hd`>7Gufwn_5U)zx&D); zf5?9Z&mZRh8I)RA&HsPltH|`znkv)(-~9hp;Xpt}eo20DMt*^Uv7P~gg_EZ*iz)*M z2ux0p5#4;1*+@#$706`+3qlA%AjJj591Lj;`9N60kjhZR5YLb_IZ;l0v$LEBvupxT znh~lDq+Ef4feD0N7$g`NCx~v|tH{SBPr!kjUns9)R7p-UOH52kv(UA$Of}avG)zg; zO*Aku(zQr4wn$7eF-S_XG@HCl^*3<}ud1aIr!Y=^Hc<*U%W8-d>BtDp24MqT19M#i z(-2s6X&V?#eyyp4Ra{GJ0#Qzwd{65PQ3^Mo(+&}=FJfS11Vs%J;NSv^Fe3>7nM^FK z0t}2SD53%kg3Q7qtQ^1?Wk*#lz%-T3?3xe*6N-8U0Y(NxqyM)Uc$gU(nFN_ZDIw?n z0mV1bPU~+s0L3{NnHU&Z8N}X(?hXcXnL%7$sf_br9wUe+8SAuZSId6}h;k-2dj^rE g$`HjMj#RM^RF07m$kmRLczE+;wzG`2UH$)?0L3WIa{vGU diff --git a/theme/formal_white/pix/roundcorner/footer_l.jpg b/theme/formal_white/pix/roundcorner/footer_l.jpg index 203abac8608d0c0e17864d15e5278b6e06e47867..63664d48c8d52d71cd03c5d481b3396e6c1061a2 100644 GIT binary patch delta 1526 zcmdm8x3-aSf;i)ni4rpe46O_dtqhG642`UeEUXL-CLSnf%-d|iXv$R2bKu#o-Lup$ z7nIa+U0QW4>R>X@)>}=hEf*f*XAS#p`(?*&sY559?&<&R#Z@X4Is4cAUylE>>vyWG zKj{De!j~n}&v2?NfB6MW{lEGDt-`;6jQo=P;*9(P1!Fw}1`8)oUltYy5MY;KVqjnb zLa>-BSWG~`jptLR+K#YW8|E-B+^~E?`R13*=2DEVlNIH}1vwbf81jLzgdvroh#{UK zXL5s__~s-z8)i*GupvAkLzudN1S1d&La_-019J&bJdZ(wfpLQ9<~xc!Oukh0=VWu0 zGA2pe$%g78lLNFlHlJ1zVN^-7v`9%wF*MUPOiQuUH8e~$&`mN0axF|#l9SVnfU?HM zlbO|i8xW&Vol8NXA~z?m*s369vVfZSWLI@3;%r#0KAR|oo3k{;iFEW*O(zjULtO(y zT|=V~LqjW511nQwZ3Dx}zcsal;o{J=1roQ=(!nZTt~J4kG~XAO1f_!g4-96Z;*iRM zRQ;gT;{4L00(z}nwer{o@kkBVrXmxjJM=e9PwtOkD(WCB6FHm%H#}fMfOAs zOB0jC#K{x1<D8JL(+#2J~GSy&ka7#NwEnUQob zF)*?)v$6>YIT;!Wi?VYFGB7a#l`yfxG(+?WvMCA)3m6to+;sS=*)(<`VD4sRVr8v| zTg%AAARws7Y=};E4SR9mQ|rmz zRc-$?m6kj6+@Gu&_2K%S+Iv@TdFw+g0;x+;JL1Z>Y2%WbPPuu@D>>^SHZcNa9?f~y zYFrklKIdp!+`^=Ng+04@x2=oOtT60+)W5yJDu4fuYt|DJ^o~}GPj1u+pULq~`kl&p zo9fMuSzEd;o|ew}cw)^GCXO%DmhPAqq2{!%hml40SAXID;MJA#pZ*rrtHq)$ delta 1072 zcmZ46$hf<1f;i*Si4rpe46F>ytqe>R49%=eO|6WKCmtwg%-?LmXv$RY^K9q()U#JM zG_juxeYG}qYx{;1TKWmq2_II% zZCCsM7rv@YKh3E!{Z-2J)0!&F|KI%oR^eShMt(_taYlZDg0Y?fgN2i)FN-Pz2nc{l zBmyY6`9HIXl(suikPS&f5Xc5$PKGpwd>|}gNM$Huh-XM*$eBD*PJDB*oDH)kBiLvj zkT#}nAi)U4FpVY*49q1!@q7je2F3}Zo8Kz(F!@v0s|=IfRLYnnm?t}^i%gE!=Gc5o zMTC(fIms+BF)7V-a)OQwpE{RzH=EpUty-t1 zCOFyUqGtQiHERpBQj>v7I2f527+D$4c{;BQ2v{EFz2fWq%Vkl^nnIXx-sR&PG?_Cu+mV7GC7`{Yk&&-+b#|10kF=Xi+0OlH8YWldPEH$2q~`>82YQ5R*ZYhOfSIO%jXSW0(&XV`K!1J>GLWuQw;+@$7l`tCp6l zs9e6fFW+0b>}T0&0qx7|?Ds>=-%dLfv9yY1s)t?SX8kEa3lF=iugmnzHu-~9hp;Y&b9eo20DMt*^Uv7P~gg_EZ*3kw4Xu*)zpFfaijSWFcxCg8^N zsZ(u7*sTq77+Du?SU#bA^8;pcDRoz%EE`w_gb)N$Ak4v##*hz$B@C$yMGWzq9pplp zH3h*2@_iE1KlK3Lo;0q)0E`oG$Wv_vGL>&s(*-5$FH77l)4$} zbBIy5Ib1`6I0sJBbP_Q%)HN{FH8ct_G_*1`urf8)HZYw0LQ_i^E)GpLAaPYK9jxLh zS`$HjCKMv-TnY*mxjA{oR>dVjscDnvYsv`~hg24%>IbD3=a&{GrvgQlCrfDC)~6O_ zmZhe+73JqD6s4qD6(klFr-D@4s>773+W}2eumPK7m6=yul9-pA>gi%vTAG<+Wu9o6 zYGPJWt~`N^fZsd*(pOMnV(^eYkz ze0{B45Kf)!sjZ`8oRns4ZkPrP)3g*599B=BsqI5lRC4Hq2-eRAreYSntXHSg}SChe>18q_S`7jrOXMX*d1^eJ<3DNCNW z`Mav=j9#}xm$Y6!ZOTsmdTUqc*N~hU8(glPKE0YxVa^H9pVgK>&Y!FA3-jM;w|VP^ zD~e4gFJE=ljobMqvYX}2#jD|~cAtstbC}DnX#DMQ=k?c@w4B=56cUopHXcit=UZ2L U{H=T(f6b3}^&NZE7yrKr0I31VVE_OC delta 1019 zcmbQ<$kxj7gSf z8NtT$fHW{Q0SQJRhG{Wj zU|=o*il;G1FfdLK-TYXQm&u88Pfj*asbG>|p1fXDX7e!>QAQqPgG93=LsMM~%T$ZW zfjZ)o|Ed1L6qHp@!xUVmJ_kc^bE<{}7DE?kI*Axq>KYj98kmF_SXh}FSs58<8yHRg zrl}=tple{RYhW4zi&c=gv6c>2@gl8>7#3V6!vX743mWMp6x zFmzO6RuBwq6#9RQfd^fxfMoOBel$4ZZV}H3?vFtK8Tj9DSO7hOpg&M!6+!9n2;-9i~$9cUU zlR7R-{rvSXs(wjnb-BrOjTvc67kU}AE}UPM?7398I5%|d(kaJ2TgsXq&{&Ym_;KcQ M8}{vX_Wy4J0C_1Wq5uE@ diff --git a/theme/formal_white/pix/roundcorner/header.jpg b/theme/formal_white/pix/roundcorner/header.jpg index cd6e9772a7e431e91899c3997d5b2c26645b2e2c..495b0d84052ce52bd3edaa45226131081ae83ef8 100644 GIT binary patch delta 667 zcmcas{k(d@1_47W14AoABLxFXD+3EFQ?rc+)-uJ)Z%M6RQ2%q?zbDfcd4zY(|9|0Y z$n;YyRhIw1`TwoLiGYm!lKkR~`~n4IJp%>{Cr@7%76uStmtkUHU;;w0m?~IIz>Viq zr`nFNTN~yuF5IwuLiy%x%;r*zj+5WXiVLzaWH6*MBr>D`$s(X~#>tK{!jt{vcs5(g zRj~@7yJPcVcLCaDI-=81{AhG|JDx`u|S2D(Y6hGx1JrYXtEX-1Y7DaOW=XQ}=s zO5F~%G@{fws?Q-t-6jnQ;@oGg*&uAFYhb8rXcPhqdTj&4$>%h6u!{3)O(e$t$p^L0 z5~FVOM(uvVdS+o35ixc_1}0{3Ou+~NwyV?3g&3F_VFF-UfYE5-|62?^%#4gog3N+I zu??L(`$VrX0|hx4nHU&Z8Mf;DX8`kUvCJwuN@M3DrDv!x!Q PiV?^@IY%qk5SYdQ$Sl2b delta 669 zcmaD}eXV-J1_1*r19K|_Qw2jaD^m+AQ{#;X)-rkOZ%wOTQ2%q?zbDgXd4zZ6{=e`w zWcsODgy`zfJr1`^C@O?DP32f2pf{9 zAdt-g#u*H$42cXWK(dG-o}mON#yB}pMtE|Z9M5J?xhhrxbeC+tth|L$IVsi5I5jC% z*TOQ@Lf6nRB~3Tcz{E(`BF)$$G0DUrDaq1o@+#HeM5#NWmPVAiK=nDqsM{={Awir2 zy)_$z4Rj66bq!2IV4<&VU^MxjrVdtdS*?l0IAHQct+T|a+k8;FU$CA@h(&~5T#$i@ z87Y2%5y^ISnz;}o1DYtKk@5dq3_Q$?j7);epjh14@pg}x2s2QSgOQ1Wk(FVi&VL3l tj~T?v@&~gSLF`viKOxGP*z6h3Lewyc1KE4*A&MA*>@%@hIUj+k3;@QHwS@ox diff --git a/theme/formal_white/pix/roundcorner/header_l.jpg b/theme/formal_white/pix/roundcorner/header_l.jpg index 92acf0b23e50eab6efe64b1d9cce1813dd414e4a..bdf88a83439111c5ecd37193fee62aebf4b47ea5 100644 GIT binary patch delta 1490 zcmdm5x1o`7f;i)vi4rpe46O_dtqhG642`Ue%&d&fCLSnfEZc0sXu?$gWs!qWX!^72 zZ6TMF_eiOKQl0U=IxGFshPM8BUH|NCE55cF)c6AT(b*k+MyR~5sN^p3=@-0jZKqu4bxIAbqx(u4Rn)C4b5~dOjDAR(~K-F zQjCo!^Q-+PPNAN9Dsc+8tIsA%;pQ?8aUvbLQPWAp&`{UFP}k5X#L&>n)WFKrSlhsG zGP{dVjscDnIbD3 z=a&{GrvgQlC!1^A)~6O_mZhe+73JqD6s4qD6(klFr-D@4s>773+W}2eumPK7m6=yu zl9-pA>gi%vTAG<+Wu9o6YGP0~063_Q$?j7);ep#1vw(lVpQ<9#QDW?gG9HRs5S=AX9clRr=m2O|^EVGQMIN#RGA zKMPs)$#;>!0fEqY=jMYYf$n2v2xNYHL5d~1^6ax0vU}~p;*211!?t?HyOm`syK0~7 z>c#H5%PGUnbo|GA`N-$5qv|1MGqKq-%v|(f)1mKggyXe;d!ctN3H03?XA6% zPmV2HpM84s++-)_Qx_f{*LD{YGEaM9b8i2H&-ur4YuByVQ7h9a3sky(*|CW?mSo$` zi>WBsvW`(xBv-#!b{FrtjTst-p`xO4hYnt>tvyzsclpMRbLN%HXP#6LzA2Q`Au1Y@ S{gwajj`OD;{rJ!D|0V!KD%#Hg delta 1226 zcmdnc$hfs`f;i*qi4rpe46F>ytqe>R49%=eEv$?zCmtwgEZuCuXu?$gRoueFGvv*= z?{8K}%Rad46?x6xYvz|V*6v4ENBsDDF(R35|D1PE7EGId>(hUR3-*7m*B5#Fs;oZB z|Np`lo&7IM>SOnRbReYM(1mbM$)V7^`P)A{M zhK|}~c3n@RG;J=?4H2xL0!#snpdLJW*7jLfVc zW9lJhF)|1UGBGO}Iwlqh85#e-#lQn}6q6t`D4o7nTjMu#iS&Y#dhVBBZs1muY14gM z`ei;)5eFj^10yR#)FI}rr?lT?EA6~G)#L(`R?W$Jup~1`l3|kc)1wAAgl&z$VvHcM zb?cHEd%7!C;%ryfZ(CfM65cR}opIyq*D|^BYrP@nGO^h+sLT~_)0!Q<=;x|O%eVGu z@b>;^fS3!CY*=}6jrMHvK~#|^wVa6(@A+YVRM~a)|t2F zvAV`>%F0~-RObGpJJT<3l|7m;lV!R3X#v~97e{oBJ_pU7JL7Fg$Xd@g>oz`8GJGR_ s>`>*FZATk diff --git a/theme/formal_white/pix/roundcorner/header_r.jpg b/theme/formal_white/pix/roundcorner/header_r.jpg index 866802b8ea6c3b2239086877a80f796662c6e4af..e9f2f3ffc62ae2ba884ff764cd6dcfce224d6be8 100644 GIT binary patch delta 1529 zcmbPLx3ZCOf;i)%i4rpe46O_dtqhG642`Ue%&iPfCmtwg%-L+gXv$R2IOEw4vsZUx zKJE}$v-RL1w}p|LmPH*p&Gu}bW8{wCEBBpAm%LHC{KTs(BDXwMCIQ#zd*rQ&w#3?AC@kj0-m`pHRN}3A4GBt}9TM4Xgq}2m&b(=3vNRNM%T5 zNCA>X4DmqBz`!`UP)2xiogB~ROgRH)RY9=vJRp5c9Uy5ShG{opU|=o*isx+Jr>M&0 zNj0BO)>5fplC+&{s4cVkfQksCiiKffvZ=9|fv#a%ilwfhVXA>{lBuDYu7znza&nrH zrA3Od@#G(>zll>QuAWMq!UgKHiBh;ZUPGKnN6yl85-~K?H89jQGzu{^v@$iYGBwsV zFr55BQ%e{w4oy`caa}DPtl~LZ6O4%o7IiKKg^Jvqyke{3lAzSI$rDw@Chyhc5GoF- zEJ)Q4N-fSWElN%W$|z4((6+5lEy^rQO>ryA&s8W&NwX?QEGkX~skBvxDOI-vny6p{ zHq9zCuec;JFFDoI#jdn8GsVh0(K6M<(AWqVQOT(|BFaV|LoeJ!<}|C6$+6lByvd0c zmL?{NiMke+spgX(s)}pEw58-Hm*%GCl>n^-YO~R=NG$O6wQ@l?d~%?+j*4+onz6ZI z8ZemCQcQ3-Wb#67Z{p%tKqo}7eij2G5P&iQ46t*sa4|A4F~j&^nuV2-iCKVwk%^U= z6(PaI$ig7N%*rMxq@-wK%5EXZz{JGJ%*etGQv%e)!YU}l#vq_*=omQh;zJ|h$0efM z*o7DvnVDGF85!!~Dg}Wy0#yYzCNA74WYn~Y<^L@P9%e>HCP8LU&U_=7$?IcqGb8fc z#RhB3dB$g-$%HvaJN{KSy7V+ zp}?p+%^4?tM}Wl{LE^dfZ?9k5zGmLG9p-m7PD&2**>=96`H#B!bM51o3n3;mvDq_Z zr+1#QaSGb9V)NpOs}8SMSy`_}kL#suoDMAM5~?DeWXF>MOl%53)HY40?TJ4|ah*w=;s z*{__t?r77t{XN^Y*(TMbp1PP~7<6`PC~N!TRF;Kq7uBB1$<{bu|MJ^%{*908uWgJ4 GmcjrXBI3>f delta 1059 zcmZ44$T+KRf;i)Xi4rpe46F>ytqe>R49%=eEv-xpCLSnf%-U?hXv$RY_S|ya?P6}u z2Nr@qLyy_mc=+e~Y;Elq;#%Ah?|c4u;oLUHkAE-!%aT^zH_20J`Tq-FLub`L^|p)u zsvB>-q%rubk@wRn6TSc6{Qp+rMLDgy`zfJr0*B**-U zfnhTfi@ub$J5YuVNmdZZ24PNy42D#OM1~X~S;P>}P{L3&xnE9vbD^9KvnC_hd>)WC zrZynK2*farCJYSBB|z~k1_=hn38I@{EAlY8Q^~879aJiqB$y}f*Ob|OO+|!}H#I5M z%s4gKMAyPH)nam@j`(Cgwcl7ob=6a`h;CD#jVZdhR6`t_!5cK4L<}r-4UBaSOhODS ztW1rpj7+o*j3%>bX$c$X8kp-En1;Y&86@tkrGr(xNoxY8t&>Z&Z6~kQQQ%E9GcicC zG%^SI$PDNs$;qE}JTcX8PS6bztnUYgJToZp;edmgm5qy$fr%L|0%9<;GBU9M69Ov> ziUcDQGpm3g3!4zTv8jb10}}`^vchx%WmyDSh1diX4IL*IZ(|o?U}R=ug-Zity`DjU zNl?)+FtL!iapA^;O8;*$@GvtnG6^z+62qIVZdYbIMhhve;Oa8fnteG?K~(+H;^KIq zDh@^_2B1Z5#T{mIy;t&?c}cV_liw@ztr;xG43aaul#-Gf8r{1h&JZlf2omgm?`d&U zV`h$LP2%Qkf!Xyf{-LQ}FK^E`UgmxoqL+z@&7MKT5n5KHfHAChZxHU6zYz?^XuE?wf+f3>%$A3{%Q;Bd42B6p0jAGB~Pm7H@lN* zOPV}pR3$z-Hobm**I#L_fHfy1A5VVbZ^?gEQid&z#c1NhCPvxjpUaM&y4mlTwbw(} mf-QSx66?m5`z?8#&esQ6?D&54@v)k3`;RaAYrX!*|C<1?3O@$` diff --git a/theme/formal_white/style/base.css b/theme/formal_white/style/base.css index 468dbea2a99..8949a13d77d 100644 --- a/theme/formal_white/style/base.css +++ b/theme/formal_white/style/base.css @@ -1,4 +1,4 @@ -body, div, p, li, input, option, textarea {font-size:8pt;line-height:1.5em;} +body, div, p, li, input, option, textarea {font-size:10pt;line-height:1.5em;} body, div, p, li, input, option, textarea, h1, h2, h3, h4, h5 {font-family:Arial, Helvetica, sans-serif;} h1.main, h2.main, h3.main, h4.main, h5.main, h6.main {text-align:center;} @@ -34,4 +34,18 @@ h1.main, h2.main, h3.main, h4.main, h5.main, h6.main {text-align:center;} .groupmanagementtable td {vertical-align:top;border-width:0px;} .groupmanagementtable td p {margin:0px;} -.pagelayout-redirect #page {background-image:none;} \ No newline at end of file +.pagelayout-redirect #page {background-image:none;} + +.course_category_tree .category {margin: 5px;padding-left: 16px;} +.course_category_tree .category .course.odd {background-color: #E3DFD4;} +.course_category_tree .category .course.even {background-color: #EEE;} +.course_category_tree .category_link { + display: block; + font-size: 120%; + font-weight: bold; + margin: 5px; +} +/* la posizione del disclosure triangle */ +.course_category_tree .category.with_children .category_label { + background-position: 0px 3px; +} \ No newline at end of file diff --git a/theme/formal_white/style/course.css b/theme/formal_white/style/course.css new file mode 100644 index 00000000000..0578c261141 --- /dev/null +++ b/theme/formal_white/style/course.css @@ -0,0 +1,119 @@ +/** Course formats **/ +.course-content ul.weeks li.section {border:1px solid #DDD;} +.course-content ul.weeks li.section .content {background-color:#FAFAFA;padding:5px 10px;} +.course-content ul.weeks li.section .content h3 {margin:0;color:#777;font-weight: normal;} +.course-content ul.weeks li.section .left {padding:5px 0;} +.course-content ul.weeks li.section .right {padding:5px 0;} + +/** Course **/ +.coursebox {border:1px solid #DDD;border-color:#DDDDDD;} +.coursebox .info {margin:5px;font-size:1em;} +.coursebox .info .name {margin:3px 0;} +.coursebox .info .teachers {margin:0 1em;font-size:0.9em;} +.coursebox .cost {font-size:0.9em;padding-top: 20px;} +.coursebox .summary {margin:5px;font-size:0.9em;} + +#page-course-recent h2.main {font-size:1.1em;} +#page-course-recent .user {font-size:0.75em;} +#page-course-recent .grade {font-style: italic;font-size:0.9em;} +#page-course-recent .forum-recent .reply .title {font-style: italic;font-size:0.9em;} +#page-course-recent .forum-recent .discussion .title {font-weight:bold;font-style: italic;font-size:0.9em;} + +.path-course-view .availabilityinfo {font-size:0.85em;color:#aaa;} +.path-course-view .availabilityinfo strong {font-weight:normal;color:black;} +.path-course-view .dimmed_text img {opacity:0.3;filter: alpha(opacity='30');} +.path-course-view .section {font-size:0.95em;line-height:1.2em;} +.path-course-view .section .activity {padding:0.2em 0;} +.path-course-view .section .activity a {line-height:1em;} +.path-course-view .section .weekdates {margin: 0;font-weight: normal;font-size: 1em;} +.path-course-view .section .groupinglabel {color: #666666;} +.path-course-view .section .left {font-weight:bold;} + +.path-course-view .weeks .section, +.path-course-view .topics .section, +.path-course-view .section td {border-color:#DDDDDD;} +.path-course-view .weeks .content , +.path-course-view .topics .content, +.path-course-view .weeks .section, +.path-course-view .topics .section {background: #FAFAFA;} +.path-course-view .section td.side {background: #FFFFFF;} +.path-course-view .weeks .current, +.path-course-view .topics .current, +.path-course-view .current td.side {background: #FFD991;} +.path-course-view .weeks .hidden, +.path-course-view .topics .hidden, +.path-course-view .hidden td.side {background: #DDDDDD;} +.path-course-view .section .weekdates {color: #777777;} +.path-course-view .weeks .weekdates , +.path-course-view .topics .weekdates {color: #333333;} + +.weeks li.section , +.topics li.section {border-style:solid;border-width:1px;} + +.weeks .content, +.topics .content {padding: 5px;} + +.categoryboxcontent {border-color:#DDDDDD;} + +#page-course-user .graph {text-align: center;} +#page-course-user .section {border-color:#AAAAAA;} +#page-course-user .info {text-align:center;} + +#page-admin-report .plugin, +#page-course-report .plugin, +#page-course-import .plugin {margin-bottom: 20px;margin-left:10%;margin-right:10%;border: 1px solid #cecece;background-color: #fdfdfd;} + +.path-course-view .unread {background: #9EBEFF;} +.path-course-view .completionprogress {font-size:0.80em; padding:8px 26px 5px 5px;} + +#page-course-category .courseboxes, +#page-course-index .courseboxes {padding:20px;} + +#page-course-report #content {padding-top:15px;padding-bottom:15px;} + +#page-course-report #region-main p, +#page-course-report-log-index #region-main .info, +#page-course-report-log-indexlive #region-main .info, +#page-course-report-stats-index #region-main .graph {text-align: center;} + +#page-course-report .logselectform, +#page-course-report .participationselectform, +#page-course-report-log-index .logselectform, +#page-course-report-participation-index .participationselectform {text-align:center;} + +.addcoursebutton {text-align:center;} +.categorypicker {text-align:center;margin-bottom:10px;} +.path-course-report-outline .loginfo {text-align:center;margin: 1em;} +.categorylist {width: 90%;margin:0 auto;text-align: left;} + +/* Course and category combo list on front page */ +.course_category_tree .controls {margin-bottom:5px;text-align:right;float:right;} +.course_category_tree .controls div {padding-right:2em;font-size:75%;} +.course_category_tree .category {background-color:#FFF;background-image:url([[pix:theme|hgradient]]);background-repeat: repeat-x;border:1px solid #ddd;margin-bottom:10px;} +.course_category_tree .category .subcategories {background-color: inherit;padding-left: 11px;border-width: 1px 0 1px 1px;border-color: #FFF;border-style: solid;} +.course_category_tree .category.with_children .category_label {background-position:3px 3px;} +.course_category_tree .category_link .category_link {font-size:95%;} +.course_category_tree .category_label {padding-left:13px;} +.course_category_tree .category_link {display:block;margin:5px;font-size:120%;font-weight:bold;} +.course_category_tree .category .courses {background-color:inherit;} +.course_category_tree .category .courses .course_link {margin:5px;margin-right:100px;} +.course_category_tree .category .course {border:1px solid #f9f9f9;border-bottom-color: #eee;border-right-width:0;} +.course_category_tree .category .course:last-child {border-bottom-color:#f6f6f6;} +.course_category_tree .category .course.even {background-color:#f6f6f6;border-color:#eee;border-top-color: #f9f9f9;} +.course_category_tree .category .course_info {right:3px;top:3px;} +.course_category_tree .category .course:hover {background-color:#eee;} +.course_category_tree .category .category {margin: 5px 0px 5px 5px;border-right: 0px transparent none;} + +/* Publication */ +#page-course-publish-metadata .metadatatext {width: 400px;} +#page-course-publish-metadata .hubscreenshot { + display:inline; + float:left; + margin-right:10px; +} +#page-course-publish-metadata .hubscreenshot img {vertical-align: bottom;} +#page-course-publish-metadata .hubdescription {} +#page-course-publish-metadata .hubinfo {display:block; margin-bottom:20px;} +#page-course-publish-metadata .hublink {} +#page-course-publish-backup .courseuploadtextinfo {text-align: center;} +#page-course-publish-backup .sharecoursecontinue {text-align: center;} \ No newline at end of file diff --git a/theme/formal_white/style/formalwhite.css b/theme/formal_white/style/formalwhite.css index d1ebc6c9fa3..da7ff621976 100644 --- a/theme/formal_white/style/formalwhite.css +++ b/theme/formal_white/style/formalwhite.css @@ -3,7 +3,7 @@ *** Core ***/ html, body { - background-color: #FBF9FA; + background-color: #EFEFEF; } .block .header { @@ -58,7 +58,7 @@ body { } #headerenvelop { /* Inside Header Middle */ - color:black; + color:#000; height: 105px; /*background-color: #E3DFD4;*/ } @@ -73,16 +73,25 @@ body { } /* Header */ +#header-i3 { + background-color: #FFF; + margin-left: 7px; + margin-right: 7px; +} + #header, #header-home { padding:0 17px; background-color: #E3DFD4; - margin-left:17px; - margin-right:17px; + margin-left:10px; + margin-right:10px; + -moz-border-radius: 6px 6px 0px 0px; + -webkit-border-radius: 6px 6px 0px 0px; + border-radius: 6px 6px 0px 0px; } #custommenu, .navbar { - margin-right: 17px; - margin-left: 17px; + margin-right: 10px; + margin-left: 10px; } .yui3-skin-sam .yui3-menu-content {border-right:none;border-left:none;} @@ -97,8 +106,8 @@ body { #page-content { float: none; width: auto; - margin-right: 17px; - margin-left: 17px; + margin-right: 10px; + margin-left: 10px; background-color: #FFF; } diff --git a/theme/formal_white/style/general.css b/theme/formal_white/style/general.css index bcf2602ab60..61c77b85335 100644 --- a/theme/formal_white/style/general.css +++ b/theme/formal_white/style/general.css @@ -130,7 +130,8 @@ img.iconhelp {vertical-align:middle;} #categoryquestions th, .user th, .user th.header, .group th.header, .admin table tr th, .admin table tr th.header {color:black; border-width:1px;} -#permissions th, td {border-bottom:1px solid #000000; padding:0.5em;} +#defineroletable .rolecap th, #defineroletable .rolecap td {border-bottom:1px solid #000000; padding:0.5em;} + #permissions tr {background-color:#EEEEEE;} #permissions tr.rolecapheading {border-top: 1px black; background-color:#E3DFD4;} .user th a:link, #categoryquestions th a:link, .group th a:link, .admin table tr th a:link { From 4afb01dbb4c418d384f9db0c234624179df4409c Mon Sep 17 00:00:00 2001 From: kordan Date: Sun, 6 Mar 2011 17:31:32 +0100 Subject: [PATCH 114/369] formal white from scratch fixing MDL-26300, MDL-25628 , MDL-25520 --- theme/formal_white/config.php | 197 +++++-- theme/formal_white/javascript/navigation.js | 154 ----- .../lang/en/theme_formal_white.php | 54 +- theme/formal_white/layout/embedded.php | 34 ++ theme/formal_white/layout/frontpage.php | 209 +++++++ theme/formal_white/layout/general.php | 273 +++++---- theme/formal_white/layout/report.php | 127 ---- theme/formal_white/lib.php | 116 ++-- theme/formal_white/pix/custommenubg.jpg | Bin 0 -> 346 bytes theme/formal_white/pix/dock_removeall.png | Bin 197 -> 0 bytes theme/formal_white/pix/gradient-sb.jpg | Bin 0 -> 13148 bytes theme/formal_white/pix/logo.jpg | Bin 7386 -> 50738 bytes theme/formal_white/pix/movedock.png | Bin 267 -> 0 bytes theme/formal_white/pix/sprite.png | Bin 0 -> 3123 bytes theme/formal_white/settings.php | 59 +- theme/formal_white/style/base.css | 51 -- theme/formal_white/style/calendar.css | 53 ++ theme/formal_white/style/core.css | 543 ++++++++++++++++++ theme/formal_white/style/course.css | 65 ++- theme/formal_white/style/dock.css | 54 -- theme/formal_white/style/editor.css | 2 - theme/formal_white/style/formal_white.css | 88 +++ theme/formal_white/style/formalwhite.css | 135 ----- theme/formal_white/style/frame.css | 158 +++++ theme/formal_white/style/fw_corners.css | 66 --- theme/formal_white/style/general.css | 240 -------- theme/formal_white/style/menu.css | 39 ++ theme/formal_white/style/pagelayout.css | 105 ++++ theme/formal_white/style/quiz.css | 31 + theme/formal_white/style/settings.css | 11 - theme/formal_white/style/tabs.css | 171 ++++++ 31 files changed, 1914 insertions(+), 1121 deletions(-) mode change 100644 => 100755 theme/formal_white/config.php delete mode 100644 theme/formal_white/javascript/navigation.js mode change 100644 => 100755 theme/formal_white/lang/en/theme_formal_white.php create mode 100755 theme/formal_white/layout/embedded.php create mode 100755 theme/formal_white/layout/frontpage.php mode change 100644 => 100755 theme/formal_white/layout/general.php delete mode 100644 theme/formal_white/layout/report.php mode change 100644 => 100755 theme/formal_white/lib.php create mode 100755 theme/formal_white/pix/custommenubg.jpg delete mode 100644 theme/formal_white/pix/dock_removeall.png create mode 100644 theme/formal_white/pix/gradient-sb.jpg mode change 100644 => 100755 theme/formal_white/pix/logo.jpg delete mode 100644 theme/formal_white/pix/movedock.png create mode 100755 theme/formal_white/pix/sprite.png mode change 100644 => 100755 theme/formal_white/settings.php delete mode 100644 theme/formal_white/style/base.css create mode 100644 theme/formal_white/style/calendar.css create mode 100644 theme/formal_white/style/core.css mode change 100644 => 100755 theme/formal_white/style/course.css delete mode 100644 theme/formal_white/style/dock.css delete mode 100644 theme/formal_white/style/editor.css create mode 100755 theme/formal_white/style/formal_white.css delete mode 100644 theme/formal_white/style/formalwhite.css create mode 100755 theme/formal_white/style/frame.css delete mode 100644 theme/formal_white/style/fw_corners.css delete mode 100644 theme/formal_white/style/general.css create mode 100755 theme/formal_white/style/menu.css create mode 100755 theme/formal_white/style/pagelayout.css create mode 100755 theme/formal_white/style/quiz.css delete mode 100644 theme/formal_white/style/settings.css create mode 100644 theme/formal_white/style/tabs.css diff --git a/theme/formal_white/config.php b/theme/formal_white/config.php old mode 100644 new mode 100755 index f2fb140bf01..bc8d4cecfc0 --- a/theme/formal_white/config.php +++ b/theme/formal_white/config.php @@ -1,5 +1,7 @@ name = 'formal_white'; //////////////////////////////////////////////////// // Name of the theme. Most likely the name of // the directory in which this file resides. //////////////////////////////////////////////////// -$THEME->parents = array('canvas','base'); + +$THEME->parents = array('base','canvas'); ///////////////////////////////////////////////////// // Which existing theme(s) in the /theme/ directory // do you want this theme to extend. A theme can @@ -46,101 +50,113 @@ $THEME->parents = array('canvas','base'); // changes you want to your theme. //////////////////////////////////////////////////// -$THEME->sheets = array('dock','base','general','fw_corners','formalwhite','settings','course'); + +$THEME->parents_exclude_sheets = array( + 'canvas'=>array( + 'core', + 'pagelayout', + 'tabs', + ), +); +//////////////////////////////////////////////////// +// An array of stylesheets not to inherit from the +// themes parents +//////////////////////////////////////////////////// + + +$THEME->sheets = array('frame' ,'menu', 'course', + 'pagelayout','core', 'calendar', + 'tabs' ,'quiz', 'formal_white'); //////////////////////////////////////////////////// // Name of the stylesheet(s) you've including in // this theme's /styles/ directory. //////////////////////////////////////////////////// -$THEME->parents_exclude_sheets = array( - 'canvas'=>array( - 'tabs', - ), -); -$THEME->resource_mp3player_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'font=Arial&fontColour=3333FF&buffer=10&waitForPlay=no&autoPlay=yes'; -/// With this you can control the colours of the "big" MP3 player -/// that is used for MP3 resources. +$THEME->enable_dock = true; +//////////////////////////////////////////////////// +// Do you want to use the new navigation dock? +//////////////////////////////////////////////////// -$THEME->filter_mediaplugin_colors = - 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'waitForPlay=yes'; -/// ...And this controls the small embedded player +$THEME->editor_sheets = array('editor'); +//////////////////////////////////////////////////// +// An array of stylesheets to include within the +// body of the editor. +//////////////////////////////////////////////////// + $THEME->layouts = array( - // Most pages - if we encounter an unknown or a missing page type, this one is used. 'base' => array( 'file' => 'general.php', - 'regions' => array() + 'regions' => array('side-pre', 'side-post'), + 'defaultregion' => 'side-post', ), - 'standard' => array( + 'general' => array( 'file' => 'general.php', - 'regions' => array('side-post'), - 'defaultregion' => 'side-post' + 'regions' => array('side-pre', 'side-post'), + 'defaultregion' => 'side-post', ), - // Course page 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-post', + 'options' => array('langmenu'=>true), ), - // Course page 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-post', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-post', ), 'frontpage' => array( - 'file' => 'general.php', + 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-pre' + 'defaultregion' => 'side-post', + 'options' => array('langmenu'=>true), ), 'admin' => array( 'file' => 'general.php', 'regions' => array('side-pre'), - 'defaultregion' => 'side-pre' + 'defaultregion' => 'side-pre', ), 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-post', + 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-post', ), 'login' => array( 'file' => 'general.php', - 'regions' => array() + 'regions' => array(), + 'options' => array('langmenu'=>true), ), // Pages that appear in pop-up windows - no navigation, no blocks, no header. 'popup' => array( - 'file' => 'general.php', + 'file' => 'embedded.php', 'regions' => array(), - 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'noblocks'=>true), + 'options' => array('nofooter'=>true, 'noblocks'=>true, 'nonavbar'=>true), ), // No blocks and minimal footer - used for legacy frame layouts only! 'frametop' => array( 'file' => 'general.php', 'regions' => array(), - 'options' => array('nofooter', 'noblocks'=>true), + 'options' => array('nofooter'=>true), ), - // Embeded pages, like iframe embeded in moodleform + // Embeded pages, like iframe embeded in moodleform (chat) 'embedded' => array( - 'file' => 'general.php', + 'file' => 'embedded.php', 'regions' => array(), - 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'noblocks'=>true), + 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true), ), // Used during upgrade and install, and for the 'This site is undergoing maintenance' message. // This must not have any blocks, and it is good idea if it does not have links to @@ -148,7 +164,7 @@ $THEME->layouts = array( 'maintenance' => array( 'file' => 'general.php', 'regions' => array(), - 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'noblocks'=>true), + 'options' => array('nofooter'=>true, 'nonavbar'=>true), ), // Should display the content and basic headers only. 'print' => array( @@ -157,19 +173,98 @@ $THEME->layouts = array( 'options' => array('nofooter'=>true, 'nonavbar'=>false, 'noblocks'=>true), ), 'report' => array( - 'file' => 'report.php', + 'file' => 'general.php', 'regions' => array('side-pre'), - 'defaultregion' => 'side-pre' + 'defaultregion' => 'side-pre', ), ); +/////////////////////////////////////////////////////////////// +// These are all of the possible layouts in Moodle. The +// simplest way to do this is to keep the theme and file +// variables the same for every layout. Including them +// all in this way allows some flexibility down the road +// if you want to add a different layout template to a +// specific page. +/////////////////////////////////////////////////////////////// -$THEME->rendererfactory = 'theme_overridden_renderer_factory'; -$THEME->enable_dock = true; -$THEME->javascripts_footer = array('navigation'); -/** - * Sets the function that will replace our settings within the CSS - */ -$THEME->csspostprocess = 'formalwhite_process_css'; +$THEME->csspostprocess = 'formal_white_user_settings'; +//////////////////////////////////////////////////// +// Allows the user to provide the name of a function +// that all CSS should be passed to before being +// delivered. +//////////////////////////////////////////////////// -$THEME->editor_sheets = array('editor'); \ No newline at end of file + +// $THEME->filter_mediaplugin_colors +//////////////////////////////////////////////////// +// Used to control the colours used in the small +// media player for the filters +//////////////////////////////////////////////////// + + +// $THEME->javascripts +//////////////////////////////////////////////////// +// An array containing the names of JavaScript files +// located in /javascript/ to include in the theme. +// (gets included in the head) +//////////////////////////////////////////////////// + + +// $THEME->javascripts_footer +//////////////////////////////////////////////////// +// As above but will be included in the page footer. +//////////////////////////////////////////////////// + + +//$THEME->larrow = "<"; +//////////////////////////////////////////////////// +// Overrides the left arrow image used throughout +// Moodle +//////////////////////////////////////////////////// + + +//$THEME->rarrow = ">"; +//////////////////////////////////////////////////// +// Overrides the right arrow image used throughout Moodle +//////////////////////////////////////////////////// + + +// $THEME->layouts +//////////////////////////////////////////////////// +// An array setting the layouts for the theme +//////////////////////////////////////////////////// + + +// $THEME->parents_exclude_javascripts +//////////////////////////////////////////////////// +// An array of JavaScript files NOT to inherit from +// the themes parents +//////////////////////////////////////////////////// + + +// $THEME->parents_exclude_sheets +//////////////////////////////////////////////////// +// An array of stylesheets not to inherit from the +// themes parents +//////////////////////////////////////////////////// + + +// $THEME->plugins_exclude_sheets +//////////////////////////////////////////////////// +// An array of plugin sheets to ignore and not +// include. +//////////////////////////////////////////////////// + + +// $THEME->rendererfactory +//////////////////////////////////////////////////// +// Sets a custom render factory to use with the +// theme, used when working with custom renderers. +//////////////////////////////////////////////////// + + +// $THEME->resource_mp3player_colors +//////////////////////////////////////////////////// +// Controls the colours for the MP3 player +//////////////////////////////////////////////////// \ No newline at end of file diff --git a/theme/formal_white/javascript/navigation.js b/theme/formal_white/javascript/navigation.js deleted file mode 100644 index 1f6b1e19169..00000000000 --- a/theme/formal_white/javascript/navigation.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Customises the dock for the fw theme and does some other cool stuff - */ -function customise_dock_for_theme() { - // If we don't have M.core_dock or Y then bail - if (!M.core_dock) { - return false; - } - // Change the defautl remove all icon to work with our black dock - M.core_dock.cfg.display.removeallicon = M.util.image_url('dock_removeall', 'theme'); - - // On draw completed add the ability to move the dock to from the left to the right - M.core_dock.on('dock:drawcompleted', fw.dock.enable_side_switching, fw.dock); - // When the dock is first drawn check to see if it should be moved - M.core_dock.on('dock:drawstarted', fw.dock.check_initial_position, fw.dock); - // Corrects the panel x position for the theme - M.core_dock.on('dock:itemadded', function(item) { - item.on('dockeditem:showstart', fw.dock.correct_panel_x_position, fw.dock, item); - item.on('dockeditem:resizecomplete', fw.dock.correct_panel_x_position, fw.dock, item); - }); - - // Override the default fix_title_orientation method with our fw method - // this will use SVG and rotate the text if possible. - M.core_dock.genericblock.prototype.fix_title_orientation = fw.dock.fix_title_orientation; - M.core_dock.genericblock.prototype.resize_block_space = fw.dock.resize_block_space; - return true; -} - -var fw = (function(){ - return { - namespaces : { - svg : 'http://www.w3.org/2000/svg' - }, - dock : { - enable_side_switching : function() { - var movedock = M.core_dock.Y.Node.create(''); - var c = M.core_dock.node.one('.controls'); - c.insertBefore(M.core_dock.Y.Node.create('
'), c.one('img')); - c.insertBefore(movedock, c.one('br')); - movedock.on('click', this.switch_dock_side); - }, - correct_panel_x_position : function(item) { - var dockoffset = M.core_dock.Y.one('#dock_item_'+item.id+'_title').get('offsetWidth'); - var panelwidth = M.core_dock.Y.one(item.panel.body).get('offsetWidth'); - var screenwidth = parseInt(M.core_dock.Y.get(document.body).get('winWidth')); - switch (M.core_dock.cfg.position) { - case 'left': - item.panel.cfg.setProperty('x', dockoffset); - break; - case 'right': - item.panel.cfg.setProperty('x', (screenwidth-panelwidth-dockoffset-5)); - break; - } - }, - switch_dock_side : function () { - var oldorientation = M.core_dock.cfg.orientation; - var oldclass = M.core_dock.cfg.css.dock+'_'+M.core_dock.cfg.position+'_'+oldorientation; - switch (M.core_dock.cfg.position) { - case 'right': - M.core_dock.cfg.position = 'left'; - M.core_dock.cfg.orientation = 'vertical'; - break; - case 'left': - M.core_dock.cfg.position = 'right'; - M.core_dock.cfg.orientation = 'vertical'; - break; - } - var newclass = M.core_dock.cfg.css.dock+'_'+M.core_dock.cfg.position+'_'+M.core_dock.cfg.orientation; - M.core_dock.node.replaceClass(oldclass, newclass); - M.core_dock.Y.Cookie.set('dock_position', M.core_dock.cfg.position); - }, - check_initial_position : function () { - var cookieposition = M.core_dock.Y.Cookie.get('dock_position'); - if (cookieposition && cookieposition != 'null' && cookieposition !== M.core_dock.cfg.position) { - var oldclass = M.core_dock.cfg.css.dock+'_'+M.core_dock.cfg.position+'_'+M.core_dock.cfg.orientation; - M.core_dock.cfg.position = cookieposition; - if (M.core_dock.node) { - var newclass = M.core_dock.cfg.css.dock+'_'+M.core_dock.cfg.position+'_'+M.core_dock.cfg.orientation; - M.core_dock.node.replaceClass(oldclass, newclass); - } - } - }, - fix_title_orientation : function (node) { - if (M.core_dock.cfg.orientation == 'vertical') { - return fw.transform.make_vertical_text(node); - } - return node; - }, - resize_block_space : function (node) { - var blockregions = { - pre: {hasblocks:true,c:'side-pre-only'}, - post: {hasblocks:true,c:'side-post-only'}, - noblocksc:'noblocks' - }; - M.core_dock.Y.all('div.block-region').each(function(blockregion){ - if (blockregion.hasClass('side-pre') && blockregion.all('.block').size() == 0) { - blockregions.pre.hasblocks = false; - } else if (blockregion.hasClass('side-post') && blockregion.all('.block').size() == 0) { - blockregions.post.hasblocks = false; - } - }); - if (blockregions.pre.hasblocks && blockregions.post.hasblocks) { - // No classes required both regions have blocks - M.core_dock.Y.one(document.body).removeClass(blockregions.pre.c).removeClass(blockregions.post.c).removeClass(blockregions.noblocksc); - } else if (blockregions.pre.hasblocks) { - // side-pre-only required: remove any other classes - M.core_dock.Y.one(document.body).addClass(blockregions.pre.c).removeClass(blockregions.post.c).removeClass(blockregions.noblocksc); - } else if (blockregions.post.hasblocks) { - // side-post-only required: remove any other classes - M.core_dock.Y.one(document.body).removeClass(blockregions.pre.c).addClass(blockregions.post.c).removeClass(blockregions.noblocksc); - } else { - // All blocks have been docked: add noblocks remove side-xxx-only's if set - M.core_dock.Y.one(document.body).removeClass(blockregions.pre.c).removeClass(blockregions.post.c).addClass(blockregions.noblocksc); - } - return '200px'; - } - }, - transform : { - make_vertical_text : function(node) { - - if (YAHOO.env.ua.ie > 0) { - if (YAHOO.env.ua.ie > 7) { - node.setAttribute('style', 'writing-mode: tb-rl; filter: flipV flipH;'); - } else { - node.innerHTML = node.innerHTML.replace(/(.)/g, "$1
"); - } - return node; - } - - var test = M.core_dock.Y.Node.create('
'+node.firstChild.nodeValue+'
'); - M.core_dock.Y.one(document.body).append(test); - var height = test.one('span').get('offsetWidth'); - test.remove(); - - var txt = document.createElementNS(fw.namespaces.svg, 'text'); - txt.setAttribute('x', '0'); - txt.setAttribute('y', '0'); - txt.setAttribute('transform','rotate(90, 5, 5)'); - txt.appendChild(document.createTextNode(node.firstChild.nodeValue)); - - var svg = document.createElementNS(fw.namespaces.svg, 'svg'); - svg.setAttribute('version', '1.1'); - svg.setAttribute('height', height); - svg.setAttribute('width', 30); - svg.appendChild(txt); - - var div = document.createElement(node.nodeName); - div.appendChild(svg); - - return div; - } - } - } -})(); \ No newline at end of file diff --git a/theme/formal_white/lang/en/theme_formal_white.php b/theme/formal_white/lang/en/theme_formal_white.php old mode 100644 new mode 100755 index 1905fe5146a..accb3b0e1f4 --- a/theme/formal_white/lang/en/theme_formal_white.php +++ b/theme/formal_white/lang/en/theme_formal_white.php @@ -23,54 +23,74 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['pluginname'] = 'Formal white'; +$string['region-side-post'] = 'Right'; +$string['region-side-pre'] = 'Left'; + $string['choosereadme'] = '
- +

Formal White

- +

Theme Discussion Forum:

http://moodle.org/mod/forum/view.php?id=46

- +

Theme Credits

http://docs.moodle.org/en/Theme_credits

- +

Theme Documentation:

http://docs.moodle.org/en/Themes

- +

Report a bug:

http://tracker.moodle.org

- +
- +

About

Formal White is a fluid-width, three-column theme ported over to 2.0 from Moodle 1.X.

- +

Tweaks

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it, then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

Credits

-

This theme was coded and is maintained by MediaTouch 2000.

+

This theme was coded and is maintained by MediaTouch 2000.

License

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License.

'; +$string['configtitle'] = 'Formal white theme'; -$string['pluginname'] = 'Formal white'; +$string['noframe'] = 'Formal white 1.9 look'; +$string['noframedesc'] = 'Select this option to require your moodle page to look like moodle 1.*, alias, without the surrounding frame.'; + +$string['displaylogo'] = 'Pages header content'; +$string['displaylogodesc'] = 'Choose whether display moodle logo or page heading text in the header.'; +$string['moodlelogo'] = 'Display moodle logo'; +$string['heading'] = 'Display page heading'; + +$string['blockcolumnwidth'] = 'Blocks colum width'; +$string['blockcolumnwidthdesc'] = 'This sets the blocks column width for the theme. Using widths lower than 200px, the calendar block is not supposed to fit.'; + +$string['blockcontentbgc'] = 'Blocks content background colour'; +$string['blockcontentbgcdesc'] = 'This sets the blocks content background colour for the theme.'; + +$string['blockcolumnbgc'] = 'Blocks columns background colour'; +$string['blockcolumnbgcdesc'] = 'This sets the blocks columns background colour for the theme.'; + +$string['configtitle'] = 'formal_white settings'; -$string['backgroundcolor'] = 'Blocks background colour'; -$string['backgroundcolordesc'] = 'This sets the blocks background colour for the theme.'; -$string['configtitle'] = 'Formal_white settings'; $string['customcss'] = 'Custom CSS'; $string['customcssdesc'] = 'Any CSS you enter here will be added to every page allowing your to easily customise this theme.'; + $string['footnote'] = 'Footnote'; $string['footnotedesc'] = 'The content from this textarea will be displayed in the footer of every page.'; -$string['logo'] = 'Logo'; -$string['logodesc'] = 'Enter the URL to an image to use as the logo for this site. Should be http://www.yoursite.com/path/to/logo.png
Preferred picture height is 100 pixels'; + +$string['logo'] = 'logo'; +$string['logodesc'] = 'Change the logo of this theme by entering the URL to a new one (i.e., http://www.somesite/animage.png). As a reference, the default logo is 300px wide by 80px high. A transparent .png will work best.
The chosen logo will be shown in each page of the site without any distinction between front page and other pages.'; + $string['regionwidth'] = 'Column width'; $string['regionwidthdesc'] = 'This sets the width of the two block regions that form the left and right columns.'; -$string['alwayslangmenu'] = 'Display languages menu'; -$string['alwayslangmenudesc'] = 'Select this option to ALWAYS display lang menu. Take care that lang menu will be shown only if your site managess more than a single language.'; diff --git a/theme/formal_white/layout/embedded.php b/theme/formal_white/layout/embedded.php new file mode 100755 index 00000000000..7aca05a0149 --- /dev/null +++ b/theme/formal_white/layout/embedded.php @@ -0,0 +1,34 @@ +doctype() ?> +htmlattributes() ?>> + + <?php echo $PAGE->title ?> + + standard_head_html() ?> + + +standard_top_of_body_html(); ?> + +
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ +standard_end_of_body_html(); ?> + + \ No newline at end of file diff --git a/theme/formal_white/layout/frontpage.php b/theme/formal_white/layout/frontpage.php new file mode 100755 index 00000000000..3bdca7efa32 --- /dev/null +++ b/theme/formal_white/layout/frontpage.php @@ -0,0 +1,209 @@ +heading; +$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); +$hasfooter = (empty($PAGE->layout_options['nofooter'])); + +$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT); +$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT); + +$showsidepre = $hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT); +$showsidepost = $hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT); + +$custommenu = $OUTPUT->custom_menu(); +$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); + +$bodyclasses = array(); +if ($showsidepre && !$showsidepost) { + $bodyclasses[] = 'side-pre-only'; +} else if ($showsidepost && !$showsidepre) { + $bodyclasses[] = 'side-post-only'; +} else if (!$showsidepost && !$showsidepre) { + $bodyclasses[] = 'content-only'; +} + +if ($hascustommenu) { + $bodyclasses[] = 'has_custom_menu'; +} + + +/************************************************************************************************/ +if (!empty($PAGE->theme->settings->logo)) { + $logourl = $PAGE->theme->settings->logo; +} else { + $logourl = $OUTPUT->pix_url('logo', 'theme'); +} + +$hasframe = !isset($PAGE->theme->settings->noframe) || !$PAGE->theme->settings->noframe; + +$displaylogo = !isset($PAGE->theme->settings->displaylogo) || $PAGE->theme->settings->displaylogo; +/************************************************************************************************/ + +echo $OUTPUT->doctype() ?> +htmlattributes() ?>> + + <?php echo $PAGE->title ?> + + standard_head_html() ?> + + + standard_top_of_body_html(); + +if ($hasframe) { ?> +
+
 
+
+
+ + + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + +
+
+
+ +
+
+
+ + + + + +
+
+ blocks_for_region('side-pre') ?> +
+
+ + + + + +
+
+ blocks_for_region('side-post') ?> +
+
+ + + +
+
+
+ + +
+ + +
+
+
 
+
+ + + + + +standard_end_of_body_html(); ?> + + \ No newline at end of file diff --git a/theme/formal_white/layout/general.php b/theme/formal_white/layout/general.php old mode 100644 new mode 100755 index dde5944cace..6d8e0c14201 --- a/theme/formal_white/layout/general.php +++ b/theme/formal_white/layout/general.php @@ -1,13 +1,16 @@ heading); +defined('MOODLE_INTERNAL') || die(); + +$hasheading = $PAGE->heading; $hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); $hasfooter = (empty($PAGE->layout_options['nofooter'])); -$hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); -$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); -$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); -$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); +$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT); +$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT); + +$showsidepre = $hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT); +$showsidepost = $hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT); $custommenu = $OUTPUT->custom_menu(); $hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); @@ -20,21 +23,23 @@ if ($showsidepre && !$showsidepost) { } else if (!$showsidepost && !$showsidepre) { $bodyclasses[] = 'content-only'; } + if ($hascustommenu) { $bodyclasses[] = 'has_custom_menu'; } + +/************************************************************************************************/ if (!empty($PAGE->theme->settings->logo)) { $logourl = $PAGE->theme->settings->logo; } else { - $logourl = $OUTPUT->pix_url('logo', 'theme'); + $logourl = $OUTPUT->pix_url('logo_small', 'theme'); } -if (!empty($PAGE->theme->settings->footnote)) { - $footnote = $PAGE->theme->settings->footnote; -} else { - $footnote = ''; -} +$hasframe = !isset($PAGE->theme->settings->noframe) || !$PAGE->theme->settings->noframe; + +$displaylogo = !isset($PAGE->theme->settings->displaylogo) || $PAGE->theme->settings->displaylogo; +/************************************************************************************************/ echo $OUTPUT->doctype() ?> htmlattributes() ?>> @@ -44,101 +49,161 @@ echo $OUTPUT->doctype() ?> standard_head_html() ?> -standard_top_of_body_html() ?> -
-
-
 
-
-
-
- -
-
+ standard_top_of_body_html(); - -
'; - echo '
'; - echo $OUTPUT->login_info(); - if (!empty($PAGE->theme->settings->alwayslangmenu)) { - echo $OUTPUT->lang_menu(); - } - echo $PAGE->headingmenu; - echo '
'; // closes:
- - echo '
'; // closes:
- echo '
'; // closes:
- - if ($hascustommenu) { - echo '
'.$custommenu.'
'; - } - - //Accessibility: breadcrumb trail/navbar now a DIV, not a table. - if ($hasnavbar) { - echo ''; - } - - } ?> - - - -
- -
-
- -
-
-
- -
-
-
- - -
-
- blocks_for_region('side-pre') ?> -
-
- - - -
-
- blocks_for_region('side-post') ?> -
-
- - -
-
- -
- -
-
-
- -
-
- - - - +if ($hasframe) { ?> +
+
 
+
+
-standard_end_of_body_html() ?> + + + + + + + + +
+ + + + + + + + + + +
+
+
+ + +
+
+
+ +
+
+
+ + + + + +
+
+ blocks_for_region('side-pre') ?> +
+
+ + + + + +
+
+ blocks_for_region('side-post') ?> +
+
+ + + +
+
+
+ + +
+ + +
+
+
 
+
+ + + + + +standard_end_of_body_html(); ?> \ No newline at end of file diff --git a/theme/formal_white/layout/report.php b/theme/formal_white/layout/report.php deleted file mode 100644 index ca1a082564f..00000000000 --- a/theme/formal_white/layout/report.php +++ /dev/null @@ -1,127 +0,0 @@ -heading); -$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); -$hasfooter = (empty($PAGE->layout_options['nofooter'])); -$hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); -$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); - -$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); -$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); - -$custommenu = $OUTPUT->custom_menu(); -$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); - -$bodyclasses = array(); -if ($showsidepre && !$showsidepost) { - $bodyclasses[] = 'side-pre-only'; -} else if ($showsidepost && !$showsidepre) { - $bodyclasses[] = 'side-post-only'; -} else if (!$showsidepost && !$showsidepre) { - $bodyclasses[] = 'content-only'; -} -if ($hascustommenu) { - $bodyclasses[] = 'has_custom_menu'; -} - -if (!empty($PAGE->theme->settings->logo)) { - $logourl = $PAGE->theme->settings->logo; -} else { - $logourl = $OUTPUT->pix_url('logo', 'theme'); -} - -if (!empty($PAGE->theme->settings->footnote)) { - $footnote = $PAGE->theme->settings->footnote; -} else { - $footnote = ''; -} - -echo $OUTPUT->doctype() ?> -htmlattributes() ?>> - - <?php echo $PAGE->title ?> - - standard_head_html() ?> - - -standard_top_of_body_html() ?> -
-
-
 
-
-
-
- -
-
- - -
'; - echo '
'; - echo $OUTPUT->login_info(); - if (!empty($PAGE->theme->settings->alwayslangmenu)) { - echo $OUTPUT->lang_menu(); - } - echo $PAGE->headingmenu; - echo '
'; // closes:
- - echo '
'; // closes:
- echo '
'; // closes:
- - if ($hascustommenu) { - echo '
'.$custommenu.'
'; - } - - //Accessibility: breadcrumb trail/navbar now a DIV, not a table. - if ($hasnavbar) { - echo ''; - } - - } ?> - - - -
-
-
- -
-
- -
-
-
- blocks_for_region('side-pre') ?> -
-
-
- -
- -
-
-
- -
-
- - - - - - -standard_end_of_body_html() ?> - - \ No newline at end of file diff --git a/theme/formal_white/lib.php b/theme/formal_white/lib.php old mode 100644 new mode 100755 index 907dd6fb8a7..b931381eebc --- a/theme/formal_white/lib.php +++ b/theme/formal_white/lib.php @@ -1,5 +1,7 @@ settings->backgroundcolor)) { - $backgroundcolor = $theme->settings->backgroundcolor; + // Set the block content background color + if (empty($theme->settings->blockcontentbgc)) { + $blockcontentbgc = '#F6F6F6'; // default (o forse è meglio #FEF9F6?) } else { - $backgroundcolor = null; + $blockcontentbgc = $theme->settings->blockcontentbgc; } - $css = formalwhite_set_backgroundcolor($css, $backgroundcolor); + $css = formal_white_set_blockcontentbgc($css, $blockcontentbgc); - // Set the region width - if (!empty($theme->settings->regionwidth)) { - $regionwidth = $theme->settings->regionwidth; + // Set the block column background color + if (empty($theme->settings->blockcolumnbgc)) { + $blockcolumnbgc = '#E3DFD4'; // default } else { - $regionwidth = null; + $blockcolumnbgc = $theme->settings->blockcolumnbgc; } - $css = formalwhite_set_regionwidth($css, $regionwidth); + $css = formal_white_set_blockcolumnbgc($css, $blockcolumnbgc); - // Set the custom CSS - if (!empty($theme->settings->customcss)) { - $customcss = $theme->settings->customcss; + // Set the logo image + if (!empty($theme->settings->logo)) { + $logo = $theme->settings->logo; } else { - $customcss = null; + $logo = null; } - $css = formalwhite_set_customcss($css, $customcss); + $css = formal_white_set_logo($css, $logo); + + // set the width of the two blocks colums + if (!empty($theme->settings->blockcolumnwidth)) { + $blockcolumnwidth = $theme->settings->blockcolumnwidth; + } else { + $blockcolumnwidth = '200'; // default + } + $css = formal_white_set_blockcolumnwidth($css, $blockcolumnwidth); // Return the CSS return $css; } + + /** - * Sets the background colour variable in CSS + * Sets the link color variable in CSS * - * @param string $css - * @param mixed $backgroundcolor - * @return string */ -function formalwhite_set_backgroundcolor($css, $backgroundcolor) { - $tag = '[[setting:backgroundcolor]]'; - $replacement = $backgroundcolor; - if (is_null($replacement)) { - $replacement = '#F7F6F1'; - } - $css = str_replace($tag, $replacement, $css); +function formal_white_set_blockcontentbgc($css, $blockcontentbgc) { + $tag = '[[setting:blockcontentbgc]]'; + $css = str_replace($tag, $blockcontentbgc, $css); return $css; } -/** - * Sets the region width variable in CSS - * - * @param string $css - * @param mixed $regionwidth - * @return string - */ -function formalwhite_set_regionwidth($css, $regionwidth) { - $tag = '[[setting:regionwidth]]'; - $doubletag = '[[setting:regionwidthdouble]]'; - $replacement = $regionwidth; - if (is_null($replacement)) { - $replacement = 200; - } - $css = str_replace($tag, $replacement.'px', $css); - $css = str_replace($doubletag, ($replacement*2).'px', $css); - $css = str_replace($tag, ($replacement+10).'px', $css); +function formal_white_set_blockcolumnbgc($css, $blockcolumnbgc) { + $tag = '[[setting:blockcolumnbgc]]'; + $css = str_replace($tag, $blockcolumnbgc, $css); return $css; } -/** - * Sets the custom css variable in CSS - * - * @param string $css - * @param mixed $customcss - * @return string - */ -function formalwhite_set_customcss($css, $customcss) { - $tag = '[[setting:customcss]]'; - $replacement = $customcss; - if (is_null($replacement)) { - $replacement = ''; - } - $css = str_replace($tag, $replacement, $css); - return $css; +function formal_white_set_logo($css, $logo) { + global $OUTPUT; + + $tag = '[[setting:logo]]'; + if (is_null($logo)) { + $logo = $OUTPUT->pix_url('logo', 'theme'); + } + $css = str_replace($tag, $logo, $css); + return $css; +} + +function formal_white_set_blockcolumnwidth($css, $blockcolumnwidth) { + $tag = '[[setting:blockcolumnwidth]]'; + $css = str_replace($tag, $blockcolumnwidth.'px', $css); + + $tag = '[[setting:minusdoubleblockcolumnwidth]]'; + $css = str_replace($tag, (-2*$blockcolumnwidth).'px', $css); + + $tag = '[[setting:doubleblockcolumnwidth]]'; + $css = str_replace($tag, (2*$blockcolumnwidth).'px', $css); + + return $css; } \ No newline at end of file diff --git a/theme/formal_white/pix/custommenubg.jpg b/theme/formal_white/pix/custommenubg.jpg new file mode 100755 index 0000000000000000000000000000000000000000..96825ddc1ca224258c291f91afbb44a4d899a5ed GIT binary patch literal 346 zcmex= Y+Zi>Vo?H8Pqc~4?vrG!e5c~f(0fk5}tpET3 literal 0 HcmV?d00001 diff --git a/theme/formal_white/pix/dock_removeall.png b/theme/formal_white/pix/dock_removeall.png deleted file mode 100644 index 6b1c076d040bced9632d2b4048b7b4772962aa69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=%3?!FCJ6-`&jKx9jP7LeL$-D$|_yc@GTvJPQ z8IJvDSpV(uB*-tA!Qt7BG!Q4r+uensgH_f8$l)yTh%9Dc;1&j9 zMuu5)B!GhKC7!;n?6;U$**O`WJ(^t(6jJhZaSY+Oo}AFYASSM+s>;eHmZrwW#&}6H hE!oY{k#R*NLs&QCgS$@+{sUDrc)I$ztaD0e0s!A7GgSZp diff --git a/theme/formal_white/pix/gradient-sb.jpg b/theme/formal_white/pix/gradient-sb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6332f0bff26cb9fa0a1e3e5639473e4565db3cbc GIT binary patch literal 13148 zcmeI3%Wm306o&0U>V%7m8xp0Fh$e0qT@-8#3B>}^hzO-osj4PYtFG$U6G8#oGL9hG zG>_0{>9&h@(TC_|lRiNnfsTQ2QQM&s2O(J!(D81dR zDpjXUPwIQ;EglB0YFcfrTa^06H8%IdvPAk4uThkC z{I29(^))HmE+yGiI%z1GEXi)A)SQ~nZ9OFix<~ePi>NuGDhhk3S~{&|(_}cLQi#n8 zu6eAz*{uwFvQ<$U9rPrwZ z(V?}1JdWPF!NInfFPJaokuk6LK6;mTG8u!vlk$V2*aQR@aUm`c0gxEog}6WjKw@+k z;sOx>iP2q%3q$}UMt31D5CM=F-G#V71VCbR7vcgD0Ey9EhzmpjBt~~3E)W5b7~O@q zKmiEnjRXnfU!TI_yDhh608{o%@-5DW(AgTnm05E9rgvM30P zk!Uy^35TO%v_Hh?{g@cLAC1RXR^svXL?W>+jfP)@Ul4?7B)S@lt*$ML%WG5H-WaSl zHv9>D_QxoFFzJ2g#0Bml_awlJ+?>bHlFQUsdcflG z*(kdN!=mDhmPLPakpL?%21IU~yZSQsd~cB_t(QyWaq!}E<}$)xsP}e0unwPkzy1L= Cy6vO@ literal 0 HcmV?d00001 diff --git a/theme/formal_white/pix/logo.jpg b/theme/formal_white/pix/logo.jpg old mode 100644 new mode 100755 index 88879ef11605512ecae094b8dbd16daeb70048f3..905b197c45c20444a69f4c238389dc0f6f99f2e4 GIT binary patch literal 50738 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 BJ7NF; diff --git a/theme/formal_white/pix/movedock.png b/theme/formal_white/pix/movedock.png deleted file mode 100644 index bae6a20b0ccf0cd1bdb4c82beef881ff96a672a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 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 literal 0 HcmV?d00001 diff --git a/theme/formal_white/settings.php b/theme/formal_white/settings.php old mode 100644 new mode 100755 index f210c6ecf88..0aaeee97921 --- a/theme/formal_white/settings.php +++ b/theme/formal_white/settings.php @@ -8,49 +8,70 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { - // Background colour setting - $name = 'theme_formal_white/backgroundcolor'; - $title = get_string('backgroundcolor','theme_formal_white'); - $description = get_string('backgroundcolordesc', 'theme_formal_white'); - $default = '#F7F6F1'; + // moodle 1.* like setting + $name = 'theme_formal_white/noframe'; + $title = get_string('noframe','theme_formal_white'); + $description = get_string('noframedesc', 'theme_formal_white'); + $setting = new admin_setting_configcheckbox($name, $title, $description, 0); + $settings->add($setting); + + // Block background colour setting + $name = 'theme_formal_white/blockcontentbgc'; + $title = get_string('blockcontentbgc','theme_formal_white'); + $description = get_string('blockcontentbgcdesc', 'theme_formal_white'); + $default = '#F6F6F6'; $previewconfig = array('selector'=>'.block .content', 'style'=>'backgroundColor'); $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, $previewconfig); $settings->add($setting); + // Block cloumns colour setting + $name = 'theme_formal_white/blockcolumnbgc'; + $title = get_string('blockcolumnbgc','theme_formal_white'); + $description = get_string('blockcolumnbgcdesc', 'theme_formal_white'); + $default = '#E3DFD4'; + $previewconfig = array('selector'=>'#page-content, #page-content #region-pre, #page-content #region-post-box', 'style'=>'backgroundColor'); + $setting = new admin_setting_configcolourpicker($name, $title, $description, $default, $previewconfig); + $settings->add($setting); + + // display logo or heading + $name = 'theme_formal_white/displaylogo'; + $title = get_string('displaylogo','theme_formal_white'); + $description = get_string('displaylogodesc', 'theme_formal_white'); + $default = '1'; + $choices = array(1=>get_string('moodlelogo', 'theme_formal_white'),0=>get_string('heading', 'theme_formal_white')); + $setting = new admin_setting_configselect($name, $title, $description, $default, $choices); + $settings->add($setting); + // Logo file setting $name = 'theme_formal_white/logo'; $title = get_string('logo','theme_formal_white'); $description = get_string('logodesc', 'theme_formal_white'); - $setting = new admin_setting_configtext($name, $title, $description, '', PARAM_URL); + $default = ''; + $setting = new admin_setting_configtext($name, $title, $description, $default, PARAM_URL); $settings->add($setting); // Block region width - $name = 'theme_formal_white/regionwidth'; - $title = get_string('regionwidth','theme_formal_white'); - $description = get_string('regionwidthdesc', 'theme_formal_white'); - $default = 200; + $name = 'theme_formal_white/blockcolumnwidth'; + $title = get_string('blockcolumnwidth','theme_formal_white'); + $description = get_string('blockcolumnwidthdesc', 'theme_formal_white'); + $default = '200'; $choices = array(150=>'150px', 170=>'170px', 200=>'200px', 240=>'240px', 290=>'290px', 350=>'350px', 420=>'420px'); $setting = new admin_setting_configselect($name, $title, $description, $default, $choices); $settings->add($setting); - // alwayslangmenu setting - $name = 'theme_formal_white/alwayslangmenu'; - $title = get_string('alwayslangmenu','theme_formal_white'); - $description = get_string('alwayslangmenudesc', 'theme_formal_white'); - $setting = new admin_setting_configcheckbox($name, $title, $description, 0); - $settings->add($setting); - // Foot note setting $name = 'theme_formal_white/footnote'; $title = get_string('footnote','theme_formal_white'); $description = get_string('footnotedesc', 'theme_formal_white'); - $setting = new admin_setting_confightmleditor($name, $title, $description, ''); + $default = ''; + $setting = new admin_setting_confightmleditor($name, $title, $description, $default); $settings->add($setting); // Custom CSS file $name = 'theme_formal_white/customcss'; $title = get_string('customcss','theme_formal_white'); $description = get_string('customcssdesc', 'theme_formal_white'); - $setting = new admin_setting_configtextarea($name, $title, $description, ''); + $default = ''; + $setting = new admin_setting_configtextarea($name, $title, $description, $default); $settings->add($setting); } \ No newline at end of file diff --git a/theme/formal_white/style/base.css b/theme/formal_white/style/base.css deleted file mode 100644 index 8949a13d77d..00000000000 --- a/theme/formal_white/style/base.css +++ /dev/null @@ -1,51 +0,0 @@ -body, div, p, li, input, option, textarea {font-size:10pt;line-height:1.5em;} -body, div, p, li, input, option, textarea, h1, h2, h3, h4, h5 {font-family:Arial, Helvetica, sans-serif;} - -h1.main, h2.main, h3.main, h4.main, h5.main, h6.main {text-align:center;} - -.generalbox {padding:10px;margin-bottom:15px;} -.generaltable, .userinfobox {margin-left:auto;margin-right:auto;} -#notice.generalbox {margin-left: auto;margin-right: auto;width: 60%;} -.notifyproblem {padding:10px;color:#660000;text-align:center;} -.notifysuccess {padding:10px;color:#006600;text-align:center;} - -.paging {text-align:center;} - -/** - * Tabs - */ -.tabtree {position:relative;margin-bottom:3.5em;} -.tabtree .tabrow0 {text-align:center;width:100%;margin:1em 0px;} -.tabtree .tabrow0 li {display:inline;margin-right:-4px;} -.tabtree .tabrow0 li.here a {position:relative;z-index:102;} -.tabtree .tabrow0 li a {background-image:url([[pix:theme|tab/left]]);padding-left:14px;padding-top:10px;background-repeat:no-repeat;padding-bottom:3px;margin-bottom:-1px;} -.tabtree .tabrow0 li a:hover {background-image:url([[pix:theme|tab/left_hover]]);} -.tabtree .tabrow0 li a span { background-image:url([[pix:theme|tab/right]]);background-repeat:no-repeat;background-position:100% 0%;padding-right:14px;padding-top:10px;padding-bottom:3px;} -.tabtree .tabrow0 li a:hover span {background-image:url([[pix:theme|tab/right_hover]]);} -.tabtree .tabrow0 ul, -.tabtree .tabrow0 div {background-image:url([[pix:theme|tab/tabrow1]]);background-position:0% 50%;position:absolute;width:100%;border-top:1px solid #aaa;padding:0.25em 0px;top:100%;margin:0px;} -.tabtree .tabrow0 .empty {height:1px;overflow:hidden;padding:0px;position:absolute;} -.tabtree .tabrow1 li a, -.tabtree .tabrow1 li a:hover, -.tabtree .tabrow1 li a span, -.tabtree .tabrow1 li a:hover span {background-image:none !important;} - -.groupmanagementtable {width:90%;} -.groupmanagementtable td {vertical-align:top;border-width:0px;} -.groupmanagementtable td p {margin:0px;} - -.pagelayout-redirect #page {background-image:none;} - -.course_category_tree .category {margin: 5px;padding-left: 16px;} -.course_category_tree .category .course.odd {background-color: #E3DFD4;} -.course_category_tree .category .course.even {background-color: #EEE;} -.course_category_tree .category_link { - display: block; - font-size: 120%; - font-weight: bold; - margin: 5px; -} -/* la posizione del disclosure triangle */ -.course_category_tree .category.with_children .category_label { - background-position: 0px 3px; -} \ No newline at end of file diff --git a/theme/formal_white/style/calendar.css b/theme/formal_white/style/calendar.css new file mode 100644 index 00000000000..58459f8886c --- /dev/null +++ b/theme/formal_white/style/calendar.css @@ -0,0 +1,53 @@ +/* i nomi dei mesi */ +.path-calendar .minicalendarblock h3 {font-size:1.0em;margin:0;text-align:center;} + +/* spaziatura fra nome del mese e minicalendar corrispondente */ +.path-calendar .block .minicalendar {margin:5px 0 10px 0;} + +/* la quadrettatura del calendario */ +.path-calendar .calendartable th, +.path-calendar .calendartable td {border:1px [[setting:blockcolumnbgc]] solid;} + +/* il rilievo del giorno corrente nel minicalendar */ +/*.path-calendar .calendartable td.today {border:2px #444444 solid;}*/ +.path-calendar .minicalendar td.today {border:2px #444444 solid;} + +/* il bordo del generico evento nella lista a centro pagina */ +.path-calendar .maincalendar .eventlist .event {border: 1px [[setting:blockcolumnbgc]] solid;} + +/* se c'è una duration... nel minicalendar */ +.path-calendar .minicalendar .calendar_event_user, +.path-calendar .minicalendar .duration_user {border-bottom:2px #A1BECB dotted;} +.path-calendar .minicalendar .calendar_event_course, +.path-calendar .minicalendar .duration_course {border-bottom:2px #FF9966 dotted;} +.path-calendar .minicalendar .calendar_event_global, +.path-calendar .minicalendar .duration_global {border-bottom:2px #66D14D dotted;} +.path-calendar .minicalendar .calendar_event_group, +.path-calendar .minicalendar .duration_group {border-bottom:2px #FBBB23 dotted;} + +/* se c'è una duration... nel calendartable */ +/* attento: non servono perché potrei avere più di una duration */ +/* per questo la casella non va segnata con un border-bottom */ +/* ma vanno riporati gli eventi al suo interno */ + +.path-calendar .maincalendar .calendarmonth th, +.path-calendar .minicalendar th {background:url([[pix:theme|gradient-sb]]) repeat-x 0 0;} + +/* i settaggi del calendario del blocco */ + +/* la quadrettatura del calendario */ +.calendartable th, +.calendartable td {border:1px [[setting:blockcolumnbgc]] solid;} + +/* il rilievo del giorno corrente nel calendario del blocco */ +.calendartable .today {border:2px #444444 solid;} + +/* se c'è una duration... nel minicalendar */ +.calendartable .calendar_event_user, +.calendartable .duration_user {border-bottom:2px #A1BECB dotted;} +.calendartable .calendar_event_course, +.calendartable .duration_course {border-bottom:2px #FF9966 dotted;} +.calendartable .calendar_event_global, +.calendartable .duration_global {border-bottom:2px #66D14D dotted;} +.calendartable .calendar_event_group, +.calendartable .duration_group {border-bottom:2px #FBBB23 dotted;} \ No newline at end of file diff --git a/theme/formal_white/style/core.css b/theme/formal_white/style/core.css new file mode 100644 index 00000000000..7694614b9fe --- /dev/null +++ b/theme/formal_white/style/core.css @@ -0,0 +1,543 @@ +/************************************************************************ + Non sono riuscito a trovare un modo per sovrascrivere la regola + border: 2px solid #ddd; + presente nel file + /theme/canvas/style/core.css + Per questo questo file è stato creato a partire dalla copia del + foglio di stile core.css del tema canvas, ed è stato adeguato alle + esigenze del tema corrente. +************************************************************************/ + +.sitetopic { + border: none; +} + +.headingblock { + border-bottom: 1px solid #ddd; + font-size: 1.3em; + color: #333; +} + +#notice { + text-align: center; +} + +.noticebox, +.expired, +.notopenyet, +.notifysuccess, +.notifyproblem, +.errorbox, +.continuebutton, +.singlebutton, +.buttons, +.singleselect { + text-align: center; + margin: 1em 0; +} + +.navbutton .singlebutton { + margin: 0; +} + +.generalbox { + border-color: #ddd; +} + +.noticebox .generalbox { + border: none; + margin:2em 0; +} + +.expired, +.notopenyet { + border: none; + color: #f00; +} + +.buttons .singlebutton input { + margin: 0 1em; +} + +.initialbar { + text-align: center; +} + +.side-pre-only #page-content #region-main-box #region-post-box #region-main-wrap #region-main { + padding-right: 0; +} + +.side-post-only #page-content #region-main-box #region-post-box #region-main-wrap #region-main { + padding-left: 0; +} + +input[type="text"], +input[type="password"], +textarea { + width: auto; + padding: 2px 0 2px 0; + margin: 5px 0 5px 0; +} + +input[type="checkbox"], +input[type="radio"] { + margin-right: 7px; +} + +/* Login +------------------------*/ + +.loginbox { + margin: 15px 25%; +} + +.loginbox .loginerrors { + color: #f00; +} + +.loginbox .loginform { + margin: 15px auto 0; + width: 50%; +} + +.loginbox .loginform .form-label { + float: none; + width: 100%; + margin: 0 auto; + text-align: left; +} +.dir-rtl .loginbox .loginform .form-label { + text-align: right; +} +.loginbox .loginform .form-input { + float: none; + width: 100%; + margin: 0 auto; +} + +.loginbox .loginform .form-input #username, +.loginbox .loginform .form-input #password { + width: 50%; + color: #000; +} + +.loginbox .loginform .form-input #loginbtn { + margin: 0.5em auto; +} + +.loginbox .forgetpass { + margin: 1em 0 0; + font-size: 0.95em; +} + +.loginbox.twocolumns { + width: 90%; + margin-left: 5%; +} + +.loginbox .guestsub { + border-top: 1px solid #DDDDDD; + margin: 5px 20% +} + +.loginbox.twocolumns .loginpanel { + border-color: #ddd; + padding-right: 0.5%; +} + +.loginbox.twocolumns .signuppanel { + padding-left: 1%; + width: 48%; +} + +#page-course-loginas #notice { + border: none; +} + +#page-login-forgot_password .generalbox { + margin: 0 auto 1.5em; + width: 75%; + padding: 10px; +} + +#page-login-signup .mform { + width: 85%; + margin: 0 auto; +} + +#page-login-signup .mform .fitem .fitemtitle { + width: 20%; +} + +#page-login-signup .mform .fitem .felement { + margin-left: 21%; +} + +/* Admin management +-----------------------*/ +.plugincompattable { + font-size: 100%; + text-align: left; +} + +/* User +-----------------------*/ + +.userinfobox { +border-color: #ddd; +padding: 0 +} + +.userinfobox .content { + text-align: left; + padding-left:10px +} + +.userinfobox .links { + vertical-align: top; + background: #f4f4f4; + padding-left: 10px; +} + +.userinfobox .links a { + display: block; + text-align: left; + +} + +.profilepicture { + float: left; + margin-right: 10px; +} + +.descriptionbox { + margin-left: 110px; + border: 1px solid #ddd; + padding: 10px; +} + +.path-user .description { + padding-bottom: 15px; + border-bottom: 1px solid #eee; +} + +.userprofile .list { + margin-top: 10px; +} + +.userprofile .list td { + padding-top: 3px; + padding-bottom: 3px; +} + +.userprofile .list .c0 { + padding-left: 0; + font-weight: bold; +} + +#page-user-view .buttons { + text-align: center; + width: 70%; + margin: 0 auto; +} + +#page-user-view .buttons div { + padding: 0 0 10px; +} + +#page-user-index .controls { + width: 100% +} + +#page-user-index .controls .singleselect { + margin: 0; +} + +.rolesform { + text-align: center; + margin: 1em 0; +} + +#participantsform { + text-align: center; +} + +#participants { + width: 100%; + margin: 1em auto 0; +} + +#participants th, +#participants td { + vertical-align: middle; +} + +.groupinfobox {border-color: #DDDDDD;width: 60%;margin-left: 20%;margin-right: 20%;} + +/* Notes +------------------------*/ + +.path-notes .generalbox { + border: none; +} + +/* Roles +------------------------*/ + +.path-admin-roles .generaltable { + /* width: 65%; hiding because it's causing problems on role/assign */ +} + +.path-admin-roles .generaltable th { + vertical-align: middle; +} + +.path-admin-roles .generaltable .lastcol { + width: 15%; +} + +.path-admin-roles .backlink { + text-align: center; +} + +/* Blogs +------------------------*/ + +.blog_entry .audience { + color: #444; + margin: 0 0 0.5em; + font-size: 0.9em; +} + +.blog_entry .tags { + margin-bottom: 0.5em; +} + +/* Tags +------------------------*/ + +#big-tag-cloud-box { + padding: 10px; +} + +#tag-management-box { + text-align: center; +} + +.tag-management-form { + border: none; + padding: 0 0 1em; +} + +#tag-management-list { + margin: 1em 0 +} + +#page-tag-index #tag-blogs { + border-width: 0 0 1px; + width: 65%; + margin: 1em auto; +} + +#tagblogentries { + margin: 0 0 1em; +} + +#tagblogentries li { + list-style: none; + padding: 0.25em 0; + margin: 0 +} + +#big-tag-cloud-box { + border: none; +} + +#tag-user-table { + width: 95%; + margin: 0 auto; + border-width: 0 0 1px; +} + +.managelink { + text-align: right; +} + +#page-tag-index .headingblock { + text-align: center; + margin-bottom: 0; +} + +#page-tag-index #tag-management-box { + border-bottom: 1px solid #ddd; + padding: 4px 0; +} + +#page-tag-index .relatedpages { + text-align: center; +} + +#page-tag-manage .lastinitial { + margin-bottom: 0.5em; +} + +#page-tag-manage .green { + text-align: center; + padding: 0 0 1em; +} + +/* YUI overlays +------------------------*/ +#helppopupbox { + z-index: 99999 !important; +} + + +/* Embedded Pages +------------------------*/ + +.pagelayout-embedded { + text-align: center; + background-color: #fff; + background-image: none; +} + +.pagelayout-embedded #content { + padding-top: 30px; +} + +/* Forms +-----------------------*/ + +.mform .fsubmit { + text-align: center; + padding: 2px; +} + +.form-label .form-shortname { + font-size: 0.8em; + color: #777; +} + +.form-description { + font-size: 0.95em; + color: #444; +} + +.mform .hidden .fitem .fgroup { + width: 100%; + text-align: center; + margin: 1em 0; +} + +.path-backup .mform .hidden .fitem .fgroup { + text-align: left; +} + +.path-backup .mform .grouped_settings { + margin:1em; +} +.path-backup .mform .grouped_settings .grouped_settings { + margin:0; +} + +/* Comments +-----------------------*/ + +.comment-list li { + background: #eee !important; + list-style: none; +} + +/* Gradebook +----------------------*/ + +.path-grade h1.headerheading { + text-align: left; /* Strangely necessary TODO: find bug */ +} + +.gradestable .lastrow th.header { + background: #ddd; +} + +.gradestable .lastrow td.cell { + background: #eee !important; +} + +.user-grade td.b1t, +.user-grade td.baggt { + background: #ddd !important; +} + +#page-grade-edit-scale-index .generaltable { + margin: 1em auto; +} + +#page-grade-report-grader-preferences .generalbox { + border: none; +} + +.path-grade-report-grader form { + text-align: left; +} + +/* Footer +-----------------------*/ + +#page-footer .logininfo { + padding: 1em 0; +} + +#page-footer .homelink, +#page-footer .sitelink { + padding: 1em 0; +} + +.homelink a { + text-decoration: none; + border-top: 1px solid #cecece; + border-bottom: 2px solid #8a8a8a; + border-left: 1px solid #cecece; + border-right: 2px solid #8a8a8a; +} + +.homelink a:hover { + text-decoration: none; + border-bottom: 1px solid #cecece; + border-top: 2px solid #8a8a8a; + border-right: 1px solid #cecece; + border-left: 2px solid #8a8a8a; +} + +/** + * Enrol - TODO: tidy up styles here + */ +.userenrolment {font-size:90%;border:1px solid #999;} +.userenrolment tr.r0 {background-color:#F9F9F9;} +.userenrolment tr.r1 {background-color:#F3F3F3;} +.userenrolment td {border:1px solid #E9E9E9;border-top-color:#F6F6F6;border-right-color:#EEE;border-left-color:#F3F3F3;} +.userenrolment td.c0 {border-left-color:#999;} +.userenrolment td.c4 {border-right-color:#999;} +.userenrolment .col_userdetails {padding:3px;min-width:35%;} +.userenrolment .col_role .roles {position:relative;} +.userenrolment .col_role .role {line-height:10px;font-size:10px;} +.userenrolment .col_role .role a img {height:8px;} +.userenrolment .col_role .addrole {background-color:#DDD;border:1px outset #EEE;-moz-border-radius:5px;} +.userenrolment .col_group {max-width:300px;} +.userenrolment .col_group .group {line-height:10px;font-size:10px;} +.userenrolment .col_group .group a img {height:8px;} +.userenrolment .col_group .addgroup {background-color:#DDD;border:1px outset #EEE;-moz-border-radius:5px;} +.userenrolment .col_enrol {max-width:300px;} +.userenrolment .col_enrol .enrolment {border:1px outset #E6E6E6;background-color:#EEE;line-height:10px;font-size:10px;-moz-border-radius:5px;} +.path-enrol .enrolusersbutton, +.path-enrol .enrolcohortbutton {float:left;} +.path-enrol .enrolusersbutton.instance1, +.path-enrol .enrolcohortbutton.instance1 {float:right;} + +/* Registration */ +#page-admin-registration-hubselector .registration_textfield {width: 400px;} + +/** + * Redirect + */ +.pagelayout-redirect #content {text-align:center;margin-top:10%;margin-bottom:10%;} \ No newline at end of file diff --git a/theme/formal_white/style/course.css b/theme/formal_white/style/course.css old mode 100644 new mode 100755 index 0578c261141..59137b4af24 --- a/theme/formal_white/style/course.css +++ b/theme/formal_white/style/course.css @@ -1,7 +1,10 @@ /** Course formats **/ +.course-content .section li.activity {margin:7px 0;} +.course-content .header {background-image:url([[pix:theme|gradient_h]]);background-repeat:repeat-x;border-top:1px #C6BDA8 solid;} +.course-content h2.header {padding-left:1em;} .course-content ul.weeks li.section {border:1px solid #DDD;} .course-content ul.weeks li.section .content {background-color:#FAFAFA;padding:5px 10px;} -.course-content ul.weeks li.section .content h3 {margin:0;color:#777;font-weight: normal;} +.course-content ul.weeks li.section .content h3 {margin:0;color:#777;font-weight:normal;} .course-content ul.weeks li.section .left {padding:5px 0;} .course-content ul.weeks li.section .right {padding:5px 0;} @@ -10,23 +13,23 @@ .coursebox .info {margin:5px;font-size:1em;} .coursebox .info .name {margin:3px 0;} .coursebox .info .teachers {margin:0 1em;font-size:0.9em;} -.coursebox .cost {font-size:0.9em;padding-top: 20px;} +.coursebox .cost {font-size:0.9em;padding-top:20px;} .coursebox .summary {margin:5px;font-size:0.9em;} #page-course-recent h2.main {font-size:1.1em;} #page-course-recent .user {font-size:0.75em;} -#page-course-recent .grade {font-style: italic;font-size:0.9em;} -#page-course-recent .forum-recent .reply .title {font-style: italic;font-size:0.9em;} -#page-course-recent .forum-recent .discussion .title {font-weight:bold;font-style: italic;font-size:0.9em;} +#page-course-recent .grade {font-style:italic;font-size:0.9em;} +#page-course-recent .forum-recent .reply .title {font-style:italic;font-size:0.9em;} +#page-course-recent .forum-recent .discussion .title {font-weight:bold;font-style:italic;font-size:0.9em;} .path-course-view .availabilityinfo {font-size:0.85em;color:#aaa;} .path-course-view .availabilityinfo strong {font-weight:normal;color:black;} -.path-course-view .dimmed_text img {opacity:0.3;filter: alpha(opacity='30');} +.path-course-view .dimmed_text img {opacity:0.3;filter:alpha(opacity='30');} .path-course-view .section {font-size:0.95em;line-height:1.2em;} .path-course-view .section .activity {padding:0.2em 0;} .path-course-view .section .activity a {line-height:1em;} -.path-course-view .section .weekdates {margin: 0;font-weight: normal;font-size: 1em;} -.path-course-view .section .groupinglabel {color: #666666;} +.path-course-view .section .weekdates {margin:0;font-weight:normal;font-size:1em;} +.path-course-view .section .groupinglabel {color:#666666;} .path-course-view .section .left {font-weight:bold;} .path-course-view .weeks .section, @@ -35,35 +38,35 @@ .path-course-view .weeks .content , .path-course-view .topics .content, .path-course-view .weeks .section, -.path-course-view .topics .section {background: #FAFAFA;} -.path-course-view .section td.side {background: #FFFFFF;} +.path-course-view .topics .section {background:transparent;} +.path-course-view .section td.side {background:#FFFFFF;} .path-course-view .weeks .current, .path-course-view .topics .current, -.path-course-view .current td.side {background: #FFD991;} +.path-course-view .current td.side {background:#FFD991;} .path-course-view .weeks .hidden, .path-course-view .topics .hidden, -.path-course-view .hidden td.side {background: #DDDDDD;} -.path-course-view .section .weekdates {color: #777777;} +.path-course-view .hidden td.side {background:#DDDDDD;} +.path-course-view .section .weekdates {color:#777777;} .path-course-view .weeks .weekdates , -.path-course-view .topics .weekdates {color: #333333;} +.path-course-view .topics .weekdates {color:#333333;} .weeks li.section , .topics li.section {border-style:solid;border-width:1px;} .weeks .content, -.topics .content {padding: 5px;} +.topics .content {padding:5px;} .categoryboxcontent {border-color:#DDDDDD;} -#page-course-user .graph {text-align: center;} +#page-course-user .graph {text-align:center;} #page-course-user .section {border-color:#AAAAAA;} #page-course-user .info {text-align:center;} #page-admin-report .plugin, #page-course-report .plugin, -#page-course-import .plugin {margin-bottom: 20px;margin-left:10%;margin-right:10%;border: 1px solid #cecece;background-color: #fdfdfd;} +#page-course-import .plugin {margin-bottom:20px;margin-left:10%;margin-right:10%;border:1px solid #cecece;background-color:#fdfdfd;} -.path-course-view .unread {background: #9EBEFF;} +.path-course-view .unread {background:#9EBEFF;} .path-course-view .completionprogress {font-size:0.80em; padding:8px 26px 5px 5px;} #page-course-category .courseboxes, @@ -74,7 +77,7 @@ #page-course-report #region-main p, #page-course-report-log-index #region-main .info, #page-course-report-log-indexlive #region-main .info, -#page-course-report-stats-index #region-main .graph {text-align: center;} +#page-course-report-stats-index #region-main .graph {text-align:center;} #page-course-report .logselectform, #page-course-report .participationselectform, @@ -83,37 +86,37 @@ .addcoursebutton {text-align:center;} .categorypicker {text-align:center;margin-bottom:10px;} -.path-course-report-outline .loginfo {text-align:center;margin: 1em;} -.categorylist {width: 90%;margin:0 auto;text-align: left;} +.path-course-report-outline .loginfo {text-align:center;margin:1em;} +.categorylist {width:90%;margin:0 auto;text-align:left;} /* Course and category combo list on front page */ .course_category_tree .controls {margin-bottom:5px;text-align:right;float:right;} .course_category_tree .controls div {padding-right:2em;font-size:75%;} -.course_category_tree .category {background-color:#FFF;background-image:url([[pix:theme|hgradient]]);background-repeat: repeat-x;border:1px solid #ddd;margin-bottom:10px;} -.course_category_tree .category .subcategories {background-color: inherit;padding-left: 11px;border-width: 1px 0 1px 1px;border-color: #FFF;border-style: solid;} -.course_category_tree .category.with_children .category_label {background-position:3px 3px;} +.course_category_tree .category {background-color:#FFF;background-image:url([[pix:theme|hgradient]]);background-repeat:repeat-x;border:1px solid #ddd;margin-bottom:10px;} +.course_category_tree .category .subcategories {background-color:inherit;padding-left:11px;border-width:1px 0 1px 1px;border-color:#FFF;border-style:solid;margin-top:8px;} +.course_category_tree .category.with_children .category_label {background-position:3px 3px;margin-left:6px;} .course_category_tree .category_link .category_link {font-size:95%;} .course_category_tree .category_label {padding-left:13px;} .course_category_tree .category_link {display:block;margin:5px;font-size:120%;font-weight:bold;} .course_category_tree .category .courses {background-color:inherit;} .course_category_tree .category .courses .course_link {margin:5px;margin-right:100px;} -.course_category_tree .category .course {border:1px solid #f9f9f9;border-bottom-color: #eee;border-right-width:0;} +.course_category_tree .category .course {border:1px solid #f9f9f9;border-bottom-color:#eee;border-right-width:0;} .course_category_tree .category .course:last-child {border-bottom-color:#f6f6f6;} -.course_category_tree .category .course.even {background-color:#f6f6f6;border-color:#eee;border-top-color: #f9f9f9;} +.course_category_tree .category .course.even {background-color:#f6f6f6;border-color:#eee;border-top-color:#f9f9f9;} .course_category_tree .category .course_info {right:3px;top:3px;} .course_category_tree .category .course:hover {background-color:#eee;} -.course_category_tree .category .category {margin: 5px 0px 5px 5px;border-right: 0px transparent none;} +.course_category_tree .category .category {margin:5px 0 5px 5px;border-right:0 transparent none;border-left:0 transparent none;border-bottom:1px transparent solid;} /* Publication */ -#page-course-publish-metadata .metadatatext {width: 400px;} +#page-course-publish-metadata .metadatatext {width:400px;} #page-course-publish-metadata .hubscreenshot { display:inline; float:left; margin-right:10px; } -#page-course-publish-metadata .hubscreenshot img {vertical-align: bottom;} +#page-course-publish-metadata .hubscreenshot img {vertical-align:bottom;} #page-course-publish-metadata .hubdescription {} #page-course-publish-metadata .hubinfo {display:block; margin-bottom:20px;} #page-course-publish-metadata .hublink {} -#page-course-publish-backup .courseuploadtextinfo {text-align: center;} -#page-course-publish-backup .sharecoursecontinue {text-align: center;} \ No newline at end of file +#page-course-publish-backup .courseuploadtextinfo {text-align:center;} +#page-course-publish-backup .sharecoursecontinue {text-align:center;} \ No newline at end of file diff --git a/theme/formal_white/style/dock.css b/theme/formal_white/style/dock.css deleted file mode 100644 index 20e23dd2bd7..00000000000 --- a/theme/formal_white/style/dock.css +++ /dev/null @@ -1,54 +0,0 @@ -/** Core overrides **/ -body.has_dock {margin-left:30px;margin-right:30px;} - -/* This CSS is for the dock */ -.dock {width:30px;position:fixed;top:0px;left:0px;height:100%;background-image:url([[pix:theme|vgradient]]);background-repeat: repeat-y;background-position:100% 0;background-color:#DDD;border-right:1px solid #AAA;z-index:2002;} -.dock .dockeditem {background-color:#DDD;} -.dock .dockeditem .firstdockitem {margin-top:1em;} -.dock .dockeditem .dockedtitle {border-bottom:1px solid #AAA;border-top:1px solid #CCC;cursor:pointer;background-image:url([[pix:theme|vgradient]]);background-position:90% 0;background-repeat: repeat-y;} -.dock .dockeditem .dockedtitle.activeitem {background-position:80% 0;} -.dock .dockeditem .dockedtitle h2 {font-size:0.8em;line-height:100%;text-transform:uppercase;text-align:center;margin:12px 0px;} -.dock .block_tree .current_branch {} -.dock .controls {position:absolute;bottom:1em;text-align:center;width:100%;} -.dock .controls img {cursor:pointer;} -.dock .bd.oversized_content {overflow-y:auto;overflow-x:visible;height:inherit;} -.dock .bd.oversized_content .content {margin:6px 6px 6px 0px;padding-bottom:6px;} -.dock .yui-panel .hd {text-align:right;border-width:0 0 1px 0;padding:3px 5px;} -.dock .yui-panel .hd .commands img {margin-right:2px;} - -/**.dock .bd .content .blockcommands {text-align:right;border:1px solid #AAA;border-width:0 0 1px 1px;background-image:url([[pix:theme|hgradient]]);background-repeat: repeat-x;}**/ -/** YUI overrides **/ -.yui-skin-sam .dock .yui-panel {border-width:1px 2px 1px 1px;border-color:#AAA;min-width:150px;} -.yui-skin-sam .dock .yui-panel .bd {border-width:0;background-color:#FAFAFA;} -/** Override the above if the dock is on the right **/ -.dock.dock_right_vertical {left:auto;right:0px;border-width:0px 0px 1px 5px;} -.dock.dock_right_vertical .commands {text-align:right;} -.yui-skin-sam .dock.dock_right_vertical .yui-panel {border-width:1px 0 1px 5px;} - -/* block expansion code */ -.block_js_expansion .block_tree {overflow-x:scroll;} -.block_js_expansion.mouseover .content {width:200%;z-index:1000;position:relative;} -.block_js_expansion.mouseover .content .block_tree {width:100%; background-color:#FAFAFA; padding-bottom:0px;} - -/* CSS for shadows */ -.divshadow div {position:absolute;width:3px;height:3px;background-color:#333;} -.divshadow .shadow_top {top:-3px;right:0px;width:100%;} -.divshadow .shadow_bottom {bottom:-3px;right:0px;width:100%;} -.divshadow .shadow_left {top:0px;left:-3px;height:100%;} -.divshadow .shadow_right {bottom:0px;right:-3px;height:100%;} -.divshadow .shadow_top_right {top:-3px;right:-3px;} -.divshadow .shadow_bottom_right {bottom:-3px;right:-3px;} -.divshadow .shadow_top_left {top:-3px;left:-3px;} -.divshadow .shadow_bottom_left {bottom:-3px;left:-3px;} - -/** IE stylings */ -.ie6 .block .block_tree {width:160px;overflow-x:scroll;} -.ie7 .block .block_tree {overflow-x:scroll;} -.ie6 .block_tree .tree_item {width:100%;} -.ie6 .dock {position:absolute;} -.ie6 .dock hr {display:none;margin:0px;height:0px;padding:0px;} -.ie6 .dock li p {background-color:inherit;} -.ie6 .dock .bd.oversized_content .content, .ie7 .dock .bd.oversized_content .content {padding-bottom:0px;} -.ie6 .block_js_expansion.mouseover .content, .ie7 .block_js_expansion.mouseover .content{ padding-bottom:2px;} -.ie6 .dock .bd.oversized_content {width:100%;} -.ie7 .dock .bd.oversized_content {width:400px;} \ No newline at end of file diff --git a/theme/formal_white/style/editor.css b/theme/formal_white/style/editor.css deleted file mode 100644 index 207301f139e..00000000000 --- a/theme/formal_white/style/editor.css +++ /dev/null @@ -1,2 +0,0 @@ -body, div, p, li, input, option, textarea {font-size:8pt;line-height:1.5em;} -body, div, p, li, input, option, textarea, h1, h2, h3, h4, h5 {font-family:Arial, Helvetica, sans-serif;} \ No newline at end of file diff --git a/theme/formal_white/style/formal_white.css b/theme/formal_white/style/formal_white.css new file mode 100755 index 00000000000..661f5730be1 --- /dev/null +++ b/theme/formal_white/style/formal_white.css @@ -0,0 +1,88 @@ +/*** + *** Core + ***/ + +html, body { + font-family:Arial, Verdana, Helvetica, sans-serif; + margin:0; + padding:0; + background-color:#EFEFEF; + font-size:13px; +} + +a:link {text-decoration:none;} +a:visited {text-decoration:none;} +a:hover {text-decoration:underline;} + +h1 {font-size:1.4em;font-weight:bold;} +h2 {font-size:1.3em;} +h3 {font-size:1.2em;} +h4 {font-weight:bold;} + +/*#page-header{}*/ +/* if (displaylogo) { */ + #headerlogo {margin:0.3em;float:left;top:1em;z-index:1;} +/* } else { */ + h1.headerheading {margin:14px 11px 8px 11px;float:left;font-size:2em;z-index:1;} +/* } */ + +/* headermenu */ +.headermenu {float:right;top:1em;z-index:2;} + +/* debug */ +/* #headerlogo {border:1px red solid;} */ +/* .headermenu {border:1px red solid;} */ + +#dock {background-color:#E3DFD4;border-right:1px #000 dashed;} + +/* navbar */ +.navbar {width:auto;padding-top:0.35em;padding-bottom:0.15em;background-image:url([[pix:theme|bg_bread]]);} +.navbar li span {color:#E3DFD4;} +.navbar li a:link, .navbar li a:visited {color:white;} + +/* breadcrumb */ +.breadcrumb {margin-left:0.8em;} + +/* generalbox */ +.generalbox {border-color:#E3DFD4;} + +/* admin pages */ +div#chooseuser {border:0 transparent none;} +table.groupmanagementtable, +table.groupmanagementtable tr, +table.groupmanagementtable td {border-width:0px;} +table.groupmanagementtable td#buttonscell {vertical-align:middle;text-align:center;} +table#defineroletable tr.rolecapheading {background-image:url([[pix:theme|gradient_h]]);background-repeat:repeat-x;} +/*table#defineroletable tr.rolecap {border-top:1px #F30 dashed;}*/ +tr.rolecap {border-top:1px #F30 dashed;} +tr.rolecapheading + tr.rolecap {border-top:none;} + + + /* course */ +ul.topics .section span.commands {margin-left:2em;} /* distanza dei comandi dagli elementi del corso */ + +/* block */ +.block {border:1px #C6BDA8 solid;margin-bottom:0.5em;} +.block .header h2 {margin:0;padding-left:0.3em;} +.block .header .title {background-image:url([[pix:theme|gradient_h]]);background-repeat:repeat-x;clear:both;line-height:2em;} +.block .header .title .commands {padding-left:0.3em;text-align:right;} +.block .content {background-color:[[setting:blockcontentbgc]];} + +/* block login */ +.block_login .btn {margin-top:0.5em;text-align:center;} + +/* tables header */ +th.header, +.formtable tbody th, +.generaltable th.header {background-image:url([[pix:theme|gradient_h]]);background-repeat:repeat-x;border-top:1px #C6BDA8 solid;background-color:#E3DFD4;} + +/* page-footer */ +#page-footer {text-align:center;width:100%;padding:0;} +#page-footer_noframe {background-color:#FFF;clear: both;float: left;width:100%;} +#page-footer_noframe-content {text-align:center;border:7px #E3DFD4 double;margin:0;} +#page-footer .logininfo {padding:0.3em 0 0.7em 0;} + +.mform fieldset {border:1px #DDD solid;} + +/** Custom CSS **/ +[[setting:customcss]] \ No newline at end of file diff --git a/theme/formal_white/style/formalwhite.css b/theme/formal_white/style/formalwhite.css deleted file mode 100644 index da7ff621976..00000000000 --- a/theme/formal_white/style/formalwhite.css +++ /dev/null @@ -1,135 +0,0 @@ - -/*** - *** Core - ***/ -html, body { - background-color: #EFEFEF; -} - -.block .header { -} - -.block .header .title { - background-image: url([[pix:theme|gradient_h]]); - background-repeat: repeat-x; - clear: both; - line-height: 2em; -} - -.block .header .title .block_action { - margin-top: 4px; -} - -.block .header .title h2 { -} - -.block .header .title .commands { - margin-left: 4px; -} - -.block .header .title .commands a { - margin: 0 2px; -} - -.block .content { - display:block; - padding:4px; -} - -body { - font-family: Helvetica, Arial, Verdana, sans-serif; - font-size: 0.95em; - line-height: 1.4; - margin: 0; - padding: 0; -} - -#page-site-index { - display:block; -} - -#page { - width:97%; - background-image: url([[pix:theme|roundcorner/header]]); - margin:15px 1.5% 0; - background-position:0 0; - background-repeat:repeat-x; - min-width: 934px; -} - -#headerenvelop { /* Inside Header Middle */ - color:#000; - height: 105px; - /*background-color: #E3DFD4;*/ -} - -#logo { - float: left; - /*display:inline;*/ -} - -.sitelogo { - margin:5px 0 -4px 3px; -} - -/* Header */ -#header-i3 { - background-color: #FFF; - margin-left: 7px; - margin-right: 7px; -} - -#header, #header-home { - padding:0 17px; - background-color: #E3DFD4; - margin-left:10px; - margin-right:10px; - -moz-border-radius: 6px 6px 0px 0px; - -webkit-border-radius: 6px 6px 0px 0px; - border-radius: 6px 6px 0px 0px; -} - -#custommenu, .navbar { - margin-right: 10px; - margin-left: 10px; -} - -.yui3-skin-sam .yui3-menu-content {border-right:none;border-left:none;} - -.navbar { - width:auto; - padding:3px 1em; - background-image: url([[pix:theme|bg_bread]]); -} - -/* content */ -#page-content { - float: none; - width: auto; - margin-right: 10px; - margin-left: 10px; - background-color: #FFF; -} - -.shrinker { /* To keep content off of the background image */ - margin:1px 0 0 0; -} - - -/* Link Colors */ -a:link, a:visited { - color:#375faf; -} -a:hover, a:active { - color:#304469; -} - -#headerenvelop a:link, #headerenvelop a:visited { - color:#375FAF; -} - -.clearfix { - min-width: 0; - /* overflow: hidden; */ - display:block; -} diff --git a/theme/formal_white/style/frame.css b/theme/formal_white/style/frame.css new file mode 100755 index 00000000000..17c6dadfc0c --- /dev/null +++ b/theme/formal_white/style/frame.css @@ -0,0 +1,158 @@ +/**** + * + * #frametop + * #framebottom + * ! #frametopright + * | |
---/
+ * ! /#frametopright + * | #frameleft + * | | #frameright + * | | | #wrapper + * | | | | #page-header + * | | | | | #headerlogo + * | | | | | | + * | | | | | h1#headerheading---/h1#headerheading + * | | | | | #headermenu---/#headermenu + * | | | | /#page-header + * | | | | #custommenu---/#custommenu + * | | | | .navbar clearfix---/.navbar clearfix + * | | | | .breadcrumb---/.breadcrumb + * | | | | .navbutton---/.navbutton + * | | | | /.navbar clearfix + * | | | | #page-content + * | | | | . + * | | | | . + * | | | | . + * | | | | /#page-content + * | | | | .clearfix---/.clearfix + * | | | /#wrapper + * | | #frameright + * | /#frameleft + * | #framebottomright + * | |
---/
+ * ! /#framebottomright + * /#framebottom + * /#frametop + * + * The body tag may also contain one of three layout specific classes that describe + * the regions of the page and allow us to theme more easily. + * + * default (no class) = Content + side pre + side post + * side-pre-only = Content + side pre + * side-post-only = Content + side post + * content-only = Content + * + ****/ + +#wrapper, +#footerwrapper { + padding:0 17px 0 17px; + float:none; /* serve a qualcosa? */ + /*clear:both;*/ + /*overflow:hidden;*/ +} + +#frametop, +#footerframetop { + background-image:url([[pix:theme|roundcorner/header]]); + margin:15px 15px 0; + background-position:0 0; + background-repeat:repeat-x; + min-width:934px; +} + +#frametopright, +#footerframetopright { /* Frame background top right */ + background-image:url([[pix:theme|roundcorner/header_r]]); + background-repeat:no-repeat; + background-position:100% 0; + text-align:left; + height:17px; + margin:0 0 0 17px; +} + +#frametopright div, +#footerframetopright div { /* Frame background top left */ + background-image:url([[pix:theme|roundcorner/header_l]]); + font-size:1px; + line-height:1%; + height:17px; + background-repeat:no-repeat; + background-position:0 0; + background-color:transparent; + position:relative; + width:17px; + margin-left:-17px; +} + +#frameleft, +#footerframeleft { /* Frame background left */ + background-image:url([[pix:theme|roundcorner/body_l]]); + background-repeat:repeat-y; + background-position:0 0; + background-color:#FFF; +} + +#frameright, +#footerframeright { /* Frame background right */ + background-image:url([[pix:theme|roundcorner/body_r]]); + background-repeat:repeat-y; + background-position:100% 0; + background-color:transparent; + /*margin-left:17px;*/ + /*padding-right:17px;*/ +} + +#framebottomright, +#footerframebottomright { /* Frame background bottom right */ + background-image:url([[pix:theme|roundcorner/footer_r]]); + background-repeat:no-repeat; + background-position:100% 0; + text-align:left; + margin:0 0 0 17px; +} + +#framebottomright div, +#footerframebottomright div { /* Frame background bottom left */ + background-image:url([[pix:theme|roundcorner/footer_l]]); + font-size:1px; + line-height:1%; + height:17px; + background-repeat:no-repeat; + background-position:0 0; + background-color:transparent; + position:relative; + width:17px; + margin-left:-17px; +} + +#framebottom, +#footerframebottom { /* Bottom Middle */ + background-image:url([[pix:theme|roundcorner/footer]]); + background-repeat:repeat-x; + background-position:0 100%; + background-attachment:scroll; + background-color:transparent; +} + +/*******************************************************************/ +/* Footer section */ +/*******************************************************************/ + +#footerwrapper { + background-color:white; + margin:0 17px 0 17px; +} + +#footerframetop { + margin-top:0; +} + +#footerwrapper p, +#footerwrapper div { + margin:0; +} + +/*******************************************************************/ +/* End of footer section */ +/*******************************************************************/ \ No newline at end of file diff --git a/theme/formal_white/style/fw_corners.css b/theme/formal_white/style/fw_corners.css deleted file mode 100644 index a031b0ac0a4..00000000000 --- a/theme/formal_white/style/fw_corners.css +++ /dev/null @@ -1,66 +0,0 @@ -div.headerleft div { /* Page background top left */ - background-image: url([[pix:theme|roundcorner/header_l]]); - font-size:1px; - line-height:1%; - height:17px; - background-repeat:no-repeat; - background-position:0 0; - background-color:transparent; - position:relative; - width:17px; - margin-left:-17px; -} - -div.headerleft { /*Page background top right */ - background-image: url([[pix:theme|roundcorner/header_r]]); - background-repeat:no-repeat; - background-position:100% 0; - text-align:left; - height:17px; - margin:0 0 0 17px; -} - -div.bodyleft { /* Page background left */ - background-image: url([[pix:theme|roundcorner/body_l]]); - background-repeat:repeat-y; - background-position:0 0; - background-color:transparent; -} - -div.bodyright { /* Page background right */ - background-image: url([[pix:theme|roundcorner/body_r]]); - background-repeat:repeat-y; - background-position:100% 0; - background-color:transparent; -} - -/* Page background shading and curvy corners at bottom of screen */ - -div.contentfooter div { /* Bottom Left */ - font-size:1px; - line-height:1%; - height:17px; - background-repeat:no-repeat; - background-position:0 0; - background-color:transparent; - position:relative; - width:17px; - margin-left:-17px; - background-image: url([[pix:theme|roundcorner/footer_l]]); -} - -div.contentfooter { /* Bottom Right */ - background-image: url([[pix:theme|roundcorner/footer_r]]); - background-position:100% 0; - text-align:left; - margin:0 0 0 17px; - background-repeat:no-repeat; -} - -#page2 { /* Bottom Middle */ - background-image: url([[pix:theme|roundcorner/footer]]); - background-repeat: repeat-x; - background-position: 0 100%; - background-attachment: scroll; - background-color: transparent; -} \ No newline at end of file diff --git a/theme/formal_white/style/general.css b/theme/formal_white/style/general.css deleted file mode 100644 index 61c77b85335..00000000000 --- a/theme/formal_white/style/general.css +++ /dev/null @@ -1,240 +0,0 @@ -a:link {text-decoration:none;color: #697F55;} -a:visited {text-decoration:none;color: #697F55;} -a:hover {text-decoration:underline;} - -img.icon, -img.iconhelp {vertical-align:middle;} - -#page {overflow:visible} -/*#page #page-content {background-color:#FFF;border:1px solid #E3DFD4;}*/ - -/******************/ -#page-header {background-color: #E3DFD4; color:#FFF;border:1px solid #E3DFD4;border-bottom: none;} -.hasnavbar #page-header {border-bottom-width:0px;} -#page-header .headermain span {color:#C8C9C7;} - -#page-header .navbar {background-image: url([[pix:theme|bg_bread]]);width:100%;} -#page-header .navbar {color:#000;} -#page-header .navbar a:link {color:#fff;} -#page-header .navbar a:visited {color:#fff;} -#page-header .navbar .breadcrumb {margin:6px 1em;float:left;} -#page-header .navbar .navbutton {float:right;margin:5px 1em;} -#region-pre .region-content{background-color:#E3DFD4;border-top:6px #E3DFD4 solid;} -#region-pre {margin-top:-6px;} -/*#region-post .region-content {background-color: #E3DFD4;}*/ -#region-post-box {background-color: #E3DFD4;} - -/** General **/ -.generalbox {border: 1px solid #DDDDDD;} -.generaltable td {border-width:0px;} -.sitetopic {border-width:0px;} -.headingblock {margin-bottom:10px;border-bottom:1px solid #E3DFD4;background-color:#FFF;padding:4px 5px;} - -.coursebox {width:100%;margin:10px 0px;border-bottom:1px solid #E3E3E3;overflow:hidden;padding-bottom:10px;} -.coursebox .info {width:35%;float:left;} -.coursebox .summary {width:60%;float:right;} - -.course-content ul {margin:0px;} -.course-content .headingblock.outline {margin-top:2em;} -.course-content .section.main {border:1px solid #E3E3E3;margin-bottom:10px;} -.course-content .section.main .left.side {float:left;width:20px;padding:5px;} -.course-content .section.main .right.side {float:right;width:20px;padding:5px;} -.course-content .section.main .content {margin:0px 30px 10px 30px;} -.course-content .section.main .content .section_add_menus {text-align:right;} - -#course-user .section {border:1px solid #DDD;margin:0px 5% 1.5em 5%;} - -#course-user .section h2, -#course-user .section .content {margin:5px 1em;} -#course-user .section table td {border:0px;} - -.generaltable {border:1px solid #DDD;} -.generaltable .cell {background-color:#FFF;border:1px solid #EEE;border-collapse: collapse;} -.generaltable .header {background-color:#EEE;border:1px solid #EEE;font-weight:bold;} - -/** Login **/ -.loginbox {margin-top:15px;margin-bottom:15px;} -.loginbox .loginform {margin-top:15px;} -.loginbox .loginform .form-label {width:39%;float:left;text-align:right;} -.loginbox .loginform .form-input {width:60%;float:right;text-align:left;} -.loginbox .loginform .form-input input {width:6em;} - -.loginbox.twocolumns {border:1px solid #DDD;} -.loginbox.twocolumns .loginpanel {float:left;width:49%;text-align:center;} -.loginbox.twocolumns .signuppanel {float:left;width:50%;border-left:1px solid #DDD;} -.loginbox.twocolumns .signuppanel h2 {text-align:center;} -.loginbox.twocolumns .signuppanel div {margin:1em;} -.loginbox.twocolumns .signuppanel div li {font-size:90%;} - -.loginbox .loginsub {margin-left:10%;margin-right:10%;padding:10px;margin-bottom:5px;} -.loginbox .guestsub {margin-left:10%;margin-right:10%;padding:10px;margin-bottom:5px;border-top:1px solid #DDD;} - -/** Blocks **/ -.block {border:1px solid #C8C9C7;background-color: #FEFEFE;margin-bottom:10px;overflow:hidden;} -.block h1, -.block h2, -.block h3, -.block h4 {margin:0px;} -.block .header {height:24px;margin:0;display:inline;} -.block .header .title {color: #000;} -.block .header .title h2 {margin: 0 0 0 4px;} -.block .content {background-color: white;} - -/** Admin **/ -.box.adminwarning {text-align:center;border:1px solid #C8C9C7;background-color:#E3E3E3;margin-bottom:1em;padding:10px 10%;} -.box.copyright {text-align:center;font-size:90%;padding:10px 10%;} -#adminsettings fieldset {border:1px solid #C8C9C7;background-color:#E3E3E3;} -#adminsettings fieldset .generalbox {margin:1em 0.5em;border-color:#C8C9C7;} -#adminsettings .form-buttons {margin-left:13em;} - -.form-item {width:100%;margin:1em 1em 2em 1em ;} -.form-item .form-label {width:12.5em;text-align:right;float:left;margin-right:0.5em;} -.form-item .form-label .form-shortname {display:block;color:#666;font-size:75%;} -.form-item .form-setting {margin-left:13em;} -.form-item .form-setting .defaultsnext {display:inline;} -.form-item .form-setting .form-defaultinfo {display:inline;margin-left:0.5em;font-size:90%;color:#666;} -.form-item .form-description {margin:0.5em 1em 0.5em 13em;} -.form-item .form-textarea textarea {width:495px;} - -#authmenu .informationbox {width:80%;margin-left:auto;margin-right:auto;margin-bottom:10px;border:1px solid #C8C9C7;padding:10px;} -#authmenu table td {border-width:0px;} - -#categoryquestions {margin-left:auto;margin-right:auto;width:100%;} - -#categoryquestions th, -.user th, -.user th.header, -.group th.header, -.admin table tr th, -.admin table tr th.header {background-color:#E3DFD4;color:#FFF;border:2px solid #E3DFD4;border-bottom-color:#111;} - -.user th a:link, -#categoryquestions th a:link, -.group th a:link, -.admin table tr th a:link {color:#FFF;text-decoration:none;} - -.user th a:visited, -#categoryquestions th a:visited, -.group th a:visited, -.admin table tr th a:visited {color:#FFF;text-decoration:underline;} - -.user tr td.cell, -#categoryquestions tr td.cell, -.group tr td.cell, -.admin table tr td.cell {border:1px solid #C8C9C7;border-width:0px 1px;} - -.user .r1 .cell, -#categoryquestions .r1 .cell, -.group .r1 .cell, -.admin table .r1 .cell {background-color:#EEE;} - -#categoryquestions th, .user th, .user th.header, .group th.header, .admin table tr th, .admin table tr th.header {color:black; border-width:1px;} - -#defineroletable .rolecap th, #defineroletable .rolecap td {border-bottom:1px solid #000000; padding:0.5em;} - -#permissions tr {background-color:#EEEEEE;} -#permissions tr.rolecapheading {border-top: 1px black; background-color:#E3DFD4;} -.user th a:link, #categoryquestions th a:link, .group th a:link, .admin table tr th a:link { - color:black; -} -.admin .plugincompattable .r1 .cell {background-color:#FFF;} - -.singlebutton, -.buttons {text-align:center;margin:20px;} -.buttons form {display:inline;} -.buttons div {display:inline;} -.buttons .singlebutton {display:inline;padding:5px;margin:0px;} -.admin .generalbox {background-color:#EEE;border-color:#C8C9C7;} - -#admin-mnet-index table td, -#files-index .column-content table td {border-width:0px;} - -/** Mforms **/ -.mform fieldset {border-color:#C8C9C7;} - -/** Tags **/ -.tag-management-form {text-align:center;} -#tag-management-list {margin-top:1em;} - -/** User **/ -.userinfobox td {border-width:0px;vertical-align:top;} -.userinfobox .side {width:120px;text-align:center;} -.userinfobox .list .label {font-weight:bold;text-align:right;} - -/** Forum **/ -.forumheaderlist, -.forumpost {margin-top:15px;border:1px solid #DDD;background-color:#EEE;} -.forumpost .header {background-color:#C8C9C7;} -.forumpost .topic {padding:7px;} -.forumpost .topic .subject {font-weight:bold;} -.forumpost .topic .author {font-size:0.8em;} -.forumpost .left {background-color:#EEE;} -.forumpost .content {background-color:#FFF;border-top:1px solid #333;} -.forumpost .content .posting {padding:4px;} -.forumpost .options {background-color:#FFF;} -.forumpost .options .commands {font-size:0.9em;clear:both;padding:0.5em 5px 5px;text-align:right;} -.forumpost .content .link {font-size:0.9em;} -.forumpost .content .footer {font-size:0.9em;padding-top:0.5em;text-align:right;} - -/** Calendar **/ -.block.block_calendar_month td, -.block.block_calendar_month th {border-width:0px;font-size:10px;padding:1px;width:14%;line-height:18px;} -#calendar abbr, -.block.block_calendar_month abbr {border-bottom-width:0px;} -#calendar .weekend, -.block.block_calendar_month .weekend {color:#A00;} -#calendar .maincalendar .calendarmonth td.today, -.block.block_calendar_month .today {border:1px solid #444;} -#calendar .eventnone a, -.block.block_calendar_month .eventnone a {color:#444;} - -#calendar {width:99%;margin:0px 1%;border-spacing:5px;border-collapse: separate;} -#calendar td, -#calendar th {border-width:0px;font-size:10px;padding:1px;width:14%;line-height:18px;vertical-align:top;} -#calendar .maincalendar {width:auto;border:1px solid #DDD;} -#calendar .maincalendar .heightcontainer {height:100%;position:relative;margin:1em;} -#calendar .maincalendar .header {padding:5px;font-weight:bold;} -#calendar .maincalendar .header .buttons {float:right;} -#calendar .maincalendar table {width:100%;} -#calendar .maincalendar .calendar-controls {width:100%;overflow:hidden;font-size:1.1em;} -#calendar .maincalendar .calendar-controls .previous {display:block;float:left;width:20%;} -#calendar .maincalendar .calendar-controls .current {display:block;float:left;width:60%;text-align:center;margin-top:0px;} -#calendar .maincalendar .calendar-controls .next {display:block;float:left;width:20%;text-align:right;} -#calendar .sidecalendar {width:200px;} -#calendar .sidecalendar h2, -#calendar .sidecalendar h3 {margin:5px;font-size:95%;} -#calendar .sidecalendar .block {border:1px solid #DDD;margin-bottom:10px;text-align:center;} -#calendar .sidecalendar .block table {margin:0px auto 5px auto;} -#calendar .sidecalendar .block .filters table {width:95%;margin:0px auto 1em auto;} -#calendar .sidecalendar .block .minicalendarblock {border-top:1px solid #DDD;} -#calendar .filters table {padding:2px;background-color: #EEE;border:1px solid #DDD;border-spacing:2px;border-collapse: separate;} -#calendar .filters table td {font-size:100%;width:auto;} -#calendar .filters .eventskey {border:1px solid #444;overflow:hidden;} -#calendar .calendar_event_global {background-color: #D6F8CD;} -#calendar .calendar_event_course {background-color: #FFD3BD;} -#calendar .calendar_event_group {background-color: #FEE7AE;} -#calendar .calendar_event_user {background-color: #DCE7EC;} -#calendar .maincalendar .calendarmonth {border-collapse: separate;} -#calendar .maincalendar .calendarmonth th {font-size:0.9em;border-bottom:2px solid #444;} -#calendar .maincalendar .calendarmonth td {border:1px solid #EEE;border-bottom-color:#CCC;border-right-color:#CCC;height:6em;} -#calendar .maincalendar .calendarmonth td div {margin:4px;font-size:0.9em;} -#calendar .maincalendar .calendarmonth td .day {font-weight:bold;} -#calendar .maincalendar .calendarmonth tr td:first-child {border-left-color:#CCC;} -#calendar .maincalendar .event {border-spacing: 0px;border:1px solid #DDD;background-color:#EEE;} -#calendar .maincalendar .event .picture {width:32px;text-align:center;} -#calendar .maincalendar .event .topic {width:auto;padding:5px;} -#calendar .maincalendar .event .side {width:32px;} -#calendar .maincalendar .event .description {width:auto;border-top:1px solid #DDD;border-left:1px solid #DDD;padding:5px;} -#calendar .maincalendar .bottom {text-align:center;} -#calendar .calendarmonth ul {margin:0px;padding:0px;} -#calendar .calendarmonth ul li {list-style: none;margin:0px;padding:2px;} - -/** User **/ -.user .rolesform, -.user .searchform, -.user #showall, -.user #participantsform {text-align:center;} -.user #participantsform table {margin-top:1em;} -.user #participantsform td {text-align:left;} -.user table.controls {margin:5px auto;border:1px solid #DDD;background-color:#EEE;border-collapse: collapse;} -.user table.controls td {border-width:0px;} \ No newline at end of file diff --git a/theme/formal_white/style/menu.css b/theme/formal_white/style/menu.css new file mode 100755 index 00000000000..5eedc9ef04f --- /dev/null +++ b/theme/formal_white/style/menu.css @@ -0,0 +1,39 @@ +/*#custommenu .yui3-menu ul {background-image:url([[pix:theme|custommenubg]]);background-repeat:repeat-x;background-color:#e1e1df;}*/ +#custommenu .yui3-menu {background-image:url([[pix:theme|custommenubg]]);background-repeat:repeat-x;background-color:#e1e1df;} + +.yui3-skin-sam .yui3-menu-content, +.yui3-skin-sam .yui3-menu .yui3-menu .yui3-menu-content, +.yui3-skin-sam .yui3-menu-horizontal .yui3-menu-label,.yui3-skin-sam .yui3-menu-horizontal .yui3-menuitem-content{ + border:0px none; +} + +/*.yui3-menu ul{ + background:url([[pix:theme|sprite]]) repeat-x 0 0; +}*/ + +.yui3-menu ul li ul{ + background:#fff; +} + +.yui3-menu ul li{ + border-right:1px solid #ccc; +} + +.yui3-menu ul li ul li{ + border-right:none; + /*border-bottom:1px dashed #ccc;*/ + padding:3px; +} + +div.yui3-menu-content { + border:none !important; +} + +ul.first-of-type li a { + border-top:none !important; + border-bottom:none !important; +} + +ul.first-of-type li a:hover { + color:#003466; +} \ No newline at end of file diff --git a/theme/formal_white/style/pagelayout.css b/theme/formal_white/style/pagelayout.css new file mode 100755 index 00000000000..32ebb5dd911 --- /dev/null +++ b/theme/formal_white/style/pagelayout.css @@ -0,0 +1,105 @@ +/************************************************************************ + questo file sovrascrive parzialmente + il corrispondente foglio di stile nel tema "base" + Lo ho ottenuto + - duplicando l'originale + - modificando quanto necessario + - cancellando quanto conservato dell'originale +************************************************************************/ + +/**** + * Three column floating div layout with 2,1,3 column order + * Based on: http://matthewjamestaylor.com/blog/holy-grail-no-quirks-mode.htm + * And: http://matthewjamestaylor.com/blog/ultimate-3-column-holy-grail-pixels.htm + * + * #page + * #page-header + * #page-content + * | #region-main-box + * | #region-post-box + * | #region-main-wrap + * | | #region-main + * | | .region-content + * | #region-pre + * | | .region-content + * | #region-post + * | | .region-content + * #page-footer + * + * The body tag may also contain one of three layout specific classes that describe + * the regions of the page and allow us to theme more easily. + * + * default (no class) = Content + side pre + side post + * side-pre-only = Content + side pre + * side-post-only = Content + side post + * content-only = Content + * + ****/ + +#page-header { + background-color:#E3DFD4; + /* arrotonadamento angoli in alto dell'header */ + -moz-border-radius:6px 6px 0px 0px; /* Firefox */ + -webkit-border-radius:6px 6px 0px 0px; /* Safari, Chrome */ + border-radius:6px 6px 0px 0px; /* CSS3 */ +} +#page-content { + /* arrotonadamento angolo in basso a sx */ + /* -moz-border-radius:0px 0px 0px 6px; /* Firefox */ + /* -webkit-border-radius:0px 0px 0px 6px; /* Safari, Chrome */ + /* border-radius:0px 0px 0px 6px; /* CSS3 */ + background-color:[[setting:blockcolumnbgc]]; /* colore della colonna di sinistra */ + float:none; +} +#page-content #region-main-box { + left:[[setting:blockcolumnwidth]]; + background-color:#FFF; +} +#page-content #region-post-box { + margin-left:[[setting:minusdoubleblockcolumnwidth]]; /*-2*[[setting:blockcolumnwidth]]*/ + /* arrotonadamento angolo in basso a dx */ + /* -moz-border-radius:0px 0px 6px 0px; /* Firefox */ + /* -webkit-border-radius:0px 0px 6px 0px; /* Safari, Chrome */ + /* border-radius:0px 0px 6px 0px; /* CSS3 */ + background-color:[[setting:blockcolumnbgc]]; /* colore del fondo della parte occupata dai contenuti della colonna centrale e della colonna dx */ +} +#page-content #region-main { + margin-left:[[setting:doubleblockcolumnwidth]];/*2*[[setting:blockcolumnwidth]]*/ + background-color:white; /* questo serve a togliere la curvatura dagli angoli della zona centrale */ +} +#page-content #region-pre { + left:[[setting:blockcolumnwidth]]; /*400-[[setting:blockcolumnwidth]]*/ + width:[[setting:blockcolumnwidth]]; + background-color:[[setting:blockcolumnbgc]]; /* colore della colonna di sx */ +} +#page-content #region-post { + width:[[setting:blockcolumnwidth]]; + /* arrotonadamento angolo in basso a dx */ + /* -moz-border-radius:0px 0px 6px 0px; /* Firefox */ + /* -webkit-border-radius:0px 0px 6px 0px; /* Safari, Chrome */ + /* border-radius:0px 0px 6px 0px; /* CSS3 */ + background-color:[[setting:blockcolumnbgc]]; /* colore del fondo della parte occupata dai contenuti della colonna centrale e della colonna dx */ +} +#page-content .region-content { + padding:0.6em 8px 0.1em 8px; /* definisco lo spazio sopra e sotto ai blocchi */ +} + +/** Only side pre **/ + .side-pre-only #page-content #region-post-box {margin-left:-[[setting:blockcolumnwidth]];} + .side-pre-only #page-content #region-main {margin-left:[[setting:blockcolumnwidth]];} + +/** Only side post **/ + .side-post-only #page-content #region-post-box {margin-left:-[[setting:blockcolumnwidth]];} + .side-post-only #page-content #region-main {margin-left:[[setting:blockcolumnwidth]];} + .has_dock.side-post-only .page-middle #region-main {margin-left:[[setting:blockcolumnwidth]];} + +/** Report layout **/ + .pagelayout-report #report-main-content .region-content {margin-left:[[setting:blockcolumnwidth]];} + .pagelayout-report #report-region-pre {width:[[setting:blockcolumnwidth]];} + +/** Correct for right to left languages **/ + .dir-rtl.pagelayout-report #report-main-content .region-content {margin-left:0;margin-right:[[setting:blockcolumnwidth]];} + +/** Stabalise IE6 behaviour on the report layout **/ +/* aggiunti/sovrascritti da me */ + .ie6.pagelayout-report #report-region-wrap {float:none;width:[[setting:blockcolumnwidth]];left:auto;position:absolute;top:0;} \ No newline at end of file diff --git a/theme/formal_white/style/quiz.css b/theme/formal_white/style/quiz.css new file mode 100755 index 00000000000..89c5cc37376 --- /dev/null +++ b/theme/formal_white/style/quiz.css @@ -0,0 +1,31 @@ +/*** + *** Core + ***/ + +/* quiz */ +#page-mod-quiz-edit div.quizpage .pagecontent {background-color:[[setting:blockcolumnbgc]];} +.questionbankwindow h2 {background-image:url([[pix:theme|gradient_h]]);background-repeat:repeat-x;border-top:1px #C6BDA8 solid;background-color:[[setting:blockcolumnbgc]];border-top:1px #C6BDA8 solid;} +#page-mod-quiz-edit .questionbankwindow div.header {background-color:transparent;} +#page-mod-quiz-edit .questionbankwindow div.header .title {color:#000;} +#page-mod-quiz-edit .questionbankwindow div.header a:link, +#page-mod-quiz-edit .questionbankwindow div.header a:visited {color:#0000EF} +#page-mod-quiz-edit div.container div.generalbox {background-color:[[setting:blockcolumnbgc]];padding:1.5em;} +#page-mod-quiz-edit div.questionbank .categoryquestionscontainer, +#page-mod-quiz-edit div.questionbank .categorysortopotionscontainer, +#page-mod-quiz-edit div.questionbank .categorypagingbarcontainer, +#page-mod-quiz-edit div.questionbank .categoryselectallcontainer {padding:0 0 1.5em 0;} +#page-mod-quiz-edit div.questionbank .categorypagingbarcontainer {padding:1em;background-color:[[setting:blockcolumnbgc]];margin:0 -1.2em;border-top:1px [[setting:blockcolumnbgc]] solid;border-bottom:1px [[setting:blockcolumnbgc]] solid;} /* spaziatura sopra e sotto alla tabella con le domande da spostare */ +#page-mod-quiz-edit div.questionbank .categoryquestionscontainer {margin:0 -1.2em -1em -1.2em;} /* tabella con le domande da spostare nel quiz*/ + +#page-mod-quiz-edit div.editq div.question div.content {background-color:[[setting:blockcontentbgc]];} /* la signola domanda nel modello della pagina*/ + +#page-mod-quiz-edit div.question div.content div.questioncontrols {background-color:[[setting:blockcontentbgc]];} /* la X per eliminare la domanda dal modello della pagina */ + +#page-mod-quiz-edit div.question div.content div.points {margin-top:-0.5em;padding-bottom:0.5em;background-color:#EEE;} /* il quadratino del grade */ +#page-mod-quiz-edit div.question div.content div.points {border-color:[[setting:blockcontentbgc]];} + +#page-mod-quiz-edit div.quizpage .pagecontent .pagestatus {background-color:[[setting:blockcontentbgc]];} +#page-mod-quiz-edit .quizpagedelete, +#page-mod-quiz-edit .quizpagedelete img {background-color:transparent;} + +#page-mod-quiz-edit #page-footer {padding:0;} \ No newline at end of file diff --git a/theme/formal_white/style/settings.css b/theme/formal_white/style/settings.css deleted file mode 100644 index 7f7e1a28716..00000000000 --- a/theme/formal_white/style/settings.css +++ /dev/null @@ -1,11 +0,0 @@ -.block .content {background-color:[[setting:backgroundcolor]];} -#page-content #region-main-box {left:[[setting:regionwidth]];} -#page-content #region-post-box {margin-left:-[[setting:regionwidthdouble]];} -#page-content #region-pre {width:[[setting:regionwidth]];left:[[setting:regionwidth]];} -#page-content #region-post {width:[[setting:regionwidth]];} -#page-content #region-main {margin-left:[[setting:regionwidthdouble]];} -.side-pre-only #page-content #region-post-box {margin-left:-[[setting:regionwidth]];} -.side-pre-only #page-content #region-main {margin-left:[[setting:regionwidth]];} - -/** Custom CSS **/ -[[setting:customcss]] \ No newline at end of file diff --git a/theme/formal_white/style/tabs.css b/theme/formal_white/style/tabs.css new file mode 100644 index 00000000000..17c7038c485 --- /dev/null +++ b/theme/formal_white/style/tabs.css @@ -0,0 +1,171 @@ +/** + * Tabs + */ +.tabtree { + position:relative; + margin-bottom:3.5em; +} +.tabtree .tabrow0 { + text-align:center; + width:100%; + margin:1em 0px; +} +/* serve a qualcosa? */ +.tabtree ul li.here .empty { + display: none; +} +.tabtree .tabrow0 li { + display:inline; + margin-right:-4px; +} +.tabtree .tabrow0 li.here { + font-weight: normal; +} +.tabtree .tabrow0 li.here .empty { + display: block; + height: 1px; + overflow: hidden; + padding: 0px; + position: absolute; + width: 100%; + bottom: -4px; +} +.tabtree .tabrow0 li.here a { + position:relative; + z-index:102; +} +.tabtree .tabrow0 li a { + background-image:url([[pix:theme|tab/left]]); + padding-left:14px; + padding-top:10px; + background-repeat:no-repeat; + padding-bottom:3px; + margin-bottom:-1px; + + background-color:transparent; + border:none; +} +.tabtree .tabrow0 li a:hover { + background-image:url([[pix:theme|tab/left_hover]]); +} +.tabtree .tabrow0 li a span { + background-image:url([[pix:theme|tab/right]]); + background-repeat:no-repeat; + background-position:100% 0%; + padding-right:14px; + padding-top:10px; + padding-bottom:3px; +} +.tabtree .tabrow0 li a:hover span { + background-image:url([[pix:theme|tab/right_hover]]); +} +.tabtree .tabrow0 ul, +.tabtree .tabrow0 div { + background-image:url([[pix:theme|tab/tabrow1]]); + background-position:0% 50%; + position:absolute; + width:100%; + border-top:1px solid #aaa; + padding:0.25em 0px; + top:100%; + margin:0px; +} +.tabtree .tabrow0 .empty { + height:1px; + overflow:hidden; + padding:0px; + position:absolute; +} +.tabtree .tabrow1 li a, +.tabtree .tabrow1 li a:hover, +.tabtree .tabrow1 li a span, +.tabtree .tabrow1 li a:hover span { + background-image:none !important; +} + +.groupmanagementtable { + width:90%; +} +.groupmanagementtable td { + vertical-align:top; + border-width:0px; +} +.groupmanagementtable td p { + margin:0px; +} + +.ie7 .tabtree .tabrow0 li { + margin-left: 0; +} + +.ie7 .tabtree .tabrow0 li.first { + margin-right: -4px; +} + +.ie7 .tabtree .tabrow0 li.onerow { + margin-right: 0; +} + +.ie7 .tabtree .tabrow0 a { + display: inline-block; + padding: 8px 0 0.35em 13px; + line-height: 1.5em; +} + +.ie7 .tabtree .tabrow0 a span { + padding: 10px 1em 10px 0; +} + +.ie7 .tabtree .tabrow0 div { + top: 2.6em; + padding: 0.2em 0; +} + +.ie7 .tabtree .tabrow0 div.empty { + margin-right: 0; +} + +.ie7.mod-quiz div.tabtree a span img.iconsmall { + margin: 0; + vertical-align: baseline; + position: relative; + top: 2px; +} + +.ie6 .tabtree { + height: 100%; +} + +.ie6 .tabtree .tabrow0 { + padding-top: 10px; +} + +.ie6 .tabtree .tabrow0 li { + margin-left: 0; +} + +.ie6 .tabtree .tabrow0 li.first { + margin-left: -4px; + margin-right: -4px; +} + +.ie6 .tabtree .tabrow0 li.last a { + margin-right: 0; +} + +.ie6 .tabtree .tabrow0 li.onerow { + margin-right: 0; +} + +.ie6 .tabtree .tabrow0 a { + padding: 0 0 0 13px; +} + +.ie6 .tabtree .tabrow0 a span { + padding: 12px 1em 4px 0; +} + +.ie6 .tabtree .tabrow0 div { + top: 3.5em; + padding: 0.2em 0; +} \ No newline at end of file From 0e412e87a4054aea19becbd61a5b170c63074f12 Mon Sep 17 00:00:00 2001 From: kordan Date: Mon, 7 Mar 2011 15:29:08 +0100 Subject: [PATCH 115/369] theme-formal_white MDL-26300, MDL-25628 , MDL-25520 one more setting and logos with transparent background to allow custom header background color --- .../lang/en/theme_formal_white.php | 47 +-- theme/formal_white/layout/frontpage.php | 31 +- theme/formal_white/layout/general.php | 31 +- theme/formal_white/lib.php | 42 ++- theme/formal_white/pix/logo.jpg | Bin 50738 -> 0 bytes theme/formal_white/pix/logo.png | Bin 0 -> 41520 bytes theme/formal_white/pix/logo_small.jpg | Bin 3093 -> 0 bytes theme/formal_white/pix/logo_small.png | Bin 0 -> 15916 bytes theme/formal_white/settings.php | 12 +- theme/formal_white/style/core.css | 308 +++++++++--------- theme/formal_white/style/formal_white.css | 28 +- theme/formal_white/style/frame.css | 12 +- theme/formal_white/style/menu.css | 22 +- theme/formal_white/style/pagelayout.css | 2 +- theme/formal_white/style/tabs.css | 64 ++-- 15 files changed, 312 insertions(+), 287 deletions(-) delete mode 100755 theme/formal_white/pix/logo.jpg create mode 100644 theme/formal_white/pix/logo.png delete mode 100644 theme/formal_white/pix/logo_small.jpg create mode 100644 theme/formal_white/pix/logo_small.png diff --git a/theme/formal_white/lang/en/theme_formal_white.php b/theme/formal_white/lang/en/theme_formal_white.php index accb3b0e1f4..d47e3336286 100755 --- a/theme/formal_white/lang/en/theme_formal_white.php +++ b/theme/formal_white/lang/en/theme_formal_white.php @@ -29,38 +29,38 @@ $string['region-side-pre'] = 'Left'; $string['choosereadme'] = '
-
+
-

Formal White

- +

Formal White

+ -

Theme Discussion Forum:

-

http://moodle.org/mod/forum/view.php?id=46

+

Theme Discussion Forum:

+

http://moodle.org/mod/forum/view.php?id=46

-

Theme Credits

-

http://docs.moodle.org/en/Theme_credits

+

Theme Credits

+

http://docs.moodle.org/en/Theme_credits

-

Theme Documentation:

-

http://docs.moodle.org/en/Themes

+

Theme Documentation:

+

http://docs.moodle.org/en/Themes

-

Report a bug:

-

http://tracker.moodle.org

-
+

Report a bug:

+

http://tracker.moodle.org

+
-
+
-

About

-

Formal White is a fluid-width, three-column theme ported over to 2.0 from Moodle 1.X.

+

About

+

Formal White is a fluid-width, three-column theme ported over to 2.0 from Moodle 1.X.

-

Tweaks

-

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it, then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

+

Tweaks

+

This theme is built upon both Base and Canvas, two parent themes included in the Moodle core. If you want to modify this theme, we recommend that you first duplicate it, then rename it before making your changes. This will prevent your customized theme from being overwritten by future Moodle upgrades, and you\'ll still have the original files if you make a mess. More information on modifying themes can be found in the MoodleDocs.

-

Credits

-

This theme was coded and is maintained by MediaTouch 2000.

+

Credits

+

This theme was coded and is maintained by MediaTouch 2000.

-

License

-

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License. -

+

License

+

This, and all other themes included in the Moodle core, are licensed under the GNU General Public License. +

'; $string['configtitle'] = 'Formal white theme'; @@ -75,6 +75,9 @@ $string['heading'] = 'Display page heading'; $string['blockcolumnwidth'] = 'Blocks colum width'; $string['blockcolumnwidthdesc'] = 'This sets the blocks column width for the theme. Using widths lower than 200px, the calendar block is not supposed to fit.'; +$string['headerbgc'] = 'Header background colour'; +$string['headerbgcdesc'] = 'This sets the blocks header background colour for the theme.'; + $string['blockcontentbgc'] = 'Blocks content background colour'; $string['blockcontentbgcdesc'] = 'This sets the blocks content background colour for the theme.'; diff --git a/theme/formal_white/layout/frontpage.php b/theme/formal_white/layout/frontpage.php index 3bdca7efa32..626b0b5c776 100755 --- a/theme/formal_white/layout/frontpage.php +++ b/theme/formal_white/layout/frontpage.php @@ -150,6 +150,7 @@ if ($hasframe) { ?> if ($hasfooter) { + if ($hasframe) { ?> @@ -159,37 +160,36 @@ if ($hasfooter) {
 
- -
- theme->settings->footnote; ?> -
+ +
+ theme->settings->footnote; ?> +
-
-
 
-
+
+
 
+
- +
+
 
+
- - - + + standard_end_of_body_html() ?> diff --git a/theme/nimble/layout/general.php b/theme/nimble/layout/general.php index 7cb973ba892..cae203a96e0 100644 --- a/theme/nimble/layout/general.php +++ b/theme/nimble/layout/general.php @@ -35,7 +35,7 @@ echo $OUTPUT->doctype() ?> standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -51,7 +51,7 @@ echo $OUTPUT->doctype() ?>
@@ -85,7 +85,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -106,12 +106,12 @@ echo $OUTPUT->doctype() ?>
- +
- +
@@ -123,7 +123,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -137,9 +137,9 @@ echo $OUTPUT->doctype() ?> - + - + @@ -153,7 +153,7 @@ echo $OUTPUT->doctype() ?> ?> - + standard_end_of_body_html() ?> diff --git a/theme/nonzero/layout/frontpage.php b/theme/nonzero/layout/frontpage.php index 7fdcfc9b233..9da35f2320e 100644 --- a/theme/nonzero/layout/frontpage.php +++ b/theme/nonzero/layout/frontpage.php @@ -31,11 +31,11 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -49,15 +49,15 @@ echo $OUTPUT->doctype() ?> echo $OUTPUT->login_info(); echo $OUTPUT->lang_menu(); echo $PAGE->headingmenu; - ?> + ?>
- + - + @@ -67,7 +67,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -75,7 +75,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -83,7 +83,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -91,7 +91,7 @@ echo $OUTPUT->doctype() ?>
- +
diff --git a/theme/nonzero/layout/general.php b/theme/nonzero/layout/general.php index ea063834de1..3f2013f72e8 100644 --- a/theme/nonzero/layout/general.php +++ b/theme/nonzero/layout/general.php @@ -28,7 +28,7 @@ echo $OUTPUT->doctype() ?> standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -68,7 +68,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -76,7 +76,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -84,7 +84,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -92,7 +92,7 @@ echo $OUTPUT->doctype() ?>
- +
diff --git a/theme/overlay/layout/frontpage.php b/theme/overlay/layout/frontpage.php index 0e8a6173ac4..6adb5eb83ce 100644 --- a/theme/overlay/layout/frontpage.php +++ b/theme/overlay/layout/frontpage.php @@ -33,11 +33,11 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -54,7 +54,7 @@ echo $OUTPUT->doctype() ?> echo $OUTPUT->login_info(); echo $OUTPUT->lang_menu(); echo $PAGE->headingmenu; - ?> + ?>
@@ -67,24 +67,24 @@ echo $OUTPUT->doctype() ?>
- +
- +

heading ?>

- -
+ +
- - - + + +
- +
@@ -92,7 +92,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -100,7 +100,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -117,7 +117,7 @@ echo $OUTPUT->doctype() ?> - + doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -54,7 +54,7 @@ echo $OUTPUT->doctype() ?> echo $OUTPUT->login_info(); echo $OUTPUT->lang_menu(); echo $PAGE->headingmenu; - ?> + ?>
@@ -67,9 +67,9 @@ echo $OUTPUT->doctype() ?>
- +
- +
@@ -77,27 +77,27 @@ echo $OUTPUT->doctype() ?> - +
- + - +
- - - + + +
- +
@@ -105,7 +105,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -113,7 +113,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -130,9 +130,9 @@ echo $OUTPUT->doctype() ?> - + - + login_info(); echo $OUTPUT->home_link(); diff --git a/theme/serenity/layout/embedded.php b/theme/serenity/layout/embedded.php index 5d222025429..a5dd7414ed0 100644 --- a/theme/serenity/layout/embedded.php +++ b/theme/serenity/layout/embedded.php @@ -5,7 +5,7 @@ standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/serenity/layout/frontpage.php b/theme/serenity/layout/frontpage.php index 5156de9f424..12e94f90fa5 100644 --- a/theme/serenity/layout/frontpage.php +++ b/theme/serenity/layout/frontpage.php @@ -2,7 +2,7 @@ $hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); $hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); - + $showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); $showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); @@ -23,17 +23,17 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
- + - +
- + @@ -55,7 +55,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -63,7 +63,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -71,7 +71,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -79,7 +79,7 @@ echo $OUTPUT->doctype() ?>
- +
diff --git a/theme/serenity/layout/general.php b/theme/serenity/layout/general.php index aa79557947c..367f4d95b2c 100644 --- a/theme/serenity/layout/general.php +++ b/theme/serenity/layout/general.php @@ -25,7 +25,7 @@ echo $OUTPUT->doctype() ?> standard_head_html() ?> - + standard_top_of_body_html() ?>
@@ -33,7 +33,7 @@ echo $OUTPUT->doctype() ?> - + - + @@ -64,7 +64,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -72,7 +72,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -80,7 +80,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -88,7 +88,7 @@ echo $OUTPUT->doctype() ?>
- +
diff --git a/theme/sky_high/layout/frontpage.php b/theme/sky_high/layout/frontpage.php index 0dbe3cc0787..7d2e3a7ba82 100644 --- a/theme/sky_high/layout/frontpage.php +++ b/theme/sky_high/layout/frontpage.php @@ -2,7 +2,7 @@ $hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); $hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); - + $showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); $showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); @@ -38,17 +38,17 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
- + - + - +
- +
- +
@@ -89,7 +89,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -97,7 +97,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -105,7 +105,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -113,7 +113,7 @@ echo $OUTPUT->doctype() ?> - + @@ -131,7 +131,7 @@ echo $OUTPUT->doctype() ?>
- home_link(); echo $OUTPUT->standard_end_of_body_html() ?>
diff --git a/theme/sky_high/layout/general.php b/theme/sky_high/layout/general.php index e8116f705dc..d26b6fe417a 100644 --- a/theme/sky_high/layout/general.php +++ b/theme/sky_high/layout/general.php @@ -38,17 +38,17 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
- + - + - + @@ -85,14 +85,14 @@ echo $OUTPUT->doctype() ?>
- - - + + +
- +
@@ -100,7 +100,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -108,7 +108,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -116,7 +116,7 @@ echo $OUTPUT->doctype() ?>
- +
@@ -124,7 +124,7 @@ echo $OUTPUT->doctype() ?> - + @@ -142,7 +142,7 @@ echo $OUTPUT->doctype() ?>
- home_link(); echo $OUTPUT->standard_end_of_body_html() ?>
diff --git a/theme/sky_high/layout/report.php b/theme/sky_high/layout/report.php index 3bd42c8571f..9c8427fac51 100644 --- a/theme/sky_high/layout/report.php +++ b/theme/sky_high/layout/report.php @@ -32,10 +32,10 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/splash/layout/general.php b/theme/splash/layout/general.php index 09da6af83a5..d17190e7e28 100644 --- a/theme/splash/layout/general.php +++ b/theme/splash/layout/general.php @@ -37,10 +37,10 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/splash/layout/report.php b/theme/splash/layout/report.php index dad56b6f559..ff92748c646 100644 --- a/theme/splash/layout/report.php +++ b/theme/splash/layout/report.php @@ -32,10 +32,10 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/standardold/layout/embedded.php b/theme/standardold/layout/embedded.php index 5d222025429..a5dd7414ed0 100644 --- a/theme/standardold/layout/embedded.php +++ b/theme/standardold/layout/embedded.php @@ -5,7 +5,7 @@ standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/standardold/layout/frontpage.php b/theme/standardold/layout/frontpage.php index dbd89d0bac7..857f9007e79 100644 --- a/theme/standardold/layout/frontpage.php +++ b/theme/standardold/layout/frontpage.php @@ -25,10 +25,10 @@ echo $OUTPUT->doctype() ?> <?php echo $PAGE->title ?> - + standard_head_html() ?> - + standard_top_of_body_html() ?>
diff --git a/theme/standardold/layout/general.php b/theme/standardold/layout/general.php index 79bee9905a8..bac2689ed57 100644 --- a/theme/standardold/layout/general.php +++ b/theme/standardold/layout/general.php @@ -31,7 +31,7 @@ echo $OUTPUT->doctype() ?> standard_head_html() ?> - + standard_top_of_body_html() ?>
From c102060deb7e74d8a2c2cb7409db76cd61f677c7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 16:04:33 +0200 Subject: [PATCH 198/369] MDL-26951 fix removing of archetype from role --- admin/roles/lib.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/roles/lib.php b/admin/roles/lib.php index e2113400017..fc6e7d8bf9e 100644 --- a/admin/roles/lib.php +++ b/admin/roles/lib.php @@ -628,7 +628,7 @@ class define_role_table_advanced extends capability_table_with_risks { // Legacy type. $archetype = optional_param('archetype', null, PARAM_RAW); - if ($archetype) { + if (isset($archetype)) { $archetypes = get_role_archetypes(); if (isset($archetypes[$archetype])){ $this->role->archetype = $archetype; @@ -716,7 +716,6 @@ class define_role_table_advanced extends capability_table_with_risks { } protected function get_archetype_field($id) { - global $OUTPUT; $options = array(); $options[''] = get_string('none'); foreach(get_role_archetypes() as $type) { From d38f419d5cc268580a99751a32359c14b558e30a Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 16:14:22 +0200 Subject: [PATCH 199/369] MDL-26987 fix invalid DML syntax in spam cleaner tool --- admin/report/spamcleaner/index.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/admin/report/spamcleaner/index.php b/admin/report/spamcleaner/index.php index eeb2f05986a..b5f1880031f 100644 --- a/admin/report/spamcleaner/index.php +++ b/admin/report/spamcleaner/index.php @@ -151,19 +151,21 @@ function search_spammers($keywords) { $params = array('userid'=>$USER->id); $keywordfull = array(); + $i = 0; foreach ($keywords as $keyword) { - $keywordfull[] = $DB->sql_like('description', ':descpat', false); - $params['descpat'] = "%$keyword%"; - $keywordfull2[] = $DB->sql_like('p.summary', ':sumpat', false); - $params['sumpat'] = "%$keyword%"; + $keywordfull[] = $DB->sql_like('description', ':descpat'.$i, false); + $params['descpat'.$i] = "%$keyword%"; + $keywordfull2[] = $DB->sql_like('p.summary', ':sumpat'.$i, false); + $params['sumpat'.$i] = "%$keyword%"; + $i++; } $conditions = '( '.implode(' OR ', $keywordfull).' )'; $conditions2 = '( '.implode(' OR ', $keywordfull2).' )'; $sql = "SELECT * FROM {user} WHERE deleted = 0 AND id <> :userid AND $conditions"; // Exclude oneself $sql2 = "SELECT u.*, p.summary FROM {user} AS u, {post} AS p WHERE $conditions2 AND u.deleted = 0 AND u.id=p.userid AND u.id <> :userid"; - $spamusers_desc = $DB->get_recordset_sql($sql); - $spamusers_blog = $DB->get_recordset_sql($sql2); + $spamusers_desc = $DB->get_recordset_sql($sql, $params); + $spamusers_blog = $DB->get_recordset_sql($sql2, $params); $keywordlist = implode(', ', $keywords); echo $OUTPUT->box(get_string('spamresult', 'report_spamcleaner').s($keywordlist)).' ...'; From ce8b66c67f9ac0122ddf637ce4e37e2f7fe9b61f Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 16:39:27 +0200 Subject: [PATCH 200/369] MDL-26881 work around the block context setting problems --- lib/pagelib.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/pagelib.php b/lib/pagelib.php index 7764aba2b55..2fef3af923e 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -762,6 +762,8 @@ class moodle_page { // fine - no change needed } else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) { // hmm - not ideal, but it might produce too many warnings due to the design of require_login + } else if ($this->_context->contextlevel == CONTEXT_MODULE and $this->_context->id == get_parent_contextid($context)) { + // hmm - most probably somebody did require_login() and after that set the block context } else { // we do not want devs to do weird switching of context levels on the fly, // because we might have used the context already such as in text filter in page title @@ -803,8 +805,12 @@ class moodle_page { $cm = $modinfo->get_cm($cm->id); } $this->_cm = $cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - $this->set_context($context); // the content of page MUST match the cm, this prints warning if there is any problem + + // unfortunately the context setting is a mess, let's try to work around some common block problems and show some debug messages + if (empty($this->_context) or $this->_context->contextlevel != CONTEXT_BLOCK) { + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + $this->set_context($context); + } if ($module) { $this->set_activity_record($module); From c6a074f867ed3c0e24fb69045cca241fd77080e9 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 17:19:23 +0200 Subject: [PATCH 201/369] MDL-26795 fix incorrect location of email change strings AMOS BEGIN MOV [auth_emailchangecancel,auth_email],[emailchangecancel,core_auth] MOV [auth_emailchangepending,auth_email],[emailchangepending,core_auth] MOV [auth_emailupdate,auth_email],[emailupdate,core_auth] MOV [auth_emailnowexists,auth_email],[emailnowexists,core_auth] MOV [auth_emailupdatemessage,auth_email],[emailupdatemessage,core_auth] MOV [auth_emailupdatesuccess,auth_email],[emailupdatesuccess,core_auth] MOV [auth_emailupdatetitle,auth_email],[emailupdatetitle,core_auth] CPY [auth_emailnoemail,auth_email],[noemail,auth_ldap] AMOS END --- auth/email/lang/en/auth_email.php | 15 --------------- auth/ldap/auth.php | 2 +- auth/ldap/lang/en/auth_ldap.php | 1 + lang/en/auth.php | 11 +++++++++++ user/edit.php | 6 +++--- user/editlib.php | 4 ++-- user/emailupdate.php | 10 +++++----- 7 files changed, 23 insertions(+), 26 deletions(-) diff --git a/auth/email/lang/en/auth_email.php b/auth/email/lang/en/auth_email.php index 7e7df487b36..00a0463c3ef 100644 --- a/auth/email/lang/en/auth_email.php +++ b/auth/email/lang/en/auth_email.php @@ -24,23 +24,8 @@ */ $string['auth_emaildescription'] = 'Email confirmation is the default authentication method. When the user signs up, choosing their own new username and password, a confirmation email is sent to the user\'s email address. This email contains a secure link to a page where the user can confirm their account. Future logins just check the username and password against the stored values in the Moodle database.'; -$string['auth_emailchangecancel'] = 'Cancel email change'; -$string['auth_emailchangepending'] = 'Change pending. Open the link sent to you at {$a->preference_newemail}.'; $string['auth_emailnoemail'] = 'Tried to send you an email but failed!'; -$string['auth_emailnoinsert'] = 'Could not add your record to the database!'; -$string['auth_emailnowexists'] = 'The email address you tried to assign to your profile has been assigned to someone else since your original request. Your request for change of email address is hereby cancelled, but you may try again with a different address.'; $string['auth_emailrecaptcha'] = 'Adds a visual/audio confirmation form element to the signup page for email self-registering users. This protects your site against spammers and contributes to a worthwhile cause. See http://recaptcha.net/learnmore.html for more details.
PHP cURL extension is required.'; $string['auth_emailrecaptcha_key'] = 'Enable reCAPTCHA element'; $string['auth_emailsettings'] = 'Settings'; -$string['auth_emailupdate'] = 'Email address update'; -$string['auth_emailupdatemessage'] = 'Dear {$a->fullname}, - -You have requested a change of your email address for your user account at {$a->site}. Please open the following URL in your browser in order to confirm this change. - -{$a->url}'; -$string['auth_emailupdatesuccess'] = 'Email address of user {$a->fullname} was successfully updated to {$a->email}.'; -$string['auth_emailupdatetitle'] = 'Confirmation of email update at {$a->site}'; -$string['auth_changingemailaddress'] = 'You have requested a change of email address, from {$a->oldemail} to {$a->newemail}. For security reasons, we are sending you an email message at the new address to confirm that it belongs to you. Your email address will be updated as soon as you open the URL sent to you in that message.'; -$string['auth_invalidnewemailkey'] = 'Error: if you are trying to confirm a change of email address, you may have made a mistake in copying the URL we sent you by email. Please copy the address and try again.'; -$string['auth_outofnewemailupdateattempts'] = 'You have run out of allowed attempts to update your email address. Your update request has been cancelled.'; $string['pluginname'] = 'Email-based self-registration'; diff --git a/auth/ldap/auth.php b/auth/ldap/auth.php index d9cd436d4ce..1fd39092ba4 100644 --- a/auth/ldap/auth.php +++ b/auth/ldap/auth.php @@ -502,7 +502,7 @@ class auth_plugin_ldap extends auth_plugin_base { events_trigger('user_created', $user); if (! send_confirmation_email($user)) { - print_error('auth_emailnoemail', 'auth_email'); + print_error('noemail', 'auth_ldap'); } if ($notify) { diff --git a/auth/ldap/lang/en/auth_ldap.php b/auth/ldap/lang/en/auth_ldap.php index 7962513b9ca..bbb0ddb20d5 100644 --- a/auth/ldap/lang/en/auth_ldap.php +++ b/auth/ldap/lang/en/auth_ldap.php @@ -114,6 +114,7 @@ $string['morethanoneuser'] = 'Strange! More than one user record found in ldap. $string['needbcmath'] = 'You need the BCMath extension to use grace logins with Active Directory'; $string['needmbstring'] = 'You need the mbstring extension to change passwords in Active Directory'; $string['nodnforusername'] = 'Error in user_update_password(). No DN for: {$a->username}'; +$string['noemail'] = 'Tried to send you an email but failed!'; $string['notcalledfromserver'] = 'Should not be called from the web server!'; $string['noupdatestobedone'] = "No updates to be done\n"; $string['nouserentriestoremove'] = "No user entries to be removed\n"; diff --git a/lang/en/auth.php b/lang/en/auth.php index 072dc59bf8b..5e68e8edaf8 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -60,6 +60,17 @@ $string['auth_user_creation'] = 'New (anonymous) users can create user accounts $string['auth_usernameexists'] = 'Selected username already exists. Please choose a new one.'; $string['auto_add_remote_users'] = 'Auto add remote users'; $string['createpasswordifneeded'] = 'Create password if needed'; +$string['emailchangecancel'] = 'Cancel email change'; +$string['emailchangepending'] = 'Change pending. Open the link sent to you at {$a->preference_newemail}.'; +$string['emailnowexists'] = 'The email address you tried to assign to your profile has been assigned to someone else since your original request. Your request for change of email address is hereby cancelled, but you may try again with a different address.'; +$string['emailupdate'] = 'Email address update'; +$string['emailupdatemessage'] = 'Dear {$a->fullname}, + +You have requested a change of your email address for your user account at {$a->site}. Please open the following URL in your browser in order to confirm this change. + +{$a->url}'; +$string['emailupdatesuccess'] = 'Email address of user {$a->fullname} was successfully updated to {$a->email}.'; +$string['emailupdatetitle'] = 'Confirmation of email update at {$a->site}'; $string['enterthenumbersyouhear'] = 'Enter the numbers you hear'; $string['enterthewordsabove'] = 'Enter the words above'; $string['errormaxconsecutiveidentchars'] = 'Passwords must have at most {$a} consecutive identical characters.'; diff --git a/user/edit.php b/user/edit.php index 379fa4214b6..5e8283503db 100644 --- a/user/edit.php +++ b/user/edit.php @@ -169,7 +169,7 @@ if ($usernew = $userform->get_data()) { $usernew->preference_newemailattemptsleft = 3; $a->oldemail = $usernew->email = $user->email; - $email_changed_html = $OUTPUT->box(get_string('auth_changingemailaddress', 'auth_email', $a), 'generalbox', 'notice'); + $email_changed_html = $OUTPUT->box(get_string('auth_changingemailaddress', 'auth', $a), 'generalbox', 'notice'); $email_changed_html .= $OUTPUT->continue_button("$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id"); $email_changed = true; } @@ -225,8 +225,8 @@ if ($usernew = $userform->get_data()) { $a->site = $SITE->fullname; $a->fullname = fullname($user, true); - $emailupdatemessage = get_string('auth_emailupdatemessage', 'auth_email', $a); - $emailupdatetitle = get_string('auth_emailupdatetitle', 'auth_email', $a); + $emailupdatemessage = get_string('emailupdatemessage', 'auth', $a); + $emailupdatetitle = get_string('emailupdatetitle', 'auth', $a); //email confirmation directly rather than using messaging so they will definitely get an email if (!$mail_results = email_to_user($temp_user, get_admin(), $emailupdatetitle, $emailupdatemessage)) { diff --git a/user/editlib.php b/user/editlib.php index 61149242973..e7ea1c7c78f 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -106,9 +106,9 @@ function useredit_shared_definition(&$mform, $editoroptions = null) { // Do not show email field if change confirmation is pending if (!empty($CFG->emailchangeconfirmation) and !empty($user->preference_newemail)) { - $notice = get_string('auth_emailchangepending', 'auth_email', $user); + $notice = get_string('emailchangepending', 'auth', $user); $notice .= '
' - . get_string('auth_emailchangecancel', 'auth_email') . ''; + . get_string('emailchangecancel', 'auth') . ''; $mform->addElement('static', 'emailpending', get_string('email'), $notice); } else { $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); diff --git a/user/emailupdate.php b/user/emailupdate.php index 044a45aa5c2..602aa164017 100644 --- a/user/emailupdate.php +++ b/user/emailupdate.php @@ -40,7 +40,7 @@ if (!$user = $DB->get_record('user', array('id' => $id))) { $preferences = get_user_preferences(null, null, $user->id); $a = new stdClass(); $a->fullname = fullname($user, true); -$stremailupdate = get_string('auth_emailupdate', 'auth_email', $a); +$stremailupdate = get_string('emailupdate', 'auth', $a); $PAGE->set_title(format_string($SITE->fullname) . ": $stremailupdate"); $PAGE->set_heading(format_string($SITE->fullname) . ": $stremailupdate"); @@ -52,7 +52,7 @@ if (empty($preferences['newemailattemptsleft'])) { } elseif ($preferences['newemailattemptsleft'] < 1) { cancel_email_update($user->id); - $stroutofattempts = get_string('auth_outofnewemailupdateattempts', 'auth_email'); + $stroutofattempts = get_string('auth_outofnewemailupdateattempts', 'auth'); echo $OUTPUT->box($stroutofattempts, 'center'); } elseif ($key == $preferences['newemailkey']) { @@ -62,7 +62,7 @@ if (empty($preferences['newemailattemptsleft'])) { // Detect duplicate before saving if ($DB->get_record('user', array('email' => $user->email))) { - $stremailnowexists = get_string('auth_emailnowexists', 'auth_email'); + $stremailnowexists = get_string('emailnowexists', 'auth'); echo $OUTPUT->box($stremailnowexists, 'center'); echo $OUTPUT->continue_button("$CFG->wwwroot/user/view.php?id=$user->id"); } else { @@ -72,7 +72,7 @@ if (empty($preferences['newemailattemptsleft'])) { $authplugin->user_update($olduser, $user); events_trigger('user_updated', $user); $a->email = $user->email; - $stremailupdatesuccess = get_string('auth_emailupdatesuccess', 'auth_email', $a); + $stremailupdatesuccess = get_string('emailupdatesuccess', 'auth', $a); echo $OUTPUT->box($stremailupdatesuccess, 'center'); echo $OUTPUT->continue_button("$CFG->wwwroot/user/view.php?id=$user->id"); } @@ -80,7 +80,7 @@ if (empty($preferences['newemailattemptsleft'])) { } else { $preferences['newemailattemptsleft']--; set_user_preference('newemailattemptsleft', $preferences['newemailattemptsleft'], $user->id); - $strinvalidkey = get_string('auth_invalidnewemailkey', 'auth_email'); + $strinvalidkey = get_string('auth_invalidnewemailkey', 'auth'); echo $OUTPUT->box($strinvalidkey, 'center'); } From c4dd3bb86f1da06b0a944c120d8bc7a0c494ac24 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 18:22:11 +0200 Subject: [PATCH 202/369] MDL-26913 set timecreated in fortpage of a newly installed site --- lib/db/install.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/db/install.php b/lib/db/install.php index 08937c50c52..03797855fe0 100644 --- a/lib/db/install.php +++ b/lib/db/install.php @@ -45,7 +45,8 @@ function xmldb_main_install() { $newsite->numsections = 0; $newsite->category = 0; $newsite->format = 'site'; // Only for this course - $newsite->timemodified = time(); + $newsite->timecreated = time(); + $newsite->timemodified = $newsite->timecreated; $newsite->id = $DB->insert_record('course', $newsite); $SITE = get_site(); From d099348e320d7512d1b487d3cd87f90d7acd2af5 Mon Sep 17 00:00:00 2001 From: Nikhil Gupta Date: Sun, 27 Mar 2011 20:34:15 +0200 Subject: [PATCH 203/369] MDL-26989 fix incorrect disabling of assignable roles --- enrol/yui/rolemanager/rolemanager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enrol/yui/rolemanager/rolemanager.js b/enrol/yui/rolemanager/rolemanager.js index 0ddb73e3db3..4455b413901 100644 --- a/enrol/yui/rolemanager/rolemanager.js +++ b/enrol/yui/rolemanager/rolemanager.js @@ -391,7 +391,7 @@ YUI.add('moodle-enrol-rolemanager', function(Y) { } var node = null; for (var i in this.roles) { - if (node = this.get('contentNode').one('#add_assignable_role_'+i)) { + if (node = this.get('contentNode').one('#add_assignable_role_'+this.roles[i])) { node.removeAttribute('disabled'); } } From 9683db71c9db8674e44690fdaf3c9a3ad149e613 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 10:54:29 +0000 Subject: [PATCH 204/369] MDL-26425 tablelib mass whitespace clean-up. --- lib/tablelib.php | 401 +++++++++++++++++++++++------------------------ 1 file changed, 200 insertions(+), 201 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 975b41823a0..0202b624f44 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -22,6 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + defined('MOODLE_INTERNAL') || die(); /** TABLE_VAR_SORT = 1 */ @@ -42,6 +43,7 @@ define('TABLE_P_TOP', 1); /** TABLE_P_BOTTOM = 2 */ define('TABLE_P_BOTTOM', 2); + /** * @package moodlecore * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} @@ -79,7 +81,6 @@ class flexible_table { */ var $showdownloadbuttonsat= array(TABLE_P_TOP); - /** * @var string Key of field returned by db query that is the id field of the * user table or equivalent. @@ -142,8 +143,8 @@ class flexible_table { * @param string $sheettitle title for downloaded data. * @return string download type. One of csv, tsv, xhtml, ods, etc */ - function is_downloading($download = null, $filename='', $sheettitle=''){ - if ($download!==null){ + function is_downloading($download = null, $filename='', $sheettitle='') { + if ($download!==null) { $this->sheettitle = $sheettitle; $this->is_downloadable(true); $this->download = $download; @@ -153,22 +154,21 @@ class flexible_table { return $this->download; } - function export_class_instance(&$exportclass=null){ - if (!is_null($exportclass)){ + function export_class_instance(&$exportclass=null) { + if (!is_null($exportclass)) { $this->started_output = true; $this->exportclass =& $exportclass; $this->exportclass->table =& $this; - } elseif (is_null($this->exportclass) && !empty($this->download)){ + } elseif (is_null($this->exportclass) && !empty($this->download)) { $classname = 'table_'.$this->download.'_export_format'; $this->exportclass = new $classname($this); - if (!$this->exportclass->document_started()){ + if (!$this->exportclass->document_started()) { $this->exportclass->start_document($this->filename); } } return $this->exportclass; } - /** * Probably don't need to call this directly. Calling is_downloading with a * param automatically sets table as downloadable. @@ -178,8 +178,8 @@ class flexible_table { * current state of table. * @return boolean whether table data is set to be downloadable. */ - function is_downloadable($downloadable = null){ - if ($downloadable !== null){ + function is_downloadable($downloadable = null) { + if ($downloadable !== null) { $this->downloadable = $downloadable; } return $this->downloadable; @@ -190,11 +190,10 @@ class flexible_table { * @param array $showat array of postions in which to show download buttons. * Containing TABLE_P_TOP and/or TABLE_P_BOTTOM */ - function show_download_buttons_at($showat){ + function show_download_buttons_at($showat) { $this->showdownloadbuttonsat = $showat; } - /** * Sets the is_sortable variable to the given boolean, sort_default_column to * the given string, and the sort_default_order to the given integer. @@ -222,7 +221,7 @@ class flexible_table { * @param string column name, null means table * @return bool */ - function is_sortable($column=null) { + function is_sortable($column = null) { if (empty($column)) { return $this->is_sortable; } @@ -231,6 +230,7 @@ class flexible_table { } return !in_array($column, $this->column_nosort); } + /** * Sets the is_collapsible variable to the given boolean. * @param bool $bool @@ -278,8 +278,8 @@ class flexible_table { * @return void */ function set_control_variables($variables) { - foreach($variables as $what => $variable) { - if(isset($this->request[$what])) { + foreach ($variables as $what => $variable) { + if (isset($this->request[$what])) { $this->request[$what] = $variable; } } @@ -305,7 +305,7 @@ class flexible_table { * @param integer $column the index of a column. */ function column_suppress($column) { - if(isset($this->column_suppress[$column])) { + if (isset($this->column_suppress[$column])) { $this->column_suppress[$column] = true; } } @@ -317,7 +317,7 @@ class flexible_table { * @return void */ function column_class($column, $classname) { - if(isset($this->column_class[$column])) { + if (isset($this->column_class[$column])) { $this->column_class[$column] = ' '.$classname; // This space needed so that classnames don't run together in the HTML } } @@ -330,7 +330,7 @@ class flexible_table { * @return void */ function column_style($column, $property, $value) { - if(isset($this->column_style[$column])) { + if (isset($this->column_style[$column])) { $this->column_style[$column][$property] = $value; } } @@ -342,7 +342,7 @@ class flexible_table { * @return void */ function column_style_all($property, $value) { - foreach(array_keys($this->columns) as $column) { + foreach (array_keys($this->columns) as $column) { $this->column_style[$column][$property] = $value; } } @@ -353,10 +353,9 @@ class flexible_table { */ function define_baseurl($url) { $this->reseturl = $url; - if(!strpos($url, '?')) { + if (!strpos($url, '?')) { $this->baseurl = $url.'?'; - } - else { + } else { $this->baseurl = $url.'&'; } } @@ -371,7 +370,7 @@ class flexible_table { $this->column_class = array(); $colnum = 0; - foreach($columns as $column) { + foreach ($columns as $column) { $this->columns[$column] = $colnum++; $this->column_style[$column] = array(); $this->column_class[$column] = ''; @@ -387,9 +386,6 @@ class flexible_table { $this->headers = $headers; } - - - /** * Must be called after table is defined. Use methods above first. Cannot * use functions below till after calling this method. @@ -398,7 +394,7 @@ class flexible_table { function setup() { global $SESSION, $CFG; - if(empty($this->columns) || empty($this->uniqueid)) { + if (empty($this->columns) || empty($this->uniqueid)) { return false; } @@ -406,7 +402,7 @@ class flexible_table { $SESSION->flextable = array(); } - if(!isset($SESSION->flextable[$this->uniqueid])) { + if (!isset($SESSION->flextable[$this->uniqueid])) { $SESSION->flextable[$this->uniqueid] = new stdClass; $SESSION->flextable[$this->uniqueid]->uniqueid = $this->uniqueid; $SESSION->flextable[$this->uniqueid]->collapse = array(); @@ -417,45 +413,43 @@ class flexible_table { $this->sess = &$SESSION->flextable[$this->uniqueid]; - if(!empty($_GET[$this->request[TABLE_VAR_SHOW]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_SHOW]]])) { + if (!empty($_GET[$this->request[TABLE_VAR_SHOW]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_SHOW]]])) { // Show this column $this->sess->collapse[$_GET[$this->request[TABLE_VAR_SHOW]]] = false; - } - else if(!empty($_GET[$this->request[TABLE_VAR_HIDE]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_HIDE]]])) { + } else if(!empty($_GET[$this->request[TABLE_VAR_HIDE]]) && isset($this->columns[$_GET[$this->request[TABLE_VAR_HIDE]]])) { // Hide this column $this->sess->collapse[$_GET[$this->request[TABLE_VAR_HIDE]]] = true; - if(array_key_exists($_GET[$this->request[TABLE_VAR_HIDE]], $this->sess->sortby)) { + if (array_key_exists($_GET[$this->request[TABLE_VAR_HIDE]], $this->sess->sortby)) { unset($this->sess->sortby[$_GET[$this->request[TABLE_VAR_HIDE]]]); } } // Now, update the column attributes for collapsed columns - foreach(array_keys($this->columns) as $column) { - if(!empty($this->sess->collapse[$column])) { + foreach (array_keys($this->columns) as $column) { + if (!empty($this->sess->collapse[$column])) { $this->column_style[$column]['width'] = '10px'; } } - if( + if ( !empty($_GET[$this->request[TABLE_VAR_SORT]]) && $this->is_sortable($_GET[$this->request[TABLE_VAR_SORT]]) && (isset($this->columns[$_GET[$this->request[TABLE_VAR_SORT]]]) || (($_GET[$this->request[TABLE_VAR_SORT]] == 'firstname' || $_GET[$this->request[TABLE_VAR_SORT]] == 'lastname') && isset($this->columns['fullname'])) )) { - if(empty($this->sess->collapse[$_GET[$this->request[TABLE_VAR_SORT]]])) { - if(array_key_exists($_GET[$this->request[TABLE_VAR_SORT]], $this->sess->sortby)) { + if (empty($this->sess->collapse[$_GET[$this->request[TABLE_VAR_SORT]]])) { + if (array_key_exists($_GET[$this->request[TABLE_VAR_SORT]], $this->sess->sortby)) { // This key already exists somewhere. Change its sortorder and bring it to the top. $sortorder = $this->sess->sortby[$_GET[$this->request[TABLE_VAR_SORT]]] == SORT_ASC ? SORT_DESC : SORT_ASC; unset($this->sess->sortby[$_GET[$this->request[TABLE_VAR_SORT]]]); $this->sess->sortby = array_merge(array($_GET[$this->request[TABLE_VAR_SORT]] => $sortorder), $this->sess->sortby); - } - else { + } else { // Key doesn't exist, so just add it to the beginning of the array, ascending order $this->sess->sortby = array_merge(array($_GET[$this->request[TABLE_VAR_SORT]] => SORT_ASC), $this->sess->sortby); } // Finally, make sure that no more than $this->maxsortkeys are present into the array - if(!empty($this->maxsortkeys) && ($sortkeys = count($this->sess->sortby)) > $this->maxsortkeys) { - while($sortkeys-- > $this->maxsortkeys) { + if (!empty($this->maxsortkeys) && ($sortkeys = count($this->sess->sortby)) > $this->maxsortkeys) { + while ($sortkeys-- > $this->maxsortkeys) { array_pop($this->sess->sortby); } } @@ -463,23 +457,23 @@ class flexible_table { } // If we didn't sort just now, then use the default sort order if one is defined and the column exists - if(empty($this->sess->sortby) && !empty($this->sort_default_column)) { + if (empty($this->sess->sortby) && !empty($this->sort_default_column)) { $this->sess->sortby = array ($this->sort_default_column => ($this->sort_default_order == SORT_DESC ? SORT_DESC : SORT_ASC)); } - if(isset($_GET[$this->request[TABLE_VAR_ILAST]])) { - if(empty($_GET[$this->request[TABLE_VAR_ILAST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_ILAST]]))) { + if (isset($_GET[$this->request[TABLE_VAR_ILAST]])) { + if (empty($_GET[$this->request[TABLE_VAR_ILAST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_ILAST]]))) { $this->sess->i_last = $_GET[$this->request[TABLE_VAR_ILAST]]; } } - if(isset($_GET[$this->request[TABLE_VAR_IFIRST]])) { - if(empty($_GET[$this->request[TABLE_VAR_IFIRST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_IFIRST]]))) { + if (isset($_GET[$this->request[TABLE_VAR_IFIRST]])) { + if (empty($_GET[$this->request[TABLE_VAR_IFIRST]]) || is_numeric(strpos(get_string('alphabet', 'langconfig'), $_GET[$this->request[TABLE_VAR_IFIRST]]))) { $this->sess->i_first = $_GET[$this->request[TABLE_VAR_IFIRST]]; } } - if(empty($this->baseurl)) { + if (empty($this->baseurl)) { $getcopy = $_GET; unset($getcopy[$this->request[TABLE_VAR_SHOW]]); unset($getcopy[$this->request[TABLE_VAR_HIDE]]); @@ -490,22 +484,20 @@ class flexible_table { $strippedurl = strip_querystring(qualified_me()); - if(!empty($getcopy)) { + if (!empty($getcopy)) { $first = false; $querystring = ''; - foreach($getcopy as $var => $val) { - if(!$first) { + foreach ($getcopy as $var => $val) { + if (!$first) { $first = true; $querystring .= '?'.$var.'='.$val; - } - else { + } else { $querystring .= '&'.$var.'='.$val; } } $this->reseturl = $strippedurl.$querystring; $querystring .= '&'; - } - else { + } else { $this->reseturl = $strippedurl; $querystring = '?'; } @@ -514,7 +506,7 @@ class flexible_table { } // If it's "the first time" we 've been here, forget the previous initials filters - if(qualified_me() == $this->reseturl) { + if (qualified_me() == $this->reseturl) { $this->sess->i_first = ''; $this->sess->i_last = ''; } @@ -542,7 +534,7 @@ class flexible_table { */ public static function get_sort_for_table($uniqueid) { global $SESSION; - if(empty($SESSION->flextable[$uniqueid])) { + if (empty($SESSION->flextable[$uniqueid])) { return ''; } @@ -562,7 +554,7 @@ class flexible_table { public static function construct_order_by($cols) { $bits = array(); - foreach($cols as $column => $order) { + foreach ($cols as $column => $order) { if ($order == SORT_ASC) { $bits[] = $column . ' ASC'; } else { @@ -600,7 +592,7 @@ class flexible_table { * @return integer the offset for LIMIT clause of SQL */ function get_page_start() { - if(!$this->use_pages) { + if (!$this->use_pages) { return ''; } return $this->currpage * $this->pagesize; @@ -610,7 +602,7 @@ class flexible_table { * @return integer the pagesize for LIMIT clause of SQL */ function get_page_size() { - if(!$this->use_pages) { + if (!$this->use_pages) { return ''; } return $this->pagesize; @@ -652,7 +644,7 @@ class flexible_table { * @param $rowwithkeys array * @param string $classname CSS class name to add to this row's tr tag. */ - function add_data_keyed($rowwithkeys, $classname = ''){ + function add_data_keyed($rowwithkeys, $classname = '') { $this->add_data($this->get_row_from_keyed($rowwithkeys), $classname); } @@ -660,7 +652,7 @@ class flexible_table { * Add a seperator line to table. */ function add_separator() { - if(!$this->setup) { + if (!$this->setup) { return false; } $this->add_data(NULL); @@ -678,14 +670,14 @@ class flexible_table { * @return boolean success. */ function add_data($row, $classname = '') { - if(!$this->setup) { + if (!$this->setup) { return false; } - if (!$this->started_output){ + if (!$this->started_output) { $this->start_output(); } - if ($this->exportclass!==null){ - if ($row === null){ + if ($this->exportclass!==null) { + if ($row === null) { $this->exportclass->add_seperator(); } else { $this->exportclass->add_data($row); @@ -696,20 +688,18 @@ class flexible_table { return true; } - - /** * You should call this to finish outputting the table data after adding * data to the table with add_data or add_data_keyed. * */ - function finish_output($closeexportclassdoc = true){ - if ($this->exportclass!==null){ + function finish_output($closeexportclassdoc = true) { + if ($this->exportclass!==null) { $this->exportclass->finish_table(); - if ($closeexportclassdoc){ + if ($closeexportclassdoc) { $this->exportclass->finish_document(); } - }else{ + } else { $this->finish_html(); } } @@ -719,7 +709,7 @@ class flexible_table { * for example. Called only when there is data to display and not * downloading. */ - function wrap_html_start(){ + function wrap_html_start() { } /** @@ -727,24 +717,23 @@ class flexible_table { * for example. Called only when there is data to display and not * downloading. */ - function wrap_html_finish(){ + function wrap_html_finish() { } - /** * * @param array $row row of data from db used to make one row of the table. * @return array one row for the table, added using add_data_keyed method. */ - function format_row($row){ + function format_row($row) { $formattedrow = array(); - foreach (array_keys($this->columns) as $column){ + foreach (array_keys($this->columns) as $column) { $colmethodname = 'col_'.$column; - if (method_exists($this, $colmethodname)){ + if (method_exists($this, $colmethodname)) { $formattedcolumn = $this->$colmethodname($row); } else { $formattedcolumn = $this->other_cols($column, $row); - if ($formattedcolumn===NULL){ + if ($formattedcolumn===NULL) { $formattedcolumn = $row->$column; } } @@ -761,10 +750,10 @@ class flexible_table { * field for the user id. * */ - function col_fullname($row){ + function col_fullname($row) { global $COURSE, $CFG; - if (!$this->download){ + if (!$this->download) { if ($COURSE->id == SITEID) { return ''. fullname($row).''; @@ -781,11 +770,10 @@ class flexible_table { * You can override this method in a child class. See the description of * build_table which calls this method. */ - function other_cols($column, $row){ + function other_cols($column, $row) { return NULL; } - /** * Used from col_* functions when text is to be displayed. Does the * right thing - either converts text to html or strips any html tags @@ -793,16 +781,16 @@ class flexible_table { * are the same as format_text function in weblib.php but some default * options are changed. */ - function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL){ - if (!$this->is_downloading()){ - if (is_null($options)){ + function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) { + if (!$this->is_downloading()) { + if (is_null($options)) { $options = new stdClass; } //some sensible defaults - if (!isset($options->para)){ + if (!isset($options->para)) { $options->para = false; } - if (!isset($options->newlines)){ + if (!isset($options->newlines)) { $options->newlines = false; } if (!isset($options->smiley)) { @@ -822,7 +810,7 @@ class flexible_table { * @deprecated 1.9.2 - Jun 2, 2008 */ function print_html() { - if(!$this->setup) { + if (!$this->setup) { return false; } $this->finish_html(); @@ -833,7 +821,7 @@ class flexible_table { * @return string initial of first name we are currently filtering by */ function get_initial_first() { - if(!$this->use_initials) { + if (!$this->use_initials) { return NULL; } @@ -845,7 +833,7 @@ class flexible_table { * @return string initial of last name we are currently filtering by */ function get_initial_last() { - if(!$this->use_initials) { + if (!$this->use_initials) { return NULL; } @@ -855,7 +843,7 @@ class flexible_table { /** * This function is not part of the public api. */ - function print_initials_bar(){ + function print_initials_bar() { if ((!empty($this->sess->i_last) || !empty($this->sess->i_first) || $this->use_initials) && isset($this->columns['fullname'])) { @@ -865,7 +853,7 @@ class flexible_table { // Bar of first initials echo '
'.get_string('firstname').' : '; - if(!empty($this->sess->i_first)) { + if (!empty($this->sess->i_first)) { echo ''.$strall.''; } else { echo ''.$strall.''; @@ -882,7 +870,7 @@ class flexible_table { // Bar of last initials echo '
'.get_string('lastname').' : '; - if(!empty($this->sess->i_last)) { + if (!empty($this->sess->i_last)) { echo ''.$strall.''; } else { echo ''.$strall.''; @@ -902,7 +890,7 @@ class flexible_table { /** * This function is not part of the public api. */ - function print_nothing_to_display(){ + function print_nothing_to_display() { global $OUTPUT; $this->print_initials_bar(); @@ -912,13 +900,13 @@ class flexible_table { /** * This function is not part of the public api. */ - function get_row_from_keyed($rowwithkeys){ - if (is_object($rowwithkeys)){ + function get_row_from_keyed($rowwithkeys) { + if (is_object($rowwithkeys)) { $rowwithkeys = (array)$rowwithkeys; } $row = array(); - foreach (array_keys($this->columns) as $column){ - if (isset($rowwithkeys[$column])){ + foreach (array_keys($this->columns) as $column) { + if (isset($rowwithkeys[$column])) { $row [] = $rowwithkeys[$column]; } else { $row[] =''; @@ -929,12 +917,12 @@ class flexible_table { /** * This function is not part of the public api. */ - function get_download_menu(){ + function get_download_menu() { $allclasses= get_declared_classes(); $exportclasses = array(); - foreach ($allclasses as $class){ + foreach ($allclasses as $class) { $matches = array(); - if (preg_match('/^table\_([a-z]+)\_export\_format$/', $class, $matches)){ + if (preg_match('/^table\_([a-z]+)\_export\_format$/', $class, $matches)) { $type = $matches[1]; $exportclasses[$type]= get_string("download$type", 'table'); } @@ -945,9 +933,9 @@ class flexible_table { /** * This function is not part of the public api. */ - function download_buttons(){ + function download_buttons() { global $OUTPUT; - if ($this->is_downloadable() && !$this->is_downloading()){ + if ($this->is_downloadable() && !$this->is_downloading()) { $downloadoptions = $this->get_download_menu(); $html = ''; $html .= '
'; @@ -966,9 +954,9 @@ class flexible_table { * needed when you start adding data to the table. * */ - function start_output(){ + function start_output() { $this->started_output = true; - if ($this->exportclass!==null){ + if ($this->exportclass!==null) { $this->exportclass->start_table($this->sheettitle); $this->exportclass->output_headers($this->headers); } else { @@ -1021,10 +1009,11 @@ class flexible_table { $suppress_lastrow = $row; } } + /** * This function is not part of the public api. */ - function finish_html(){ + function finish_html() { global $OUTPUT; if (!$this->started_output) { //no data has been added to the table. @@ -1034,10 +1023,10 @@ class flexible_table { echo html_writer::end_tag('div'); $this->wrap_html_finish(); // Paging bar - if(in_array(TABLE_P_BOTTOM, $this->showdownloadbuttonsat)) { + if (in_array(TABLE_P_BOTTOM, $this->showdownloadbuttonsat)) { echo $this->download_buttons(); } - if($this->use_pages) { + if ($this->use_pages) { $pagingbar = new paging_bar($this->totalrows, $this->currpage, $this->pagesize, $this->baseurl); $pagingbar->pagevar = $this->request[TABLE_VAR_PAGE]; echo $OUTPUT->render($pagingbar); @@ -1047,20 +1036,19 @@ class flexible_table { /** * This function is not part of the public api. */ - function print_headers(){ + function print_headers() { global $CFG, $OUTPUT; echo '
 '.$icon_hide.'
make_styles_string($this->column_style[$column]).'>'; + if (empty($this->sess->collapse[$column])) { if ($this->column_suppress[$column] && $suppress_lastrow !== NULL && $suppress_lastrow[$index] === $data) { - echo ' '; + $content = ' '; } else { - echo $data; + $content = $data; } } else { - echo ' '; + $content = ' '; } - echo '
'; + echo html_writer::end_tag('table'); echo html_writer::end_tag('div'); $this->wrap_html_finish(); + // Paging bar - if (in_array(TABLE_P_BOTTOM, $this->showdownloadbuttonsat)) { + if(in_array(TABLE_P_BOTTOM, $this->showdownloadbuttonsat)) { echo $this->download_buttons(); } - if ($this->use_pages) { + + if($this->use_pages) { $pagingbar = new paging_bar($this->totalrows, $this->currpage, $this->pagesize, $this->baseurl); $pagingbar->pagevar = $this->request[TABLE_VAR_PAGE]; echo $OUTPUT->render($pagingbar); } } } + + protected function show_hide_link($column, $index) { + global $OUTPUT; + // Some headers contain
tags, do not include in title, hence the + // strip tags. + + if (!empty($this->sess->collapse[$column])) { + return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_SHOW] => $column)), + html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/switch_plus'), 'alt' => get_string('show'))), + array('title' => get_string('show') . ' ' . strip_tags($this->headers[$index]))); + + } else if ($this->headers[$index] !== NULL) { + return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_HIDE] => $column)), + html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/switch_minus'), 'alt' => get_string('hide'))), + array('title' => get_string('hide') . ' ' . strip_tags($this->headers[$index]))); + } + } + /** * This function is not part of the public api. */ function print_headers() { global $CFG, $OUTPUT; - echo ''; + echo html_writer::start_tag('tr'); foreach ($this->columns as $column => $index) { - $icon_hide = ''; - $icon_sort = ''; + $icon_hide = ''; if ($this->is_collapsible) { - if (!empty($this->sess->collapse[$column])) { - // some headers contain < br/> tags, do not include in title - $icon_hide = ' '.get_string('show').''; - } else if($this->headers[$index] !== NULL) { - // some headers contain < br/> tags, do not include in title - $icon_hide = ' '.get_string('hide').''; - } + $icon_hide = $this->show_hide_link($column, $index); } $primary_sort_column = ''; @@ -1041,29 +1060,11 @@ class flexible_table { case 'fullname': if ($this->is_sortable($column)) { - $icon_sort_first = $icon_sort_last = ''; - if ($primary_sort_column == 'firstname') { - $lsortorder = get_string('asc'); - if ($primary_sort_order == SORT_ASC) { - $icon_sort_first = ' '.get_string('asc').''; - $fsortorder = get_string('asc'); - } else { - $icon_sort_first = ' '.get_string('desc').''; - $fsortorder = get_string('desc'); - } - } else if($primary_sort_column == 'lastname') { - $fsortorder = get_string('asc'); - if ($primary_sort_order == SORT_ASC) { - $icon_sort_last = ' '.get_string('asc').''; - $lsortorder = get_string('asc'); - } else { - $icon_sort_last = ' '.get_string('desc').''; - $lsortorder = get_string('desc'); - } - } else { - $fsortorder = get_string('asc'); - $lsortorder = get_string('asc'); - } + $firstnamesortlink = $this->sort_link(get_string('firstname'), + 'firstname', $primary_sort_column === 'firstname', $primary_sort_order); + + $lastnamesortlink = $this->sort_link(get_string('lastname'), + 'lastname', $primary_sort_column === 'lastname', $primary_sort_order); $override = new stdClass(); $override->firstname = 'firstname'; @@ -1073,11 +1074,9 @@ class flexible_table { if (($CFG->fullnamedisplay == 'firstname lastname') or ($CFG->fullnamedisplay == 'firstname') or ($CFG->fullnamedisplay == 'language' and $fullnamelanguage == 'firstname lastname' )) { - $this->headers[$index] = ''.get_string('firstname').get_accesshide(get_string('sortby').' '.get_string('firstname').' '.$fsortorder).' '.$icon_sort_first.' / '. - ''.get_string('lastname').get_accesshide(get_string('sortby').' '.get_string('lastname').' '.$lsortorder).' '.$icon_sort_last; + $this->headers[$index] = $firstnamesortlink . ' / ' . $lastnamesortlink; } else { - $this->headers[$index] = ''.get_string('lastname').get_accesshide(get_string('sortby').' '.get_string('lastname').' '.$lsortorder).' '.$icon_sort_last.' / '. - ''.get_string('firstname').get_accesshide(get_string('sortby').' '.get_string('firstname').' '.$fsortorder).' '.$icon_sort_first; + $this->headers[$index] = $lastnamesortlink . ' / ' . $firstnamesortlink; } } break; @@ -1088,39 +1087,62 @@ class flexible_table { default: if ($this->is_sortable($column)) { - if ($primary_sort_column == $column) { - if ($primary_sort_order == SORT_ASC) { - $icon_sort = ' '.get_string('asc').''; - $localsortorder = get_string('asc'); - } else { - $icon_sort = ' '.get_string('desc').''; - $localsortorder = get_string('desc'); - } - } else { - $localsortorder = get_string('asc'); - } - $this->headers[$index] = ''.$this->headers[$index].get_accesshide(get_string('sortby').' '.$this->headers[$index].' '.$localsortorder).''; + $this->headers[$index] = $this->sort_link($this->headers[$index], + $column, $primary_sort_column == $column, $primary_sort_order); } } + $attributes = array( + 'class' => 'header c' . $index . $this->column_class[$column], + 'scope' => 'col', + ); if ($this->headers[$index] === NULL) { - echo ' '; - } else if(!empty($this->sess->collapse[$column])) { - echo ''.$icon_hide.''; + $content = ' '; + } else if (!empty($this->sess->collapse[$column])) { + $content = $icon_hide; } else { - // took out nowrap for accessibility, might need replacement - if (!is_array($this->column_style[$column])) { - // $usestyles = array('white-space:nowrap'); - $usestyles = ''; - } else { - // $usestyles = $this->column_style[$column]+array('white-space'=>'nowrap'); - $usestyles = $this->column_style[$column]; - } - echo 'make_styles_string($usestyles).' scope="col">'.$this->headers[$index].$icon_sort.'
'.$icon_hide.'
'; + if (is_array($this->column_style[$column])) { + $attributes['style'] = $this->make_styles_string($this->column_style[$column]); + } + $content = $this->headers[$index] . html_writer::tag('div', + $icon_hide, array('class' => 'commands')); } - + echo html_writer::tag('th', $content, $attributes); } - echo ''; + + echo html_writer::end_tag('tr'); + } + + protected function sort_icon($isprimary, $order) { + global $OUTPUT; + + if (!$isprimary) { + return ''; + } + + if ($order == SORT_ASC) { + return html_writer::empty_tag('img', + array('src' => $OUTPUT->pix_url('t/down'), 'alt' => get_string('asc'))); + } else { + return html_writer::empty_tag('img', + array('src' => $OUTPUT->pix_url('t/up'), 'alt' => get_string('desc'))); + } + } + + protected function sort_order_name($isprimary, $order) { + if ($isprimary && $order != SORT_ASC) { + return get_string('desc'); + } else { + return get_string('asc'); + } + } + + protected function sort_link($text, $column, $isprimary, $order) { + return html_writer::link($this->baseurl->out(false, + array($this->request[TABLE_VAR_SORT] => $column)), + $text . get_accesshide(get_string('sortby') . ' ' . + $text . ' ' . $this->sort_order_name($isprimary, $order))) . ' ' . + $this->sort_icon($isprimary, $order); } /** @@ -1145,44 +1167,25 @@ class flexible_table { $this->wrap_html_start(); // Start of main data table - echo html_writer::start_tag('div', array('class'=>'no-overflow')); - echo 'make_attributes_string($this->attributes).'>'; + echo html_writer::start_tag('div', array('class' => 'no-overflow')); + echo html_writer::start_tag('table', $this->attributes); } /** * This function is not part of the public api. - * @todo Document - * @return type? + * @param array $styles CSS-property => value + * @return string values suitably to go in a style="" attribute in HTML. */ - function make_styles_string(&$styles) { + function make_styles_string($styles) { if (empty($styles)) { - return ''; + return null; } - $string = ' style="'; - foreach ($styles as $property => $value) { - $string .= $property.':'.$value.';'; + $string = ''; + foreach($styles as $property => $value) { + $string .= $property . ':' . $value . ';'; } - $string .= '"'; - return $string; - } - - /** - * This function is not part of the public api. - * @todo Document - * @return type? - */ - function make_attributes_string(&$attributes) { - if (empty($attributes)) { - return ''; - } - - $string = ' '; - foreach ($attributes as $attr => $value) { - $string .= ($attr.'="'.$value.'" '); - } - return $string; } } From ba9164e57563388662efb7ffd6e709d7d969eda2 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 16 Feb 2011 13:06:29 +0000 Subject: [PATCH 213/369] MDL-26425 tablelib more cleanup, mostly to PHPdocs, following sam's comments. --- lib/tablelib.php | 97 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index 5ff2066c9f7..e3d905dd4f1 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -96,7 +96,7 @@ class flexible_table { var $download = ''; /** - * @var boolean whether data is downloadable from table. Determines whether + * @var bool whether data is downloadable from table. Determines whether * to display download buttons. Set by method downloadable(). */ var $downloadable = false; @@ -108,7 +108,7 @@ class flexible_table { var $defaultdownloadformat = 'csv'; /** - * @var boolean Has start output been called yet? + * @var bool Has start output been called yet? */ var $started_output = false; @@ -116,18 +116,18 @@ class flexible_table { /** * Constructor - * @param int $uniqueid - * @todo Document properly + * @param int $uniqueid all tables have to have a unique id, this is used + * as a key when storing table properties like sort order in the session. */ function __construct($uniqueid) { $this->uniqueid = $uniqueid; $this->request = array( - TABLE_VAR_SORT => 'tsort', - TABLE_VAR_HIDE => 'thide', - TABLE_VAR_SHOW => 'tshow', - TABLE_VAR_IFIRST => 'tifirst', - TABLE_VAR_ILAST => 'tilast', - TABLE_VAR_PAGE => 'page' + TABLE_VAR_SORT => 'tsort', + TABLE_VAR_HIDE => 'thide', + TABLE_VAR_SHOW => 'tshow', + TABLE_VAR_IFIRST => 'tifirst', + TABLE_VAR_ILAST => 'tilast', + TABLE_VAR_PAGE => 'page', ); } @@ -166,12 +166,17 @@ class flexible_table { return $this->download; } - function export_class_instance(&$exportclass=null) { + /** + * Get, and optionally set, the export class. + * @param $exportclass (optional) if passed, set the table to use this export class. + * @return table_default_export_format_parent the export class in use (after any set). + */ + function export_class_instance($exportclass = null) { if (!is_null($exportclass)) { $this->started_output = true; - $this->exportclass =& $exportclass; - $this->exportclass->table =& $this; - } elseif (is_null($this->exportclass) && !empty($this->download)) { + $this->exportclass = $exportclass; + $this->exportclass->table = $this; + } else if (is_null($this->exportclass) && !empty($this->download)) { $classname = 'table_'.$this->download.'_export_format'; $this->exportclass = new $classname($this); if (!$this->exportclass->document_started()) { @@ -185,10 +190,10 @@ class flexible_table { * Probably don't need to call this directly. Calling is_downloading with a * param automatically sets table as downloadable. * - * @param boolean $downloadable optional param to set whether data from + * @param bool $downloadable optional param to set whether data from * table is downloadable. If ommitted this function can be used to get * current state of table. - * @return boolean whether table data is set to be downloadable. + * @return bool whether table data is set to be downloadable. */ function is_downloadable($downloadable = null) { if ($downloadable !== null) { @@ -314,7 +319,7 @@ class flexible_table { * For example, in the quiz overview report, the fullname column is set to be suppressed, so * that when one student has made multiple attempts, their name is only printed in the row * for their first attempt. - * @param integer $column the index of a column. + * @param int $column the index of a column. */ function column_suppress($column) { if (isset($this->column_suppress[$column])) { @@ -324,7 +329,7 @@ class flexible_table { /** * Sets the given $column index to the given $classname in $this->column_class. - * @param integer $column + * @param int $column * @param string $classname * @return void */ @@ -336,7 +341,7 @@ class flexible_table { /** * Sets the given $column index and $property index to the given $value in $this->column_style. - * @param integer $column + * @param int $column * @param string $property * @param mixed $value * @return void @@ -349,7 +354,7 @@ class flexible_table { /** * Sets all columns' $propertys to the given $value in $this->column_style. - * @param integer $property + * @param int $property * @param string $value * @return void */ @@ -565,7 +570,7 @@ class flexible_table { } /** - * @return integer the offset for LIMIT clause of SQL + * @return int the offset for LIMIT clause of SQL */ function get_page_start() { if (!$this->use_pages) { @@ -575,7 +580,7 @@ class flexible_table { } /** - * @return integer the pagesize for LIMIT clause of SQL + * @return int the pagesize for LIMIT clause of SQL */ function get_page_size() { if (!$this->use_pages) { @@ -643,7 +648,7 @@ class flexible_table { * * @param array $row a numerically keyed row of data to add to the table. * @param string $classname CSS class name to add to this row's tr tag. - * @return boolean success. + * @return bool success. */ function add_data($row, $classname = '') { if (!$this->setup) { @@ -815,6 +820,14 @@ class flexible_table { return $this->sess->i_last; } + /** + * Helper function, used by {@link print_initials_bar()} to output one initial bar. + * @param array $alpha of letters in the alphabet. + * @param string $current the currently selected letter. + * @param string $class class name to add to this initial bar. + * @param string $title the name to put in front of this initial bar. + * @param string $urlvar URL parameter name for this initial. + */ protected function print_one_initials_bar($alpha, $current, $class, $title, $urlvar) { echo html_writer::start_tag('div', array('class' => 'initialbar ' . $class)) . $title . ' : '; @@ -1018,6 +1031,13 @@ class flexible_table { } } + /** + * Generate the HTML for the collapse/uncollapse icon. This is a helper method + * used by {@link print_headers()}. + * @param string $column the column name, index into various names. + * @param int $index numerical index of the column. + * @return string HTML fragment. + */ protected function show_hide_link($column, $index) { global $OUTPUT; // Some headers contain
tags, do not include in title, hence the @@ -1113,6 +1133,12 @@ class flexible_table { echo html_writer::end_tag('tr'); } + /** + * Generate the HTML for the sort icon. This is a helper method used by {@link sort_link()}. + * @param bool $isprimary whether an icon is needed (it is only needed for the primary sort column.) + * @param int $order SORT_ASC or SORT_DESC + * @return string HTML fragment. + */ protected function sort_icon($isprimary, $order) { global $OUTPUT; @@ -1129,6 +1155,13 @@ class flexible_table { } } + /** + * Generate the correct tool tip for changing the sort order. This is a + * helper method used by {@link sort_link()}. + * @param bool $isprimary whether the is column is the current primary sort column. + * @param int $order SORT_ASC or SORT_DESC + * @return string the correct title. + */ protected function sort_order_name($isprimary, $order) { if ($isprimary && $order != SORT_ASC) { return get_string('desc'); @@ -1137,6 +1170,14 @@ class flexible_table { } } + /** + * Generate the HTML for the sort link. This is a helper method used by {@link print_headers()}. + * @param string $text the text for the link. + * @param string $column the column name, may be a fake column like 'firstname' or a real one. + * @param bool $isprimary whether the is column is the current primary sort column. + * @param int $order SORT_ASC or SORT_DESC + * @return string HTML fragment. + */ protected function sort_link($text, $column, $isprimary, $order) { return html_writer::link($this->baseurl->out(false, array($this->request[TABLE_VAR_SORT] => $column)), @@ -1210,11 +1251,11 @@ class table_sql extends flexible_table { public $rawdata = NULL; /** - * @var boolean Overriding default for this. + * @var bool Overriding default for this. */ public $is_sortable = true; /** - * @var boolean Overriding default for this. + * @var bool Overriding default for this. */ public $is_collapsible = true; @@ -1296,8 +1337,8 @@ class table_sql extends flexible_table { /** * Query the db. Store results in the table object for use by build_table. * - * @param integer $pagesize size of page for paginated displayed table. - * @param boolean $useinitialsbar do you want to use the initials bar. Bar + * @param int $pagesize size of page for paginated displayed table. + * @param bool $useinitialsbar do you want to use the initials bar. Bar * will only be used if there is a fullname column defined for the table. */ function query_db($pagesize, $useinitialsbar=true) { @@ -1379,7 +1420,7 @@ class table_default_export_format_parent { var $table; /** - * @var boolean output started. Keeps track of whether any output has been + * @var bool output started. Keeps track of whether any output has been * started yet. */ var $documentstarted = false; From a208aefbc455d3a57cbb9318abe46677ea4a831e Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 18 Feb 2011 12:28:21 +0000 Subject: [PATCH 214/369] MDL-26425 change all table subclasses to use parent::__construct --- mod/quiz/report/overview/overview_table.php | 2 +- mod/quiz/report/responses/responses_table.php | 2 +- mod/quiz/report/statistics/statistics_question_table.php | 2 +- mod/quiz/report/statistics/statistics_table.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/quiz/report/overview/overview_table.php b/mod/quiz/report/overview/overview_table.php index 0cbbfecdd30..3dabcf5898d 100644 --- a/mod/quiz/report/overview/overview_table.php +++ b/mod/quiz/report/overview/overview_table.php @@ -11,7 +11,7 @@ class quiz_report_overview_table extends table_sql { function quiz_report_overview_table($quiz , $qmsubselect, $groupstudents, $students, $detailedmarks, $questions, $candelete, $reporturl, $displayoptions, $context){ - parent::table_sql('mod-quiz-report-overview-report'); + parent::__construct('mod-quiz-report-overview-report'); $this->quiz = $quiz; $this->qmsubselect = $qmsubselect; $this->groupstudents = $groupstudents; diff --git a/mod/quiz/report/responses/responses_table.php b/mod/quiz/report/responses/responses_table.php index f7a906db991..12a05bbd5b4 100644 --- a/mod/quiz/report/responses/responses_table.php +++ b/mod/quiz/report/responses/responses_table.php @@ -10,7 +10,7 @@ class quiz_report_responses_table extends table_sql { function quiz_report_responses_table($quiz , $qmsubselect, $groupstudents, $students, $questions, $candelete, $reporturl, $displayoptions, $context){ - parent::table_sql('mod-quiz-report-responses-report'); + parent::__construct('mod-quiz-report-responses-report'); $this->quiz = $quiz; $this->qmsubselect = $qmsubselect; $this->groupstudents = $groupstudents; diff --git a/mod/quiz/report/statistics/statistics_question_table.php b/mod/quiz/report/statistics/statistics_question_table.php index c9674bc566e..27811429cd9 100644 --- a/mod/quiz/report/statistics/statistics_question_table.php +++ b/mod/quiz/report/statistics/statistics_question_table.php @@ -8,7 +8,7 @@ class quiz_report_statistics_question_table extends flexible_table { var $question; function quiz_report_statistics_question_table($qid){ - parent::flexible_table('mod-quiz-report-statistics-question-table'.$qid); + parent::__construct('mod-quiz-report-statistics-question-table'.$qid); } /** diff --git a/mod/quiz/report/statistics/statistics_table.php b/mod/quiz/report/statistics/statistics_table.php index 508da380d42..fafc27c890b 100644 --- a/mod/quiz/report/statistics/statistics_table.php +++ b/mod/quiz/report/statistics/statistics_table.php @@ -6,7 +6,7 @@ class quiz_report_statistics_table extends flexible_table { var $quiz; function quiz_report_statistics_table(){ - parent::flexible_table('mod-quiz-report-statistics-report'); + parent::__construct('mod-quiz-report-statistics-report'); } /** From 43070e6193fca66f034b8e0b3fdf325e34a47067 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 23:48:41 +0200 Subject: [PATCH 215/369] MDL-26992 fix broken upload users templates --- admin/uploaduser.php | 23 ++++++++++++++++------ admin/uploaduserlib.php | 43 +++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/admin/uploaduser.php b/admin/uploaduser.php index 1861a5d1547..0e166384fb5 100644 --- a/admin/uploaduser.php +++ b/admin/uploaduser.php @@ -307,6 +307,9 @@ if ($formdata = $mform2->is_cancelled()) { // process templates $user->$field = uu_process_template($formdata->$field, $user); $formdefaults[$field] = true; + if (in_array($field, $upt->columns)) { + $upt->track($field, s($user->$field), 'normal'); + } } } foreach ($PRF_FIELDS as $field) { @@ -614,7 +617,13 @@ if ($formdata = $mform2->is_cancelled()) { $isinternalauth = $auth->is_internal(); - if ($DB->record_exists('user', array('email'=>$user->email))) { + if (empty($user->email)) { + $upt->track('email', get_string('invalidemail'), 'error'); + $upt->track('status', $strusernotaddederror, 'error'); + $userserrors++; + continue; + + } else if ($DB->record_exists('user', array('email'=>$user->email))) { if ($noemailduplicates) { $upt->track('email', $stremailduplicate, 'error'); $upt->track('status', $strusernotaddederror, 'error'); @@ -898,11 +907,13 @@ while ($linenum <= $previewrows and $fields = $cir->next()) { $rowcols['status'][] = get_string('missingusername'); } - if (!validate_email($rowcols['email'])) { - $rowcols['status'][] = get_string('invalidemail'); - } - if ($DB->record_exists('user', array('email'=>$rowcols['email']))) { - $rowcols['status'][] = $stremailduplicate; + if (isset($rowcols['email'])) { + if (!validate_email($rowcols['email'])) { + $rowcols['status'][] = get_string('invalidemail'); + } + if ($DB->record_exists('user', array('email'=>$rowcols['email']))) { + $rowcols['status'][] = $stremailduplicate; + } } $rowcols['status'] = implode('
', $rowcols['status']); $data[] = $rowcols; diff --git a/admin/uploaduserlib.php b/admin/uploaduserlib.php index 7df9290268f..d36bccccdda 100644 --- a/admin/uploaduserlib.php +++ b/admin/uploaduserlib.php @@ -248,33 +248,48 @@ function uu_process_template($template, $user) { if (is_null($result)) { return $template; //error during regex processing?? + } + + if (is_array($template)) { + $template['text'] = $result; + return $t; } else { - if (array($template)) { - $template['text'] = $t; - return $t; - } else { - return $t; - } + return $result; } } /** * Internal callback function. */ -function uu_process_template_callback($block, $username, $firstname, $lastname) { +function uu_process_template_callback($username, $firstname, $lastname, $block) { $textlib = textlib_get_instance(); - $repl = $block[0]; switch ($block[3]) { - case 'u': $repl = $username; break; - case 'f': $repl = $firstname; break; - case 'l': $repl = $lastname; break; + case 'u': + $repl = $username; + break; + case 'f': + $repl = $firstname; + break; + case 'l': + $repl = $lastname; + break; + default: + return $block[0]; } + switch ($block[1]) { - case '+': $repl = $textlib->strtoupper($repl); break; - case '-': $repl = $textlib->strtolower($repl); break; - case '~': $repl = $textlib->strtotitle($repl); break; + case '+': + $repl = $textlib->strtoupper($repl); + break; + case '-': + $repl = $textlib->strtolower($repl); + break; + case '~': + $repl = $textlib->strtotitle($repl); + break; } + if (!empty($block[2])) { $repl = $textlib->substr($repl, 0 , $block[2]); } From cfdac90f2b294feae23696a7a7bbe1ab28b8ac0b Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Mon, 28 Mar 2011 17:31:01 +0800 Subject: [PATCH 216/369] MOD-WIKI MDL-26213 1. Rewrite the image urls in diff.php and viewdiff.php 2. Fxied image urls in search.php 3. Add modcontext variable to avoid using duplicated get_context_instance calls --- mod/wiki/lock.php | 2 +- mod/wiki/pagelib.php | 146 ++++++++++++++++-------------------------- mod/wiki/renderer.php | 4 +- 3 files changed, 59 insertions(+), 93 deletions(-) diff --git a/mod/wiki/lock.php b/mod/wiki/lock.php index 214ca89603d..fd2d99bc455 100644 --- a/mod/wiki/lock.php +++ b/mod/wiki/lock.php @@ -66,7 +66,7 @@ if (!empty($section) && !$sectioncontent = wiki_get_section_page($page, $section print_error('invalidsection', 'wiki'); } -require_course_login($course->id); +require_course_login($course->id, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/wiki:editpage', $context); diff --git a/mod/wiki/pagelib.php b/mod/wiki/pagelib.php index f49545eab25..2d1597c05a9 100644 --- a/mod/wiki/pagelib.php +++ b/mod/wiki/pagelib.php @@ -64,6 +64,11 @@ abstract class page_wiki { */ protected $gid; + /** + * @var object module context object + */ + protected $modcontext; + /** * @var int Current user ID */ @@ -92,6 +97,7 @@ abstract class page_wiki { function __construct($wiki, $subwiki, $cm) { global $PAGE, $CFG; $this->subwiki = $subwiki; + $this->modcontext = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); // initialise wiki renderer $this->wikioutput = $PAGE->get_renderer('mod_wiki'); @@ -291,11 +297,10 @@ class page_wiki_view extends page_wiki { function print_content() { global $PAGE, $CFG; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); if (wiki_user_can_view($this->subwiki)) { if (!empty($this->page)) { - wiki_print_page_content($this->page, $context, $this->subwiki->id); + wiki_print_page_content($this->page, $this->modcontext, $this->subwiki->id); $wiki = $PAGE->activityrecord; } else { print_string('nocontent', 'wiki'); @@ -398,7 +403,6 @@ class page_wiki_edit extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); if (wiki_user_can_edit($this->subwiki)) { $this->print_edit(); } else { @@ -519,9 +523,6 @@ class page_wiki_edit extends page_wiki { } } - $cm = $PAGE->cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id; if (!empty($this->section)) { $url .= "§ion=" . $this->section; @@ -537,16 +538,16 @@ class page_wiki_edit extends page_wiki { switch ($format) { case 'html': $data->newcontentformat = FORMAT_HTML; - $data = file_prepare_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $context, 'mod_wiki', 'attachments', $this->subwiki->id); + $data = file_prepare_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id); break; default: //$draftitemid = file_get_submitted_draft_itemid('attachments'); - //file_prepare_draft_area($draftitemid, $context->id, 'mod_wiki', 'attachments', $this->subwiki->id); + //file_prepare_draft_area($draftitemid, $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id); //$data->attachments = $draftitemid; } if ($version->contentformat != 'html') { - $params['contextid'] = $context->id; + $params['contextid'] = $this->modcontext->id; $params['component'] = 'mod_wiki'; $params['filearea'] = 'attachments'; $params['fileitemid'] = $this->subwiki->id; @@ -560,7 +561,7 @@ class page_wiki_edit extends page_wiki { if ($formdata = $form->get_data()) { if ($format != 'html') { - $errors = $this->process_uploads($context); + $errors = $this->process_uploads($this->modcontext); if (!empty($errors)) { $contenterror = ""; foreach ($errors as $e) { @@ -610,21 +611,19 @@ class page_wiki_comments extends page_wiki { } function print_content() { - global $CFG, $OUTPUT, $USER, $PAGE, $COURSE; + global $CFG, $OUTPUT, $USER, $PAGE; require_once($CFG->dirroot . '/mod/wiki/locallib.php'); $page = $this->page; $subwiki = $this->subwiki; $wiki = $PAGE->activityrecord; - $cm = $PAGE->cm; - $course = $COURSE; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); + list($context, $course, $cm) = get_context_info_array($this->modcontext->id); - require_capability('mod/wiki:viewcomment', $context, NULL, true, 'noviewcommentpermission', 'wiki'); + require_capability('mod/wiki:viewcomment', $this->modcontext, NULL, true, 'noviewcommentpermission', 'wiki'); - $comments = wiki_get_comments($context->id, $page->id); + $comments = wiki_get_comments($this->modcontext->id, $page->id); - if (has_capability('mod/wiki:editcomment', $context)) { + if (has_capability('mod/wiki:editcomment', $this->modcontext)) { echo ''; } @@ -676,11 +675,11 @@ class page_wiki_comments extends page_wiki { $t->data = array($row1, $row2); $actionicons = false; - if ((has_capability('mod/wiki:managecomment', $context))) { + if ((has_capability('mod/wiki:managecomment', $this->modcontext))) { $urledit = new moodle_url('/mod/wiki/editcomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'edit')); $urldelet = new moodle_url('/mod/wiki/instancecomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'delete')); $actionicons = true; - } else if ((has_capability('mod/wiki:editcomment', $context)) and ($USER->id == $user->id)) { + } else if ((has_capability('mod/wiki:editcomment', $this->modcontext)) and ($USER->id == $user->id)) { $urledit = new moodle_url('/mod/wiki/editcomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'edit')); $urldelet = new moodle_url('/mod/wiki/instancecomments.php', array('commentid' => $comment->id, 'pageid' => $page->id, 'action' => 'delete')); $actionicons = true; @@ -738,8 +737,7 @@ class page_wiki_editcomment extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:editcomment', $context, NULL, true, 'noeditcommentpermission', 'wiki'); + require_capability('mod/wiki:editcomment', $this->modcontext, NULL, true, 'noeditcommentpermission', 'wiki'); if ($this->action == 'add') { $this->add_comment_form(); @@ -848,10 +846,9 @@ class page_wiki_search extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); - echo $this->wikioutput->search_result($this->search_result); + echo $this->wikioutput->search_result($this->search_result, $this->subwiki); } } @@ -928,10 +925,8 @@ class page_wiki_create extends page_wiki { function print_content($pagetitle = '') { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - // @TODO: Change this to has_capability and show an alternative interface. - require_capability('mod/wiki:createpage', $context, NULL, true, 'nocreatepermission', 'wiki'); + require_capability('mod/wiki:createpage', $this->modcontext, NULL, true, 'nocreatepermission', 'wiki'); $data = new stdClass(); if (!empty($pagetitle)) { $data->pagetitle = $pagetitle; @@ -980,8 +975,7 @@ class page_wiki_preview extends page_wiki_edit { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:editpage', $context, NULL, true, 'noeditpermission', 'wiki'); + require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki'); $this->print_preview(); } @@ -1017,7 +1011,6 @@ class page_wiki_preview extends page_wiki_edit { $version = wiki_get_current_version($this->page->id); $format = $version->contentformat; $content = $version->content; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id; if (!empty($this->section)) { @@ -1026,7 +1019,7 @@ class page_wiki_preview extends page_wiki_edit { $params = array('attachmentoptions' => page_wiki_edit::$attachmentoptions, 'format' => $this->format, 'version' => $this->versionnumber); if ($this->format != 'html') { - $params['contextid'] = $context->id; + $params['contextid'] = $this->modcontext->id; $params['component'] = 'mod_wiki'; $params['filearea'] = 'attachments'; $params['fileitemid'] = $this->page->id; @@ -1086,8 +1079,7 @@ class page_wiki_diff extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); $this->print_diff_content(); } @@ -1118,12 +1110,9 @@ class page_wiki_diff extends page_wiki { /** * Given two versions of a page, prints a page displaying the differences between them. * - * @uses $CFG - * - * @param int $pageid The page id whose versions will be displayed. - * @param int $cm The course id, needed to print user images. - * @param int $compare The first version number to be compared. - * @param int $comparewith The second version number to be compared. + * @global object $CFG + * @global object $OUTPUT + * @global object $PAGE */ private function print_diff_content() { global $CFG, $OUTPUT, $PAGE; @@ -1132,12 +1121,13 @@ class page_wiki_diff extends page_wiki { $total = wiki_count_wiki_page_versions($pageid) - 1; $oldversion = wiki_get_wiki_page_version($pageid, $this->compare); + $newversion = wiki_get_wiki_page_version($pageid, $this->comparewith); if ($oldversion && $newversion) { - $oldtext = format_text($oldversion->content); - $newtext = format_text($newversion->content); + $oldtext = format_text(file_rewrite_pluginfile_urls($oldversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id)); + $newtext = format_text(file_rewrite_pluginfile_urls($newversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id)); list($diff1, $diff2) = ouwiki_diff_html($oldtext, $newtext); $oldversion->diff = $diff1; $oldversion->user = wiki_get_user_info($oldversion->userid); @@ -1196,8 +1186,7 @@ class page_wiki_history extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); $this->print_history_content(); } @@ -1225,16 +1214,9 @@ class page_wiki_history extends page_wiki { /** * Prints the history for a given wiki page * - * @uses $CFG - * - * @param int $pageid The page id whose history should be displayed. - * @param int $cm The course id, needed to print user images. - * @param wikipage $wikipage - * @param int $allversion This tells how results should be displayed. - * If $allversion == 0 : Only $rowsperpage will be displayed at a time, and $paging is the page being displayed. - * If $allversion != 0 : All versions will be printed in a single table. - * @param int $paging Desired page to be displayed, this is ignored if $allversion!=0. - * @param int $rowsperpage How many rows to be displayed in each page, this is ignored if $allversion!=0. + * @global object $CFG + * @global object $OUTPUT + * @global object $PAGE */ private function print_history_content() { global $CFG, $OUTPUT, $PAGE; @@ -1431,8 +1413,7 @@ class page_wiki_map extends page_wiki { function print_content() { global $CFG, $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); if ($this->view > 0) { //echo ''; @@ -1866,8 +1847,7 @@ class page_wiki_restoreversion extends page_wiki { function print_content() { global $CFG, $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:managewiki', $context, NULL, true, 'nomanagewikipermission', 'wiki'); + require_capability('mod/wiki:managewiki', $this->modcontext, NULL, true, 'nomanagewikipermission', 'wiki'); $this->print_restoreversion(); } @@ -1951,9 +1931,6 @@ class page_wiki_save extends page_wiki_edit { protected function print_save() { global $CFG, $USER, $OUTPUT, $PAGE; - $cm = $PAGE->cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id; if (!empty($this->section)) { $url .= "§ion=" . $this->section; @@ -1962,7 +1939,7 @@ class page_wiki_save extends page_wiki_edit { $params = array('attachmentoptions' => page_wiki_edit::$attachmentoptions, 'format' => $this->format, 'version' => $this->versionnumber); if ($this->format != 'html') { - $params['contextid'] = $context->id; + $params['contextid'] = $this->modcontext->id; $params['component'] = 'mod_wiki'; $params['filearea'] = 'attachments'; $params['fileitemid'] = $this->page->id; @@ -1974,7 +1951,7 @@ class page_wiki_save extends page_wiki_edit { $data = false; if ($data = $form->get_data()) { if ($this->format == 'html') { - $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $context, 'mod_wiki', 'attachments', $this->subwiki->id); + $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id); } if (isset($this->section)) { @@ -1986,7 +1963,7 @@ class page_wiki_save extends page_wiki_edit { if ($save && $data) { if ($this->format != 'html') { - $errors = $this->process_uploads($context); + $errors = $this->process_uploads($this->modcontext); } if (!empty($CFG->usetags)) { tag_set('wiki_pages', $this->page->id, $data->tags); @@ -2036,8 +2013,7 @@ class page_wiki_viewversion extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); $this->print_version_view(); } @@ -2066,15 +2042,12 @@ class page_wiki_viewversion extends page_wiki { /** * Given an old page version, output the version content * - * @uses $CFG - * - * @param page $page The page whose version will be displayed. - * @param int $cm The course id, needed to print user images. - * @param int $version The version number to be displayed. + * @global object $CFG + * @global object $OUTPUT + * @global object $PAGE */ private function print_version_view() { global $CFG, $OUTPUT, $PAGE; - $cm = $PAGE->cm; $pageversion = wiki_get_version($this->version->id); if ($pageversion) { @@ -2087,6 +2060,9 @@ class page_wiki_viewversion extends page_wiki { $heading .= '  → ' . $OUTPUT->user_picture(wiki_get_user_info($pageversion->userid), array('popup' => true)) . '

'; print_container($heading, false, 'mdl-align wiki_modifieduser wiki_headingtime'); $options = array('swid' => $this->subwiki->id, 'pretty_print' => true, 'pageid' => $this->page->id); + + $pageversion->content = file_rewrite_pluginfile_urls($pageversion->content, 'pluginfile.php', $this->modcontext->id, 'mod_wiki', 'attachments', $this->subwiki->id); + $parseroutput = wiki_parse_content($pageversion->contentformat, $pageversion->content, $options); $content = print_container(format_text($parseroutput['parsed_text'], FORMAT_HTML, array('overflowdiv'=>true)), false, '', '', true); echo $OUTPUT->box($content, 'generalbox wiki_contentbox'); @@ -2109,8 +2085,7 @@ class page_wiki_confirmrestore extends page_wiki_save { function print_content() { global $CFG, $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:managewiki', $context, NULL, true, 'nomanagewikipermission', 'wiki'); + require_capability('mod/wiki:managewiki', $this->modcontext, NULL, true, 'nomanagewikipermission', 'wiki'); $version = wiki_get_version($this->version->id); if (wiki_restore_page($this->page, $version->content, $version->userid)) { @@ -2138,8 +2113,7 @@ class page_wiki_prettyview extends page_wiki { function print_content() { global $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:viewpage', $context, NULL, true, 'noviewpagepermission', 'wiki'); + require_capability('mod/wiki:viewpage', $this->modcontext, NULL, true, 'noviewpagepermission', 'wiki'); $this->print_pretty_view(); } @@ -2174,22 +2148,20 @@ class page_wiki_handlecomments extends page_wiki { public function print_content() { global $CFG, $PAGE, $USER; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - if ($this->action == 'add') { - if (has_capability('mod/wiki:editcomment', $context)) { + if (has_capability('mod/wiki:editcomment', $this->modcontext)) { $this->add_comment($this->content, $this->commentid); } } else if ($this->action == 'edit') { $comment = wiki_get_comment($this->commentid); - $edit = has_capability('mod/wiki:editcomment', $context); + $edit = has_capability('mod/wiki:editcomment', $this->modcontext); $owner = ($comment->userid == $USER->id); if ($owner && $edit) { $this->add_comment($this->content, $this->commentid); } } else if ($this->action == 'delete') { $comment = wiki_get_comment($this->commentid); - $manage = has_capability('mod/wiki:managecomment', $context); + $manage = has_capability('mod/wiki:managecomment', $this->modcontext); $owner = ($comment->userid == $USER->id); if ($owner || $manage) { $this->delete_comment($this->commentid); @@ -2220,10 +2192,8 @@ class page_wiki_handlecomments extends page_wiki { require_once($CFG->dirroot . "/mod/wiki/locallib.php"); $pageid = $this->page->id; - $cm = $PAGE->cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - wiki_add_comment($context, $pageid, $content, $this->format); + wiki_add_comment($this->modcontext, $pageid, $content, $this->format); if (!$idcomment) { redirect($CFG->wwwroot . '/mod/wiki/comments.php?pageid=' . $pageid, get_string('createcomment', 'wiki'), 2); @@ -2236,11 +2206,9 @@ class page_wiki_handlecomments extends page_wiki { private function delete_comment($commentid) { global $CFG, $PAGE; - $cm = $PAGE->cm; - $context = get_context_instance(CONTEXT_MODULE, $cm->id); $pageid = $this->page->id; - wiki_delete_comment($commentid, $context, $pageid); + wiki_delete_comment($commentid, $this->modcontext, $pageid); } } @@ -2269,8 +2237,7 @@ class page_wiki_lock extends page_wiki_edit { public function print_content() { global $USER, $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:editpage', $context, NULL, true, 'noeditpermission', 'wiki'); + require_capability('mod/wiki:editpage', $this->modcontext, NULL, true, 'noeditpermission', 'wiki'); wiki_set_lock($this->page->id, $USER->id, $this->section); } @@ -2287,8 +2254,7 @@ class page_wiki_overridelocks extends page_wiki_edit { function print_content() { global $CFG, $PAGE; - $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); - require_capability('mod/wiki:overridelock', $context, NULL, true, 'nooverridelockpermission', 'wiki'); + require_capability('mod/wiki:overridelock', $this->modcontext, NULL, true, 'nooverridelockpermission', 'wiki'); wiki_delete_locks($this->page->id, null, $this->section, true, true); diff --git a/mod/wiki/renderer.php b/mod/wiki/renderer.php index b8197dec2d9..515860b7936 100644 --- a/mod/wiki/renderer.php +++ b/mod/wiki/renderer.php @@ -52,7 +52,7 @@ class mod_wiki_renderer extends plugin_renderer_base { return $this->output->container($this->output->render($select), 'wiki_index'); } - public function search_result($records) { + public function search_result($records, $subwiki) { global $CFG, $PAGE; $table = new html_table(); $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); @@ -63,7 +63,7 @@ class mod_wiki_renderer extends plugin_renderer_base { $table->head = array('title' => format_string($page->title) . ' (' . html_writer::link($CFG->wwwroot . '/mod/wiki/view.php?pageid=' . $page->id, get_string('view', 'wiki')) . ')'); $table->align = array('title' => 'left'); $table->width = '100%'; - $table->data = array(array(file_rewrite_pluginfile_urls(format_text($page->cachedcontent, FORMAT_HTML), 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $page->id))); + $table->data = array(array(file_rewrite_pluginfile_urls(format_text($page->cachedcontent, FORMAT_HTML), 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $subwiki->id))); $table->colclasses = array('wikisearchresults'); $html .= html_writer::table($table); } From e1ce68c2f9a9ae937f8bbe7aa779a3cbf08cc18d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 27 Mar 2011 20:44:50 +0200 Subject: [PATCH 217/369] MDL-26991 use archetypes instead of deprecated 'legacy' when defining roles in enrol plugins --- enrol/authorize/db/access.php | 8 ++++---- enrol/category/db/access.php | 2 +- enrol/cohort/db/access.php | 2 +- enrol/guest/db/access.php | 2 +- enrol/ldap/db/access.php | 2 +- enrol/manual/db/access.php | 10 +++++----- enrol/meta/db/access.php | 4 ++-- enrol/paypal/db/access.php | 8 ++++---- enrol/self/db/access.php | 8 ++++---- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/enrol/authorize/db/access.php b/enrol/authorize/db/access.php index 38a74096daf..c04804b4c74 100644 --- a/enrol/authorize/db/access.php +++ b/enrol/authorize/db/access.php @@ -5,7 +5,7 @@ $capabilities = array( 'enrol/authorize:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), @@ -13,7 +13,7 @@ $capabilities = array( 'enrol/authorize:manage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -22,7 +22,7 @@ $capabilities = array( 'enrol/authorize:unenrol' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), @@ -30,7 +30,7 @@ $capabilities = array( 'enrol/authorize:unenrolself' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( ) ), diff --git a/enrol/category/db/access.php b/enrol/category/db/access.php index 945af281fb5..d18e55a4ba5 100644 --- a/enrol/category/db/access.php +++ b/enrol/category/db/access.php @@ -33,7 +33,7 @@ $capabilities = array( 'enrol/category:synchronised' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_SYSTEM, - 'legacy' => array( + 'archetypes' => array( ) ), ); diff --git a/enrol/cohort/db/access.php b/enrol/cohort/db/access.php index 36735ef7e29..45303537c3e 100644 --- a/enrol/cohort/db/access.php +++ b/enrol/cohort/db/access.php @@ -32,7 +32,7 @@ $capabilities = array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) diff --git a/enrol/guest/db/access.php b/enrol/guest/db/access.php index a1feaf9b6fe..2fa37e6f2b9 100644 --- a/enrol/guest/db/access.php +++ b/enrol/guest/db/access.php @@ -31,7 +31,7 @@ $capabilities = array( 'enrol/guest:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) diff --git a/enrol/ldap/db/access.php b/enrol/ldap/db/access.php index 1963af662d2..8eb1aa60b71 100644 --- a/enrol/ldap/db/access.php +++ b/enrol/ldap/db/access.php @@ -31,7 +31,7 @@ $capabilities = array( 'enrol/ldap:manage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), diff --git a/enrol/manual/db/access.php b/enrol/manual/db/access.php index 11460e88b19..4658fc7b57d 100644 --- a/enrol/manual/db/access.php +++ b/enrol/manual/db/access.php @@ -31,7 +31,7 @@ $capabilities = array( 'enrol/manual:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), @@ -39,7 +39,7 @@ $capabilities = array( 'enrol/manual:enrol' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -48,7 +48,7 @@ $capabilities = array( 'enrol/manual:manage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -57,7 +57,7 @@ $capabilities = array( 'enrol/manual:unenrol' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -66,7 +66,7 @@ $capabilities = array( 'enrol/manual:unenrolself' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( ) ), diff --git a/enrol/meta/db/access.php b/enrol/meta/db/access.php index 45b9cc8a171..6215c50b6fb 100644 --- a/enrol/meta/db/access.php +++ b/enrol/meta/db/access.php @@ -30,7 +30,7 @@ $capabilities = array( 'enrol/meta:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -40,7 +40,7 @@ $capabilities = array( 'enrol/meta:selectaslinked' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), diff --git a/enrol/paypal/db/access.php b/enrol/paypal/db/access.php index c6db98ca46a..c474d92a8d9 100644 --- a/enrol/paypal/db/access.php +++ b/enrol/paypal/db/access.php @@ -31,7 +31,7 @@ $capabilities = array( 'enrol/paypal:config' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), @@ -39,7 +39,7 @@ $capabilities = array( 'enrol/paypal:manage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) @@ -48,7 +48,7 @@ $capabilities = array( 'enrol/paypal:unenrol' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'manager' => CAP_ALLOW, ) ), @@ -56,7 +56,7 @@ $capabilities = array( 'enrol/paypal:unenrolself' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( ) ), diff --git a/enrol/self/db/access.php b/enrol/self/db/access.php index 32bc34a4ca9..54fa9d8be22 100644 --- a/enrol/self/db/access.php +++ b/enrol/self/db/access.php @@ -32,7 +32,7 @@ $capabilities = array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) @@ -42,7 +42,7 @@ $capabilities = array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) @@ -51,7 +51,7 @@ $capabilities = array( 'enrol/self:unenrolself' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'student' => CAP_ALLOW, ) ), @@ -59,7 +59,7 @@ $capabilities = array( 'enrol/self:unenrol' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) From 4b59f327cd4885c0e6f805149c1fdd536cb8140b Mon Sep 17 00:00:00 2001 From: Helen Foster Date: Mon, 28 Mar 2011 17:07:55 +0200 Subject: [PATCH 218/369] MDL-26744 enrol meta lang string improvement thanks to Ray Lawrence --- enrol/meta/lang/en/enrol_meta.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enrol/meta/lang/en/enrol_meta.php b/enrol/meta/lang/en/enrol_meta.php index c7558083fe6..187f6b3db4a 100644 --- a/enrol/meta/lang/en/enrol_meta.php +++ b/enrol/meta/lang/en/enrol_meta.php @@ -28,6 +28,6 @@ $string['linkedcourse'] = 'Link course'; $string['meta:config'] = 'Configure meta enrol instances'; $string['meta:selectaslinked'] = 'Select course as meta linked'; $string['nosyncroleids'] = 'Roles that are not synchronised'; -$string['nosyncroleids_desc'] = 'By default all course level role assignments are synchronised from parent to child courses. Roles that are selected here will not be included in the synchronisation process. The current roles will be updated in the next cron execution.'; +$string['nosyncroleids_desc'] = 'By default all course level role assignments are synchronised from parent to child courses. Roles that are selected here will not be included in the synchronisation process. The roles available for synchronisation will be updated in the next cron execution.'; $string['pluginname'] = 'Course meta link'; $string['pluginname_desc'] = 'Course meta link enrolment plugin synchronises enrolments and roles in two different courses.'; From 0947b90b980d9a92ec44169bb764ccfceaebe66c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 30 Mar 2011 14:32:49 +0200 Subject: [PATCH 219/369] weekly release --- version.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/version.php b/version.php index ce4fe2b5980..86ac9f62e04 100644 --- a/version.php +++ b/version.php @@ -30,9 +30,10 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011032300.00; // YYYYMMDD = date of the last version bump - // XX = daily increments +$version = 2011033000.00; // YYYYMMDD = weekly release date of this DEV branch + // RR = release increments - 00 in DEV branches + // .XX = incremental changes -$release = '2.1dev (Build: 20110323)'; // Human-friendly version name +$release = '2.1dev (Build: 20110330)'; // Human-friendly version name $maturity = MATURITY_ALPHA; // this version's maturity level From dae6b38c5127584f84a779481b1a0e55eb6acdfb Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 30 Mar 2011 18:01:39 +0200 Subject: [PATCH 220/369] sync version with stable --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 86ac9f62e04..f304b4e16f4 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2011033000.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2011033002.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From c646dd26ea6c2f5bc873eec366af38a641e040eb Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sat, 19 Mar 2011 00:32:45 +0100 Subject: [PATCH 221/369] MDL-26891 profiling - earlier runs This allows profiling to be started earlier in the setup.php execution, by configuring everything in the config.php file. That way some interesting code is also profiled, like DB connections, load of config records... 100% compatible with normal profiling and enabled via special setting $CFG->earlyprofilingenabled Example (to be put on config.php): $CFG->earlyprofilingenabled = true; $CFG->profilingautofrec = 3; $CFG->profilingincluded = '/*'; $CFG->profilingallowme = true; (to enable early profiling for 1/3 of any requests while also allowing to use the PROFILEME PGC) --- admin/report/profiling/settings.php | 2 +- config-dist.php | 7 +++ lib/setup.php | 15 ++++-- lib/xhprof/readme_moodle.txt | 6 +-- lib/xhprof/xhprof_moodle.php | 72 +++++++++++++++++++++++------ 5 files changed, 79 insertions(+), 23 deletions(-) diff --git a/admin/report/profiling/settings.php b/admin/report/profiling/settings.php index b7c724bbf88..bf2dc5ff2cb 100644 --- a/admin/report/profiling/settings.php +++ b/admin/report/profiling/settings.php @@ -3,6 +3,6 @@ defined('MOODLE_INTERNAL') || die; // profiling report, added to development -if (extension_loaded('xhprof') && function_exists('xhprof_enable') && !empty($CFG->profilingenabled)) { +if (extension_loaded('xhprof') && function_exists('xhprof_enable') && (!empty($CFG->profilingenabled) || !empty($CFG->earlyprofilingenabled))) { $ADMIN->add('development', new admin_externalpage('reportprofiling', get_string('pluginname', 'report_profiling'), "$CFG->wwwroot/$CFG->admin/report/profiling/index.php", 'moodle/site:config')); } diff --git a/config-dist.php b/config-dist.php index e5952af4a3f..61c4e20bc00 100644 --- a/config-dist.php +++ b/config-dist.php @@ -297,6 +297,13 @@ $CFG->admin = 'admin'; // Print to footer (works with the default theme) // define('MDL_PERFTOFOOT', true); // +// Enable earlier profiling that causes more code to be covered +// on every request (db connections, config load, other inits...). +// Requires extra configuration to be defined in config.php like: +// profilingincluded, profilingexcluded, profilingautofrec, +// profilingallowme, profilingallowall, profilinglifetime +// $CFG->earlyprofilingenabled = true; +// // Force displayed usernames // A little hack to anonymise user names for all students. If you set these // then all non-teachers will always see these for every person. diff --git a/lib/setup.php b/lib/setup.php index de6f9fff90b..5c8bcace351 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -228,6 +228,14 @@ if (!defined('MOODLE_INTERNAL')) { // necessary because cli installer has to def define('MOODLE_INTERNAL', true); } +// Early profiling start, based exclusively on config.php $CFG settings +if (!empty($CFG->earlyprofilingenabled)) { + require_once($CFG->libdir . '/xhprof/xhprof_moodle.php'); + if (profiling_start()) { + register_shutdown_function('profiling_stop'); + } +} + /** * Database connection. Used for all access to the database. * @global moodle_database $DB @@ -669,11 +677,12 @@ session_get_instance(); $SESSION = &$_SESSION['SESSION']; $USER = &$_SESSION['USER']; -// include and start profiling if needed, and register profiling_stop as shutdown function +// Late profiling, only happening if early one wasn't started if (!empty($CFG->profilingenabled)) { require_once($CFG->libdir . '/xhprof/xhprof_moodle.php'); - profiling_start(); - register_shutdown_function('profiling_stop'); + if (profiling_start()) { + register_shutdown_function('profiling_stop'); + } } // Process theme change in the URL. diff --git a/lib/xhprof/readme_moodle.txt b/lib/xhprof/readme_moodle.txt index c75c3d470f9..6168abd7b7f 100644 --- a/lib/xhprof/readme_moodle.txt +++ b/lib/xhprof/readme_moodle.txt @@ -25,9 +25,6 @@ TODO: * export/import profiling runs: Allow to pick any profile record, encapsulate it into some serialized/encoded way and allow download/upload. It requires DB changes in order to be able to specify the source of each record (own/imported). - * move profiling start to earlier place: detect if all the needed $CFG->profilingXXX variables - have been defined in config.php file and if that condition is fullfilled, start profiling - @ the very first lines of setup.php (as early as possible). * improvements to the listing mode: various commodity details like: - allow to filter by various criteria - inline (and ajax) editing of reference/comment and deleting @@ -38,4 +35,5 @@ TODO: - cpu times (all them are right now enabled for everybody by default) -20101122 - Eloy Lafuente (stronk7): Original import of 0.9.2 release +20101122 - MDL-24600 - Eloy Lafuente (stronk7): Original import of 0.9.2 release +20110318 - MDL-26891 - Eloy Lafuente (stronk7): Implemented earlier profiling runs diff --git a/lib/xhprof/xhprof_moodle.php b/lib/xhprof/xhprof_moodle.php index 26958c83bfc..b268c324fb7 100644 --- a/lib/xhprof/xhprof_moodle.php +++ b/lib/xhprof/xhprof_moodle.php @@ -69,7 +69,7 @@ function profiling_start() { } // If profiling isn't enabled, nothing to start - if (!$CFG->profilingenabled) { + if (empty($CFG->profilingenabled) && empty($CFG->earlyprofilingenabled)) { return false; } @@ -78,19 +78,22 @@ function profiling_start() { return false; } + // Set script (from global if available, else our own) + $script = !empty($SCRIPT) ? $SCRIPT : profiling_get_script(); + // Get PGC variables $check = 'PROFILEME'; $profileme = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false; - $profileme = $profileme && $CFG->profilingallowme; + $profileme = $profileme && !empty($CFG->profilingallowme); $check = 'DONTPROFILEME'; $dontprofileme = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false; - $dontprofileme = $dontprofileme && $CFG->profilingallowme; + $dontprofileme = $dontprofileme && !empty($CFG->profilingallowme); $check = 'PROFILEALL'; $profileall = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false; - $profileall = $profileall && $CFG->profilingallowall; + $profileall = $profileall && !empty($CFG->profilingallowall); $check = 'PROFILEALLSTOP'; $profileallstop = isset($_POST[$check]) || isset($_GET[$check]) || isset($_COOKIE[$check]) ? true : false; - $profileallstop = $profileallstop && $CFG->profilingallowall; + $profileallstop = $profileallstop && !empty($CFG->profilingallowall); // DONTPROFILEME detected, nothing to start if ($dontprofileme) { @@ -98,12 +101,12 @@ function profiling_start() { } // PROFILEALLSTOP detected, clean the mark in seesion and continue - if ($profileallstop) { + if ($profileallstop && !empty($SESSION)) { unset($SESSION->profileall); } // PROFILEALL detected, set the mark in session and continue - if ($profileall) { + if ($profileall && !empty($SESSION)) { $SESSION->profileall = true; // SESSION->profileall detected, set $profileall @@ -113,21 +116,23 @@ function profiling_start() { // Evaluate automatic (random) profiling if necessary $profileauto = false; - if ($CFG->profilingautofrec) { + if (!empty($CFG->profilingautofrec)) { $profileauto = (mt_rand(1, $CFG->profilingautofrec) === 1); } - // See if the $SCRIPT matches any of the included patterns - $profileincluded = profiling_string_matches($SCRIPT, $CFG->profilingincluded); + // See if the $script matches any of the included patterns + $included = empty($CFG->profilingincluded) ? '' : $CFG->profilingincluded; + $profileincluded = profiling_string_matches($script, $included); - // See if the $SCRIPT matches any of the excluded patterns - $profileexcluded = profiling_string_matches($SCRIPT, $CFG->profilingexcluded); + // See if the $script matches any of the excluded patterns + $excluded = empty($CFG->profilingexcluded) ? '' : $CFG->profilingexcluded; + $profileexcluded = profiling_string_matches($script, $excluded); // Decide if profile auto must happen (observe matchings) $profileauto = $profileauto && $profileincluded && !$profileexcluded; // Decide if profile by match must happen (only if profileauto is disabled) - $profilematch = $profileincluded && !$profileexcluded && !$CFG->profilingautofrec; + $profilematch = $profileincluded && !$profileexcluded && empty($CFG->profilingautofrec); // If not auto, me, all, match have been detected, nothing to do if (!$profileauto && !$profileme && !$profileall && !$profilematch) { @@ -138,6 +143,9 @@ function profiling_start() { $ignore = array('call_user_func', 'call_user_func_array'); xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY, array('ignored_functions' => $ignore)); profiling_is_running(true); + + // Started, return true + return true; } /** @@ -152,7 +160,7 @@ function profiling_stop() { } // If profiling isn't enabled, nothing to stop - if (!$CFG->profilingenabled) { + if (empty($CFG->profilingenabled) && empty($CFG->earlyprofilingenabled)) { return false; } @@ -161,17 +169,23 @@ function profiling_stop() { return false; } + // Set script (from global if available, else our own) + $script = !empty($SCRIPT) ? $SCRIPT : profiling_get_script(); + // Arrived here, profiling is running, stop and save everything profiling_is_running(false); $data = xhprof_disable(); $run = new moodle_xhprofrun(); - $run->prepare_run($SCRIPT); + $run->prepare_run($script); $runid = $run->save_run($data, null); profiling_is_saved(true); // Prune old runs profiling_prune_old_runs($runid); + + // Finished, return true + return true; } function profiling_prune_old_runs($exception = 0) { @@ -190,6 +204,34 @@ function profiling_prune_old_runs($exception = 0) { runid != :exception', $params); } +/** + * Returns the path to the php script being requested + * + * Note this function is a partial copy of initialise_fullme() and + * setup_get_remote_url(), in charge of setting $FULLME, $SCRIPT and + * friends. To be used by early profiling runs in situations where + * $SCRIPT isn't defined yet + * + * @return string absolute path (wwwroot based) of the script being executed + */ +function profiling_get_script() { + global $CFG; + + $wwwroot = parse_url($CFG->wwwroot); + + if (!isset($wwwroot['path'])) { + $wwwroot['path'] = ''; + } + $wwwroot['path'] .= '/'; + + $path = $_SERVER['SCRIPT_NAME']; + + if (strpos($path, $wwwroot['path']) === 0) { + return substr($path, strlen($wwwroot['path']) - 1); + } + return ''; +} + function profiling_urls($report, $runid, $runid2 = null) { global $CFG; From c7ce62f9c8a582ec2942c1544e3c51490bfdee9d Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 7 Mar 2011 16:58:51 +0100 Subject: [PATCH 222/369] MDL-26542 get_in_or_equal - adding $onemptyitems + tests --- lib/dml/moodle_database.php | 17 +++++++- lib/dml/simpletest/testdml.php | 72 +++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 2d6b2be9ea1..b647ca9adb7 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -569,12 +569,25 @@ abstract class moodle_database { * @param int $type bound param type SQL_PARAMS_QM or SQL_PARAMS_NAMED * @param string named param placeholder start * @param bool true means equal, false not equal + * @param mixed $onemptyitems defines the behavior when the array of items is empty. Defaults to false, + * meaning throw exceptions. Other values will become part of the returned SQL fragment. * @return array - $sql and $params */ - public function get_in_or_equal($items, $type=SQL_PARAMS_QM, $start='param0000', $equal=true) { - if (is_array($items) and empty($items)) { + public function get_in_or_equal($items, $type=SQL_PARAMS_QM, $start='param0000', $equal=true, $onemptyitems=false) { + // default behavior, throw exception on empty array + if (is_array($items) and empty($items) and $onemptyitems === false) { throw new coding_exception('moodle_database::get_in_or_equal() does not accept empty arrays'); } + // handle $onemptyitems on empty array of items + if (is_array($items) and empty($items)) { + if (is_null($onemptyitems)) { // Special case, NULL value + $sql = $equal ? ' IS NULL' : ' IS NOT NULL'; + return (array($sql, array())); + } else { + $items = array($onemptyitems); // Rest of cases, prepare $items for std processing + } + } + if ($type == SQL_PARAMS_QM) { if (!is_array($items) or count($items) == 1) { $sql = $equal ? '= ?' : '<> ?'; diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index 6a71f4e88e8..f574bcdccd1 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -223,11 +223,81 @@ class dml_test extends UnitTestCase { // Correct usage of single value $in_value = 'value1'; - list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false); + list($usql, $params) = $DB->get_in_or_equal($in_value, SQL_PARAMS_NAMED, 'param01', false); $this->assertEqual("<> :param01", $usql); $this->assertEqual(1, count($params)); $this->assertEqual($in_value, $params['param01']); + // Some incorrect tests + + // Incorrect usage passing not-allowed params type + $in_values = array(1, 2, 3); + try { + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_DOLLAR, 'param01', false); + $this->fail('An Exception is missing, expected due to not supported SQL_PARAMS_DOLLAR'); + } catch (exception $e) { + $this->assertTrue($e instanceof dml_exception); + $this->assertEqual($e->errorcode, 'typenotimplement'); + } + + // Incorrect usage passing empty array + $in_values = array(); + try { + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false); + $this->fail('An Exception is missing, expected due to empty array of items'); + } catch (exception $e) { + $this->assertTrue($e instanceof coding_exception); + } + + // Test using $onemptyitems + + // Correct usage passing empty array and $onemptyitems = NULL (equal = true, QM) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param01', true, NULL); + $this->assertEqual(' IS NULL', $usql); + $this->assertIdentical(array(), $params); + + // Correct usage passing empty array and $onemptyitems = NULL (equal = false, NAMED) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false, NULL); + $this->assertEqual(' IS NOT NULL', $usql); + $this->assertIdentical(array(), $params); + + // Correct usage passing empty array and $onemptyitems = true (equal = true, QM) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param01', true, true); + $this->assertEqual('= ?', $usql); + $this->assertIdentical(array(true), $params); + + // Correct usage passing empty array and $onemptyitems = true (equal = false, NAMED) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false, true); + $this->assertEqual('<> :param01', $usql); + $this->assertIdentical(array('param01' => true), $params); + + // Correct usage passing empty array and $onemptyitems = -1 (equal = true, QM) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param01', true, -1); + $this->assertEqual('= ?', $usql); + $this->assertIdentical(array(-1), $params); + + // Correct usage passing empty array and $onemptyitems = -1 (equal = false, NAMED) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false, -1); + $this->assertEqual('<> :param01', $usql); + $this->assertIdentical(array('param01' => -1), $params); + + // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = true, QM) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_QM, 'param01', true, 'onevalue'); + $this->assertEqual('= ?', $usql); + $this->assertIdentical(array('onevalue'), $params); + + // Correct usage passing empty array and $onemptyitems = 'onevalue' (equal = false, NAMED) + $in_values = array(); + list($usql, $params) = $DB->get_in_or_equal($in_values, SQL_PARAMS_NAMED, 'param01', false, 'onevalue'); + $this->assertEqual('<> :param01', $usql); + $this->assertIdentical(array('param01' => 'onevalue'), $params); } public function test_fix_table_names() { From 71811083baa66a928638e33b19c528129f91ef26 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 30 Mar 2011 20:25:43 +0100 Subject: [PATCH 223/369] MDL-27035 table_sql forgets to set countparams. --- lib/tablelib.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tablelib.php b/lib/tablelib.php index e3d905dd4f1..efceb9c42f9 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -1346,6 +1346,7 @@ class table_sql extends flexible_table { if (!$this->is_downloading()) { if ($this->countsql === NULL) { $this->countsql = 'SELECT COUNT(1) FROM '.$this->sql->from.' WHERE '.$this->sql->where; + $this->countparams = $this->sql->params; } if ($useinitialsbar && !$this->is_downloading()) { $totalinitials = $DB->count_records_sql($this->countsql, $this->countparams); From 899d5e2d50bfddec8012390df263909b36f89605 Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Thu, 31 Mar 2011 11:50:57 +0200 Subject: [PATCH 224/369] MDL-26931 Order blog entries by the creation date --- blog/locallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/locallib.php b/blog/locallib.php index 52ff8c324b3..1cc4b0c71f5 100644 --- a/blog/locallib.php +++ b/blog/locallib.php @@ -718,7 +718,7 @@ class blog_listing { global $DB; if (empty($this->entries)) { - if ($sqlarray = $this->get_entry_fetch_sql()) { + if ($sqlarray = $this->get_entry_fetch_sql(false, 'created DESC')) { $this->entries = $DB->get_records_sql($sqlarray['sql'], $sqlarray['params'], $start, $limit); } else { return false; From 15e16f0e93a3fdffd6946bb44f7d22c8efc75499 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 25 Mar 2011 11:24:22 +0100 Subject: [PATCH 225/369] MDL-26914 Added new language pack installer class and unit tests for it The new class wraps some common coding patterns to install a language pack via component_installer. Most notably it deals with the parental dependency of the language packs. The new class should also be the only place holding the information about the location of language packs for the given Moodle version. --- lib/componentlib.class.php | 264 ++++++++++++++++++++++++++++ lib/simpletest/testcomponentlib.php | 115 ++++++++++++ 2 files changed, 379 insertions(+) diff --git a/lib/componentlib.class.php b/lib/componentlib.class.php index b064161c51f..39209bc4ef3 100644 --- a/lib/componentlib.class.php +++ b/lib/componentlib.class.php @@ -549,3 +549,267 @@ class component_installer { } } /// End of component_installer class + + +/** + * Language packs installer + * + * This class wraps the functionality provided by {@link component_installer} + * and adds support for installing a set of language packs. + * + * Given an array of required language packs, this class fetches them all + * and installs them. It detects eventual dependencies and installs + * all parent languages, too. + * + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lang_installer { + + /** lang pack was successfully downloaded and deployed */ + const RESULT_INSTALLED = 'installed'; + /** lang pack was up-to-date so no download was needed */ + const RESULT_UPTODATE = 'uptodate'; + /** there was a problem with downloading the lang pack */ + const RESULT_DOWNLOADERROR = 'downloaderror'; + + /** @var array of languages to install */ + protected $queue = array(); + /** @var string the code of language being currently installed */ + protected $current; + /** @var array of languages already installed by this instance */ + protected $done = array(); + /** @var string this Moodle major version */ + protected $version; + + /** + * Prepare the installer + * + * @todo Moodle major version is hardcoded here, should be obtained from version.php or so + * @param string|array $langcode a code of the language to install + */ + public function __construct($langcode = '') { + global $CFG; + + $this->set_queue($langcode); + $this->version = '2.0'; + + if (!empty($CFG->langotherroot) and $CFG->langotherroot !== $CFG->dataroot . '/lang') { + debugging('The in-built language pack installer does not support alternative location ' . + 'of languages root directory. You are supposed to install and update your language '. + 'packs on your own.'); + } + } + + /** + * Sets the queue of language packs to be installed + * + * @param string|array $langcodes language code like 'cs' or a list of them + */ + public function set_queue($langcodes) { + if (is_array($langcodes)) { + $this->queue = $langcodes; + } else if (!empty($langcodes)) { + $this->queue = array($langcodes); + } + } + + /** + * Runs the installer + * + * This method calls {@link self::install_language_pack} for every language in the + * queue. If a dependency is detected, the parent language is added to the queue. + * + * @return array results, array of self::RESULT_xxx constants indexed by language code + */ + public function run() { + + $results = array(); + + while ($this->current = array_shift($this->queue)) { + + if ($this->was_processed($this->current)) { + // do not repeat yourself + continue; + } + + if ($this->current === 'en') { + $this->mark_processed($this->current); + continue; + } + + $results[$this->current] = $this->install_language_pack($this->current); + + if (in_array($results[$this->current], array(self::RESULT_INSTALLED, self::RESULT_UPTODATE))) { + if ($parentlang = $this->get_parent_language($this->current)) { + if (!$this->is_queued($parentlang) and !$this->was_processed($parentlang)) { + $this->add_to_queue($parentlang); + } + } + } + + $this->mark_processed($this->current); + } + + return $results; + } + + /** + * Returns the URL where a given language pack can be downloaded + * + * Alternatively, if the parameter is empty, returns URL of the page with the + * list of all available language packs. + * + * @param string $langcode language code like 'cs' or empty for unknown + * @return string URL + */ + public function lang_pack_url($langcode = '') { + + $baseurl = 'http://download.moodle.org/langpack/' . $this->version . '/'; + + if (empty($langcode)) { + return $baseurl; + } else { + return $baseurl . $langcode . '.zip'; + } + } + + /** + * Returns the list of available language packs from download.moodle.org + * + * @return array|bool false if can not download + */ + public function get_remote_list_of_languages() { + $source = 'http://download.moodle.org/langpack/' . $this->version . '/languages.md5'; + $availablelangs = array(); + + if ($content = download_file_content($source)) { + $alllines = explode("\n", $content); + foreach($alllines as $line) { + if (!empty($line)){ + $availablelangs[] = explode(',', $line); + } + } + return $availablelangs; + + } else { + return false; + } + } + + // Internal implementation ///////////////////////////////////////////////// + + /** + * Adds a language pack (or a list of them) to the queue + * + * @param string|array $langcodes code of the language to install or a list of them + */ + protected function add_to_queue($langcodes) { + if (is_array($langcodes)) { + $this->queue = array_merge($this->queue, $langcodes); + } else if (!empty($langcodes)) { + $this->queue[] = $langcodes; + } + } + + /** + * Checks if the given language is queued or if the queue is empty + * + * @example $installer->is_queued('es'); // is Spanish going to be installed? + * @example $installer->is_queued(); // is there a language queued? + * + * @param string $langcode language code or empty string for "any" + * @return boolean + */ + protected function is_queued($langcode = '') { + + if (empty($langcode)) { + return !empty($this->queue); + + } else { + return in_array($langcode, $this->queue); + } + } + + /** + * Checks if the given language has already been processed by this instance + * + * @see self::mark_processed() + * @param string $langcode + * @return boolean + */ + protected function was_processed($langcode) { + return isset($this->done[$langcode]); + } + + /** + * Mark the given language pack as processed + * + * @see self::was_processed() + * @param string $langcode + */ + protected function mark_processed($langcode) { + $this->done[$langcode] = 1; + } + + /** + * Returns a parent language of the given installed language + * + * @param string $langcode + * @return string parent language's code + */ + protected function get_parent_language($langcode) { + return get_parent_language($langcode); + } + + /** + * Perform the actual language pack installation + * + * @uses component_installer + * @param string $langcode + * @return int return status + */ + protected function install_language_pack($langcode) { + + // initialise new component installer to process this language + $installer = new component_installer('http://download.moodle.org', 'langpack/' . $this->version, + $langcode . '.zip', 'languages.md5', 'lang'); + + if (!$installer->requisitesok) { + throw new lang_installer_exception('installer_requisites_check_failed'); + } + + $status = $installer->install(); + + if ($status == COMPONENT_ERROR) { + if ($installer->get_error() === 'remotedownloaderror') { + return self::RESULT_DOWNLOADERROR; + } else { + throw new lang_installer_exception($installer->get_error(), $langcode); + } + + } else if ($status == COMPONENT_UPTODATE) { + return self::RESULT_UPTODATE; + + } else if ($status == COMPONENT_INSTALLED) { + return self::RESULT_INSTALLED; + + } else { + throw new lang_installer_exception('unexpected_installer_result', $status); + } + } +} + + +/** + * Exception thrown by {@link lang_installer} + * + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lang_installer_exception extends moodle_exception { + + public function __construct($errorcode, $debuginfo = null) { + parent::__construct($errorcode, 'error', '', null, $debuginfo); + } +} diff --git a/lib/simpletest/testcomponentlib.php b/lib/simpletest/testcomponentlib.php index a5918fc1eb9..13d15438efa 100644 --- a/lib/simpletest/testcomponentlib.php +++ b/lib/simpletest/testcomponentlib.php @@ -58,6 +58,121 @@ class componentlib_test extends UnitTestCase { //check if correct files were downloaded $this->assertEqual('2af180e813dc3f446a9bb7b6af87ce24', md5_file($destpath.'/'.'test.jpg')); $this->assertEqual('47250a973d1b88d9445f94db4ef2c97a', md5_file($destpath.'/'.'test.html')); + } + /** + * Test the public API of the {@link lang_installer} class + */ + public function test_lang_installer() { + + // test the manipulation with the download queue + $installer = new testable_lang_installer(); + $this->assertFalse($installer->protected_is_queued()); + $installer->protected_add_to_queue('cs'); + $installer->protected_add_to_queue(array('cs', 'sk')); + $this->assertTrue($installer->protected_is_queued()); + $this->assertTrue($installer->protected_is_queued('cs')); + $this->assertTrue($installer->protected_is_queued('sk')); + $this->assertFalse($installer->protected_is_queued('de_kids')); + $installer->set_queue('de_kids'); + $this->assertFalse($installer->protected_is_queued('cs')); + $this->assertFalse($installer->protected_is_queued('sk')); + $this->assertFalse($installer->protected_is_queued('de')); + $this->assertFalse($installer->protected_is_queued('de_du')); + $this->assertTrue($installer->protected_is_queued('de_kids')); + $installer->set_queue(array('cs', 'de_kids')); + $this->assertTrue($installer->protected_is_queued('cs')); + $this->assertFalse($installer->protected_is_queued('sk')); + $this->assertFalse($installer->protected_is_queued('de')); + $this->assertFalse($installer->protected_is_queued('de_du')); + $this->assertTrue($installer->protected_is_queued('de_kids')); + $installer->set_queue(array()); + $this->assertFalse($installer->protected_is_queued()); + unset($installer); + + // install a set of lang packs + $installer = new testable_lang_installer(array('cs', 'de_kids', 'xx')); + $result = $installer->run(); + $this->assertEqual($result['cs'], lang_installer::RESULT_UPTODATE); + $this->assertEqual($result['de_kids'], lang_installer::RESULT_INSTALLED); + $this->assertEqual($result['xx'], lang_installer::RESULT_DOWNLOADERROR); + // the following two were automatically added to the queue + $this->assertEqual($result['de_du'], lang_installer::RESULT_INSTALLED); + $this->assertEqual($result['de'], lang_installer::RESULT_UPTODATE); + + // exception throwing + $installer = new testable_lang_installer(array('yy')); + $this->expectException('lang_installer_exception'); + $installer->run(); + } +} + +/** + * Testable lang_installer subclass that does not actually install anything + * and provides access to the protected methods of the parent class + * + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class testable_lang_installer extends lang_installer { + + /** + * @see parent::is_queued() + */ + public function protected_is_queued($langcode = '') { + return $this->is_queued($langcode); + } + + /** + * @see parent::add_to_queue() + */ + public function protected_add_to_queue($langcodes) { + return $this->add_to_queue($langcodes); + } + + /** + * Simulate lang pack installation via component_installer + * + * Language packages 'de_du' and 'de_kids' reported as installed + * Language packages 'cs' and 'de' reported as up-to-date + * Language package 'xx' returns download error + * All other language packages will throw an unknown exception + * + * @see parent::install_language_pack() + */ + protected function install_language_pack($langcode) { + + switch ($langcode) { + case 'de_du': + case 'de_kids': + return self::RESULT_INSTALLED; + + case 'cs': + case 'de': + return self::RESULT_UPTODATE; + + case 'xx': + return self::RESULT_DOWNLOADERROR; + + default: + throw new lang_installer_exception('testing-unknown-exception', $langcode); + } + } + + /** + * Simulate detection of parent languge + * + * @see parent::get_parent_language() + */ + protected function get_parent_language($langcode) { + + switch ($langcode) { + case 'de_kids': + return 'de_du'; + case 'de_du': + return 'de'; + default: + return ''; + } } } From 74a4c9a9ee7fb1ae67d27c0a8aed00a653c47967 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Tue, 29 Mar 2011 21:09:59 +0200 Subject: [PATCH 226/369] MDL-26914 When installing a lang pack, install all the grandparents too All places where a language pack is installed now use the new language package installer that takes case of the parental dependencies. --- admin/cli/install.php | 29 +++---- admin/cli/install_database.php | 29 +++---- admin/langimport.php | 141 ++++++++++++--------------------- install.php | 27 +++---- lang/en/admin.php | 1 + lib/upgradelib.php | 26 +++--- 6 files changed, 94 insertions(+), 159 deletions(-) diff --git a/admin/cli/install.php b/admin/cli/install.php index fc643b53265..1c37f549057 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -376,25 +376,16 @@ if ($interactive) { } } -//download lang pack with optional notification -if ($CFG->lang != 'en') { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $CFG->lang.'.zip', 'languages.md5', 'lang')) { - if ($cd->install() == COMPONENT_ERROR) { - if ($cd->get_error() == 'remotedownloaderror') { - $a = new stdClass(); - $a->url = 'http://download.moodle.org/langpack/2.0/'.$CFG->lang.'.zip'; - $a->dest = $CFG->dataroot.'/lang'; - cli_problem(get_string($cd->get_error(), 'error', $a)); - } else { - cli_problem(get_string($cd->get_error(), 'error')); - } - } else { - // install parent lang if defined - if ($parentlang = get_parent_language()) { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $parentlang.'.zip', 'languages.md5', 'lang')) { - $cd->install(); - } - } +// download required lang packs +if ($CFG->lang !== 'en') { + $installer = new lang_installer($CFG->lang); + $results = $installer->run(); + foreach ($results as $langcode => $langstatus) { + if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) { + $a = new stdClass(); + $a->url = $installer->lang_pack_url($langcode); + $a->dest = $CFG->dataroot.'/lang'; + cli_problem(get_string('remotedownloaderror', 'error', $a)); } } } diff --git a/admin/cli/install_database.php b/admin/cli/install_database.php index 17f6d59309d..ac58928f6a6 100644 --- a/admin/cli/install_database.php +++ b/admin/cli/install_database.php @@ -121,26 +121,17 @@ if (!file_exists($CFG->dirroot.'/install/lang/'.$options['lang'])) { } $CFG->lang = $options['lang']; -//download lang pack with optional notification -if ($CFG->lang != 'en') { +// download required lang packs +if ($CFG->lang !== 'en') { make_upload_directory('lang'); - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $CFG->lang.'.zip', 'languages.md5', 'lang')) { - if ($cd->install() == COMPONENT_ERROR) { - if ($cd->get_error() == 'remotedownloaderror') { - $a = new stdClass(); - $a->url = 'http://download.moodle.org/langpack/2.0/'.$CFG->lang.'.zip'; - $a->dest = $CFG->dataroot.'/lang'; - cli_problem(get_string($cd->get_error(), 'error', $a)); - } else { - cli_problem(get_string($cd->get_error(), 'error')); - } - } else { - // install parent lang if defined - if ($parentlang = get_parent_language()) { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $parentlang.'.zip', 'languages.md5', 'lang')) { - $cd->install(); - } - } + $installer = new lang_installer($CFG->lang); + $results = $installer->run(); + foreach ($results as $langcode => $langstatus) { + if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) { + $a = new stdClass(); + $a->url = $installer->lang_pack_url($langcode); + $a->dest = $CFG->dataroot.'/lang'; + cli_problem(get_string('remotedownloaderror', 'error', $a)); } } } diff --git a/admin/langimport.php b/admin/langimport.php index 3ebb9deef43..4aa614b2193 100644 --- a/admin/langimport.php +++ b/admin/langimport.php @@ -18,7 +18,7 @@ /** * Fetches language packages from download.moodle.org server * - * Language packages are available at http://download.moodle.org/langpack/2.0/ + * Language packages are available at http://download.moodle.org/langpack/ * in ZIP format together with a file languages.md5 containing their hashes * and meta info. * Locally, language packs are saved into $CFG->dataroot/lang/ @@ -33,8 +33,6 @@ require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/filelib.php'); require_once($CFG->libdir.'/componentlib.class.php'); -$thisversion = '2.0'; // TODO this information should be taken from version.php or similar source - admin_externalpage_setup('langimport'); if (!empty($CFG->skiplangupgrade)) { @@ -63,41 +61,22 @@ if (($mode == INSTALLATION_OF_SELECTED_LANG) and confirm_sesskey() and !empty($p make_upload_directory('temp'); make_upload_directory('lang'); - if (is_array($pack)) { - $packs = $pack; - } else { - $packs = array($pack); - } - - foreach ($packs as $pack) { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion, $pack.'.zip', 'languages.md5', 'lang')) { - $status = $cd->install(); - switch ($status) { - case COMPONENT_ERROR: - if ($cd->get_error() == 'remotedownloaderror') { - $a = new stdClass(); - $a->url = 'http://download.moodle.org/langpack/'.$thisversion.'/'.$pack.'.zip'; - $a->dest = $CFG->dataroot.'/lang'; - print_error($cd->get_error(), 'error', 'langimport.php', $a); - } else { - print_error($cd->get_error(), 'error', 'langimport.php'); - } - break; - case COMPONENT_INSTALLED: - $notice_ok[] = get_string('langpackinstalled','admin',$pack); - if ($parentlang = get_parent_language($pack)) { - // install also parent pack if specified - if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion, - $parentlang.'.zip', 'languages.md5', 'lang')) { - $cd->install(); - } - } - break; - case COMPONENT_UPTODATE: - break; - } - } else { - echo $OUTPUT->notification('Had an unspecified error with the component installer, sorry.'); + $installer = new lang_installer($pack); + $results = $installer->run(); + foreach ($results as $langcode => $langstatus) { + switch ($langstatus) { + case lang_installer::RESULT_DOWNLOADERROR: + $a = new stdClass(); + $a->url = $installer->lang_pack_url($langcode); + $a->dest = $CFG->dataroot.'/lang'; + print_error('remotedownloaderror', 'error', 'langimport.php', $a); + break; + case lang_installer::RESULT_INSTALLED: + $notice_ok[] = get_string('langpackinstalled', 'admin', $langcode); + break; + case lang_installer::RESULT_UPTODATE: + $notice_ok[] = get_string('langpackuptodate', 'admin', $langcode); + break; } } } @@ -136,7 +115,9 @@ if ($mode == DELETION_OF_SELECTED_LANG and !empty($uninstalllang)) { if ($mode == UPDATE_ALL_LANG) { set_time_limit(0); - if (!$availablelangs = get_remote_list_of_languages()) { + $installer = new lang_installer(); + + if (!$availablelangs = $installer->get_remote_list_of_languages()) { print_error('cannotdownloadlanguageupdatelist', 'error'); } $md5array = array(); // (string)langcode => (string)md5 @@ -171,8 +152,8 @@ if ($mode == UPDATE_ALL_LANG) { make_upload_directory('temp'); make_upload_directory('lang'); - $updated = false; // any packs updated? - foreach ($neededlangs as $pack) { + // clean-up currently installed versions of the packs + foreach ($neededlangs as $packindex => $pack) { if ($pack == 'en') { continue; } @@ -185,41 +166,38 @@ if ($mode == UPDATE_ALL_LANG) { if (file_exists($dest1)) { if (!remove_dir($dest1)) { $notice_error[] = 'Could not delete old directory '.$dest1.', update of '.$pack.' failed, please check permissions.'; + unset($neededlangs[$packindex]); continue; } } if (file_exists($dest2)) { if (!remove_dir($dest2)) { $notice_error[] = 'Could not delete old directory '.$dest2.', update of '.$pack.' failed, please check permissions.'; + unset($neededlangs[$packindex]); continue; } } + } - // copy and unzip new version - if ($cd = new component_installer('http://download.moodle.org', 'langpack/'.$thisversion, $pack.'.zip', 'languages.md5', 'lang')) { - $status = $cd->install(); - switch ($status) { - - case COMPONENT_ERROR: - if ($cd->get_error() == 'remotedownloaderror') { - $a = new stdClass(); - $a->url = 'http://download.moodle.org/langpack/'.$thisversion.'/'.$pack.'.zip'; - $a->dest = $CFG->dataroot.'/lang'; - print_error($cd->get_error(), 'error', 'langimport.php', $a); - } else { - print_error($cd->get_error(), 'error', 'langimport.php'); - } - break; - - case COMPONENT_UPTODATE: - // should not get here - break; - - case COMPONENT_INSTALLED: - $notice_ok[] = get_string('langpackupdated', 'admin', $pack); - $updated = true; - break; - } + // install all needed language packs + $installer->set_queue($neededlangs); + $results = $installer->run(); + $updated = false; // any packs updated? + foreach ($results as $langcode => $langstatus) { + switch ($langstatus) { + case lang_installer::RESULT_DOWNLOADERROR: + $a = new stdClass(); + $a->url = $installer->lang_pack_url($langcode); + $a->dest = $CFG->dataroot.'/lang'; + print_error('remotedownloaderror', 'error', 'langimport.php', $a); + break; + case lang_installer::RESULT_INSTALLED: + $updated = true; + $notice_ok[] = get_string('langpackinstalled', 'admin', $langcode); + break; + case lang_installer::RESULT_UPTODATE: + $notice_ok[] = get_string('langpackuptodate', 'admin', $langcode); + break; } } @@ -228,6 +206,8 @@ if ($mode == UPDATE_ALL_LANG) { } else { $notice_ok[] = get_string('nolangupdateneeded','admin'); } + + unset($installer); } get_string_manager()->reset_caches(); @@ -239,7 +219,7 @@ $installedlangs = get_string_manager()->get_list_of_translations(true); $missingparents = array(); foreach ($installedlangs as $installedlang => $unused) { $parent = get_parent_language($installedlang); - if (empty($parent) or ($parent === 'en')) { + if (empty($parent)) { continue; } if (!isset($installedlangs[$parent])) { @@ -247,7 +227,9 @@ foreach ($installedlangs as $installedlang => $unused) { } } -if ($availablelangs = get_remote_list_of_languages()) { +$installer = new lang_installer(); + +if ($availablelangs = $installer->get_remote_list_of_languages()) { $remote = true; } else { $remote = false; @@ -357,26 +339,3 @@ function is_installed_lang($lang, $md5check) { } return false; } - -/** - * Returns the list of available language packs from download.moodle.org - * - * @return array|bool false if can not download - */ -function get_remote_list_of_languages() { - $source = 'http://download.moodle.org/langpack/2.0/languages.md5'; - $availablelangs = array(); - - if ($content = download_file_content($source)) { - $alllines = explode("\n", $content); - foreach($alllines as $line) { - if (!empty($line)){ - $availablelangs[] = explode(',', $line); - } - } - return $availablelangs; - - } else { - return false; - } -} diff --git a/install.php b/install.php index 4a4896ad0f1..b615587b7d4 100644 --- a/install.php +++ b/install.php @@ -354,24 +354,15 @@ if ($config->stage == INSTALL_DATABASETYPE) { if ($config->stage == INSTALL_DOWNLOADLANG) { $downloaderror = ''; -// Download and install lang component, lang dir was already created in install_init_dataroot - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $CFG->lang.'.zip', 'languages.md5', 'lang')) { - if ($cd->install() == COMPONENT_ERROR) { - if ($cd->get_error() == 'remotedownloaderror') { - $a = new stdClass(); - $a->url = 'http://download.moodle.org/langpack/2.0/'.$config->lang.'.zip'; - $a->dest = $CFG->dataroot.'/lang'; - $downloaderror = get_string($cd->get_error(), 'error', $a); - } else { - $downloaderror = get_string($cd->get_error(), 'error'); - } - } else { - // install parent lang if defined - if ($parentlang = get_parent_language()) { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $parentlang.'.zip', 'languages.md5', 'lang')) { - $cd->install(); - } - } + // download and install required lang packs, the lang dir has already been created in install_init_dataroot + $installer = new lang_installer($CFG->lang); + $results = $installer->run(); + foreach ($results as $langcode => $langstatus) { + if ($langstatus === lang_installer::RESULT_DOWNLOADERROR) { + $a = new stdClass(); + $a->url = $installer->lang_pack_url($langcode); + $a->dest = $CFG->dataroot.'/lang'; + $downloaderror = get_string('remotedownloaderror', 'error', $a); } } diff --git a/lang/en/admin.php b/lang/en/admin.php index 7c67ea9a5e6..874535ba6e4 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -648,6 +648,7 @@ $string['langpackremoved'] = 'Language pack was uninstalled'; $string['langpacks'] = 'Language packs'; $string['langpackupdated'] = 'Language pack {$a} was successfully updated'; $string['langpackupdateskipped'] = 'Update of {$a} language pack skipped'; +$string['langpackuptodate'] = 'Language pack {$a} is up-to-date'; $string['langpackwillbeupdated'] = 'NOTE: Moodle will try to download updates for your language packs during the upgrade.'; $string['langrmyourself'] = 'To prevent data loss, lang.php is not able to overwrite existing file with empty content. Please, remove the file manually in order to get rid of it.'; $string['langstringcache'] = 'Cache all language strings'; diff --git a/lib/upgradelib.php b/lib/upgradelib.php index e0ba25c3028..a526068897c 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1259,11 +1259,10 @@ function upgrade_init_javascript() { $PAGE->requires->js_init_code($js); } - /** * Try to upgrade the given language pack (or current language) * - * @todo hardcoded Moodle version here - shall be provided by version.php or similar script + * @param string $lang the code of the language to update, defaults to the current language */ function upgrade_language_pack($lang='') { global $CFG, $OUTPUT; @@ -1286,16 +1285,19 @@ function upgrade_language_pack($lang='') { require_once($CFG->libdir.'/componentlib.class.php'); - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $lang.'.zip', 'languages.md5', 'lang')) { - $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED) - - if ($status == COMPONENT_INSTALLED) { - if ($parentlang = get_parent_language($lang)) { - if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $parentlang.'.zip', 'languages.md5', 'lang')) { - $cd->install(); - } - } - echo $OUTPUT->notification(get_string('success'), 'notifysuccess'); + $installer = new lang_installer($pack); + $results = $installer->run(); + foreach ($results as $langcode => $langstatus) { + switch ($langstatus) { + case lang_installer::RESULT_DOWNLOADERROR: + echo $OUTPUT->notification($pack . '.zip'); + break; + case lang_installer::RESULT_INSTALLED: + echo $OUTPUT->notification(get_string('langpackinstalled', 'admin', $langcode), 'notifysuccess'); + break; + case lang_installer::RESULT_UPTODATE: + echo $OUTPUT->notification(get_string('langpackuptodate', 'admin', $langcode), 'notifysuccess'); + break; } } From fa820563289464bc638aa8cfe8fcb7056b33ea1e Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 24 Mar 2011 14:39:14 +0100 Subject: [PATCH 227/369] MDL-11288 Added ability to duplicate module in the course Internally, the new script modduplicate.php performs a single activity backup and restore and then moves the newly created copy right below the original. --- course/lib.php | 4 + course/mod.php | 37 +++++++++ course/modduplicate.php | 145 ++++++++++++++++++++++++++++++++++++ lang/en/moodle.php | 5 +- lib/ajax/section_classes.js | 7 ++ 5 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 course/modduplicate.php diff --git a/course/lib.php b/course/lib.php index 377a27575ee..10fd77ded29 100644 --- a/course/lib.php +++ b/course/lib.php @@ -3160,6 +3160,10 @@ function make_editing_buttons($mod, $absolute=false, $moveselect=true, $indent=- '&sesskey='.$sesskey.$section.'">'."\n". + ''."\n". 'wwwroot/course/modedit.php?update=$update&return=$returntomod"); +} else if (!empty($duplicate)) { + $cm = get_coursemodule_from_id('', $duplicate, 0, true, MUST_EXIST); + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + + require_login($course->id); + $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); + $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); + require_capability('moodle/course:manageactivities', $coursecontext); + + if (!$confirm or !confirm_sesskey()) { + $PAGE->set_title(get_string('duplicate')); + $PAGE->set_heading($course->fullname); + $PAGE->navbar->add(get_string('duplicatinga', 'core', format_string($cm->name))); + $PAGE->set_pagelayout('incourse'); + + $a = new stdClass(); + $a->modtype = get_string('modulename', $cm->modname); + $a->modname = format_string($cm->name); + $a->modid = $cm->id; + + echo $OUTPUT->header(); + echo $OUTPUT->confirm( + get_string('duplicateconfirm', 'core', $a), + new single_button( + new moodle_url('/course/modduplicate.php', array('cmid' => $cm->id, 'course' => $course->id)), + get_string('continue'), + 'post'), + new single_button( + new moodle_url('/course/view.php#section-' . $cm->sectionnum, array('id' => $cm->course)), + get_string('cancel'), + 'get') + ); + echo $OUTPUT->footer(); + die(); + } + } else if (!empty($delete)) { if (!$cm = get_coursemodule_from_id('', $delete, 0, true)) { print_error('invalidcoursemodule'); diff --git a/course/modduplicate.php b/course/modduplicate.php new file mode 100644 index 00000000000..632f191853e --- /dev/null +++ b/course/modduplicate.php @@ -0,0 +1,145 @@ +. + +/** + * Duplicates a given course module + * + * The script backups and restores a single activity as if it was imported + * from the same course, using the default import settings. The newly created + * copy of the activity is then moved right below the original one. + * + * @package core + * @subpackage course + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(dirname(__FILE__)) . '/config.php'); +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); +require_once($CFG->libdir . '/filelib.php'); + +$cmid = required_param('cmid', PARAM_INT); +$courseid = required_param('course', PARAM_INT); + +$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); +$cm = get_coursemodule_from_id('', $cmid, $course->id, true, MUST_EXIST); +$cmcontext = get_context_instance(CONTEXT_MODULE, $cm->id); +$context = get_context_instance(CONTEXT_COURSE, $courseid); +$section = $DB->get_record('course_sections', array('id' => $cm->section, 'course' => $cm->course)); + +require_login($course); +require_sesskey(); +require_capability('moodle/course:manageactivities', $context); +require_capability('moodle/backup:backuptargetimport', $context); +require_capability('moodle/restore:restoretargetimport', $context); + +$PAGE->set_title(get_string('duplicate')); +$PAGE->set_heading($course->fullname); +$PAGE->set_url(new moodle_url('/course/modduplicate.php', array('cmid' => $cm->id, 'courseid' => $course->id))); +$PAGE->set_pagelayout('incourse'); + +$output = $PAGE->get_renderer('core', 'backup'); + +// backup the activity + +$bc = new backup_controller(backup::TYPE_1ACTIVITY, $cm->id, backup::FORMAT_MOODLE, + backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id); + +$backupid = $bc->get_backupid(); +$backupbasepath = $bc->get_plan()->get_basepath(); + +$bc->execute_plan(); + +$bc->destroy(); + +// restore the backup immediately + +$rc = new restore_controller($backupid, $courseid, + backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_CURRENT_ADDING); + +if (!$rc->execute_precheck()) { + $precheckresults = $rc->get_precheck_results(); + if (is_array($precheckresults) && !empty($precheckresults['errors'])) { + if (empty($CFG->keeptempdirectoriesonbackup)) { + fulldelete($backupbasepath); + } + + echo $output->header(); + echo $output->precheck_notices($precheckresults); + echo $output->continue_button(new moodle_url('/course/view.php', array('id' => $course->id))); + echo $output->footer(); + die(); + } +} + +$rc->execute_plan(); + +// now a bit hacky part follows - we try to get the cmid of the newly +// restored copy of the module +$newcmid = null; +$tasks = $rc->get_plan()->get_tasks(); +foreach ($tasks as $task) { + if (is_subclass_of($task, 'restore_activity_task')) { + if ($task->get_old_contextid() == $cmcontext->id) { + $newcmid = $task->get_moduleid(); + break; + } + } +} + +// if we know the cmid of the new course module, let us move it +// right below the original one. otherwise it will stay at the +// end of the section +if ($newcmid) { + $newcm = get_coursemodule_from_id('', $newcmid, $course->id, true, MUST_EXIST); + moveto_module($newcm, $section, $cm); + moveto_module($cm, $section, $newcm); +} + +$rc->destroy(); + +if (empty($CFG->keeptempdirectoriesonbackup)) { + fulldelete($backupbasepath); +} + +$a = new stdClass(); +$a->modtype = get_string('modulename', $cm->modname); +$a->modname = format_string($cm->name); + +echo $output->header(); + +if ($newcmid) { + echo $output->confirm( + get_string('duplicatesuccess', 'core', $a), + new single_button( + new moodle_url('/course/modedit.php', array('update' => $newcmid)), + get_string('duplicatecontedit'), + 'get'), + new single_button( + new moodle_url('/course/view.php#section-' . $cm->sectionnum, array('id' => $cm->course)), + get_string('duplicatecontcourse'), + 'get') + ); + +} else { + echo $output->notification(get_string('duplicatesuccess', 'core', $a), 'notifysuccess'); + echo $output->continue_button( + new moodle_url('/course/view.php#section-' . $cm->sectionnum, array('id' => $course->id)) + ); +} + +echo $output->footer(); diff --git a/lang/en/moodle.php b/lang/en/moodle.php index faa6d9cbbb4..c520725506d 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -461,8 +461,11 @@ $string['downloadods'] = 'Download in ODS format'; $string['downloadtext'] = 'Download in text format'; $string['doyouagree'] = 'Have you read these conditions and understood them?'; $string['duplicate'] = 'Duplicate'; +$string['duplicateconfirm'] = 'Are you sure you want to duplicate {$a->modtype} \'{$a->modname}\' ?'; +$string['duplicatecontcourse'] = 'Return to the course'; +$string['duplicatecontedit'] = 'Edit the new copy'; +$string['duplicatesuccess'] = '{$a->modtype} \'{$a->modname}\' has been duplicated successfully'; $string['duplicatinga'] = 'Duplicating: {$a}'; -$string['duplicatingain'] = 'Duplicating {$a->what} in {$a->in}'; $string['edhelpaspellpath'] = 'To use spell-checking within the editor, you MUST have aspell 0.50 or later installed on your server, and you must specify the correct path to access the aspell binary. On Unix/Linux systems, this path is usually /usr/bin/aspell, but it might be something else.'; $string['edhelpbgcolor'] = 'Define the edit area\'s background color.
Valid values are, for example: #FFFFFF or white'; $string['edhelpcleanword'] = 'This setting enables or disables Word-specific format filtering.'; diff --git a/lib/ajax/section_classes.js b/lib/ajax/section_classes.js index bc52f9588cc..46420d2b459 100644 --- a/lib/ajax/section_classes.js +++ b/lib/ajax/section_classes.js @@ -631,6 +631,7 @@ resource_class.prototype.init_buttons = function() { var moveLeft = false; var moveRight = false; var updateButton = null; + var duplicateButton = null; var assignButton = null; // for RTL support @@ -643,6 +644,8 @@ resource_class.prototype.init_buttons = function() { moveRight = true; } else if (buttons[x].className == 'editing_update') { updateButton = buttons[x].cloneNode(true); + } else if (buttons[x].className == 'editing_duplicate') { + duplicateButton = buttons[x].cloneNode(true); } else if (buttons[x].className == 'editing_assign') { assignButton = buttons[x].cloneNode(true); } else if (buttons[x].className == 'editing_groupsnone') { @@ -691,6 +694,10 @@ resource_class.prototype.init_buttons = function() { // Add edit button back in. commandContainer.appendChild(updateButton); + if (duplicateButton) { + commandContainer.appendChild(duplicateButton); + } + // Add the delete button. var button = main.mk_button('a', main.portal.icons['delete'], main.portal.strings['delete'], null, [['class', 'iconsmall']]); YAHOO.util.Event.addListener(button, 'click', this.delete_button, this, true); From b9934a173a7bebc23db4cd3a0970a99f2fb933fe Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 10 Mar 2011 00:50:18 +0100 Subject: [PATCH 228/369] MDL-26784 Improved plugins check screen and the new plugins management screen This patch introduces new lib/pluginlib.php library that provides unified access meta-information about all present plugin types. The library defines plugin_manager singleton that in turn gathers information about all present plugins and their status. The list of plugins can be rendered either as plugins check table or plugins control panel. This makes print_plugins_table() function obsolete and because it is not expected to be called by any contrib plugin, the function is removed. CSS for the legacy table generated by print_plugins_table() is cleaned up. --- admin/index.php | 37 +- admin/plugins.php | 41 + admin/renderer.php | 296 ++++ admin/settings/plugins.php | 1 + lang/en/admin.php | 1 + lib/adminlib.php | 203 +-- lib/moodlelib.php | 35 - lib/outputrequirementslib.php | 8 +- lib/pluginlib.php | 1483 +++++++++++++++++++++ theme/anomaly/style/general.css | 4 +- theme/base/style/admin.css | 28 +- theme/canvas/style/admin.css | 7 +- theme/canvas/style/tables.css | 5 +- theme/formal_white/style/core.css | 9 +- theme/formal_white/style/formal_white.css | 4 +- theme/standard/style/admin.css | 5 - 16 files changed, 1890 insertions(+), 277 deletions(-) create mode 100644 admin/plugins.php create mode 100644 admin/renderer.php create mode 100644 lib/pluginlib.php diff --git a/admin/index.php b/admin/index.php index f40ad17512a..8b66c1f25b4 100644 --- a/admin/index.php +++ b/admin/index.php @@ -48,6 +48,7 @@ $id = optional_param('id', '', PARAM_TEXT); $confirmupgrade = optional_param('confirmupgrade', 0, PARAM_BOOL); $confirmrelease = optional_param('confirmrelease', 0, PARAM_BOOL); $confirmplugins = optional_param('confirmplugincheck', 0, PARAM_BOOL); +$showallplugins = optional_param('showallplugins', 0, PARAM_BOOL); $agreelicense = optional_param('agreelicense', 0, PARAM_BOOL); // Check some PHP server settings @@ -255,17 +256,19 @@ if ($version > $CFG->version) { // upgrade $PAGE->set_title($strplugincheck); $PAGE->set_heading($strplugincheck); $PAGE->set_cacheable(false); - echo $OUTPUT->header(); - echo $OUTPUT->heading($strplugincheck); - echo $OUTPUT->box_start('generalbox', 'notice'); - print_string('pluginchecknotice'); - echo $OUTPUT->box_end(); - print_plugin_tables(); + $output = $PAGE->get_renderer('core', 'admin'); + $pluginman = plugin_manager::instance(); + + echo $output->header(); + echo $output->box_start('generalbox'); + echo $output->container(get_string('pluginchecknotice', 'core_plugin'), 'generalbox', 'notice'); + echo $output->plugins_check($pluginman->get_plugins(), array('full' => $showallplugins)); + echo $output->box_end(); print_upgrade_reload('index.php?confirmupgrade=1&confirmrelease=1'); $button = new single_button(new moodle_url('index.php', array('confirmupgrade'=>1, 'confirmrelease'=>1, 'confirmplugincheck'=>1)), get_string('upgradestart', 'admin'), 'get'); $button->class = 'continuebutton'; - echo $OUTPUT->render($button); - echo $OUTPUT->footer(); + echo $output->render($button); + echo $output->footer(); die(); } else { @@ -293,17 +296,19 @@ if (moodle_needs_upgrading()) { $PAGE->set_title($strplugincheck); $PAGE->set_heading($strplugincheck); $PAGE->set_cacheable(false); - echo $OUTPUT->header(); - echo $OUTPUT->heading($strplugincheck); - echo $OUTPUT->box_start('generalbox', 'notice'); - print_string('pluginchecknotice'); - echo $OUTPUT->box_end(); - print_plugin_tables(); + $output = $PAGE->get_renderer('core', 'admin'); + $pluginman = plugin_manager::instance(); + + echo $output->header(); + echo $output->box_start('generalbox'); + echo $output->container(get_string('pluginchecknotice', 'core_plugin'), 'generalbox', 'notice'); + echo $output->plugins_check($pluginman->get_plugins(), array('full' => $showallplugins)); + echo $output->box_end(); print_upgrade_reload('index.php'); $button = new single_button(new moodle_url('index.php', array('confirmplugincheck'=>1)), get_string('upgradestart', 'admin'), 'get'); $button->class = 'continuebutton'; - echo $OUTPUT->render($button); - echo $OUTPUT->footer(); + echo $output->render($button); + echo $output->footer(); die(); } } diff --git a/admin/plugins.php b/admin/plugins.php new file mode 100644 index 00000000000..165dfaca945 --- /dev/null +++ b/admin/plugins.php @@ -0,0 +1,41 @@ +. + +/** + * UI for general plugins management + * + * @package core + * @subpackage admin + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(dirname(__FILE__)) . '/config.php'); +require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->libdir . '/pluginlib.php'); + +require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); +admin_externalpage_setup('pluginsoverview'); +$output = $PAGE->get_renderer('core', 'admin'); +$pluginman = plugin_manager::instance(); + +echo $output->header(); +echo $output->heading(get_string('pluginsoverview', 'core_admin')); +echo $output->box_start('generalbox'); +echo $output->plugins_control_panel($pluginman->get_plugins()); +echo $output->box_end(); +echo $output->footer(); diff --git a/admin/renderer.php b/admin/renderer.php new file mode 100644 index 00000000000..08b81e3b03b --- /dev/null +++ b/admin/renderer.php @@ -0,0 +1,296 @@ +. + +/** + * Renderer for core_admin subsystem + * + * @package core + * @subpackage admin + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir . '/pluginlib.php'); + +/** + * Standard HTML output renderer for core_admin subsystem + */ +class core_admin_renderer extends plugin_renderer_base { + + /** + * Displays all known plugins and information about their installation or upgrade + * + * This default implementation renders all plugins into one big table. The rendering + * options support: + * (bool)full = false: whether to display up-to-date plugins, too + * + * @param array $plugininfo as returned by {@see plugin_manager::get_plugins()} + * @param array $options rendering options + * @return string HTML code + */ + public function plugins_check(array $plugininfo, array $options = null) { + + if (empty($plugininfo)) { + return ''; + } + + if (empty($options)) { + $options = array( + 'full' => false, + ); + } + + $pluginman = plugin_manager::instance(); + + $table = new html_table(); + $table->id = 'plugins-check'; + $table->head = array( + get_string('displayname', 'core_plugin'), + get_string('rootdir', 'core_plugin'), + get_string('source', 'core_plugin'), + get_string('versiondb', 'core_plugin'), + get_string('versiondisk', 'core_plugin'), + get_string('status', 'core_plugin'), + ); + $table->colclasses = array( + 'displayname', 'rootdir', 'source', 'versiondb', 'versiondisk', 'status', + ); + $table->data = array(); + + $numofhighlighted = array(); // number of highlighted rows per this subsection + + foreach ($plugininfo as $type => $plugins) { + + $header = new html_table_cell($pluginman->plugintype_name_plural($type)); + $header->header = true; + $header->colspan = count($table->head); + $header = new html_table_row(array($header)); + $header->attributes['class'] = 'plugintypeheader type-' . $type; + + $numofhighlighted[$type] = 0; + + if (empty($plugins) and $options['full']) { + $msg = new html_table_cell(get_string('noneinstalled', 'core_plugin')); + $msg->colspan = count($table->head); + $row = new html_table_row(array($msg)); + $row->attributes['class'] .= 'msg msg-noneinstalled'; + $table->data[] = $header; + $table->data[] = $row; + continue; + } + + $plugintyperows = array(); + + foreach ($plugins as $name => $plugin) { + $row = new html_table_row(); + $row->attributes['class'] = 'type-' . $plugin->type . ' name-' . $plugin->type . '_' . $plugin->name; + + if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name)) { + $icon = $this->output->pix_icon('icon', '', $plugin->type . '_' . $plugin->name, array('class' => 'smallicon pluginicon')); + } else { + $icon = $this->output->pix_icon('spacer', '', 'moodle', array('class' => 'smallicon pluginicon noicon')); + } + $displayname = $icon . ' ' . $plugin->displayname; + $displayname = new html_table_cell($displayname); + + $rootdir = new html_table_cell($plugin->get_dir()); + + if ($isstandard = $plugin->is_standard()) { + $row->attributes['class'] .= ' standard'; + $source = new html_table_cell(get_string('sourcestd', 'core_plugin')); + } else { + $row->attributes['class'] .= ' extension'; + $source = new html_table_cell(get_string('sourceext', 'core_plugin')); + } + + $versiondb = new html_table_cell($plugin->versiondb); + $versiondisk = new html_table_cell($plugin->versiondisk); + + $statuscode = $plugin->get_status(); + $row->attributes['class'] .= ' status-' . $statuscode; + + $status = new html_table_cell(get_string('status_' . $statuscode, 'core_plugin')); + + if ($isstandard and in_array($statuscode, array(plugin_manager::PLUGIN_STATUS_NODB, plugin_manager::PLUGIN_STATUS_UPTODATE))) { + if (empty($options['full'])) { + continue; + } + } else { + $numofhighlighted[$type]++; + } + + $row->cells = array($displayname, $rootdir, $source, $versiondb, $versiondisk, $status); + $plugintyperows[] = $row; + } + + if (empty($numofhighlighted[$type]) and empty($options['full'])) { + continue; + } + + $table->data[] = $header; + $table->data = array_merge($table->data, $plugintyperows); + } + + $sumofhighlighted = array_sum($numofhighlighted); + + if ($sumofhighlighted == 0) { + $out = $this->output->container_start('nonehighlighted', 'plugins-check-info'); + $out .= $this->output->heading(get_string('nonehighlighted', 'core_plugin')); + if (empty($options['full'])) { + $out .= html_writer::link(new moodle_url('/admin/index.php', + array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1)), + get_string('nonehighlightedinfo', 'core_plugin')); + } + $out .= $this->output->container_end(); + + } else { + $out = $this->output->container_start('somehighlighted', 'plugins-check-info'); + $out .= $this->output->heading(get_string('somehighlighted', 'core_plugin', $sumofhighlighted)); + if (empty($options['full'])) { + $out .= html_writer::link(new moodle_url('/admin/index.php', + array('confirmupgrade' => 1, 'confirmrelease' => 1, 'showallplugins' => 1)), + get_string('somehighlightedinfo', 'core_plugin')); + } + $out .= $this->output->container_end(); + } + + if ($sumofhighlighted > 0 or $options['full']) { + $out .= html_writer::table($table); + } + + return $out; + } + + /** + * Displays all known plugins and links to manage them + * + * This default implementation renders all plugins into one big table. + * + * @param array $plugininfo as returned by {@see plugin_manager::get_plugins()} + * @return string HTML code + */ + public function plugins_control_panel(array $plugininfo) { + + if (empty($plugininfo)) { + return ''; + } + + $pluginman = plugin_manager::instance(); + + $table = new html_table(); + $table->id = 'plugins-control-panel'; + $table->head = array( + get_string('displayname', 'core_plugin'), + get_string('systemname', 'core_plugin'), + get_string('source', 'core_plugin'), + get_string('version', 'core_plugin'), + get_string('availability', 'core_plugin'), + get_string('settings', 'core_plugin'), + get_string('uninstall','core_plugin'), + ); + $table->colclasses = array( + 'displayname', 'systemname', 'source', 'version', 'availability', 'settings', 'uninstall', + ); + + foreach ($plugininfo as $type => $plugins) { + + $header = new html_table_cell($pluginman->plugintype_name_plural($type)); + $header->header = true; + $header->colspan = count($table->head); + $header = new html_table_row(array($header)); + $header->attributes['class'] = 'plugintypeheader type-' . $type; + $table->data[] = $header; + + if (empty($plugins)) { + $msg = new html_table_cell(get_string('noneinstalled', 'core_plugin')); + $msg->colspan = count($table->head); + $row = new html_table_row(array($msg)); + $row->attributes['class'] .= 'msg msg-noneinstalled'; + $table->data[] = $row; + continue; + } + + foreach ($plugins as $name => $plugin) { + $row = new html_table_row(); + $row->attributes['class'] = 'type-' . $plugin->type . ' name-' . $plugin->type . '_' . $plugin->name; + + if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name)) { + $icon = $this->output->pix_icon('icon', '', $plugin->type . '_' . $plugin->name, array('class' => 'smallicon pluginicon')); + } else { + $icon = $this->output->pix_icon('spacer', '', 'moodle', array('class' => 'smallicon pluginicon noicon')); + } + if ($plugin->get_status() === plugin_manager::PLUGIN_STATUS_MISSING) { + $msg = html_writer::tag('span', get_string('status_missing', 'core_plugin'), array('class' => 'notifyproblem')); + $row->attributes['class'] .= ' missingfromdisk'; + } else { + $msg = ''; + } + $displayname = $icon . ' ' . $plugin->displayname . ' ' . $msg; + $displayname = new html_table_cell($displayname); + + $systemname = new html_table_cell($plugin->type . '_' . $plugin->name); + + if ($plugin->is_standard()) { + $row->attributes['class'] .= ' standard'; + $source = new html_table_cell(get_string('sourcestd', 'core_plugin')); + } else { + $row->attributes['class'] .= ' extension'; + $source = new html_table_cell(get_string('sourceext', 'core_plugin')); + } + + $version = new html_table_cell($plugin->versiondb); + + $isenabled = $plugin->is_enabled(); + if (is_null($isenabled)) { + $availability = new html_table_cell(''); + } else if ($isenabled) { + $row->attributes['class'] .= ' enabled'; + $icon = $this->output->pix_icon('i/hide', get_string('pluginenabled', 'core_plugin')); + $availability = new html_table_cell($icon . ' ' . get_string('pluginenabled', 'core_plugin')); + } else { + $row->attributes['class'] .= ' disabled'; + $icon = $this->output->pix_icon('i/show', get_string('plugindisabled', 'core_plugin')); + $availability = new html_table_cell($icon . ' ' . get_string('plugindisabled', 'core_plugin')); + } + + $settingsurl = $plugin->get_settings_url(); + if (is_null($settingsurl)) { + $settings = new html_table_cell(''); + } else { + $settings = html_writer::link($settingsurl, get_string('settings', 'core_plugin')); + $settings = new html_table_cell($settings); + } + + $uninstallurl = $plugin->get_uninstall_url(); + if (is_null($uninstallurl)) { + $uninstall = new html_table_cell(''); + } else { + $uninstall = html_writer::link($uninstallurl, get_string('uninstall', 'core_plugin')); + $uninstall = new html_table_cell($uninstall); + } + + $row->cells = array( + $displayname, $systemname, $source, $version, $availability, $settings, $uninstall + ); + $table->data[] = $row; + } + } + + return html_writer::table($table); + } +} diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index af1266eed14..bf8060500e5 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -5,6 +5,7 @@ */ if ($hassiteconfig) { + $ADMIN->add('modules', new admin_page_pluginsoverview()); $ADMIN->add('modules', new admin_category('modsettings', get_string('activitymodules'))); $ADMIN->add('modsettings', new admin_page_managemods()); $modules = $DB->get_records('modules', array(), "name ASC"); diff --git a/lang/en/admin.php b/lang/en/admin.php index 7c67ea9a5e6..b5032679b4d 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -800,6 +800,7 @@ $string['pleaserefreshregistration'] = 'Your site has been registered with moodl $string['pleaseregister'] = 'Please register your site to remove this button'; $string['plugin'] = 'Plugin'; $string['plugins'] = 'Plugins'; +$string['pluginsoverview'] = 'Plugins overview'; $string['profilecategory'] = 'Category'; $string['profilecategoryname'] = 'Category name (must be unique)'; $string['profilecategorynamenotunique'] = 'This category name is already in use'; diff --git a/lib/adminlib.php b/lib/adminlib.php index ffbd3d2e025..d93c83d44ca 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -4586,6 +4586,21 @@ class admin_setting_special_registerauth extends admin_setting_configselect { } +/** + * General plugins manager + */ +class admin_page_pluginsoverview extends admin_externalpage { + + /** + * Sets basic information about the external page + */ + public function __construct() { + global $CFG; + parent::__construct('pluginsoverview', get_string('pluginsoverview', 'core_admin'), + "$CFG->wwwroot/$CFG->admin/plugins.php"); + } +} + /** * Module manage page * @@ -6116,194 +6131,6 @@ function db_replace($search, $replace) { return true; } -/** - * Prints tables of detected plugins, one table per plugin type, - * and prints whether they are part of the standard Moodle - * distribution or not. - */ -function print_plugin_tables() { - global $DB; - $plugins_standard = array(); - $plugins_standard['mod'] = array('assignment', - 'chat', - 'choice', - 'data', - 'feedback', - 'folder', - 'forum', - 'glossary', - 'imscp', - 'label', - 'lesson', - 'page', - 'quiz', - 'resource', - 'scorm', - 'survey', - 'url', - 'wiki', - 'workshop'); - - $plugins_standard['blocks'] = array('activity_modules', - 'admin_bookmarks', - 'blog_menu', - 'blog_recent', - 'blog_tags', - 'calendar_month', - 'calendar_upcoming', - 'comments', - 'community', - 'completionstatus', - 'course_list', - 'course_overview', - 'course_summary', - 'feedback', - 'glossary_random', - 'html', - 'login', - 'mentees', - 'messages', - 'mnet_hosts', - 'myprofile', - 'navigation', - 'news_items', - 'online_users', - 'participants', - 'private_files', - 'quiz_results', - 'recent_activity', - 'rss_client', - 'search', - 'search_forums', - 'section_links', - 'selfcompletion', - 'settings', - 'site_main_menu', - 'social_activities', - 'tag_flickr', - 'tag_youtube', - 'tags'); - - $plugins_standard['filter'] = array('activitynames', - 'algebra', - 'censor', - 'emailprotect', - 'emoticon', - 'filter', - 'mediaplugin', - 'multilang', - 'tex', - 'tidy', - 'urltolink'); - - $plugins_installed = array(); - $installed_mods = $DB->get_records('modules', null, 'name'); - $installed_blocks = $DB->get_records('block', null, 'name'); - - foreach($installed_mods as $mod) { - $plugins_installed['mod'][] = $mod->name; - } - - foreach($installed_blocks as $block) { - $plugins_installed['blocks'][] = $block->name; - } - $plugins_installed['filter'] = array(); - - $plugins_ondisk = array(); - $plugins_ondisk['mod'] = array_keys(get_plugin_list('mod')); - $plugins_ondisk['blocks'] = array_keys(get_plugin_list('block')); - $plugins_ondisk['filter'] = array_keys(get_plugin_list('filter')); - - $strstandard = get_string('standard'); - $strnonstandard = get_string('nonstandard'); - $strmissingfromdisk = '(' . get_string('missingfromdisk') . ')'; - $strabouttobeinstalled = '(' . get_string('abouttobeinstalled') . ')'; - - $html = ''; - - $html .= ''; - - foreach ($plugins_ondisk as $cat => $list_ondisk) { - if ($cat == 'mod') { - $strcaption = get_string('activitymodule'); - } elseif ($cat == 'filter') { - $strcaption = get_string('managefilters'); - } else { - $strcaption = get_string($cat); - } - - $html .= ''; - } - - $html .= '
' . "\n"; - $html .= '\n" - . '\n" - . '\n\n"; - - $row = 1; - - foreach ($list_ondisk as $k => $plugin) { - $status = 'ok'; - $standard = 'standard'; - $note = ''; - - if (!in_array($plugin, $plugins_standard[$cat])) { - $standard = 'nonstandard'; - $status = 'warning'; - } - - // Get real name and full path of plugin - $plugin_name = "[[$plugin]]"; - - $plugin_path = "$cat/$plugin"; - - $plugin_name = get_plugin_name($plugin, $cat); - - // Determine if the plugin is about to be installed - if ($cat != 'filter' && !in_array($plugin, $plugins_installed[$cat])) { - $note = $strabouttobeinstalled; - $plugin_name = $plugin; - } - - $html .= "\n" - . "\n" - . "\n" - . "\n\n"; - $row++; - - // If the plugin was both on disk and in the db, unset the value from the installed plugins list - if ($key = array_search($plugin, $plugins_installed[$cat])) { - unset($plugins_installed[$cat][$key]); - } - } - - // If there are plugins left in the plugins_installed list, it means they are missing from disk - foreach ($plugins_installed[$cat] as $k => $missing_plugin) { - // Make sure the plugin really is missing from disk - if (!in_array($missing_plugin, $plugins_ondisk[$cat])) { - $standard = 'standard'; - $status = 'warning'; - - if (!in_array($missing_plugin, $plugins_standard[$cat])) { - $standard = 'nonstandard'; - } - - $plugin_name = $missing_plugin; - $html .= "\n" - . "\n" - . "\n" - . "\n\n"; - $row++; - } - } - - $html .= '
' . $strcaption . '
' . get_string('directory') . "' . get_string('name') . "' . get_string('status') . "
$plugin_path$plugin_name" . ${'str' . $standard} . " $note
?$plugin_name" . ${'str' . $standard} . " $strmissingfromdisk

'; - - echo $html; -} - - /** * Manage repository settings * diff --git a/lib/moodlelib.php b/lib/moodlelib.php index ca2cd0750f0..547fe6b91f9 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -9659,41 +9659,6 @@ function object_array_unique($array, $keep_key_assoc = true) { return $keep_key_assoc ? $array : array_values($array); } -/** - * Returns the language string for the given plugin. - * - * @param string $plugin the plugin code name - * @param string $type the type of plugin (mod, block, filter) - * @return string The plugin language string - */ -function get_plugin_name($plugin, $type='mod') { - $plugin_name = ''; - - switch ($type) { - case 'mod': - $plugin_name = get_string('modulename', $plugin); - break; - case 'blocks': - $plugin_name = get_string('pluginname', "block_$plugin"); - if (empty($plugin_name) || $plugin_name == '[[pluginname]]') { - if (($block = block_instance($plugin)) !== false) { - $plugin_name = $block->get_title(); - } else { - $plugin_name = "[[$plugin]]"; - } - } - break; - case 'filter': - $plugin_name = filter_get_name('filter/' . $plugin); - break; - default: - $plugin_name = $plugin; - break; - } - - return $plugin_name; -} - /** * Is a userid the primary administrator? * diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 2e1e782a6f0..ef646e6ca10 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -847,13 +847,13 @@ class page_requirements_manager { * passed in $module. * * - * $PAGE->strings_for_js(Array('one', 'two', 'three'), 'mymod', Array('a', null, 3)); + * $PAGE->requires->strings_for_js(array('one', 'two', 'three'), 'mymod', array('a', null, 3)); * * // The above is identitical to calling * - * $PAGE->string_for_js('one', 'mymod', 'a'); - * $PAGE->string_for_js('two', 'mymod'); - * $PAGE->string_for_js('three', 'mymod', 3); + * $PAGE->requires->string_for_js('one', 'mymod', 'a'); + * $PAGE->requires->string_for_js('two', 'mymod'); + * $PAGE->requires->string_for_js('three', 'mymod', 3); * * * @param array $identifiers An array of desired strings diff --git a/lib/pluginlib.php b/lib/pluginlib.php new file mode 100644 index 00000000000..fa1d8bfb585 --- /dev/null +++ b/lib/pluginlib.php @@ -0,0 +1,1483 @@ +. + +/** + * Defines classes used for plugins management + * + * This library provides a unified interface to various plugin types in + * Moodle. It is mainly used by the plugins management admin page and the + * plugins check page during the upgrade. + * + * @package core + * @subpackage admin + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Singleton class providing general plugins management functionality + */ +class plugin_manager { + + /** the plugin is shipped with standard Moodle distribution */ + const PLUGIN_SOURCE_STANDARD = 'std'; + /** the plugin is added extension */ + const PLUGIN_SOURCE_EXTENSION = 'ext'; + + /** the plugin uses neither database nor capabilities, no versions */ + const PLUGIN_STATUS_NODB = 'nodb'; + /** the plugin is up-to-date */ + const PLUGIN_STATUS_UPTODATE = 'uptodate'; + /** the plugin is about to be installed */ + const PLUGIN_STATUS_NEW = 'new'; + /** the plugin is about to be upgraded */ + const PLUGIN_STATUS_UPGRADE = 'upgrade'; + /** the version at the disk is lower than the one already installed */ + const PLUGIN_STATUS_DOWNGRADE = 'downgrade'; + /** the plugin is installed but missing from disk */ + const PLUGIN_STATUS_MISSING = 'missing'; + + /** @var plugin_manager holds the singleton instance */ + protected static $singletoninstance; + /** @var array of raw plugins information */ + protected $pluginsinfo = null; + /** @var array of raw subplugins information */ + protected $subpluginsinfo = null; + + /** + * Direct initiation not allowed, use the factory method {@link self::instance()} + * + * @todo we might want to specify just a single plugin type to work with + */ + protected function __construct() { + $this->get_plugins(true); + } + + /** + * Sorry, this is singleton + */ + protected function __clone() { + } + + /** + * Factory method for this class + * + * @return plugin_manager the singleton instance + */ + public static function instance() { + global $CFG; + + if (is_null(self::$singletoninstance)) { + self::$singletoninstance = new self(); + } + return self::$singletoninstance; + } + + /** + * Returns a tree of known plugins and information about them + * + * @param bool $disablecache force reload, cache can be used otherwise + * @return array + */ + public function get_plugins($disablecache=false) { + + if ($disablecache or is_null($this->pluginsinfo)) { + $this->pluginsinfo = array(); + $plugintypes = get_plugin_types(); + foreach ($plugintypes as $plugintype => $plugintyperootdir) { + if (in_array($plugintype, array('base', 'general'))) { + throw new coding_exception('Illegal usage of reserved word for plugin type'); + } + if (class_exists('plugintype_' . $plugintype)) { + $plugintypeclass = 'plugintype_' . $plugintype; + } else { + $plugintypeclass = 'plugintype_general'; + } + if (!in_array('plugintype_interface', class_implements($plugintypeclass))) { + throw new coding_exception('Class ' . $plugintypeclass . ' must implement plugintype_interface'); + } + $plugins = call_user_func(array($plugintypeclass, 'get_plugins'), $plugintype, $plugintyperootdir, $plugintypeclass); + $this->pluginsinfo[$plugintype] = $plugins; + } + } + + return $this->pluginsinfo; + } + + /** + * Returns list of plugins that define their subplugins and information about them + * + * At the moment, only activity modules can define subplugins. + * + * @param double $disablecache force reload, cache can be used otherwise + * @return array + */ + public function get_subplugins($disablecache=false) { + + if ($disablecache or is_null($this->subpluginsinfo)) { + $this->subpluginsinfo = array(); + $mods = get_plugin_list('mod'); + foreach ($mods as $mod => $moddir) { + $modsubplugins = array(); + if (file_exists($moddir . '/db/subplugins.php')) { + include($moddir . '/db/subplugins.php'); + foreach ($subplugins as $subplugintype => $subplugintyperootdir) { + $subplugin = new stdClass(); + $subplugin->type = $subplugintype; + $subplugin->typerootdir = $subplugintyperootdir; + $modsubplugins[$subplugintype] = $subplugin; + } + $this->subpluginsinfo['mod_' . $mod] = $modsubplugins; + } + } + } + + return $this->subpluginsinfo; + } + + /** + * Returns the name of the plugin that defines the given subplugin type + * + * If the given subplugin type is not actually a subplugin, returns false. + * + * @param string $subplugintype the name of subplugin type, eg. workshopform or quiz + * @return false|string the name of the parent plugin, eg. mod_workshop + */ + public function get_parent_of_subplugin($subplugintype) { + + $parent = false; + foreach ($this->get_subplugins() as $pluginname => $subplugintypes) { + if (isset($subplugintypes[$subplugintype])) { + $parent = $pluginname; + break; + } + } + + return $parent; + } + + /** + * Returns a localized name of a given plugin + * + * @param string $plugin name of the plugin, eg mod_workshop or auth_ldap + * @return string + */ + public function plugin_name($plugin) { + list($type, $name) = normalize_component($plugin); + return $this->pluginsinfo[$type][$name]->displayname; + } + + /** + * Returns a localized name of a plugin type in plural form + * + * Most plugin types define their names in core_plugin lang file. In case of subplugins, + * we try to ask the parent plugin for the name. In the worst case, we will return + * the value of the passed $type parameter. + * + * @param string $type the type of the plugin, e.g. mod or workshopform + * @return string + */ + public function plugintype_name_plural($type) { + + if (get_string_manager()->string_exists('type_' . $type . '_plural', 'core_plugin')) { + // for most plugin types, their names are defined in core_plugin lang file + return get_string('type_' . $type . '_plural', 'core_plugin'); + + } else if ($parent = $this->get_parent_of_subplugin($type)) { + // if this is a subplugin, try to ask the parent plugin for the name + if (get_string_manager()->string_exists('subplugintype_' . $type . '_plural', $parent)) { + return $this->plugin_name($parent) . ' / ' . get_string('subplugintype_' . $type . '_plural', $parent); + } else { + return $this->plugin_name($parent) . ' / ' . $type; + } + + } else { + return $type; + } + } + + /** + * Defines a white list of all plugins shipped in the standard Moodle distribution + * + * @return false|array array of standard plugins or false if the type is unknown + */ + public static function standard_plugins_list($type) { + static $standard_plugins = array( + + 'assignment' => array( + 'offline', 'online', 'upload', 'uploadsingle' + ), + + 'auth' => array( + 'cas', 'db', 'email', 'fc', 'imap', 'ldap', 'manual', 'mnet', + 'nntp', 'nologin', 'none', 'pam', 'pop3', 'radius', + 'shibboleth', 'webservice' + ), + + 'block' => array( + 'activity_modules', 'admin_bookmarks', 'blog_menu', + 'blog_recent', 'blog_tags', 'calendar_month', + 'calendar_upcoming', 'comments', 'community', + 'completionstatus', 'course_list', 'course_overview', + 'course_summary', 'feedback', 'glossary_random', 'html', + 'login', 'mentees', 'messages', 'mnet_hosts', 'myprofile', + 'navigation', 'news_items', 'online_users', 'participants', + 'private_files', 'quiz_results', 'recent_activity', + 'rss_client', 'search', 'search_forums', 'section_links', + 'selfcompletion', 'settings', 'site_main_menu', + 'social_activities', 'tag_flickr', 'tag_youtube', 'tags' + ), + + 'coursereport' => array( + 'completion', 'log', 'outline', 'participation', 'progress', 'stats' + ), + + 'datafield' => array( + 'checkbox', 'date', 'file', 'latlong', 'menu', 'multimenu', + 'number', 'picture', 'radiobutton', 'text', 'textarea', 'url' + ), + + 'datapreset' => array( + 'imagegallery' + ), + + 'editor' => array( + 'textarea', 'tinymce' + ), + + 'enrol' => array( + 'authorize', 'category', 'cohort', 'database', 'flatfile', + 'guest', 'imsenterprise', 'ldap', 'manual', 'meta', 'mnet', + 'paypal', 'self' + ), + + 'filter' => array( + 'activitynames', 'algebra', 'censor', 'emailprotect', + 'emoticon', 'mediaplugin', 'multilang', 'tex', 'tidy', + 'urltolink', 'mod_data', 'mod_glossary' + ), + + 'format' => array( + 'scorm', 'social', 'topics', 'weeks' + ), + + 'gradeexport' => array( + 'ods', 'txt', 'xls', 'xml' + ), + + 'gradeimport' => array( + 'csv', 'xml' + ), + + 'gradereport' => array( + 'grader', 'outcomes', 'overview', 'user' + ), + + 'local' => array( + ), + + 'message' => array( + 'email', 'jabber', 'popup' + ), + + 'mnetservice' => array( + 'enrol' + ), + + 'mod' => array( + 'assignment', 'chat', 'choice', 'data', 'feedback', 'folder', + 'forum', 'glossary', 'imscp', 'label', 'lesson', 'page', + 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop' + ), + + 'plagiarism' => array( + ), + + 'portfolio' => array( + 'boxnet', 'download', 'flickr', 'googledocs', 'mahara', 'picasa' + ), + + 'profilefield' => array( + 'checkbox', 'datetime', 'menu', 'text', 'textarea' + ), + + 'qformat' => array( + 'aiken', 'blackboard', 'blackboard_six', 'examview', 'gift', + 'learnwise', 'missingword', 'multianswer', 'qti_two', 'webct', + 'xhtml', 'xml' + ), + + 'qtype' => array( + 'calculated', 'calculatedmulti', 'calculatedsimple', + 'description', 'essay', 'match', 'missingtype', 'multianswer', + 'multichoice', 'numerical', 'random', 'randomsamatch', + 'shortanswer', 'truefalse' + ), + + 'quiz' => array( + 'grading', 'overview', 'responses', 'statistics' + ), + + 'report' => array( + 'backups', 'capability', 'configlog', 'courseoverview', + 'customlang', 'log', 'profiling', 'questioninstances', + 'security', 'spamcleaner', 'stats', 'unittest', 'unsuproles' + ), + + 'repository' => array( + 'alfresco', 'boxnet', 'coursefiles', 'dropbox', 'filesystem', + 'flickr', 'flickr_public', 'googledocs', 'local', 'merlot', + 'picasa', 'recent', 's3', 'upload', 'url', 'user', 'webdav', + 'wikimedia', 'youtube' + ), + + 'theme' => array( + 'anomaly', 'arialist', 'base', 'binarius', 'boxxie', 'brick', + 'canvas', 'formal_white', 'formfactor', 'fusion', + 'leatherbound', 'magazine', 'nimble', 'nonzero', 'overlay', + 'serenity', 'sky_high', 'splash', 'standard', 'standardold' + ), + + 'webservice' => array( + 'amf', 'rest', 'soap', 'xmlrpc' + ), + + 'workshopallocation' => array( + 'manual', 'random' + ), + + 'workshopeval' => array( + 'best' + ), + + 'workshopform' => array( + 'accumulative', 'comments', 'numerrors', 'rubric' + ) + ); + + if (isset($standard_plugins[$type])) { + return $standard_plugins[$type]; + + } else { + return false; + } + } +} + +/** + * All classes that represent a plugin of some type must implement this interface + */ +interface plugintype_interface { + + /** + * Gathers and returns the information about all plugins of the given type + * + * Passing the parameter $typeclass allows us to reach the same effect as with the + * late binding in PHP 5.3. Once PHP 5.3 is required, we can refactor this to use + * {@example $plugin = new static();} instead of {@example $plugin = new $typeclass()} + * + * @param string $type the name of the plugintype, eg. mod, auth or workshopform + * @param string $typerootdir full path to the location of the plugin dir + * @param string $typeclass the name of the actually called class + * @return array of plugintype classes, indexed by the plugin name + */ + public static function get_plugins($type, $typerootdir, $typeclass); + + /** + * Sets $displayname property to a localized name of the plugin + * + * @return void + */ + public function set_display_name(); + + /** + * Sets $versiondisk property to a numerical value representing the + * version of the plugin's source code. + * + * If the value is null after calling this method, either the plugin + * does not use versioning (typically does not have any database + * data) or is missing from disk. + * + * @return void + */ + public function set_version_disk(); + + /** + * Sets $versiondb property to a numerical value representing the + * currently installed version of the plugin. + * + * If the value is null after calling this method, either the plugin + * does not use versioning (typically does not have any database + * data) or has not been installed yet. + * + * @return void + */ + public function set_version_db(); + + /** + * Sets $versionrequires property to a numerical value representing + * the version of Moodle core that this plugin requires. + * + * @return void + */ + public function set_version_requires(); + + /** + * Sets $source property to one of plugin_manager::PLUGIN_SOURCE_xxx + * constants. + * + * If the property's value is null after calling this method, then + * the type of the plugin has not been recognized and you should throw + * an exception. + * + * @return void + */ + public function set_source(); + + /** + * Returns true if the plugin is shipped with the official distribution + * of the current Moodle version, false otherwise. + * + * @return bool + */ + public function is_standard(); + + /** + * Returns the status of the plugin + * + * @return string one of plugin_manager::PLUGIN_STATUS_xxx constants + */ + public function get_status(); + + /** + * Returns the information about plugin availability + * + * True means that the plugin is enabled. False means that the plugin is + * disabled. Null means that the information is not available, or the + * plugin does not support configurable availability or the availability + * can not be changed. + * + * @return null|bool + */ + public function is_enabled(); + + /** + * Returns the URL of the plugin settings screen + * + * Null value means that the plugin either does not have the settings screen + * or its location is not available via this library. + * + * @return null|moodle_url + */ + public function get_settings_url(); + + /** + * Returns the URL of the screen where this plugin can be uninstalled + * + * Visiting that URL must be safe, that is a manual confirmation is needed + * for actual uninstallation of the plugin. Null value means that the + * plugin either does not support uninstallation, or does not require any + * database cleanup or the location of the screen is not available via this + * library. + * + * @return null|moodle_url + */ + public function get_uninstall_url(); + + /** + * Returns relative directory of the plugin with heading '/' + * + * @example /mod/workshop + * @return string + */ + public function get_dir(); +} + +/** + * Defines public properties that all plugintype classes must have + * and provides default implementation of required methods. + */ +abstract class plugintype_base { + + /** @var string the plugintype name, eg. mod, auth or workshopform */ + public $type; + /** @var string full path to the location of all the plugins of this type */ + public $typerootdir; + /** @var string the plugin name, eg. assignment, ldap */ + public $name; + /** @var string the localized plugin name */ + public $displayname; + /** @var string the plugin source, one of plugin_manager::PLUGIN_SOURCE_xxx constants */ + public $source; + /** @var fullpath to the location of this plugin */ + public $rootdir; + /** @var int|string the version of the plugin's source code */ + public $versiondisk; + /** @var int|string the version of the installed plugin */ + public $versiondb; + /** @var int|float|string required version of Moodle core */ + public $versionrequires; + /** @var int number of instances of the plugin - not supported yet */ + public $instances; + /** @var int order of the plugin among other plugins of the same type - not supported yet */ + public $sortorder; + + /** + * @see plugintype_interface::get_plugins() + */ + public static function get_plugins($type, $typerootdir, $typeclass) { + + // get the information about plugins at the disk + $plugins = get_plugin_list($type); + $ondisk = array(); + foreach ($plugins as $pluginname => $pluginrootdir) { + $plugin = new $typeclass(); + $plugin->type = $type; + $plugin->typerootdir = $typerootdir; + $plugin->name = $pluginname; + $plugin->rootdir = $pluginrootdir; + + $plugin->set_display_name(); + $plugin->set_version_disk(); + $plugin->set_version_db(); + $plugin->set_version_requires(); + $plugin->set_source(); + + $ondisk[$pluginname] = $plugin; + } + return $ondisk; + } + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + if (! get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) { + $this->displayname = '[pluginname,' . $this->type . '_' . $this->name . ']'; + } else { + $this->displayname = get_string('pluginname', $this->type . '_' . $this->name); + } + } + + /** + * @see plugintype_interface::set_version_disk() + */ + public function set_version_disk() { + + if (empty($this->rootdir)) { + return; + } + + $versionfile = $this->rootdir . '/version.php'; + + if (is_readable($versionfile)) { + include($versionfile); + if (isset($plugin->version)) { + $this->versiondisk = $plugin->version; + } + } + } + + /** + * @see plugintype_interface::set_version_db() + */ + public function set_version_db() { + + if ($ver = self::get_version_from_config_plugins($this->type . '_' . $this->name)) { + $this->versiondb = $ver; + } + } + + /** + * @see plugintype_interface::set_version_requires() + */ + public function set_version_requires() { + + if (empty($this->rootdir)) { + return; + } + + $versionfile = $this->rootdir . '/version.php'; + + if (is_readable($versionfile)) { + include($versionfile); + if (isset($plugin->requires)) { + $this->versionrequires = $plugin->requires; + } + } + } + + /** + * @see plugintype_interface::set_source() + */ + public function set_source() { + + $standard = plugin_manager::standard_plugins_list($this->type); + + if ($standard !== false) { + $standard = array_flip($standard); + if (isset($standard[$this->name])) { + $this->source = plugin_manager::PLUGIN_SOURCE_STANDARD; + } else { + $this->source = plugin_manager::PLUGIN_SOURCE_EXTENSION; + } + } + } + + /** + * @see plugintype_interface::is_standard() + */ + public function is_standard() { + return $this->source === plugin_manager::PLUGIN_SOURCE_STANDARD; + } + + /** + * @see plugintype_interface::get_status() + */ + public function get_status() { + + if (is_null($this->versiondb) and is_null($this->versiondisk)) { + return plugin_manager::PLUGIN_STATUS_NODB; + + } else if (is_null($this->versiondb) and !is_null($this->versiondisk)) { + return plugin_manager::PLUGIN_STATUS_NEW; + + } else if (!is_null($this->versiondb) and is_null($this->versiondisk)) { + return plugin_manager::PLUGIN_STATUS_MISSING; + + } else if ((string)$this->versiondb === (string)$this->versiondisk) { + return plugin_manager::PLUGIN_STATUS_UPTODATE; + + } else if ($this->versiondb < $this->versiondisk) { + return plugin_manager::PLUGIN_STATUS_UPGRADE; + + } else if ($this->versiondb > $this->versiondisk) { + return plugin_manager::PLUGIN_STATUS_DOWNGRADE; + + } else { + // $version = pi(); and similar funny jokes - hopefully Donald E. Knuth will never contribute to Moodle ;-) + throw new coding_exception('Unable to determine plugin state, check the plugin versions'); + } + } + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + return null; + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + return null; + } + + /** + * @see plugintype_interface::get_uninstall_url() + */ + public function get_uninstall_url() { + return null; + } + + /** + * @see plugintype_interface::get_dir() + */ + public function get_dir() { + global $CFG; + + return substr($this->rootdir, strlen($CFG->dirroot)); + } + + /** + * Provides access to plugin versions from {config_plugins} + * + * @param string $plugin plugin name + * @param double $disablecache optional, defaults to false + * @return int|false the stored value or false if not found + */ + protected function get_version_from_config_plugins($plugin, $disablecache=false) { + global $DB; + static $pluginversions = null; + + if (is_null($pluginversions) or $disablecache) { + $pluginversions = $DB->get_records_menu('config_plugins', array('name' => 'version'), 'plugin', 'plugin,value'); + } + + if (!array_key_exists($plugin, $pluginversions)) { + return false; + } + + return $pluginversions[$plugin]; + } +} + +/** + * General class for all plugin types that do not have their own class + */ +class plugintype_general extends plugintype_base implements plugintype_interface { + +} + +/** + * Class for page side blocks + */ +class plugintype_block extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::get_plugins() + */ + public static function get_plugins($type, $typerootdir, $typeclass) { + + // get the information about blocks at the disk + $blocks = parent::get_plugins($type, $typerootdir, $typeclass); + + // add blocks missing from disk + $blocksinfo = self::get_blocks_info(); + foreach ($blocksinfo as $blockname => $blockinfo) { + if (isset($blocks[$blockname])) { + continue; + } + $plugin = new $typeclass(); + $plugin->type = $type; + $plugin->typerootdir = $typerootdir; + $plugin->name = $blockname; + $plugin->rootdir = null; + $plugin->displayname = $blockname; + $plugin->versiondb = $blockinfo->version; + $plugin->set_source(); + + $blocks[$blockname] = $plugin; + } + + return $blocks; + } + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + + if (get_string_manager()->string_exists('pluginname', 'block_' . $this->name)) { + $this->displayname = get_string('pluginname', 'block_' . $this->name); + + } else if (($block = block_instance($this->name)) !== false) { + $this->displayname = $block->get_title(); + + } else { + parent::set_display_name(); + } + } + + /** + * @see plugintype_interface::set_version_db() + */ + public function set_version_db() { + global $DB; + + $blocksinfo = self::get_blocks_info(); + if (isset($blocksinfo[$this->name]->version)) { + $this->versiondb = $blocksinfo[$this->name]->version; + } + } + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + + $blocksinfo = self::get_blocks_info(); + if (isset($blocksinfo[$this->name]->visible)) { + if ($blocksinfo[$this->name]->visible) { + return true; + } else { + return false; + } + } else { + return parent::is_enabled(); + } + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if (($block = block_instance($this->name)) === false) { + return parent::get_settings_url(); + + } else if ($block->has_config()) { + if (!empty($this->rootdir) and file_exists($this->rootdir . '/settings.php')) { + return new moodle_url('/admin/settings.php', array('section' => 'blocksetting' . $this->name)); + } else { + $blocksinfo = self::get_blocks_info(); + return new moodle_url('/admin/block.php', array('block' => $blocksinfo[$this->name]->id)); + } + + } else { + return parent::get_settings_url(); + } + } + + /** + * @see plugintype_interface::get_uninstall_url() + */ + public function get_uninstall_url() { + + $blocksinfo = self::get_blocks_info(); + return new moodle_url('/admin/blocks.php', array('delete' => $blocksinfo[$this->name]->id, 'sesskey' => sesskey())); + } + + /** + * Provides access to the records in {block} table + * + * @param bool $disablecache do not use internal static cache + * @return array array of stdClasses + */ + protected static function get_blocks_info($disablecache=false) { + global $DB; + static $blocksinfocache = null; + + if (is_null($blocksinfocache) or $disablecache) { + $blocksinfocache = $DB->get_records('block', null, 'name', 'name,id,version,visible'); + } + + return $blocksinfocache; + } +} + +/** + * Class for text filters + */ +class plugintype_filter extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::get_plugins() + */ + public static function get_plugins($type, $typerootdir, $typeclass) { + global $CFG; + + $filters = array(); + + // get the list of filters from both /filter and /mod location + $installed = filter_get_all_installed(); + + foreach ($installed as $filterlegacyname => $displayname) { + $plugin = new $typeclass(); + $plugin->type = $type; + $plugin->typerootdir = $typerootdir; + $plugin->name = self::normalize_legacy_name($filterlegacyname); + $plugin->rootdir = $CFG->dirroot . '/' . $filterlegacyname; + $plugin->displayname = $displayname; + + $plugin->set_version_disk(); + $plugin->set_version_db(); + $plugin->set_version_requires(); + $plugin->set_source(); + + $filters[$plugin->name] = $plugin; + } + + // make sure that all installed filters are registered + $globalstates = self::get_global_states(); + $needsreload = false; + foreach (array_keys($installed) as $filterlegacyname) { + if (!isset($globalstates[self::normalize_legacy_name($filterlegacyname)])) { + filter_set_global_state($filterlegacyname, TEXTFILTER_DISABLED); + $needsreload = true; + } + } + if ($needsreload) { + $globalstates = self::get_global_states(true); + } + + // make sure that all registered filters are installed, just in case + foreach ($globalstates as $name => $info) { + if (!isset($filters[$name])) { + // oops, there is a record in filter_active but the filter is not installed + $plugin = new $typeclass(); + $plugin->type = $type; + $plugin->typerootdir = $typerootdir; + $plugin->name = $name; + $plugin->rootdir = $CFG->dirroot . '/' . $info->legacyname; + $plugin->displayname = $info->legacyname; + + $plugin->set_version_db(); + + if (is_null($plugin->versiondb)) { + // this is a hack to stimulate 'Missing from disk' error + // because $plugin->versiondisk will be null !== false + $plugin->versiondb = false; + } + + $filters[$plugin->name] = $plugin; + } + } + + return $filters; + } + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + // do nothing, the name is set in self::get_plugins() + } + + /** + * @see plugintype_interface::set_version_disk() + */ + public function set_version_disk() { + + if (strpos($this->name, 'mod_') === 0) { + // filters bundled with modules do not use versioning + return; + } + + return parent::set_version_disk(); + } + + /** + * @see plugintype_interface::set_version_requires() + */ + public function set_version_requires() { + + if (strpos($this->name, 'mod_') === 0) { + // filters bundled with modules do not use versioning + return; + } + + return parent::set_version_requires(); + } + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + + $globalstates = self::get_global_states(); + + foreach ($globalstates as $filterlegacyname => $info) { + $name = self::normalize_legacy_name($filterlegacyname); + if ($name === $this->name) { + if ($info->active == TEXTFILTER_DISABLED) { + return false; + } else { + // it may be 'On' or 'Off, but available' + return null; + } + } + } + + return null; + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + $globalstates = self::get_global_states(); + $legacyname = $globalstates[$this->name]->legacyname; + if (filter_has_global_settings($legacyname)) { + return new moodle_url('/admin/settings.php', array('section' => 'filtersetting' . str_replace('/', '', $legacyname))); + } else { + return null; + } + } + + /** + * @see plugintype_interface::get_uninstall_url() + */ + public function get_uninstall_url() { + + if (strpos($this->name, 'mod_') === 0) { + return null; + } else { + $globalstates = self::get_global_states(); + $legacyname = $globalstates[$this->name]->legacyname; + return new moodle_url('/admin/filters.php', array('sesskey' => sesskey(), 'filterpath' => $legacyname, 'action' => 'delete')); + } + } + + /** + * Convert legacy filter names like 'filter/foo' or 'mod/bar' into frankenstyle + * + * @param string $legacyfiltername legacy filter name + * @return string frankenstyle-like name + */ + protected static function normalize_legacy_name($legacyfiltername) { + + $name = str_replace('/', '_', $legacyfiltername); + if (strpos($name, 'filter_') === 0) { + $name = substr($name, 7); + if (empty($name)) { + throw new coding_exception('Unable to determine filter name: ' . $legacyfiltername); + } + } + + return $name; + } + + /** + * Provides access to the results of {@link filter_get_global_states()} + * but indexed by the normalized filter name + * + * The legacy filter name is available as ->legacyname property. + * + * @param bool $disablecache + * @return array + */ + protected static function get_global_states($disablecache=false) { + global $DB; + static $globalstatescache = null; + + if ($disablecache or is_null($globalstatescache)) { + + if (!$DB->get_manager()->table_exists('filter_active')) { + // we're upgrading from 1.9 and the table used by {@link filter_get_global_states()} + // does not exist yet + $globalstatescache = array(); + + } else { + foreach (filter_get_global_states() as $legacyname => $info) { + $name = self::normalize_legacy_name($legacyname); + $filterinfo = new stdClass(); + $filterinfo->legacyname = $legacyname; + $filterinfo->active = $info->active; + $filterinfo->sortorder = $info->sortorder; + $globalstatescache[$name] = $filterinfo; + } + } + } + + return $globalstatescache; + } +} + +/** + * Class for activity modules + */ +class plugintype_mod extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::get_plugins() + */ + public static function get_plugins($type, $typerootdir, $typeclass) { + + // get the information about plugins at the disk + $modules = parent::get_plugins($type, $typerootdir, $typeclass); + + // add modules missing from disk + $modulesinfo = self::get_modules_info(); + foreach ($modulesinfo as $modulename => $moduleinfo) { + if (isset($modules[$modulename])) { + continue; + } + $plugin = new $typeclass(); + $plugin->type = $type; + $plugin->typerootdir = $typerootdir; + $plugin->name = $modulename; + $plugin->rootdir = null; + $plugin->displayname = $modulename; + $plugin->versiondb = $moduleinfo->version; + $plugin->set_source(); + + $modules[$modulename] = $plugin; + } + + return $modules; + } + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + if (get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) { + $this->displayname = get_string('pluginname', $this->type . '_' . $this->name); + } else { + $this->displayname = get_string('modulename', $this->type . '_' . $this->name); + } + } + + /** + * @see plugintype_interface::set_version_disk() + */ + public function set_version_disk() { + + if (empty($this->rootdir)) { + return; + } + + $versionfile = $this->rootdir . '/version.php'; + + if (is_readable($versionfile)) { + include($versionfile); + if (isset($module->version)) { + $this->versiondisk = $module->version; + } + } + } + + /** + * @see plugintype_interface::set_version_db() + */ + public function set_version_db() { + global $DB; + + $modulesinfo = self::get_modules_info(); + if (isset($modulesinfo[$this->name]->version)) { + $this->versiondb = $modulesinfo[$this->name]->version; + } + } + + /** + * @see plugintype_interface::set_version_requires() + */ + public function set_version_requires() { + + if (empty($this->rootdir)) { + return; + } + + $versionfile = $this->rootdir . '/version.php'; + + if (is_readable($versionfile)) { + include($versionfile); + if (isset($module->requires)) { + $this->versionrequires = $module->requires; + } + } + } + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + + $modulesinfo = self::get_modules_info(); + if (isset($modulesinfo[$this->name]->visible)) { + if ($modulesinfo[$this->name]->visible) { + return true; + } else { + return false; + } + } else { + return parent::is_enabled(); + } + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if (!empty($this->rootdir) and (file_exists($this->rootdir . '/settings.php') or file_exists($this->rootdir . '/settingstree.php'))) { + return new moodle_url('/admin/settings.php', array('section' => 'modsetting' . $this->name)); + } else { + return parent::get_settings_url(); + } + } + + /** + * @see plugintype_interface::get_uninstall_url() + */ + public function get_uninstall_url() { + + if ($this->name !== 'forum') { + return new moodle_url('/admin/modules.php', array('delete' => $this->name, 'sesskey' => sesskey())); + } else { + return null; + } + } + + /** + * Provides access to the records in {modules} table + * + * @param bool $disablecache do not use internal static cache + * @return array array of stdClasses + */ + protected static function get_modules_info($disablecache=false) { + global $DB; + static $modulesinfocache = null; + + if (is_null($modulesinfocache) or $disablecache) { + $modulesinfocache = $DB->get_records('modules', null, 'name', 'name,id,version,visible'); + } + + return $modulesinfocache; + } +} + +/** + * Class for question types + */ +class plugintype_qtype extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + $this->displayname = get_string($this->name, 'qtype_' . $this->name); + } +} + +/** + * Class for question formats + */ +class plugintype_qformat extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::set_display_name() + */ + public function set_display_name() { + $this->displayname = get_string($this->name, 'qformat_' . $this->name); + } +} + +/** + * Class for authentication plugins + */ +class plugintype_auth extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + global $CFG; + /** @var null|array list of enabled authentication plugins */ + static $enabled = null; + + if (in_array($this->name, array('nologin', 'manual'))) { + // these two are always enabled and can't be disabled + return null; + } + + if (is_null($enabled)) { + $enabled = explode(',', $CFG->auth); + } + + return isset($enabled[$this->name]); + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if (!empty($this->rootdir) and file_exists($this->rootdir . '/settings.php')) { + return new moodle_url('/admin/settings.php', array('section' => 'authsetting' . $this->name)); + } else { + return new moodle_url('/admin/auth_config.php', array('auth' => $this->name)); + } + } +} + +/** + * Class for enrolment plugins + */ +class plugintype_enrol extends plugintype_base implements plugintype_interface { + + /** + * We do not actually need whole enrolment classes here so we do not call + * {@link enrol_get_plugins()}. Note that this may produce slightly different + * results, for example if the enrolment plugin does not contain lib.php + * but it is listed in $CFG->enrol_plugins_enabled + * + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + global $CFG; + /** @var null|array list of enabled enrolment plugins */ + static $enabled = null; + + if (is_null($enabled)) { + $enabled = explode(',', $CFG->enrol_plugins_enabled); + } + + return isset($enabled[$this->name]); + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if ($this->is_enabled() or (!empty($this->rootdir) and file_exists($this->rootdir . '/settings.php'))) { + return new moodle_url('/admin/settings.php', array('section' => 'enrolsettings' . $this->name)); + } else { + return parent::get_settings_url(); + } + } + + /** + * @see plugintype_interface::get_uninstall_url() + */ + public function get_uninstall_url() { + return new moodle_url('/admin/enrol.php', array('action' => 'uninstall', 'enrol' => $this->name, 'sesskey' => sesskey())); + } +} + +/** + * Class for messaging processors + */ +class plugintype_message extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if ($this->name === 'jabber') { + return new moodle_url('/admin/settings.php', array('section' => 'jabber')); + } + + if ($this->name === 'email') { + return new moodle_url('/admin/settings.php', array('section' => 'mail')); + } + + } +} + +/** + * Class for repositories + */ +class plugintype_repository extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + + $enabled = self::get_enabled_repositories(); + + return isset($enabled[$this->name]); + } + + /** + * @see plugintype_interface::get_settings_url() + */ + public function get_settings_url() { + + if ($this->is_enabled()) { + return new moodle_url('/admin/repository.php', array('sesskey' => sesskey(), 'action' => 'edit', 'repos' => $this->name)); + } else { + return parent::get_settings_url(); + } + } + + /** + * Provides access to the records in {repository} table + * + * @param bool $disablecache do not use internal static cache + * @return array array of stdClasses + */ + protected static function get_enabled_repositories($disablecache=false) { + global $DB; + static $repositories = null; + + if (is_null($repositories) or $disablecache) { + $repositories = $DB->get_records('repository', null, 'type', 'type,visible,sortorder'); + } + + return $repositories; + } +} + +/** + * Class for portfolios + */ +class plugintype_portfolio extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + + $enabled = self::get_enabled_portfolios(); + + return isset($enabled[$this->name]); + } + + /** + * Provides access to the records in {portfolio_instance} table + * + * @param bool $disablecache do not use internal static cache + * @return array array of stdClasses + */ + protected static function get_enabled_portfolios($disablecache=false) { + global $DB; + static $portfolios = null; + + if (is_null($portfolios) or $disablecache) { + $portfolios = array(); + $instances = $DB->get_recordset('portfolio_instance', null, 'plugin'); + foreach ($instances as $instance) { + if (isset($portfolios[$instance->plugin])) { + if ($instance->visible) { + $portfolios[$instance->plugin]->visible = $instance->visible; + } + } else { + $portfolios[$instance->plugin] = $instance; + } + } + } + + return $portfolios; + } +} + +/** + * Class for themes + */ +class plugintype_theme extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + global $CFG; + + if ((!empty($CFG->theme) and $CFG->theme === $this->name) or + (!empty($CFG->themelegacy) and $CFG->themelegacy === $this->name)) { + return true; + } else { + return parent::is_enabled(); + } + } +} + +/** + * Class representing an MNet service + */ +class plugintype_mnetservice extends plugintype_base implements plugintype_interface { + + /** + * @see plugintype_interface::is_enabled() + */ + public function is_enabled() { + global $CFG; + + if (empty($CFG->mnet_dispatcher_mode) || $CFG->mnet_dispatcher_mode !== 'strict') { + return false; + } else { + return parent::is_enabled(); + } + } +} diff --git a/theme/anomaly/style/general.css b/theme/anomaly/style/general.css index 4a7a2a36fb4..b850a89846c 100644 --- a/theme/anomaly/style/general.css +++ b/theme/anomaly/style/general.css @@ -121,8 +121,6 @@ html, body {background-color:#C8C9C7;} .group .r1 .cell, .admin table .r1 .cell {background-color:#EEE;} -.admin .plugincompattable .r1 .cell {background-color:#FFF;} - .singlebutton, .buttons {text-align:center;margin:20px;} .buttons form {display:inline;} @@ -222,4 +220,4 @@ html, body {background-color:#C8C9C7;} /** Overide for RTL layout **/ .dir-rtl #page-header .navbar .breadcrumb {float:right;} -.dir-rtl #page-header .navbar .navbutton {float:left;} \ No newline at end of file +.dir-rtl #page-header .navbar .navbutton {float:left;} diff --git a/theme/base/style/admin.css b/theme/base/style/admin.css index 77fec1df685..447ff464d69 100644 --- a/theme/base/style/admin.css +++ b/theme/base/style/admin.css @@ -3,11 +3,6 @@ **/ .formtable tbody th {font-weight: normal;text-align: right;} -.plugincompattable td.nonstandard, -.plugincompattable td.missingplugin {font-weight: bold;} -.plugincompattable td.standard, -.plugincompattable td.warning {font-style: normal;} - .path-admin .manageauthtable {width:100%;} #page-admin-index .c0 {vertical-align: top;} @@ -174,3 +169,26 @@ .dir-rtl #adminsettings .form-item .form-setting, .dir-rtl #adminsettings .form-item .form-label, .dir-rtl #adminsettings .form-item .form-description { float: right;text-align: right} + +/** Plugins check */ +#page-admin-index #plugins-check-info {text-align:center;margin:1em;} +#page-admin-index #plugins-check {margin-left:auto; margin-right:auto;} +#page-admin-index #plugins-check .displayname .pluginicon {width:16px;} +#page-admin-index #plugins-check .missingfromdisk .displayname {background-color:#ffd3d9;} +#page-admin-index #plugins-check .standard .source {color:#999;} +#page-admin-index #plugins-check .extension .source {background-color:#f3f2aa;} +#page-admin-index #plugins-check .msg td {text-align:center;} +#page-admin-index #plugins-check .status-downgrade .status {background-color:#ffd3d9;} +#page-admin-index #plugins-check .status-missing .status {background-color:#ffd3d9;} +#page-admin-index #plugins-check .status-new .status {background-color:#e7f1c3;} +#page-admin-index #plugins-check .status-nodb .status {color:#999;} +#page-admin-index #plugins-check .status-upgrade .status {background-color:#d2ebff;} +#page-admin-index #plugins-check .status-uptodate .status {color:#999;} + +/** Plugins management */ +#page-admin-plugins #plugins-control-panel {margin-left:auto; margin-right:auto;} +#page-admin-plugins #plugins-control-panel .displayname .pluginicon {width:16px;} +#page-admin-plugins #plugins-control-panel .missingfromdisk .displayname {background-color:#ffd3d9;} +#page-admin-plugins #plugins-control-panel .disabled .availability {background-color:#eee;} +#page-admin-plugins #plugins-control-panel .extension .source {background-color:#f3f2aa;} +#page-admin-plugins #plugins-control-panel .msg td {text-align:center;} diff --git a/theme/canvas/style/admin.css b/theme/canvas/style/admin.css index 650dcf86aa1..0b23550f15a 100644 --- a/theme/canvas/style/admin.css +++ b/theme/canvas/style/admin.css @@ -110,15 +110,10 @@ } .plugincheckwrapper {text-align: center;} -.plugincompattable {font-size: 70%;text-align: left;} -.plugincompattable caption {text-align: center;width: 100%;font-weight: bold;font-size: 130%;} -.plugincompattable td.ok {color: #008000;} -.plugincompattable td.warning {color: #DF7800;} -.plugincompattable td.error {color: #DF0000;} /** * Web services */ #page-admin-webservice-service_users .missingcaps {color: #ff6600;font-size: 90%;} #page-admin-setting-webservicetokens .missingcaps {color: #ff6600;font-size: 90%;} -#page-admin-webservice-service_functions .functiondesc {font-size: 90%;} \ No newline at end of file +#page-admin-webservice-service_functions .functiondesc {font-size: 90%;} diff --git a/theme/canvas/style/tables.css b/theme/canvas/style/tables.css index 0006ec6848b..e0425018a08 100644 --- a/theme/canvas/style/tables.css +++ b/theme/canvas/style/tables.css @@ -6,8 +6,6 @@ #page-admin-course-category .generalbox td, #attempts th, #attempts td, -.plugincompattable th, -.plugincompattable td, .environmenttable th, .environmenttable td, .forumheaderlist td, @@ -22,9 +20,8 @@ .results .header, #attempts .header, .generaltable .header, -.plugincompattable th, .environmenttable th, .forumheaderlist th { background: #f3f3f3; border-bottom-width: 2px; -} \ No newline at end of file +} diff --git a/theme/formal_white/style/core.css b/theme/formal_white/style/core.css index f360292b005..c6128d550a3 100644 --- a/theme/formal_white/style/core.css +++ b/theme/formal_white/style/core.css @@ -173,13 +173,6 @@ input[type="radio"] { margin-left: 21%; } -/* Admin management ------------------------*/ -.plugincompattable { - font-size: 100%; - text-align: left; -} - /* User -----------------------*/ @@ -540,4 +533,4 @@ padding: 0 /** * Redirect */ -.pagelayout-redirect #content {text-align:center;margin-top:10%;margin-bottom:10%;} \ No newline at end of file +.pagelayout-redirect #content {text-align:center;margin-top:10%;margin-bottom:10%;} diff --git a/theme/formal_white/style/formal_white.css b/theme/formal_white/style/formal_white.css index bd6eb9b4cd4..6a74e1ed5d9 100644 --- a/theme/formal_white/style/formal_white.css +++ b/theme/formal_white/style/formal_white.css @@ -57,8 +57,6 @@ h1.headerheading {margin:14px 11px 8px 11px;float:left;font-size:2em;z-index:1;} #page-admin-course-category .generalbox td, #attempts th, #attempts td, -.plugincompattable th, -.plugincompattable td, .environmenttable th, .environmenttable td, .forumheaderlist td, @@ -113,4 +111,4 @@ ul.topics .section span.commands {margin-left:2em;} /* distanza dei comandi dagl #page-footer .moodledocs {text-align:center;background-color:#EFEFEF;padding:0.7em 0 0.8em 0;} /** Custom CSS **/ -[[setting:customcss]] \ No newline at end of file +[[setting:customcss]] diff --git a/theme/standard/style/admin.css b/theme/standard/style/admin.css index 7beb53b6c84..39cf0fe3b82 100644 --- a/theme/standard/style/admin.css +++ b/theme/standard/style/admin.css @@ -38,11 +38,6 @@ #page-admin-report-questioninstances-index #settingsform p {margin-bottom: 0;} .plugincheckwrapper {text-align: center;} -.plugincompattable {font-size: 70%;text-align: left;} -.plugincompattable caption {text-align: center;width: 100%;font-weight: bold;font-size: 130%;} -.plugincompattable td.ok {color: #008000;} -.plugincompattable td.warning {color: #DF7800;} -.plugincompattable td.error {color: #DF0000;} #page-admin-index .explanation, .path-admin-roles .cell.c1, From 91dedc324ff62ef836fb274ac7dbb62ab3591a57 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 10 Mar 2011 15:01:54 +0100 Subject: [PATCH 229/369] MDL-26784 Strings for the new plugin manager The new strings file core_plugin defines names of all plugin types supported by Moodle. Some strings have already been defined elsewhere and we use AMOS script here to copy their translation, if it is available. AMOS BEGIN CPY [settings,core],[settings,core_plugin] CPY [status,core],[status,core_plugin] CPY [missingfromdisk,core],[status_missing,core_plugin] CPY [nodatabase,core_admin],[status_nodb,core_plugin] CPY [authenticationplugins,core],[type_auth_plural,core_plugin] CPY [block,core],[type_block,core_plugin] CPY [blocks,core],[type_block_plural,core_plugin] CPY [coursereport,core],[type_coursereport,core_plugin] CPY [coursereports,core],[type_coursereport_plural,core_plugin] CPY [filter,core],[type_filter,core_plugin] CPY [courseformats,core],[type_format_plural,core_plugin] CPY [activitymodule,core],[type_mod,core_plugin] CPY [activitymodules,core],[type_mod_plural,core_plugin] CPY [plagiarism,core_plagiarism],[type_plagiarism,core_plugin] CPY [portfolio,core_portfolio],[type_portfolio,core_plugin] CPY [portfolios,core_portfolio],[type_portfolio_plural,core_plugin] CPY [questiontype,core_admin],[type_qtype,core_plugin] CPY [questiontypes,core_admin],[type_qtype_plural,core_plugin] CPY [repository,core_repository],[type_repository,core_plugin] CPY [theme,core],[type_theme,core_plugin] CPY [themes,core],[type_theme_plural,core_plugin] CPY [uninstallplugin,core_admin],[uninstall,core_plugin] CPY [version,core],[version,core_plugin] CPY [assignmenttype,mod_assignment],[subplugintype_assignment,mod_assignment] CPY [presets,mod_data],[subplugintype_datapreset_plural,mod_data] CPY [evaluationmethod,mod_workshop],[subplugintype_workshopeval,mod_workshop] CPY [strategy,mod_workshop],[subplugintype_workshopform,mod_workshop] AMOS END --- lang/en/moodle.php | 3 - lang/en/plugin.php | 104 ++++++++++++++++++++++++++ lang/en/repository.php | 2 +- mod/assignment/lang/en/assignment.php | 2 + mod/data/lang/en/data.php | 4 + mod/workshop/lang/en/workshop.php | 6 ++ 6 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 lang/en/plugin.php diff --git a/lang/en/moodle.php b/lang/en/moodle.php index faa6d9cbbb4..0137c2895aa 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1263,9 +1263,6 @@ $string['pleaseusesearch'] = 'Please use the search'; $string['plugin'] = 'Plugin'; $string['plugindeletefiles'] = 'All data associated with the plugin \'{$a->name}\' has been deleted from the database. To prevent the plugin re-installing itself, you should now delete this directory from your server: {$a->directory}'; $string['plugincheck'] = 'Plugins check'; -$string['pluginchecknotice'] = 'The following tables show the modules, blocks and filters that have been detected in your current Moodle installation; -They indicate which plugins are standard, and which are not. All non-standard plugins should be checked and upgraded to their most recent versions -before continuing with this Moodle upgrade.'; $string['pluginsetup'] = 'Setting up plugin tables'; $string['policyaccept'] = 'I understand and agree'; $string['policyagree'] = 'You must agree to this policy to continue using this site. Do you agree?'; diff --git a/lang/en/plugin.php b/lang/en/plugin.php new file mode 100644 index 00000000000..6c11d795e35 --- /dev/null +++ b/lang/en/plugin.php @@ -0,0 +1,104 @@ +. + +/** + * Defines names of plugin types and some strings used at the plugin managment + * + * @package core + * @subpackage admin + * @copyright 2011 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['availability'] = 'Availability'; +$string['displayname'] = 'Plugin name'; +$string['nonehighlighted'] = 'No plugins require your attention during this upgrade'; +$string['nonehighlightedinfo'] = 'Display the list of all installed plugins anyway'; +$string['noneinstalled'] = 'No plugins of this type are installed'; +$string['showall'] = 'Reload and show all plugins'; +$string['pluginchecknotice'] = 'This page displays plugins that may require your attention during the upgrade. Highlighted items include new plugins that are about to be installed, updated plugins that are about to be upgraded and any missing plugins. Contributed plugins are also highlighted. +It is recommended that you check whether there are more recent versions of contributed plugins available and update their source code before continuing with this Moodle upgrade.'; +$string['plugindisable'] = 'Disable'; +$string['plugindisabled'] = 'Disabled'; +$string['pluginenable'] = 'Enable'; +$string['pluginenabled'] = 'Enabled'; +$string['rootdir'] = 'Directory'; +$string['settings'] = 'Settings'; +$string['somehighlighted'] = 'Number of plugins requiring attention during this upgrade: {$a}'; +$string['somehighlightedinfo'] = 'Display the full list of installed plugins'; +$string['source'] = 'Source'; +$string['sourceext'] = 'Extension'; +$string['sourcestd'] = 'Standard'; +$string['status'] = 'Status'; +$string['status_downgrade'] = 'Higher version already installed!'; +$string['status_missing'] = 'Missing from disk!'; +$string['status_new'] = 'To be installed'; +$string['status_nodb'] = 'No database'; +$string['status_upgrade'] = 'To be upgraded'; +$string['status_uptodate'] = 'Up-to-date'; +$string['systemname'] = 'Identifier'; +$string['type_auth'] = 'Authentication method'; +$string['type_auth_plural'] = 'Authentication methods'; +$string['type_block'] = 'Block'; +$string['type_block_plural'] = 'Blocks'; +$string['type_coursereport'] = 'Course report'; +$string['type_coursereport_plural'] = 'Course reports'; +$string['type_editor'] = 'Editor'; +$string['type_editor_plural'] = 'Editors'; +$string['type_enrol'] = 'Enrolment method'; +$string['type_enrol_plural'] = 'Enrolment methods'; +$string['type_filter'] = 'Text filter'; +$string['type_filter_plural'] = 'Text filters'; +$string['type_format'] = 'Course format'; +$string['type_format_plural'] = 'Course formats'; +$string['type_gradeexport'] = 'Grade export method'; +$string['type_gradeexport_plural'] = 'Grade export methods'; +$string['type_gradeimport'] = 'Grade import method'; +$string['type_gradeimport_plural'] = 'Grade import methods'; +$string['type_gradereport'] = 'Gradebook report'; +$string['type_gradereport_plural'] = 'Gradebook reports'; +$string['type_local'] = 'Local plugin'; +$string['type_local_plural'] = 'Local plugins'; +$string['type_message'] = 'Messaging processor'; +$string['type_message_plural'] = 'Messaging processors'; +$string['type_mnetservice'] = 'MNet service'; +$string['type_mnetservice_plural'] = 'MNet services'; +$string['type_mod'] = 'Activity module'; +$string['type_mod_plural'] = 'Activity modules'; +$string['type_plagiarism'] = 'Plagiarism prevention plugin'; +$string['type_plagiarism_plural'] = 'Plagiarism prevention plugins'; +$string['type_portfolio'] = 'Portfolio'; +$string['type_portfolio_plural'] = 'Portfolios'; +$string['type_profilefield'] = 'Profile field type'; +$string['type_profilefield_plural'] = 'Profile field types'; +$string['type_qformat'] = 'Question import/export format'; +$string['type_qformat_plural'] = 'Question import/export formats'; +$string['type_qtype'] = 'Question type'; +$string['type_qtype_plural'] = 'Question types'; +$string['type_report'] = 'Site report'; +$string['type_report_plural'] = 'Site reports'; +$string['type_repository'] = 'Repository'; +$string['type_repository_plural'] = 'Repositories'; +$string['type_theme'] = 'Theme'; +$string['type_theme_plural'] = 'Themes'; +$string['type_webservice'] = 'Webservice protocol'; +$string['type_webservice_plural'] = 'Webservice protocols'; +$string['uninstall'] = 'Uninstall'; +$string['version'] = 'Version'; +$string['versiondb'] = 'Current version'; +$string['versiondisk'] = 'New version'; diff --git a/lang/en/repository.php b/lang/en/repository.php index 9664ff6a322..86fbb43a439 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -32,7 +32,7 @@ $string['addplugin'] = 'Add a repository plugin'; $string['allowexternallinks'] = 'Allow external links'; $string['areamainfile'] = 'Main file'; $string['coursebackup'] = 'Course backups'; -$string['pluginname'] = 'Repository plugin name'; +$string['pluginname'] = 'Repository plugin name'; // todo fix this, this string identifier is reserved $string['pluginnamehelp'] = 'If you leave this empty the default name will be used.'; $string['sectionbackup'] = 'Section backups'; $string['activitybackup'] = 'Activity backup'; diff --git a/mod/assignment/lang/en/assignment.php b/mod/assignment/lang/en/assignment.php index c1d7cbb8024..b56aa8e525f 100644 --- a/mod/assignment/lang/en/assignment.php +++ b/mod/assignment/lang/en/assignment.php @@ -180,6 +180,8 @@ $string['submitedformarking'] = 'Assignment was already submitted for marking an $string['submitformarking'] = 'Final submission for assignment marking'; $string['submitted'] = 'Submitted'; $string['submittedfiles'] = 'Submitted files'; +$string['subplugintype_assignment'] = 'Assignment type'; +$string['subplugintype_assignment_plural'] = 'Assignment types'; $string['trackdrafts'] = 'Enable "Send for marking" button'; $string['trackdrafts_help'] = 'The "Send for marking" button allows students to indicate to the teacher that they have finished working on an assignment. The teacher may choose to revert the assignment to draft status (if it requires further work, for example).'; $string['typeblog'] = 'Blog post'; diff --git a/mod/data/lang/en/data.php b/mod/data/lang/en/data.php index b8d029f8e56..eb49b32bdee 100644 --- a/mod/data/lang/en/data.php +++ b/mod/data/lang/en/data.php @@ -294,6 +294,10 @@ $string['selectedrequired'] = 'All selected required'; $string['showall'] = 'Show all entries'; $string['single'] = 'View single'; $string['singletemplate'] = 'Single template'; +$string['subplugintype_datafield'] = 'Database field type'; +$string['subplugintype_datafield_plural'] = 'Database field types'; +$string['subplugintype_datapreset'] = 'Preset'; +$string['subplugintype_datapreset_plural'] = 'Presets'; $string['teachersandstudents'] = '{$a->teachers} and {$a->students}'; $string['templates'] = 'Templates'; $string['templatesaved'] = 'Template saved'; diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index d68a95cccc4..200d0605a71 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -209,6 +209,12 @@ $string['submissionsettings'] = 'Submission settings'; $string['submissionstart'] = 'Open for submissions from'; $string['submissionstartdatetime'] = 'Open for submissions from {$a->daydatetime} ({$a->distanceday})'; $string['submissiontitle'] = 'Title'; +$string['subplugintype_workshopallocation'] = 'Submissions allocation method'; +$string['subplugintype_workshopallocation_plural'] = 'Submissions allocation methods'; +$string['subplugintype_workshopeval'] = 'Grading evaluation method'; +$string['subplugintype_workshopeval_plural'] = 'Grading evaluation methods'; +$string['subplugintype_workshopform'] = 'Grading strategy'; +$string['subplugintype_workshopform_plural'] = 'Grading strategies'; $string['switchingphase'] = 'Switching phase'; $string['switchphase'] = 'Switch phase'; $string['switchphase10info'] = 'You are about to switch the workshop into the Setup phase. In this phase, users cannot modify their submissions or their assessments. Teachers may use this phase to change workshop settings, modify the grading strategy of tweak assessment forms.'; From 52d1a8043c5e541c596c6537d42059b863c63c62 Mon Sep 17 00:00:00 2001 From: Jenny Gray Date: Thu, 31 Mar 2011 14:44:35 +0100 Subject: [PATCH 230/369] MDL-25651 add capability check to my private files navigation link --- lib/navigationlib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/navigationlib.php b/lib/navigationlib.php index 6824ee66411..4434d7c3825 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -1653,8 +1653,8 @@ class global_navigation extends navigation_node { $usernode->add(get_string('messages', 'message'), $url, self::TYPE_SETTING, null, 'messages'); } - // TODO: Private file capability check - if ($iscurrentuser) { + $context = get_context_instance(CONTEXT_USER, $USER->id); + if ($iscurrentuser && has_capability('moodle/user:manageownfiles', $context)) { $url = new moodle_url('/user/files.php'); $usernode->add(get_string('myfiles'), $url, self::TYPE_SETTING); } From 5deabe4338980e015a9d9c162d668a2f66750f98 Mon Sep 17 00:00:00 2001 From: Mary Evans Date: Fri, 1 Apr 2011 02:43:23 +0100 Subject: [PATCH 231/369] Fix for MDL-27016 added min-width --- theme/boxxie/style/core.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/theme/boxxie/style/core.css b/theme/boxxie/style/core.css index 19770e49f4a..448e67682e2 100644 --- a/theme/boxxie/style/core.css +++ b/theme/boxxie/style/core.css @@ -7,6 +7,7 @@ body { margin: 10px 5%; background: #5b7439; padding: 5px; + min-width: 930px; /* fixes minimum page width */ } #page { @@ -16,6 +17,10 @@ body { } +#page-content { + min-width: inherit; +} + a:link, a:visited { color: #69804e; From 9d61d9ac6dd737cc67837b7bf516040e40dadfe4 Mon Sep 17 00:00:00 2001 From: Rossiani Wijaya Date: Fri, 1 Apr 2011 16:55:37 +0800 Subject: [PATCH 232/369] MDL-26185: simplify the logic of email message output and removing email address cache --- message/output/email/message_output_email.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/message/output/email/message_output_email.php b/message/output/email/message_output_email.php index dff487450e0..0445fbe4aa3 100644 --- a/message/output/email/message_output_email.php +++ b/message/output/email/message_output_email.php @@ -46,18 +46,8 @@ class message_output_email extends message_output { return true; } - //hold onto email preference because /admin/cron.php sends a lot of messages at once - static $useremailaddresses = array(); - //check user preference for where user wants email sent - if (!array_key_exists($eventdata->userto->id, $useremailaddresses)) { - $useremailaddresses[$eventdata->userto->id] = get_user_preferences('message_processor_email_email', $eventdata->userto->email, $eventdata->userto->id); - } - $usertoemailaddress = $useremailaddresses[$eventdata->userto->id]; - - if ( !empty($usertoemailaddress)) { - $userto->email = $usertoemailaddress; - } + $eventdata->userto->email = get_user_preferences('message_processor_email_email', $eventdata->userto->email, $eventdata->userto->id); $result = email_to_user($eventdata->userto, $eventdata->userfrom, $eventdata->subject, $eventdata->fullmessage, $eventdata->fullmessagehtml); From af8851282eb211614600d39f426f2f3ba98953c4 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Mon, 4 Apr 2011 14:37:35 +0800 Subject: [PATCH 233/369] enrolments MDL-26858 Added finish user enrolments button to JS dialogue --- enrol/renderer.php | 3 ++- .../enrolmentmanager/assets/skins/sam/enrolmentmanager.css | 2 +- enrol/yui/enrolmentmanager/enrolmentmanager.js | 7 ++++++- lang/en/enrol.php | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/enrol/renderer.php b/enrol/renderer.php index d7a9cb407ed..6e30ee118c0 100644 --- a/enrol/renderer.php +++ b/enrol/renderer.php @@ -685,7 +685,8 @@ class course_enrolment_users_table extends course_enrolment_table { 'unlimitedduration', 'startdatetoday', 'durationdays', - 'enrolperiod'), 'enrol'); + 'enrolperiod', + 'finishenrollingusers'), 'enrol'); $this->moodlepage->requires->string_for_js('assignroles', 'role'); $this->moodlepage->requires->string_for_js('startingfrom', 'moodle'); diff --git a/enrol/yui/enrolmentmanager/assets/skins/sam/enrolmentmanager.css b/enrol/yui/enrolmentmanager/assets/skins/sam/enrolmentmanager.css index ff047dc2531..72be3ff785e 100644 --- a/enrol/yui/enrolmentmanager/assets/skins/sam/enrolmentmanager.css +++ b/enrol/yui/enrolmentmanager/assets/skins/sam/enrolmentmanager.css @@ -60,7 +60,7 @@ Structure of the user enroller panel .user-enroller-panel .uep-loading-lightbox.hidden {display:none;} .user-enroller-panel .uep-loading-lightbox .loading-icon {margin:auto;vertical-align:middle;margin-top:125px;} -.user-enroller-panel .uep-footer {padding:3px;background-color:#ddd;} +.user-enroller-panel .uep-footer {padding:3px;background-color:#ddd;text-align:center;} .user-enroller-panel .uep-search {margin:3px;} .user-enroller-panel .uep-search label {padding-right:8px;} .user-enroller-panel .uep-search input {width:70%;} diff --git a/enrol/yui/enrolmentmanager/enrolmentmanager.js b/enrol/yui/enrolmentmanager/enrolmentmanager.js index 9cbfb39318b..864cd913222 100644 --- a/enrol/yui/enrolmentmanager/enrolmentmanager.js +++ b/enrol/yui/enrolmentmanager/enrolmentmanager.js @@ -58,7 +58,8 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) { DURATION : 'duration', ACTIVE : 'active', SEARCH : 'uep-search', - CLOSE : 'close' + CLOSE : 'close', + CLOSEBTN : 'close-button' }; var USERENROLLER = function(config) { @@ -98,6 +99,9 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) { .append(Y.Node.create('
') .append(Y.Node.create('')) ) + .append(Y.Node.create('
') + .append(Y.Node.create('')) + ) ) ) ); @@ -109,6 +113,7 @@ YUI.add('moodle-enrol-enrolmentmanager', function(Y) { } }, this); this.get(UEP.BASE).one('.'+CSS.HEADER+' .'+CSS.CLOSE).on('click', this.hide, this); + this.get(UEP.BASE).one('.'+CSS.FOOTER+' .'+CSS.CLOSEBTN+' input').on('click', this.hide, this); this._loadingNode = this.get(UEP.BASE).one('.'+CSS.CONTENT+' .'+CSS.LIGHTBOX); var params = this.get(UEP.PARAMS); params['id'] = this.get(UEP.COURSEID); diff --git a/lang/en/enrol.php b/lang/en/enrol.php index 228e1595f9d..5abd0cbe1ef 100644 --- a/lang/en/enrol.php +++ b/lang/en/enrol.php @@ -60,6 +60,7 @@ $string['errajaxfailedenrol'] = 'Failed to enrol user'; $string['errajaxsearch'] = 'Error when searching users'; $string['errorenrolcohort'] = 'Error creating cohort sync enrolment instance in this course.'; $string['errorenrolcohortusers'] = 'Error enrolling cohort members in this course.'; +$string['finishenrollingusers'] = 'Finish enrolling users'; $string['invalidenrolinstance'] = 'Invalid enrolment instance'; $string['invalidrole'] = 'Invalid role'; $string['manageenrols'] = 'Manage enrol plugins'; From a1ead9a4787cf58d09a6de2115a629ccf0b24806 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Mon, 4 Apr 2011 14:49:28 +0800 Subject: [PATCH 234/369] enrolments MDL-26560 Fixed panel.user bug with role assignments dialogue --- enrol/yui/rolemanager/rolemanager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enrol/yui/rolemanager/rolemanager.js b/enrol/yui/rolemanager/rolemanager.js index 4455b413901..a6d515cadfa 100644 --- a/enrol/yui/rolemanager/rolemanager.js +++ b/enrol/yui/rolemanager/rolemanager.js @@ -93,7 +93,7 @@ YUI.add('moodle-enrol-rolemanager', function(Y) { if (o.error) { new M.core.ajaxException(o); } else { - panel.user.addRoleToDisplay(args.roleid, this.get(ASSIGNABLEROLES)[args.roleid]); + this.users[userid].addRoleToDisplay(args.roleid, this.get(ASSIGNABLEROLES)[args.roleid]); } } catch (e) { new M.core.exception(e); From 656d17c2c6fcce33a414e6930eada6d9edf26242 Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Mon, 4 Apr 2011 11:27:09 +0200 Subject: [PATCH 235/369] gradebook MDL-20946 fixed average calculation where users have multiple gradeable roles --- grade/lib.php | 40 ++++++++++------ grade/report/grader/lib.php | 93 +++++++++++++++++-------------------- grade/report/user/lib.php | 46 +++++++++--------- 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/grade/lib.php b/grade/lib.php index 848408a7523..b8651a983e5 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -85,10 +85,16 @@ class graded_users_iterator { return false; } + $coursecontext = get_context_instance(CONTEXT_COURSE, $this->course->id); + $relatedcontexts = get_related_contexts_string($coursecontext); + list($gradebookroles_sql, $params) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr0'); - $relatedcontexts = get_related_contexts_string(get_context_instance(CONTEXT_COURSE, $this->course->id)); + //limit to users with an active enrolment + list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext); + + $params = array_merge($params, $enrolledparams); if ($this->groupid) { $groupsql = "INNER JOIN {groups_members} gm ON gm.userid = u.id"; @@ -123,31 +129,39 @@ class graded_users_iterator { // $params contents: gradebookroles and groupid (for $groupwheresql) $users_sql = "SELECT u.* $ofields FROM {user} u - INNER JOIN {role_assignments} ra ON u.id = ra.userid + JOIN ($enrolledsql) je ON je.id = u.id $groupsql - WHERE u.deleted=0 - AND ra.roleid $gradebookroles_sql - AND ra.contextid $relatedcontexts + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid $gradebookroles_sql + AND ra.contextid $relatedcontexts + ) rainner ON rainner.userid = u.id + WHERE u.deleted = 0 $groupwheresql ORDER BY $order"; - $this->users_rs = $DB->get_recordset_sql($users_sql, $params); if (!empty($this->grade_items)) { $itemids = array_keys($this->grade_items); list($itemidsql, $grades_params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED, 'items0'); $params = array_merge($params, $grades_params); + // $params contents: gradebookroles, enrolledparams, groupid (for $groupwheresql) and itemids - // $params contents: gradebookroles, groupid (for $groupwheresql) and itemids $grades_sql = "SELECT g.* $ofields FROM {grade_grades} g - INNER JOIN {user} u ON g.userid = u.id - INNER JOIN {role_assignments} ra ON u.id = ra.userid + JOIN {user} u ON g.userid = u.id + JOIN ($enrolledsql) je ON je.id = u.id $groupsql - WHERE ra.roleid $gradebookroles_sql - AND ra.contextid $relatedcontexts - $groupwheresql - AND g.itemid $itemidsql + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid $gradebookroles_sql + AND ra.contextid $relatedcontexts + ) rainnner ON rainner.userid = u.id + WHERE u.deleted = 0 + AND g.itemid $itemidsql + $groupwheresql ORDER BY $order, g.itemid ASC"; $this->grades_rs = $DB->get_recordset_sql($grades_sql, $params); } else { diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php index d76d679c8e4..4b5d23bc73d 100644 --- a/grade/report/grader/lib.php +++ b/grade/report/grader/lib.php @@ -342,55 +342,47 @@ class grade_report_grader extends grade_report { //fields we need from the user table $userfields = user_picture::fields('u', array('idnumber')); + $sortjoin = $sort = $params = null; + //if the user has clicked one of the sort asc/desc arrows if (is_numeric($this->sortitemid)) { $params = array_merge(array('gitemid'=>$this->sortitemid), $gradebookrolesparams, $this->groupwheresql_params, $enrolledparams); - // the MAX() magic is required in order to please PG - $sort = "MAX(g.finalgrade) $this->sortorder"; - $sql = "SELECT $userfields - FROM {user} u - JOIN ($enrolledsql) je - ON je.id = u.id - JOIN {role_assignments} ra - ON ra.userid = u.id - $this->groupsql - LEFT JOIN {grade_grades} g - ON (g.userid = u.id AND g.itemid = :gitemid) - WHERE ra.roleid $gradebookrolessql - AND u.deleted = 0 - AND ra.contextid ".get_related_contexts_string($this->context)." - $this->groupwheresql - GROUP BY $userfields - ORDER BY $sort"; + $sortjoin = "LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = $this->sortitemid"; + $sort = "g.finalgrade $this->sortorder"; } else { + $sortjoin = ''; switch($this->sortitemid) { case 'lastname': - $sort = "u.lastname $this->sortorder, u.firstname $this->sortorder"; break; + $sort = "u.lastname $this->sortorder, u.firstname $this->sortorder"; + break; case 'firstname': - $sort = "u.firstname $this->sortorder, u.lastname $this->sortorder"; break; + $sort = "u.firstname $this->sortorder, u.lastname $this->sortorder"; + break; case 'idnumber': default: - $sort = "u.idnumber $this->sortorder"; break; + $sort = "u.idnumber $this->sortorder"; + break; } $params = array_merge($gradebookrolesparams, $this->groupwheresql_params, $enrolledparams); - - $sql = "SELECT DISTINCT $userfields - FROM {user} u - JOIN ($enrolledsql) je - ON je.id = u.id - JOIN {role_assignments} ra - ON u.id = ra.userid - $this->groupsql - WHERE ra.roleid $gradebookrolessql - AND u.deleted = 0 - AND ra.contextid ".get_related_contexts_string($this->context)." - $this->groupwheresql - ORDER BY $sort"; } + $sql = "SELECT $userfields + FROM {user} u + JOIN ($enrolledsql) je ON je.id = u.id + $this->groupsql + $sortjoin + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid IN ($this->gradebookroles) + AND ra.contextid " . get_related_contexts_string($this->context) . " + ) rainner ON rainner.userid = u.id + AND u.deleted = 0 + $this->groupwheresql + ORDER BY $sort"; $this->users = $DB->get_records_sql($sql, $params, $this->get_pref('studentsperpage') * $this->page, $this->get_pref('studentsperpage')); @@ -1294,25 +1286,25 @@ class grade_report_grader extends grade_report { $params = array_merge(array('courseid'=>$this->courseid), $gradebookrolesparams, $enrolledparams, $groupwheresqlparams); // find sums of all grade items in course - $SQL = "SELECT g.itemid, SUM(g.finalgrade) AS sum + $sql = "SELECT g.itemid, SUM(g.finalgrade) AS sum FROM {grade_items} gi - JOIN {grade_grades} g - ON g.itemid = gi.id - JOIN {user} u - ON u.id = g.userid - JOIN ($enrolledsql) je - ON je.id = u.id - JOIN {role_assignments} ra - ON ra.userid = u.id + JOIN {grade_grades} g ON g.itemid = gi.id + JOIN {user} u ON u.id = g.userid + JOIN ($enrolledsql) je ON je.id = u.id + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid $gradebookrolessql + AND ra.contextid " . get_related_contexts_string($this->context) . " + ) rainner ON rainner.userid = u.id $groupsql WHERE gi.courseid = :courseid - AND ra.roleid $gradebookrolessql - AND ra.contextid ".get_related_contexts_string($this->context)." - AND g.finalgrade IS NOT NULL - $groupwheresql - GROUP BY g.itemid"; + AND u.deleted = 0 + AND g.finalgrade IS NOT NULL + $groupwheresql + GROUP BY g.itemid"; $sumarray = array(); - if ($sums = $DB->get_records_sql($SQL, $params)) { + if ($sums = $DB->get_records_sql($sql, $params)) { foreach ($sums as $itemid => $csum) { $sumarray[$itemid] = $csum->sum; } @@ -1320,7 +1312,7 @@ class grade_report_grader extends grade_report { // MDL-10875 Empty grades must be evaluated as grademin, NOT always 0 // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table) - $SQL = "SELECT gi.id, COUNT(u.id) AS count + $sql = "SELECT gi.id, COUNT(DISTINCT u.id) AS count FROM {grade_items} gi CROSS JOIN {user} u JOIN ($enrolledsql) je @@ -1333,11 +1325,12 @@ class grade_report_grader extends grade_report { WHERE gi.courseid = :courseid AND ra.roleid $gradebookrolessql AND ra.contextid ".get_related_contexts_string($this->context)." + AND u.deleted = 0 AND g.id IS NULL $groupwheresql GROUP BY gi.id"; - $ungradedcounts = $DB->get_records_sql($SQL, $params); + $ungradedcounts = $DB->get_records_sql($sql, $params); $avgrow = new html_table_row(); $avgrow->attributes['class'] = 'avg'; diff --git a/grade/report/user/lib.php b/grade/report/user/lib.php index 7a84094a356..22791e1d666 100644 --- a/grade/report/user/lib.php +++ b/grade/report/user/lib.php @@ -618,19 +618,21 @@ class grade_report_user extends grade_report { // find sums of all grade items in course $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum FROM {grade_items} gi - JOIN {grade_grades} gg - ON gg.itemid = gi.id - JOIN ($enrolledsql) je - ON je.id = gg.userid - JOIN {role_assignments} ra - ON ra.userid = gg.userid + JOIN {grade_grades} gg ON gg.itemid = gi.id + JOIN {user} u ON u.id = gg.userid + JOIN ($enrolledsql) je ON je.id = gg.userid + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid $gradebookrolessql + AND ra.contextid " . get_related_contexts_string($this->context) . " + ) rainner ON rainner.userid = u.id $groupsql WHERE gi.courseid = :courseid - AND ra.roleid $gradebookrolessql - AND ra.contextid ".get_related_contexts_string($this->context)." - AND gg.finalgrade IS NOT NULL - AND gg.hidden = 0 - $groupwheresql + AND u.deleted = 0 + AND gg.finalgrade IS NOT NULL + AND gg.hidden = 0 + $groupwheresql GROUP BY gg.itemid"; $sum_array = array(); @@ -649,19 +651,21 @@ class grade_report_user extends grade_report { $sql = "SELECT gi.id, COUNT(u.id) AS count FROM {grade_items} gi JOIN {user} u - JOIN ($enrolledsql) je - ON je.id = u.id - JOIN {role_assignments} ra - ON ra.userid = u.id + JOIN ($enrolledsql) je ON je.id = u.id + JOIN ( + SELECT DISTINCT ra.userid + FROM {role_assignments} ra + WHERE ra.roleid $gradebookrolessql + AND ra.contextid " . get_related_contexts_string($this->context) . " + ) rainner ON rainner.userid = u.id LEFT JOIN {grade_grades} gg ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0) $groupsql - WHERE gi.courseid = :courseid - AND ra.roleid $gradebookrolessql - AND ra.contextid ".get_related_contexts_string($this->context)." - AND gg.finalgrade IS NULL - $groupwheresql - GROUP BY gi.id"; + WHERE gi.courseid = :courseid + AND u.deleted = 0 + AND gg.finalgrade IS NULL + $groupwheresql + GROUP BY gi.id"; $ungraded_counts = $DB->get_records_sql($sql, $params); From 05edae9f89c755a4169f8ac07b3ea65d82566f2d Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Tue, 5 Apr 2011 11:41:24 +0930 Subject: [PATCH 236/369] MDL-27084: mod/feedback fix bad syntax in database query --- mod/feedback/lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index 1d238e9f97a..a75d8c957d5 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -1786,10 +1786,10 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid $params = array(); if($courseid) { - $courseselect = "fv.course_id = :courseid"; + $courseselect = "AND fv.course_id = :courseid"; $params['courseid'] = $courseid; }else { - $courseselect = "1"; + $courseselect = ''; } if($guestid) { @@ -1807,7 +1807,7 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid WHERE fc.id = fv.completed $userselect AND fc.feedback = :feedbackid - AND $courseselect + $courseselect AND fi.id = fv.item $usergroup"; $params['feedbackid'] = $feedbackid; @@ -2779,4 +2779,4 @@ function feedback_init_feedback_session() { $SESSION->feedback = new stdClass(); } } -} \ No newline at end of file +} From 6e9ce8e76637d86990500598592f3bdc7a113ad3 Mon Sep 17 00:00:00 2001 From: Jonathan Harker Date: Tue, 5 Apr 2011 16:00:21 +1200 Subject: [PATCH 237/369] MDL-22308 Update lib/bennu to latest upstream. --- lib/bennu/iCalendar_components.php | 429 ++++++++++++++++++++++++----- lib/bennu/iCalendar_properties.php | 232 ++++++++++++---- lib/bennu/iCalendar_rfc2445.php | 4 + 3 files changed, 545 insertions(+), 120 deletions(-) diff --git a/lib/bennu/iCalendar_components.php b/lib/bennu/iCalendar_components.php index 5a4127d3177..92350981dc0 100644 --- a/lib/bennu/iCalendar_components.php +++ b/lib/bennu/iCalendar_components.php @@ -9,7 +9,6 @@ * See http://bennu.sourceforge.net/ for more information and downloads. * * @author Ioannis Papaioannou - * @version $Id$ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -19,12 +18,13 @@ class iCalendar_component { var $components = NULL; var $valid_properties = NULL; var $valid_components = NULL; + /** + * Added to hold errors from last run of unserialize + * @var $parser_errors array + */ + var $parser_errors = NULL; - function iCalendar_component() { - $this->construct(); - } - - function construct() { + function __construct() { // Initialize the components array if(empty($this->components)) { $this->components = array(); @@ -99,13 +99,13 @@ class iCalendar_component { return false; } - // If this property is restricted to only once, blindly overwrite value - if(!$xname && $this->valid_properties[$name] & RFC2445_ONCE) { - $this->properties[$name] = array($property); - } - - // Otherwise add it to the instance array for this property - else { + // Check if the property already exists, and is limited to one occurrance, + // DON'T overwrite the value - this can be done explicity with set_value() instead. + if(!$xname && $this->valid_properties[$name] & RFC2445_ONCE && isset($this->properties[$name])) { + return false; + } + else { + // Otherwise add it to the instance array for this property $this->properties[$name][] = $property; } @@ -218,13 +218,112 @@ class iCalendar_component { return $string; } + + /** + * unserialize() + * + * I needed a way to convert an iCalendar component back to a Bennu object so I could + * easily access and modify it after it had been stored; if this functionality is already + * present somewhere in the library, I apologize for adding it here unnecessarily; however, + * I couldn't find it so I added it myself. + * @param string $string the iCalendar object to load in to this iCalendar_component + * @return bool true if the file parsed with no errors. False if there were errors. + */ + + function unserialize($string) { + $string = rfc2445_unfold($string); // Unfold any long lines + $lines = explode(RFC2445_CRLF, $string); // Create an array of lines + + $components = array(); // Initialise a stack of components + $this->clear_errors(); + foreach ($lines as $key => $line) { + // Divide the line up into label, parameters and data fields. + if (!preg_match('#^(?P
Customize for more details", E_USER_WARNING); + } else { + $this->triggerError("Useless DefinitionID declaration", E_USER_WARNING); + } + } + } + // initialize it + $def = $this->initDefinition($type); + $def->optimized = $optimized; + return $def; } + throw new HTMLPurifier_Exception("The impossible happened!"); + } + + private function initDefinition($type) { // quick checks failed, let's create the object if ($type == 'HTML') { - $this->definitions[$type] = new HTMLPurifier_HTMLDefinition(); + $def = new HTMLPurifier_HTMLDefinition(); } elseif ($type == 'CSS') { - $this->definitions[$type] = new HTMLPurifier_CSSDefinition(); + $def = new HTMLPurifier_CSSDefinition(); } elseif ($type == 'URI') { - $this->definitions[$type] = new HTMLPurifier_URIDefinition(); + $def = new HTMLPurifier_URIDefinition(); } else { throw new HTMLPurifier_Exception("Definition of $type type not supported"); } - // quick abort if raw - if ($raw) { - if (is_null($this->get($type . '.DefinitionID'))) { - // fatally error out if definition ID not set - throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID"); - } - return $this->definitions[$type]; - } - // set it up - $this->lock = $type; - $this->definitions[$type]->setup($this); - $this->lock = null; - // save in cache - $cache->set($this->definitions[$type], $this); - return $this->definitions[$type]; + $this->definitions[$type] = $def; + return $def; + } + + public function maybeGetRawDefinition($name) { + return $this->getDefinition($name, true, true); + } + + public function maybeGetRawHTMLDefinition() { + return $this->getDefinition('HTML', true, true); + } + + public function maybeGetRawCSSDefinition() { + return $this->getDefinition('CSS', true, true); + } + + public function maybeGetRawURIDefinition() { + return $this->getDefinition('URI', true, true); } /** @@ -549,17 +673,22 @@ class HTMLPurifier_Config /** * Produces a nicely formatted error message by supplying the - * stack frame information from two levels up and OUTSIDE of - * HTMLPurifier_Config. + * stack frame information OUTSIDE of HTMLPurifier_Config. */ protected function triggerError($msg, $no) { // determine previous stack frame - $backtrace = debug_backtrace(); - if ($this->chatty && isset($backtrace[1])) { - $frame = $backtrace[1]; - $extra = " on line {$frame['line']} in file {$frame['file']}"; - } else { - $extra = ''; + $extra = ''; + if ($this->chatty) { + $trace = debug_backtrace(); + // zip(tail(trace), trace) -- but PHP is not Haskell har har + for ($i = 0, $c = count($trace); $i < $c - 1; $i++) { + if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') { + continue; + } + $frame = $trace[$i]; + $extra = " invoked on line {$frame['line']} in file {$frame['file']}"; + break; + } } trigger_error($msg . $extra, $no); } diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema.php b/lib/htmlpurifier/HTMLPurifier/ConfigSchema.php index 67be5c71fd8..fadf7a5890f 100644 --- a/lib/htmlpurifier/HTMLPurifier/ConfigSchema.php +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema.php @@ -60,7 +60,13 @@ class HTMLPurifier_ConfigSchema { * Unserializes the default ConfigSchema. */ public static function makeFromSerial() { - return unserialize(file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema.ser')); + $contents = file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema.ser'); + $r = unserialize($contents); + if (!$r) { + $hash = sha1($contents); + trigger_error("Unserialization of configuration schema failed, sha1 of file was $hash", E_USER_ERROR); + } + return $r; } /** diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema.ser index 978089c6291e7d828f6233ac632cedd8a98fdfd7..245ba5d2d09c71529c7e1357160a3393ff280a4d 100644 GIT binary patch delta 544 zcmZq8-jg@MoY8W!yrS&J(BsVFhGteu&cVTYjyXB`<*6xd`FSP9O4fdp->J$?HfL!Q zF*Jn8hZL0-m!zgBStnT;On#^)Klvt$p{hAhE-^VHRWCTTC^Io9vnsVHAhjqrv$!}j zKM!b3rj?1M@nl1F`OT`Vsq7-gR!SZrzCL<>`Dyte>p+HWZsoCJl(Do@@-HnZC@s-* z%dGIs%S$Z+DFn$IT2C%ClG=QY_W{#TboC6T$!`@5n2d}z%PU@Dk-{F@nO3?MzyP0% w8Q7Ut=D@&~oxD_Sf->R2Hr;Hf{+vS;Gnj$KY!)#{V8R*BKn2#D3ynmW0d#1w+yDRo delta 128 zcmdm!*P1=SoY7>nr{ELj$wunZlaoZ-CO=k}nk*@1yt!1YfqgTdoGIhxB>DABlLS48 zQFxz;$QH7FilR97vJn;@{0)o0(2~Q diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt new file mode 100644 index 00000000000..3fd4654065d --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt @@ -0,0 +1,12 @@ +CSS.AllowedFonts +TYPE: lookup/null +VERSION: 4.3.0 +DEFAULT: NULL +--DESCRIPTION-- +

+ Allows you to manually specify a set of allowed fonts. If + NULL, all fonts are allowed. This directive + affects generic names (serif, sans-serif, monospace, cursive, + fantasy) as well as specific font families. +

+--# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt new file mode 100644 index 00000000000..e733a61e8a7 --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt @@ -0,0 +1,9 @@ +CSS.Trusted +TYPE: bool +VERSION: 4.2.1 +DEFAULT: false +--DESCRIPTION-- +Indicates whether or not the user's CSS input is trusted or not. If the +input is trusted, a more expansive set of allowed properties. See +also %HTML.Trusted. +--# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt new file mode 100644 index 00000000000..b2b83d9ab6a --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt @@ -0,0 +1,11 @@ +Cache.SerializerPermissions +TYPE: int +VERSION: 4.3.0 +DEFAULT: 0755 +--DESCRIPTION-- + +

+ Directory permissions of the files and directories created inside + the DefinitionCache/Serializer or other custom serializer path. +

+--# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt new file mode 100644 index 00000000000..700b30924a1 --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt @@ -0,0 +1,7 @@ +HTML.Nofollow +TYPE: bool +VERSION: 4.3.0 +DEFAULT: FALSE +--DESCRIPTION-- +If enabled, nofollow rel attributes are added to all outgoing links. +--# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt index 89133b1a385..1db9237e9ee 100644 --- a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt @@ -5,4 +5,5 @@ DEFAULT: false --DESCRIPTION-- Indicates whether or not the user input is trusted or not. If the input is trusted, a more expansive set of allowed tags and attributes will be used. +See also %CSS.Trusted. --# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt new file mode 100644 index 00000000000..d6f0d9f2955 --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt @@ -0,0 +1,15 @@ +Output.FixInnerHTML +TYPE: bool +VERSION: 4.3.0 +DEFAULT: true +--DESCRIPTION-- +

+ If true, HTML Purifier will protect against Internet Explorer's + mishandling of the innerHTML attribute by appending + a space to any attribute that does not contain angled brackets, spaces + or quotes, but contains a backtick. This slightly changes the + semantics of any given attribute, so if this is unacceptable and + you do not use innerHTML on any of your pages, you can + turn this directive off. +

+--# vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/Definition.php b/lib/htmlpurifier/HTMLPurifier/Definition.php index a7408c97498..c7f82eba430 100644 --- a/lib/htmlpurifier/HTMLPurifier/Definition.php +++ b/lib/htmlpurifier/HTMLPurifier/Definition.php @@ -12,6 +12,17 @@ abstract class HTMLPurifier_Definition */ public $setup = false; + /** + * If true, write out the final definition object to the cache after + * setup. This will be true only if all invocations to get a raw + * definition object are also optimized. This does not cause file + * system thrashing because on subsequent calls the cached object + * is used and any writes to the raw definition object are short + * circuited. See enduser-customize.html for the high-level + * picture. + */ + public $optimized = null; + /** * What type of definition is it? */ diff --git a/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php b/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php index 8a5144273b9..73d5e90a602 100644 --- a/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php +++ b/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer.php @@ -9,14 +9,14 @@ class HTMLPurifier_DefinitionCache_Serializer extends $file = $this->generateFilePath($config); if (file_exists($file)) return false; if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); + return $this->_write($file, serialize($def), $config); } public function set($def, $config) { if (!$this->checkDefType($def)) return; $file = $this->generateFilePath($config); if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); + return $this->_write($file, serialize($def), $config); } public function replace($def, $config) { @@ -24,7 +24,7 @@ class HTMLPurifier_DefinitionCache_Serializer extends $file = $this->generateFilePath($config); if (!file_exists($file)) return false; if (!$this->_prepareDir($config)) return false; - return $this->_write($file, serialize($def)); + return $this->_write($file, serialize($def), $config); } public function get($config) { @@ -97,22 +97,33 @@ class HTMLPurifier_DefinitionCache_Serializer extends * Convenience wrapper function for file_put_contents * @param $file File name to write to * @param $data Data to write into file + * @param $config Config object * @return Number of bytes written if success, or false if failure. */ - private function _write($file, $data) { - return file_put_contents($file, $data); + private function _write($file, $data, $config) { + $result = file_put_contents($file, $data); + if ($result !== false) { + // set permissions of the new file (no execute) + $chmod = $config->get('Cache.SerializerPermissions'); + if (!$chmod) { + $chmod = 0644; // invalid config or simpletest + } + $chmod = $chmod & 0666; + chmod($file, $chmod); + } + return $result; } /** * Prepares the directory that this type stores the serials in + * @param $config Config object * @return True if successful */ private function _prepareDir($config) { $directory = $this->generateDirectoryPath($config); - //$chmod = $config->get('Cache.SerializerPermissions'); // it would be nice to get this accepted in upstream - global $CFG; $chmod = $CFG->directorypermissions; + $chmod = $config->get('Cache.SerializerPermissions'); if (!$chmod) { - $chmod = 0755; + $chmod = 0755; // invalid config or simpletest } if (!is_dir($directory)) { $base = $this->generateBaseDirectoryPath($config); @@ -136,6 +147,9 @@ class HTMLPurifier_DefinitionCache_Serializer extends /** * Tests permissions on a directory and throws out friendly * error messages and attempts to chmod it itself if possible + * @param $dir Directory path + * @param $chmod Permissions + * @return True if directory writable */ private function _testPermissions($dir, $chmod) { // early abort, if it is writable, everything is hunky-dory @@ -152,10 +166,9 @@ class HTMLPurifier_DefinitionCache_Serializer extends if (fileowner($dir) === posix_getuid()) { // we can chmod it ourselves $chmod = $chmod | 0700; - chmod($dir, $chmod); - return true; + if (chmod($dir, $chmod)) return true; } elseif (filegroup($dir) === posix_getgid()) { - $chmod = $chmod | 0007; + $chmod = $chmod | 0070; } else { // PHP's probably running as nobody, so we'll // need to give global permissions diff --git a/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer/README b/lib/htmlpurifier/HTMLPurifier/DefinitionCache/Serializer/README old mode 100644 new mode 100755 diff --git a/lib/htmlpurifier/HTMLPurifier/EntityLookup/entities.ser b/lib/htmlpurifier/HTMLPurifier/EntityLookup/entities.ser index f2b8b8f2db0..e8b08128beb 100644 --- a/lib/htmlpurifier/HTMLPurifier/EntityLookup/entities.ser +++ b/lib/htmlpurifier/HTMLPurifier/EntityLookup/entities.ser @@ -1 +1 @@ -a:246:{s:4:"nbsp";s:2:" ";s:5:"iexcl";s:2:"¡";s:4:"cent";s:2:"¢";s:5:"pound";s:2:"£";s:6:"curren";s:2:"¤";s:3:"yen";s:2:"¥";s:6:"brvbar";s:2:"¦";s:4:"sect";s:2:"§";s:3:"uml";s:2:"¨";s:4:"copy";s:2:"©";s:4:"ordf";s:2:"ª";s:5:"laquo";s:2:"«";s:3:"not";s:2:"¬";s:3:"shy";s:2:"­";s:3:"reg";s:2:"®";s:4:"macr";s:2:"¯";s:3:"deg";s:2:"°";s:6:"plusmn";s:2:"±";s:5:"acute";s:2:"´";s:5:"micro";s:2:"µ";s:4:"para";s:2:"¶";s:6:"middot";s:2:"·";s:5:"cedil";s:2:"¸";s:4:"ordm";s:2:"º";s:5:"raquo";s:2:"»";s:6:"iquest";s:2:"¿";s:6:"Agrave";s:2:"À";s:6:"Aacute";s:2:"Á";s:5:"Acirc";s:2:"Â";s:6:"Atilde";s:2:"Ã";s:4:"Auml";s:2:"Ä";s:5:"Aring";s:2:"Å";s:5:"AElig";s:2:"Æ";s:6:"Ccedil";s:2:"Ç";s:6:"Egrave";s:2:"È";s:6:"Eacute";s:2:"É";s:5:"Ecirc";s:2:"Ê";s:4:"Euml";s:2:"Ë";s:6:"Igrave";s:2:"Ì";s:6:"Iacute";s:2:"Í";s:5:"Icirc";s:2:"Î";s:4:"Iuml";s:2:"Ï";s:3:"ETH";s:2:"Ð";s:6:"Ntilde";s:2:"Ñ";s:6:"Ograve";s:2:"Ò";s:6:"Oacute";s:2:"Ó";s:5:"Ocirc";s:2:"Ô";s:6:"Otilde";s:2:"Õ";s:4:"Ouml";s:2:"Ö";s:5:"times";s:2:"×";s:6:"Oslash";s:2:"Ø";s:6:"Ugrave";s:2:"Ù";s:6:"Uacute";s:2:"Ú";s:5:"Ucirc";s:2:"Û";s:4:"Uuml";s:2:"Ü";s:6:"Yacute";s:2:"Ý";s:5:"THORN";s:2:"Þ";s:5:"szlig";s:2:"ß";s:6:"agrave";s:2:"à";s:6:"aacute";s:2:"á";s:5:"acirc";s:2:"â";s:6:"atilde";s:2:"ã";s:4:"auml";s:2:"ä";s:5:"aring";s:2:"å";s:5:"aelig";s:2:"æ";s:6:"ccedil";s:2:"ç";s:6:"egrave";s:2:"è";s:6:"eacute";s:2:"é";s:5:"ecirc";s:2:"ê";s:4:"euml";s:2:"ë";s:6:"igrave";s:2:"ì";s:6:"iacute";s:2:"í";s:5:"icirc";s:2:"î";s:4:"iuml";s:2:"ï";s:3:"eth";s:2:"ð";s:6:"ntilde";s:2:"ñ";s:6:"ograve";s:2:"ò";s:6:"oacute";s:2:"ó";s:5:"ocirc";s:2:"ô";s:6:"otilde";s:2:"õ";s:4:"ouml";s:2:"ö";s:6:"divide";s:2:"÷";s:6:"oslash";s:2:"ø";s:6:"ugrave";s:2:"ù";s:6:"uacute";s:2:"ú";s:5:"ucirc";s:2:"û";s:4:"uuml";s:2:"ü";s:6:"yacute";s:2:"ý";s:5:"thorn";s:2:"þ";s:4:"yuml";s:2:"ÿ";s:4:"quot";s:1:""";s:3:"amp";s:1:"&";s:2:"lt";s:1:"<";s:2:"gt";s:1:">";s:4:"apos";s:1:"'";s:5:"OElig";s:2:"Œ";s:5:"oelig";s:2:"œ";s:6:"Scaron";s:2:"Š";s:6:"scaron";s:2:"š";s:4:"Yuml";s:2:"Ÿ";s:4:"circ";s:2:"ˆ";s:5:"tilde";s:2:"˜";s:4:"ensp";s:3:" ";s:4:"emsp";s:3:" ";s:6:"thinsp";s:3:" ";s:4:"zwnj";s:3:"‌";s:3:"zwj";s:3:"‍";s:3:"lrm";s:3:"‎";s:3:"rlm";s:3:"‏";s:5:"ndash";s:3:"–";s:5:"mdash";s:3:"—";s:5:"lsquo";s:3:"‘";s:5:"rsquo";s:3:"’";s:5:"sbquo";s:3:"‚";s:5:"ldquo";s:3:"“";s:5:"rdquo";s:3:"”";s:5:"bdquo";s:3:"„";s:6:"dagger";s:3:"†";s:6:"Dagger";s:3:"‡";s:6:"permil";s:3:"‰";s:6:"lsaquo";s:3:"‹";s:6:"rsaquo";s:3:"›";s:4:"euro";s:3:"€";s:4:"fnof";s:2:"ƒ";s:5:"Alpha";s:2:"Α";s:4:"Beta";s:2:"Β";s:5:"Gamma";s:2:"Γ";s:5:"Delta";s:2:"Δ";s:7:"Epsilon";s:2:"Ε";s:4:"Zeta";s:2:"Ζ";s:3:"Eta";s:2:"Η";s:5:"Theta";s:2:"Θ";s:4:"Iota";s:2:"Ι";s:5:"Kappa";s:2:"Κ";s:6:"Lambda";s:2:"Λ";s:2:"Mu";s:2:"Μ";s:2:"Nu";s:2:"Ν";s:2:"Xi";s:2:"Ξ";s:7:"Omicron";s:2:"Ο";s:2:"Pi";s:2:"Π";s:3:"Rho";s:2:"Ρ";s:5:"Sigma";s:2:"Σ";s:3:"Tau";s:2:"Τ";s:7:"Upsilon";s:2:"Υ";s:3:"Phi";s:2:"Φ";s:3:"Chi";s:2:"Χ";s:3:"Psi";s:2:"Ψ";s:5:"Omega";s:2:"Ω";s:5:"alpha";s:2:"α";s:4:"beta";s:2:"β";s:5:"gamma";s:2:"γ";s:5:"delta";s:2:"δ";s:7:"epsilon";s:2:"ε";s:4:"zeta";s:2:"ζ";s:3:"eta";s:2:"η";s:5:"theta";s:2:"θ";s:4:"iota";s:2:"ι";s:5:"kappa";s:2:"κ";s:6:"lambda";s:2:"λ";s:2:"mu";s:2:"μ";s:2:"nu";s:2:"ν";s:2:"xi";s:2:"ξ";s:7:"omicron";s:2:"ο";s:2:"pi";s:2:"π";s:3:"rho";s:2:"ρ";s:6:"sigmaf";s:2:"ς";s:5:"sigma";s:2:"σ";s:3:"tau";s:2:"τ";s:7:"upsilon";s:2:"υ";s:3:"phi";s:2:"φ";s:3:"chi";s:2:"χ";s:3:"psi";s:2:"ψ";s:5:"omega";s:2:"ω";s:8:"thetasym";s:2:"ϑ";s:5:"upsih";s:2:"ϒ";s:3:"piv";s:2:"ϖ";s:4:"bull";s:3:"•";s:6:"hellip";s:3:"…";s:5:"prime";s:3:"′";s:5:"Prime";s:3:"″";s:5:"oline";s:3:"‾";s:5:"frasl";s:3:"⁄";s:6:"weierp";s:3:"℘";s:5:"image";s:3:"ℑ";s:4:"real";s:3:"ℜ";s:5:"trade";s:3:"™";s:7:"alefsym";s:3:"ℵ";s:4:"larr";s:3:"←";s:4:"uarr";s:3:"↑";s:4:"rarr";s:3:"→";s:4:"darr";s:3:"↓";s:4:"harr";s:3:"↔";s:5:"crarr";s:3:"↵";s:4:"lArr";s:3:"⇐";s:4:"uArr";s:3:"⇑";s:4:"rArr";s:3:"⇒";s:4:"dArr";s:3:"⇓";s:4:"hArr";s:3:"⇔";s:6:"forall";s:3:"∀";s:4:"part";s:3:"∂";s:5:"exist";s:3:"∃";s:5:"empty";s:3:"∅";s:5:"nabla";s:3:"∇";s:4:"isin";s:3:"∈";s:5:"notin";s:3:"∉";s:2:"ni";s:3:"∋";s:4:"prod";s:3:"∏";s:3:"sum";s:3:"∑";s:5:"minus";s:3:"−";s:6:"lowast";s:3:"∗";s:5:"radic";s:3:"√";s:4:"prop";s:3:"∝";s:5:"infin";s:3:"∞";s:3:"ang";s:3:"∠";s:3:"and";s:3:"∧";s:2:"or";s:3:"∨";s:3:"cap";s:3:"∩";s:3:"cup";s:3:"∪";s:3:"int";s:3:"∫";s:3:"sim";s:3:"∼";s:4:"cong";s:3:"≅";s:5:"asymp";s:3:"≈";s:2:"ne";s:3:"≠";s:5:"equiv";s:3:"≡";s:2:"le";s:3:"≤";s:2:"ge";s:3:"≥";s:3:"sub";s:3:"⊂";s:3:"sup";s:3:"⊃";s:4:"nsub";s:3:"⊄";s:4:"sube";s:3:"⊆";s:4:"supe";s:3:"⊇";s:5:"oplus";s:3:"⊕";s:6:"otimes";s:3:"⊗";s:4:"perp";s:3:"⊥";s:4:"sdot";s:3:"⋅";s:5:"lceil";s:3:"⌈";s:5:"rceil";s:3:"⌉";s:6:"lfloor";s:3:"⌊";s:6:"rfloor";s:3:"⌋";s:4:"lang";s:3:"〈";s:4:"rang";s:3:"〉";s:3:"loz";s:3:"◊";s:6:"spades";s:3:"♠";s:5:"clubs";s:3:"♣";s:6:"hearts";s:3:"♥";s:5:"diams";s:3:"♦";} \ No newline at end of file +a:253:{s:4:"fnof";s:2:"ƒ";s:5:"Alpha";s:2:"Α";s:4:"Beta";s:2:"Β";s:5:"Gamma";s:2:"Γ";s:5:"Delta";s:2:"Δ";s:7:"Epsilon";s:2:"Ε";s:4:"Zeta";s:2:"Ζ";s:3:"Eta";s:2:"Η";s:5:"Theta";s:2:"Θ";s:4:"Iota";s:2:"Ι";s:5:"Kappa";s:2:"Κ";s:6:"Lambda";s:2:"Λ";s:2:"Mu";s:2:"Μ";s:2:"Nu";s:2:"Ν";s:2:"Xi";s:2:"Ξ";s:7:"Omicron";s:2:"Ο";s:2:"Pi";s:2:"Π";s:3:"Rho";s:2:"Ρ";s:5:"Sigma";s:2:"Σ";s:3:"Tau";s:2:"Τ";s:7:"Upsilon";s:2:"Υ";s:3:"Phi";s:2:"Φ";s:3:"Chi";s:2:"Χ";s:3:"Psi";s:2:"Ψ";s:5:"Omega";s:2:"Ω";s:5:"alpha";s:2:"α";s:4:"beta";s:2:"β";s:5:"gamma";s:2:"γ";s:5:"delta";s:2:"δ";s:7:"epsilon";s:2:"ε";s:4:"zeta";s:2:"ζ";s:3:"eta";s:2:"η";s:5:"theta";s:2:"θ";s:4:"iota";s:2:"ι";s:5:"kappa";s:2:"κ";s:6:"lambda";s:2:"λ";s:2:"mu";s:2:"μ";s:2:"nu";s:2:"ν";s:2:"xi";s:2:"ξ";s:7:"omicron";s:2:"ο";s:2:"pi";s:2:"π";s:3:"rho";s:2:"ρ";s:6:"sigmaf";s:2:"ς";s:5:"sigma";s:2:"σ";s:3:"tau";s:2:"τ";s:7:"upsilon";s:2:"υ";s:3:"phi";s:2:"φ";s:3:"chi";s:2:"χ";s:3:"psi";s:2:"ψ";s:5:"omega";s:2:"ω";s:8:"thetasym";s:2:"ϑ";s:5:"upsih";s:2:"ϒ";s:3:"piv";s:2:"ϖ";s:4:"bull";s:3:"•";s:6:"hellip";s:3:"…";s:5:"prime";s:3:"′";s:5:"Prime";s:3:"″";s:5:"oline";s:3:"‾";s:5:"frasl";s:3:"⁄";s:6:"weierp";s:3:"℘";s:5:"image";s:3:"ℑ";s:4:"real";s:3:"ℜ";s:5:"trade";s:3:"™";s:7:"alefsym";s:3:"ℵ";s:4:"larr";s:3:"←";s:4:"uarr";s:3:"↑";s:4:"rarr";s:3:"→";s:4:"darr";s:3:"↓";s:4:"harr";s:3:"↔";s:5:"crarr";s:3:"↵";s:4:"lArr";s:3:"⇐";s:4:"uArr";s:3:"⇑";s:4:"rArr";s:3:"⇒";s:4:"dArr";s:3:"⇓";s:4:"hArr";s:3:"⇔";s:6:"forall";s:3:"∀";s:4:"part";s:3:"∂";s:5:"exist";s:3:"∃";s:5:"empty";s:3:"∅";s:5:"nabla";s:3:"∇";s:4:"isin";s:3:"∈";s:5:"notin";s:3:"∉";s:2:"ni";s:3:"∋";s:4:"prod";s:3:"∏";s:3:"sum";s:3:"∑";s:5:"minus";s:3:"−";s:6:"lowast";s:3:"∗";s:5:"radic";s:3:"√";s:4:"prop";s:3:"∝";s:5:"infin";s:3:"∞";s:3:"ang";s:3:"∠";s:3:"and";s:3:"∧";s:2:"or";s:3:"∨";s:3:"cap";s:3:"∩";s:3:"cup";s:3:"∪";s:3:"int";s:3:"∫";s:6:"there4";s:3:"∴";s:3:"sim";s:3:"∼";s:4:"cong";s:3:"≅";s:5:"asymp";s:3:"≈";s:2:"ne";s:3:"≠";s:5:"equiv";s:3:"≡";s:2:"le";s:3:"≤";s:2:"ge";s:3:"≥";s:3:"sub";s:3:"⊂";s:3:"sup";s:3:"⊃";s:4:"nsub";s:3:"⊄";s:4:"sube";s:3:"⊆";s:4:"supe";s:3:"⊇";s:5:"oplus";s:3:"⊕";s:6:"otimes";s:3:"⊗";s:4:"perp";s:3:"⊥";s:4:"sdot";s:3:"⋅";s:5:"lceil";s:3:"⌈";s:5:"rceil";s:3:"⌉";s:6:"lfloor";s:3:"⌊";s:6:"rfloor";s:3:"⌋";s:4:"lang";s:3:"〈";s:4:"rang";s:3:"〉";s:3:"loz";s:3:"◊";s:6:"spades";s:3:"♠";s:5:"clubs";s:3:"♣";s:6:"hearts";s:3:"♥";s:5:"diams";s:3:"♦";s:4:"quot";s:1:""";s:3:"amp";s:1:"&";s:2:"lt";s:1:"<";s:2:"gt";s:1:">";s:4:"apos";s:1:"'";s:5:"OElig";s:2:"Œ";s:5:"oelig";s:2:"œ";s:6:"Scaron";s:2:"Š";s:6:"scaron";s:2:"š";s:4:"Yuml";s:2:"Ÿ";s:4:"circ";s:2:"ˆ";s:5:"tilde";s:2:"˜";s:4:"ensp";s:3:" ";s:4:"emsp";s:3:" ";s:6:"thinsp";s:3:" ";s:4:"zwnj";s:3:"‌";s:3:"zwj";s:3:"‍";s:3:"lrm";s:3:"‎";s:3:"rlm";s:3:"‏";s:5:"ndash";s:3:"–";s:5:"mdash";s:3:"—";s:5:"lsquo";s:3:"‘";s:5:"rsquo";s:3:"’";s:5:"sbquo";s:3:"‚";s:5:"ldquo";s:3:"“";s:5:"rdquo";s:3:"”";s:5:"bdquo";s:3:"„";s:6:"dagger";s:3:"†";s:6:"Dagger";s:3:"‡";s:6:"permil";s:3:"‰";s:6:"lsaquo";s:3:"‹";s:6:"rsaquo";s:3:"›";s:4:"euro";s:3:"€";s:4:"nbsp";s:2:" ";s:5:"iexcl";s:2:"¡";s:4:"cent";s:2:"¢";s:5:"pound";s:2:"£";s:6:"curren";s:2:"¤";s:3:"yen";s:2:"¥";s:6:"brvbar";s:2:"¦";s:4:"sect";s:2:"§";s:3:"uml";s:2:"¨";s:4:"copy";s:2:"©";s:4:"ordf";s:2:"ª";s:5:"laquo";s:2:"«";s:3:"not";s:2:"¬";s:3:"shy";s:2:"­";s:3:"reg";s:2:"®";s:4:"macr";s:2:"¯";s:3:"deg";s:2:"°";s:6:"plusmn";s:2:"±";s:4:"sup2";s:2:"²";s:4:"sup3";s:2:"³";s:5:"acute";s:2:"´";s:5:"micro";s:2:"µ";s:4:"para";s:2:"¶";s:6:"middot";s:2:"·";s:5:"cedil";s:2:"¸";s:4:"sup1";s:2:"¹";s:4:"ordm";s:2:"º";s:5:"raquo";s:2:"»";s:6:"frac14";s:2:"¼";s:6:"frac12";s:2:"½";s:6:"frac34";s:2:"¾";s:6:"iquest";s:2:"¿";s:6:"Agrave";s:2:"À";s:6:"Aacute";s:2:"Á";s:5:"Acirc";s:2:"Â";s:6:"Atilde";s:2:"Ã";s:4:"Auml";s:2:"Ä";s:5:"Aring";s:2:"Å";s:5:"AElig";s:2:"Æ";s:6:"Ccedil";s:2:"Ç";s:6:"Egrave";s:2:"È";s:6:"Eacute";s:2:"É";s:5:"Ecirc";s:2:"Ê";s:4:"Euml";s:2:"Ë";s:6:"Igrave";s:2:"Ì";s:6:"Iacute";s:2:"Í";s:5:"Icirc";s:2:"Î";s:4:"Iuml";s:2:"Ï";s:3:"ETH";s:2:"Ð";s:6:"Ntilde";s:2:"Ñ";s:6:"Ograve";s:2:"Ò";s:6:"Oacute";s:2:"Ó";s:5:"Ocirc";s:2:"Ô";s:6:"Otilde";s:2:"Õ";s:4:"Ouml";s:2:"Ö";s:5:"times";s:2:"×";s:6:"Oslash";s:2:"Ø";s:6:"Ugrave";s:2:"Ù";s:6:"Uacute";s:2:"Ú";s:5:"Ucirc";s:2:"Û";s:4:"Uuml";s:2:"Ü";s:6:"Yacute";s:2:"Ý";s:5:"THORN";s:2:"Þ";s:5:"szlig";s:2:"ß";s:6:"agrave";s:2:"à";s:6:"aacute";s:2:"á";s:5:"acirc";s:2:"â";s:6:"atilde";s:2:"ã";s:4:"auml";s:2:"ä";s:5:"aring";s:2:"å";s:5:"aelig";s:2:"æ";s:6:"ccedil";s:2:"ç";s:6:"egrave";s:2:"è";s:6:"eacute";s:2:"é";s:5:"ecirc";s:2:"ê";s:4:"euml";s:2:"ë";s:6:"igrave";s:2:"ì";s:6:"iacute";s:2:"í";s:5:"icirc";s:2:"î";s:4:"iuml";s:2:"ï";s:3:"eth";s:2:"ð";s:6:"ntilde";s:2:"ñ";s:6:"ograve";s:2:"ò";s:6:"oacute";s:2:"ó";s:5:"ocirc";s:2:"ô";s:6:"otilde";s:2:"õ";s:4:"ouml";s:2:"ö";s:6:"divide";s:2:"÷";s:6:"oslash";s:2:"ø";s:6:"ugrave";s:2:"ù";s:6:"uacute";s:2:"ú";s:5:"ucirc";s:2:"û";s:4:"uuml";s:2:"ü";s:6:"yacute";s:2:"ý";s:5:"thorn";s:2:"þ";s:4:"yuml";s:2:"ÿ";} \ No newline at end of file diff --git a/lib/htmlpurifier/HTMLPurifier/Generator.php b/lib/htmlpurifier/HTMLPurifier/Generator.php index e6221db7609..fee1a5f84e8 100644 --- a/lib/htmlpurifier/HTMLPurifier/Generator.php +++ b/lib/htmlpurifier/HTMLPurifier/Generator.php @@ -36,6 +36,11 @@ class HTMLPurifier_Generator */ private $_flashCompat; + /** + * Cache of %Output.FixInnerHTML + */ + private $_innerHTMLFix; + /** * Stack for keeping track of object information when outputting IE * compatibility code. @@ -54,6 +59,7 @@ class HTMLPurifier_Generator public function __construct($config, $context) { $this->config = $config; $this->_scriptFix = $config->get('Output.CommentScriptContents'); + $this->_innerHTMLFix = $config->get('Output.FixInnerHTML'); $this->_sortAttr = $config->get('Output.SortAttr'); $this->_flashCompat = $config->get('Output.FlashCompat'); $this->_def = $config->getHTMLDefinition(); @@ -132,19 +138,7 @@ class HTMLPurifier_Generator $_extra = ''; if ($this->_flashCompat) { if ($token->name == "object" && !empty($this->_flashStack)) { - $flash = array_pop($this->_flashStack); - $compat_token = new HTMLPurifier_Token_Empty("embed"); - foreach ($flash->attr as $name => $val) { - if ($name == "classid") continue; - if ($name == "type") continue; - if ($name == "data") $name = "src"; - $compat_token->attr[$name] = $val; - } - foreach ($flash->param as $name => $val) { - if ($name == "movie") $name = "src"; - $compat_token->attr[$name] = $val; - } - $_extra = ""; + // doesn't do anything for now } } return $_extra . 'name . '>'; @@ -202,6 +196,37 @@ class HTMLPurifier_Generator continue; } } + // Workaround for Internet Explorer innerHTML bug. + // Essentially, Internet Explorer, when calculating + // innerHTML, omits quotes if there are no instances of + // angled brackets, quotes or spaces. However, when parsing + // HTML (for example, when you assign to innerHTML), it + // treats backticks as quotes. Thus, + // `` + // becomes + // `` + // becomes + // + // Fortunately, all we need to do is trigger an appropriate + // quoting style, which we do by adding an extra space. + // This also is consistent with the W3C spec, which states + // that user agents may ignore leading or trailing + // whitespace (in fact, most don't, at least for attributes + // like alt, but an extra space at the end is barely + // noticeable). Still, we have a configuration knob for + // this, since this transformation is not necesary if you + // don't process user input with innerHTML or you don't plan + // on supporting Internet Explorer. + if ($this->_innerHTMLFix) { + if (strpos($value, '`') !== false) { + // check if correct quoting style would not already be + // triggered + if (strcspn($value, '"\' <>') === strlen($value)) { + // protect! + $value .= ' '; + } + } + } $html .= $key.'="'.$this->escape($value).'" '; } return rtrim($html); diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModule/Nofollow.php b/lib/htmlpurifier/HTMLPurifier/HTMLModule/Nofollow.php new file mode 100644 index 00000000000..3aa6654a5cb --- /dev/null +++ b/lib/htmlpurifier/HTMLPurifier/HTMLModule/Nofollow.php @@ -0,0 +1,19 @@ +addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_Nofollow(); + } + +} + +// vim: et sw=4 sts=4 diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php b/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php index ea256716bb1..9f3758a3227 100644 --- a/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php +++ b/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeEmbed.php @@ -21,7 +21,7 @@ class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule 'allowscriptaccess' => 'Enum#never', 'allownetworking' => 'Enum#internal', 'flashvars' => 'Text', - 'wmode' => 'Enum#window', + 'wmode' => 'Enum#window,transparent,opaque', 'name' => 'ID', ) ); diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php b/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php index 64ab8c07031..00da342ef85 100644 --- a/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php +++ b/lib/htmlpurifier/HTMLPurifier/HTMLModule/SafeObject.php @@ -29,7 +29,6 @@ class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule 'width' => 'Pixels#' . $max, 'height' => 'Pixels#' . $max, 'data' => 'URI#embedded', - 'classid' => 'Enum#clsid:d27cdb6e-ae6d-11cf-96b8-444553540000', 'codebase' => new HTMLPurifier_AttrDef_Enum(array( 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0')), ) diff --git a/lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php b/lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php index f5c4a1d2cbb..362e3b78db5 100644 --- a/lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php +++ b/lib/htmlpurifier/HTMLPurifier/HTMLModuleManager.php @@ -216,19 +216,19 @@ class HTMLPurifier_HTMLModuleManager } } - // add proprietary module (this gets special treatment because - // it is completely removed from doctypes, etc.) + // custom modules if ($config->get('HTML.Proprietary')) { $modules[] = 'Proprietary'; } - - // add SafeObject/Safeembed modules if ($config->get('HTML.SafeObject')) { $modules[] = 'SafeObject'; } if ($config->get('HTML.SafeEmbed')) { $modules[] = 'SafeEmbed'; } + if ($config->get('HTML.Nofollow')) { + $modules[] = 'Nofollow'; + } // merge in custom modules $modules = array_merge($modules, $this->userModules); diff --git a/lib/htmlpurifier/HTMLPurifier/Lexer.php b/lib/htmlpurifier/HTMLPurifier/Lexer.php index 325d5c5f138..9bdbbbb25b7 100644 --- a/lib/htmlpurifier/HTMLPurifier/Lexer.php +++ b/lib/htmlpurifier/HTMLPurifier/Lexer.php @@ -235,7 +235,7 @@ class HTMLPurifier_Lexer */ protected static function removeIEConditional($string) { return preg_replace( - '##si', // probably should generalize for all strings + '##si', // probably should generalize for all strings '', $string ); @@ -273,11 +273,11 @@ class HTMLPurifier_Lexer $html = $this->escapeCommentedCDATA($html); } - $html = $this->removeIEConditional($html); - // escape CDATA $html = $this->escapeCDATA($html); + $html = $this->removeIEConditional($html); + // extract body from document if applicable if ($config->get('Core.ConvertDocumentToFragment')) { $e = false; diff --git a/lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php b/lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php index 20dc2ed48c1..82f377450b9 100644 --- a/lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php +++ b/lib/htmlpurifier/HTMLPurifier/Lexer/DOMLex.php @@ -72,23 +72,57 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer } /** - * Recursive function that tokenizes a node, putting it into an accumulator. - * + * Iterative function that tokenizes a node, putting it into an accumulator. + * To iterate is human, to recurse divine - L. Peter Deutsch * @param $node DOMNode to be tokenized. * @param $tokens Array-list of already tokenized tokens. - * @param $collect Says whether or start and close are collected, set to - * false at first recursion because it's the implicit DIV - * tag you're dealing with. * @returns Tokens of node appended to previously passed tokens. */ - protected function tokenizeDOM($node, &$tokens, $collect = false) { + protected function tokenizeDOM($node, &$tokens) { + $level = 0; + $nodes = array($level => array($node)); + $closingNodes = array(); + do { + while (!empty($nodes[$level])) { + $node = array_shift($nodes[$level]); // FIFO + $collect = $level > 0 ? true : false; + $needEndingTag = $this->createStartNode($node, $tokens, $collect); + if ($needEndingTag) { + $closingNodes[$level][] = $node; + } + if ($node->childNodes && $node->childNodes->length) { + $level++; + $nodes[$level] = array(); + foreach ($node->childNodes as $childNode) { + array_push($nodes[$level], $childNode); + } + } + } + $level--; + if ($level && isset($closingNodes[$level])) { + while($node = array_pop($closingNodes[$level])) { + $this->createEndNode($node, $tokens); + } + } + } while ($level > 0); + } + + /** + * @param $node DOMNode to be tokenized. + * @param $tokens Array-list of already tokenized tokens. + * @param $collect Says whether or start and close are collected, set to + * false at first recursion because it's the implicit DIV + * tag you're dealing with. + * @returns bool if the token needs an endtoken + */ + protected function createStartNode($node, &$tokens, $collect) { // intercept non element nodes. WE MUST catch all of them, // but we're not getting the character reference nodes because // those should have been preprocessed if ($node->nodeType === XML_TEXT_NODE) { $tokens[] = $this->factory->createText($node->data); - return; + return false; } elseif ($node->nodeType === XML_CDATA_SECTION_NODE) { // undo libxml's special treatment of

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 z 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