Merge branch 'install_master' of git://git.moodle.org/moodle-install
authorDan Poltawski <dan@moodle.com>
Fri, 1 Nov 2013 07:47:31 +0000 (15:47 +0800)
committerDan Poltawski <dan@moodle.com>
Fri, 1 Nov 2013 07:47:31 +0000 (15:47 +0800)
388 files changed:
admin/roles/assign.php
admin/roles/check.php
admin/roles/define.php
admin/roles/override.php
admin/roles/permissions.php
admin/roles/usersroles.php
admin/settings.php
admin/settings/frontpage.php
admin/tests/behat/behat_admin.php
admin/tests/behat/display_short_names.feature
admin/tool/behat/tests/behat/basic_actions.feature
admin/tool/customlang/edit.php
admin/tool/customlang/index.php
admin/tool/generator/classes/testplan_backend.php
admin/tool/installaddon/classes/installer.php
admin/tool/installaddon/deploy.php
admin/tool/installaddon/tests/installer_test.php
admin/tool/uploaduser/index.php
admin/tool/uploaduser/user_form.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_section_task.class.php
backup/util/dbops/backup_controller_dbops.class.php
backup/util/dbops/restore_dbops.class.php
badges/action.php
badges/award.php
badges/criteria.php
badges/criteria_action.php
badges/criteria_settings.php
badges/edit.php
badges/index.php
badges/overview.php
badges/recipients.php
blocks/community/communitycourse.php
blocks/community/locallib.php
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js
blocks/navigation/yui/src/navigation/js/navigation.js
blocks/settings/styles.css
blog/locallib.php
calendar/classes/type_base.php
calendar/tests/calendartype_test_example.php
calendar/type/gregorian/classes/structure.php
cohort/assign.php
cohort/edit.php
cohort/index.php
completion/tests/behat/restrict_activity_by_date.feature [new file with mode: 0644]
completion/tests/behat/restrict_activity_by_grade.feature [new file with mode: 0644]
completion/tests/behat/restrict_section_availability.feature
config-dist.php
course/classes/management/helper.php
course/classes/management_renderer.php
course/delete.php
course/dnduploadlib.php
course/editcategory.php
course/format/renderer.php
course/management.php
course/modedit.php
course/reset.php
course/tests/behat/behat_course.php
course/tests/behat/category_management.feature
course/tests/behat/category_resort.feature
course/tests/behat/course_category_management_listing.feature
course/tests/courselib_test.php
course/user.php
course/yui/toolboxes/toolboxes.js
files/index.php
files/renderer.php
files/tests/behat/course_files.feature
filter/manage.php
grade/edit/outcome/import.php
grade/edit/outcome/import_outcomes_form.php
lang/en/backup.php
lang/en/moodle.php
lib/accesslib.php
lib/adminlib.php
lib/ajax/getsiteadminbranch.php [new file with mode: 0644]
lib/classes/event/blog_entry_created.php
lib/classes/event/blog_entry_deleted.php
lib/classes/event/blog_entry_updated.php
lib/classes/event/content_viewed.php
lib/classes/event/course_completed.php
lib/classes/event/course_completion_updated.php
lib/classes/event/course_deleted.php
lib/classes/event/course_module_completion_updated.php
lib/classes/event/course_module_created.php
lib/classes/event/course_module_updated.php
lib/classes/event/role_assigned.php
lib/classes/event/role_unassigned.php
lib/classes/event/user_deleted.php
lib/classes/event/user_enrolment_created.php
lib/classes/event/user_enrolment_deleted.php
lib/classes/event/user_enrolment_updated.php
lib/classes/session/handler.php
lib/classes/session/manager.php
lib/classes/session/memcached.php
lib/classes/useragent.php
lib/coursecatlib.php
lib/db/events.php
lib/db/upgrade.php
lib/dml/moodle_database.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/oci_native_moodle_database.php
lib/dml/pgsql_native_moodle_database.php
lib/dml/sqlite3_pdo_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/editor/tinymce/db/upgrade.php
lib/editor/tinymce/lang/en/editor_tinymce.php
lib/editor/tinymce/plugins/dragmath/dragmath.php
lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.png
lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.svg [new file with mode: 0644]
lib/editor/tinymce/plugins/pdw/lib.php
lib/editor/tinymce/plugins/pdw/readme_moodle.txt
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js
lib/editor/tinymce/plugins/pdw/version.php
lib/editor/tinymce/plugins/wrap/tinymce/editor_plugin.js
lib/editor/tinymce/readme_moodle.txt
lib/editor/tinymce/settings.php
lib/editor/tinymce/styles.css
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/abbr.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/abbr.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/acronym.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/acronym.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_center.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_center.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_left.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_left.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_right.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_right.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.png [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.svg [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bold.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bold.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bullet_list.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bullet_list.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/button_bg.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/cancel.png [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/cancel.svg [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/cleanup_messy_code.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/cleanup_messy_code.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/clear_formatting.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/clear_formatting.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/decrease_indent.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/decrease_indent.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/delete.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/delete.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/document_properties.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/document_properties.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/emoticons.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/emoticons.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/find_replace.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/find_replace.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/help.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/help.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/increase_indent.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/increase_indent.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_edit_image.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_edit_image.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_edit_video.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_edit_video.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_nonbreaking_space.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_nonbreaking_space.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_time.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/insert_time.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/italic.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/italic.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers_over.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers_over.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers_under.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/layers_under.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/left_to_right.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/left_to_right.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/merge_cells.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/numbered_list.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/numbered_list.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/page_break.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/page_break.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/paste.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/paste.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/question.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/question.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/resize.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/resize.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/right_to_left.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/right_to_left.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/save.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/save.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/show_invisible_characters.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/show_invisible_characters.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/spellcheck.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/split_cells.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/strikethrough.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/strikethrough.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/styleprops.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/styleprops.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/subscript.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/subscript.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/superscript.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/superscript.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/table.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/template.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/template.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_color.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_color.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_color_picker.png [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_color_picker.svg [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_highlight.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_highlight.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_highlight_picker.png [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/text_highlight_picker.svg [new file with mode: 0644]
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/underline.png
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/underline.svg
lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/ui.css
lib/editor/tinymce/tiny_mce/3.5.8/tiny_mce.js
lib/editor/tinymce/tiny_mce/3.5.8/tiny_mce_src.js
lib/editor/tinymce/version.php
lib/filelib.php
lib/form/dateselector.php
lib/form/datetimeselector.php
lib/form/yui/dateselector/dateselector.js
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/portfolio/exporter.php
lib/portfoliolib.php
lib/tests/accesslib_test.php
lib/tests/behat/behat_general.php
lib/tests/completionlib_test.php
lib/tests/eventslib_test.php
lib/tests/moodlelib_test.php
lib/tests/useragent_test.php
lib/upgrade.txt
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit-debug.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit-min.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-debug.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue-min.js
lib/yui/build/moodle-core-notification-dialogue/moodle-core-notification-dialogue.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-debug.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip-min.js
lib/yui/build/moodle-core-tooltip/moodle-core-tooltip.js
lib/yui/src/blocks/js/blocks.js
lib/yui/src/formautosubmit/js/formautosubmit.js
lib/yui/src/notification/js/dialogue.js
lib/yui/src/tooltip/js/tooltip.js
login/change_password.php
message/edit.php
message/tests/behat/display_history.feature [new file with mode: 0644]
mod/assign/feedback/editpdf/ajax_progress.php [new file with mode: 0644]
mod/assign/feedback/editpdf/classes/document_services.php
mod/assign/feedback/editpdf/classes/renderer.php
mod/assign/feedback/editpdf/classes/widget.php
mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php
mod/assign/feedback/editpdf/locallib.php
mod/assign/feedback/editpdf/styles.css
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotation.js
mod/assign/feedback/editpdf/yui/src/editor/js/annotationstamp.js
mod/assign/feedback/editpdf/yui/src/editor/js/colourpicker.js
mod/assign/feedback/editpdf/yui/src/editor/js/comment.js
mod/assign/feedback/editpdf/yui/src/editor/js/commentmenu.js
mod/assign/feedback/editpdf/yui/src/editor/js/commentsearch.js
mod/assign/feedback/editpdf/yui/src/editor/js/dropdown.js
mod/assign/feedback/editpdf/yui/src/editor/js/editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/globals.js
mod/assign/feedback/editpdf/yui/src/editor/js/stamppicker.js
mod/assign/gradingtable.php
mod/assign/locallib.php
mod/assign/tests/locallib_test.php
mod/book/classes/event/course_module_viewed.php
mod/book/tool/importhtml/locallib.php
mod/chat/lib.php
mod/choice/classes/event/course_module_viewed.php
mod/data/templates.php
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/rsslib.php
mod/forum/tests/behat/edit_post_student.feature
mod/glossary/rsslib.php
mod/glossary/tests/behat/entries_require_approval.feature [new file with mode: 0644]
mod/lti/locallib.php
mod/lti/tests/locallib_test.php
mod/page/classes/event/course_module_viewed.php
mod/workshop/classes/event/course_module_viewed.php
pix/a/add_file.png
pix/a/add_file.svg [new file with mode: 0644]
pix/a/create_folder.png
pix/a/create_folder.svg [new file with mode: 0644]
pix/a/download_all.png
pix/a/download_all.svg [new file with mode: 0644]
pix/a/help.png
pix/a/help.svg [new file with mode: 0644]
pix/a/logout.png
pix/a/logout.svg [new file with mode: 0644]
pix/a/refresh.png
pix/a/refresh.svg [new file with mode: 0644]
pix/a/search.png
pix/a/search.svg [new file with mode: 0644]
pix/a/setting.png
pix/a/setting.svg [new file with mode: 0644]
pix/a/view_icon_active.png [new file with mode: 0644]
pix/a/view_icon_active.svg [new file with mode: 0644]
pix/a/view_list_active.png [new file with mode: 0644]
pix/a/view_list_active.svg [new file with mode: 0644]
pix/a/view_tree_active.png [new file with mode: 0644]
pix/a/view_tree_active.svg [new file with mode: 0644]
question/tests/behat/delete_questions.feature [new file with mode: 0644]
report/log/user.php
report/loglive/index.php
report/outline/user.php
report/stats/index.php
report/stats/user.php
repository/filepicker.js
theme/base/pix/fp/add_file.png [new file with mode: 0644]
theme/base/pix/fp/add_file.svg [new file with mode: 0644]
theme/base/pix/fp/create_folder.png [new file with mode: 0644]
theme/base/pix/fp/create_folder.svg [new file with mode: 0644]
theme/base/pix/fp/download_all.png [new file with mode: 0644]
theme/base/pix/fp/download_all.svg [new file with mode: 0644]
theme/base/pix/fp/help.png [new file with mode: 0644]
theme/base/pix/fp/help.svg [new file with mode: 0644]
theme/base/pix/fp/logout.png [new file with mode: 0644]
theme/base/pix/fp/logout.svg [new file with mode: 0644]
theme/base/pix/fp/refresh.png [new file with mode: 0644]
theme/base/pix/fp/refresh.svg [new file with mode: 0644]
theme/base/pix/fp/search.png [new file with mode: 0644]
theme/base/pix/fp/search.svg [new file with mode: 0644]
theme/base/pix/fp/setting.png [new file with mode: 0644]
theme/base/pix/fp/setting.svg [new file with mode: 0644]
theme/base/pix/fp/view_icon_active.png
theme/base/pix/fp/view_icon_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_icon_inactive.png [deleted file]
theme/base/pix/fp/view_icon_selected.png [deleted file]
theme/base/pix/fp/view_list_active.png
theme/base/pix/fp/view_list_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_list_inactive.png [deleted file]
theme/base/pix/fp/view_list_selected.png [deleted file]
theme/base/pix/fp/view_tree_active.png
theme/base/pix/fp/view_tree_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_tree_inactive.png [deleted file]
theme/base/pix/fp/view_tree_selected.png [deleted file]
theme/base/style/core.css
theme/base/style/course.css
theme/base/style/filemanager.css
theme/bootstrapbase/less/moodle/core.less
theme/bootstrapbase/less/moodle/course.less
theme/bootstrapbase/less/moodle/filemanager.less
theme/bootstrapbase/pix/fp/add_file.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/add_file.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/create_folder.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/create_folder.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/download_all.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/download_all.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/help.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/help.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/logout.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/logout.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/refresh.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/refresh.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/search.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/search.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/setting.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/setting.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_icon_active.png
theme/bootstrapbase/pix/fp/view_icon_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_icon_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_icon_selected.png [deleted file]
theme/bootstrapbase/pix/fp/view_list_active.png
theme/bootstrapbase/pix/fp/view_list_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_list_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_list_selected.png [deleted file]
theme/bootstrapbase/pix/fp/view_tree_active.png
theme/bootstrapbase/pix/fp/view_tree_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_tree_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_tree_selected.png [deleted file]
theme/bootstrapbase/style/moodle.css
user/edit.php
user/editadvanced.php
user/profile/field/datetime/define.class.php
version.php

index 980e2ae..421eca2 100644 (file)
@@ -149,12 +149,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid, 'roleid' => $roleid));
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index 0590165..938fc90 100644 (file)
@@ -50,6 +50,14 @@ if (!has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride',
     print_error('nopermissions', 'error', '', get_string('checkpermissions', 'core_role'));
 }
 $PAGE->set_url($url);
+
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+} else {
+    $PAGE->set_context($context);
+}
+
 $PAGE->set_context($context);
 
 $courseid = $course->id;
@@ -79,12 +87,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid), $CFG->wwwroot . '/' . $CFG->admin . '/roles/check.php');
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index 265b100..d30ad3e 100644 (file)
@@ -201,8 +201,7 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $de
     $event = \core\event\role_capabilities_updated::create(
         array(
             'context' => $systemcontext,
-            'objectid' => $roleid,
-            'other' => array('name' => $definitiontable->get_role_name())
+            'objectid' => $roleid
         )
     );
     $event->set_legacy_logdata(array(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' . $tableroleid,
index bc506f1..ab80e69 100644 (file)
@@ -53,9 +53,19 @@ if (!has_capability('moodle/role:override', $context)) {
     $safeoverridesonly = true;
 }
 $PAGE->set_url($url);
-$PAGE->set_context($context);
 $PAGE->set_pagelayout('admin');
 
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+    navigation_node::override_active_url(new moodle_url('/admin/roles/permissions.php',
+        array('contextid'=>$context->id, 'userid'=>$context->instanceid, 'courseid'=>$course->id)));
+
+} else {
+    $PAGE->set_context($context);
+    navigation_node::override_active_url(new moodle_url('/admin/roles/permissions.php', array('contextid'=>$context->id)));
+}
+
 $courseid = $course->id;
 
 $returnurl = new moodle_url('/admin/roles/permissions.php', array('contextid' => $context->id));
@@ -91,12 +101,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array(), $PAGE->url);
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
@@ -130,8 +139,7 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
         array(
             'context' => $context,
             'objectid' => $roleid,
-            'courseid' => $courseid,
-            'other' => array('name' => $rolename)
+            'courseid' => $courseid
         )
     );
 
index 8af137a..3670a86 100644 (file)
@@ -57,7 +57,14 @@ if ($course) {
 require_login($course, false, $cm);
 require_capability('moodle/role:review', $context);
 $PAGE->set_url($url);
-$PAGE->set_context($context);
+
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+} else {
+    $PAGE->set_context($context);
+}
+
 $courseid = $course->id;
 
 
@@ -88,12 +95,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array(), $PAGE->url);
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index c62c979..99ded8f 100644 (file)
@@ -41,11 +41,17 @@ $systemcontext = context_system::instance();
 $baseurl = new moodle_url('/admin/roles/usersroles.php', array('userid'=>$userid, 'courseid'=>$courseid));
 
 $PAGE->set_url($baseurl);
-$PAGE->set_context($coursecontext);
 $PAGE->set_pagelayout('admin');
 
 // Check login and permissions.
-require_login($course);
+if ($course->id == SITEID) {
+    require_login();
+    $PAGE->set_context($usercontext);
+} else {
+    require_login($course);
+    $PAGE->set_context($coursecontext);
+}
+
 $canview = has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride',
         'moodle/role:override', 'moodle/role:manage'), $usercontext);
 if (!$canview) {
@@ -120,10 +126,10 @@ $title = get_string('xroleassignments', 'core_role', $fullname);
 
 // Course header.
 $PAGE->set_title($title);
-if ($courseid != SITEID) {
+if ($courseid == SITEID) {
     $PAGE->set_heading($fullname);
 } else {
-    $PAGE->set_heading($course->fullname);
+    $PAGE->set_heading($course->fullname.': '.$fullname);
 }
 echo $OUTPUT->header();
 echo $OUTPUT->heading($title, 3);
index c8444c5..3236444 100644 (file)
@@ -14,6 +14,7 @@ $PAGE->set_url('/admin/settings.php', array('section' => $section));
 $PAGE->set_pagetype('admin-setting-' . $section);
 $PAGE->set_pagelayout('admin');
 $PAGE->navigation->clear_cache();
+navigation_node::require_admin_tree();
 
 $adminroot = admin_get_root(); // need all settings
 $settingspage = $adminroot->locate($section, true);
index e52f6ff..d435022 100644 (file)
@@ -69,29 +69,6 @@ if (!during_initial_install()) { //do not use during installation
         }
         $temp->add(new admin_setting_configselect('defaultfrontpageroleid', new lang_string('frontpagedefaultrole', 'admin'), '', $defaultfrontpageroleid, $options));
 
-
         $ADMIN->add('frontpage', $temp);
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpageroles', new lang_string('frontpageroles', 'admin'), "$CFG->wwwroot/$CFG->admin/roles/assign.php?contextid=" . $frontpagecontext->id, 'moodle/role:assign', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagefilters', new lang_string('frontpagefilters', 'admin'), "$CFG->wwwroot/filter/manage.php?contextid=" . $frontpagecontext->id, 'moodle/filter:manage', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagebackup', new lang_string('frontpagebackup', 'admin'), $CFG->wwwroot.'/backup/backup.php?id='.SITEID, 'moodle/backup:backupcourse', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagerestore', new lang_string('frontpagerestore', 'admin'), $CFG->wwwroot.'/backup/restorefile.php?contextid='.$frontpagecontext->id, 'moodle/restore:restorecourse', false, $frontpagecontext));
-
-        $questioncapabilities = array(
-                'moodle/question:add',
-                'moodle/question:editmine',
-                'moodle/question:editall',
-                'moodle/question:viewmine',
-                'moodle/question:viewall',
-                'moodle/question:movemine',
-                'moodle/question:moveall');
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagequestions', new lang_string('frontpagequestions', 'admin'), $CFG->wwwroot.'/question/edit.php?courseid='.SITEID, $questioncapabilities, false, $frontpagecontext));
-
-        if (!empty($SITE->legacyfiles) and $SITE->legacyfiles === 2) {
-            $ADMIN->add('frontpage', new admin_externalpage('sitefiles', new lang_string('sitelegacyfiles'), $CFG->wwwroot . '/files/index.php?id=' . SITEID, 'moodle/course:managefiles', false, $frontpagecontext));
-        }
     }
 }
index 6b4f88f..91afdcf 100644 (file)
@@ -28,7 +28,8 @@
 require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
 require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php');
 
-use Behat\Gherkin\Node\TableNode as TableNode,
+use Behat\Behat\Context\Step\Given as Given,
+    Behat\Gherkin\Node\TableNode as TableNode,
     Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
 
 /**
@@ -110,4 +111,23 @@ class behat_admin extends behat_base {
             $this->getSession()->wait($timeout, $javascript);
         }
     }
+
+    /**
+     * Goes to notification page ensuring site admin navigation is loaded.
+     *
+     * @Given /^I go to notifications page$/
+     * @return Given[]
+     */
+    public function i_go_to_notifications_page() {
+        if ($this->running_javascript()) {
+            return array(
+                new Given('I expand "' . get_string('administrationsite') . '" node'),
+                new Given('I follow "' . get_string('notifications') . '"')
+            );
+        } else {
+            return array(
+                new Given('I follow "' . get_string('administrationsite') . '"')
+            );
+        }
+    }
 }
index f17f092..86231b2 100644 (file)
@@ -15,7 +15,8 @@ Feature: Display extended course names
     And I should not see "C_shortname Course fullname"
 
   Scenario: Courses list with extended course names
-    Given I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][not(contains(., 'Site administration'))][contains(., 'Appearance')]" "xpath_element"
+    Given I go to notifications page
+    And I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][contains(., 'Appearance')]" "xpath_element"
     And I check "Display extended course names"
     When I press "Save changes"
     And I am on homepage
index 364b54e..c5dc276 100644 (file)
@@ -20,6 +20,10 @@ Feature: Page contents assertions
     And I wait "2" seconds
     And I hover ".region-content .generaltable td span" "css_element"
     Then I should see "I'm the description"
+    And "Grouping" "select" in the "region-main" "region" should be visible
+    And "Group" "select" should be visible
+    And "Messaging" "link" in the "Administration" "block" should not be visible
+    And "Change password" "link" should not be visible
     And I should see "Filter groups by"
     And I should not see "Filter groupssss by"
     And I should see "Group members" in the ".region-content table th.c1" "css_element"
index 6aaec2f..71c54fe 100644 (file)
@@ -24,6 +24,7 @@
 require(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/filter_form.php');
+require_once($CFG->libdir.'/adminlib.php');
 
 require_login(SITEID, false);
 require_capability('tool/customlang:edit', context_system::instance());
@@ -32,11 +33,10 @@ $lng                    = required_param('lng', PARAM_LANG);
 $currentpage            = optional_param('p', 0, PARAM_INT);
 $translatorsubmitted    = optional_param('translatorsubmitted', 0, PARAM_BOOL);
 
-$PAGE->set_pagelayout('report'); // Allows for wide page contents.
-$PAGE->set_url('/admin/tool/customlang/edit.php', array('lng' => $lng));
-navigation_node::override_active_url(new moodle_url('/admin/tool/customlang/index.php'));
-$PAGE->set_title(get_string('pluginname', 'tool_customlang'));
-$PAGE->set_heading(get_string('pluginname', 'tool_customlang'));
+admin_externalpage_setup('toolcustomlang', '', null,
+    new moodle_url('/admin/tool/customlang/edit.php', array('lng' => $lng)),
+    array('pagelayout' => 'report')); // Hack: allows for wide page contents.
+
 $PAGE->requires->js_init_call('M.tool_customlang.init_editor', array(), true);
 
 if (empty($lng)) {
index aff45ef..431a911 100644 (file)
@@ -29,7 +29,7 @@ require(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->libdir.'/adminlib.php');
 
-require_login(SITEID, false);
+require_login(null, false);
 require_capability('tool/customlang:view', context_system::instance());
 
 $action  = optional_param('action', '', PARAM_ALPHA);
index 7499500..2e43b4c 100644 (file)
@@ -317,7 +317,7 @@ class tool_generator_testplan_backend extends tool_generator_backend {
 
         // Checks that the selected course has enough users.
         $coursesizes = tool_generator_course_backend::get_users_per_size();
-        if (count($users) < $coursesizes[$size]) {
+        if (count($users) < self::$users[$size]) {
             $errors['size'] = get_string('notenoughusers', 'tool_generator');
         }
 
index 1a1866c..e759c43 100644 (file)
@@ -392,8 +392,10 @@ class tool_installaddon_installer {
      *
      * @param string $source full path to the existing directory
      * @param string $target full path to the new location of the directory
+     * @param int $dirpermissions
+     * @param int $filepermissions
      */
-    public function move_directory($source, $target) {
+    public function move_directory($source, $target, $dirpermissions, $filepermissions) {
 
         if (file_exists($target)) {
             throw new tool_installaddon_installer_exception('err_folder_already_exists', array('path' => $target));
@@ -405,7 +407,16 @@ class tool_installaddon_installer {
             throw new tool_installaddon_installer_exception('err_no_such_folder', array('path' => $source));
         }
 
-        make_writable_directory($target);
+        if (!file_exists($target)) {
+            // Do not use make_writable_directory() here - it is intended for dataroot only.
+            mkdir($target, true);
+            @chmod($target, $dirpermissions);
+        }
+
+        if (!is_writable($target)) {
+            closedir($handle);
+            throw new tool_installaddon_installer_exception('err_folder_not_writable', array('path' => $target));
+        }
 
         while ($filename = readdir($handle)) {
             $sourcepath = $source.'/'.$filename;
@@ -416,10 +427,11 @@ class tool_installaddon_installer {
             }
 
             if (is_dir($sourcepath)) {
-                $this->move_directory($sourcepath, $targetpath);
+                $this->move_directory($sourcepath, $targetpath, $dirpermissions, $filepermissions);
 
             } else {
                 rename($sourcepath, $targetpath);
+                @chmod($targetpath, $filepermissions);
             }
         }
 
index 7dea2cc..b80af83 100644 (file)
@@ -69,6 +69,10 @@ if (file_exists($plugintypepath.'/'.$pluginname)) {
         get_string('invaliddata', 'core_error'));
 }
 
-$installer->move_directory($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname);
+// Copy permissions form the plugin type directory.
+$dirpermissions = fileperms($plugintypepath);
+$filepermissions = ($dirpermissions & 0666); // Strip execute flags.
+
+$installer->move_directory($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname, $dirpermissions, $filepermissions);
 fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid);
 redirect(new moodle_url('/admin'));
index 28e37bd..948294c 100644 (file)
@@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die();
  * @copyright 2013 David Mudrak <david@moodle.com>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class tool_installaddon_installer_test extends advanced_testcase {
+class tool_installaddon_installer_testcase extends advanced_testcase {
 
     public function test_get_addons_repository_url() {
         $installer = testable_tool_installaddon_installer::instance();
@@ -137,7 +137,7 @@ class tool_installaddon_installer_test extends advanced_testcase {
         file_put_contents($contentsdir.'/readme.txt', 'Hello world!');
 
         $installer = tool_installaddon_installer::instance();
-        $installer->move_directory($jobroot.'/contents', $jobroot.'/moved');
+        $installer->move_directory($jobroot.'/contents', $jobroot.'/moved', 0777, 0666);
 
         $this->assertFalse(is_dir($jobroot.'/contents'));
         $this->assertTrue(is_file($jobroot.'/moved/sub/folder/readme.txt'));
index a9f7afa..82f7ccc 100644 (file)
@@ -85,7 +85,7 @@ $today = time();
 $today = make_timestamp(date('Y', $today), date('m', $today), date('d', $today), 0, 0, 0);
 
 // array of all valid fields for validation
-$STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email',
+$STD_FIELDS = array('id', 'username', 'email',
         'city', 'country', 'lang', 'timezone', 'mailformat',
         'maildisplay', 'maildigest', 'htmleditor', 'autosubscribe',
         'institution', 'department', 'idnumber', 'skype',
@@ -97,6 +97,8 @@ $STD_FIELDS = array('id', 'firstname', 'lastname', 'username', 'email',
         'deleted',     // 1 means delete user
         'mnethostid',  // Can not be used for adding, updating or deleting of users - only for enrolments, groups, cohorts and suspending.
     );
+// Include all name fields.
+$STD_FIELDS = array_merge($STD_FIELDS, get_all_user_name_fields());
 
 $PRF_FIELDS = array();
 
index 9dfc288..f922995 100644 (file)
@@ -26,7 +26,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 require_once $CFG->libdir.'/formslib.php';
-
+require_once($CFG->dirroot . '/user/editlib.php');
 
 /**
  * Upload a file CVS file with user information.
@@ -375,24 +375,20 @@ class admin_uploaduser_form2 extends moodleform {
 
         // look for other required data
         if ($optype != UU_USER_UPDATE) {
-            if (!in_array('firstname', $columns)) {
-                $errors['uutype'] = get_string('missingfield', 'error', 'firstname');
-            }
-
-            if (!in_array('lastname', $columns)) {
-                if (isset($errors['uutype'])) {
-                    $errors['uutype'] = '';
-                } else {
-                    $errors['uutype'] = ' ';
+            $requiredusernames = useredit_get_required_name_fields();
+            $missing = array();
+            foreach ($requiredusernames as $requiredusername) {
+                if (!in_array($requiredusername, $columns)) {
+                    $missing[] = get_string('missingfield', 'error', $requiredusername);;
                 }
-                $errors['uutype'] .= get_string('missingfield', 'error', 'lastname');
             }
-
+            if ($missing) {
+                $errors['uutype'] = implode('<br />',  $missing);
+            }
             if (!in_array('email', $columns) and empty($data['email'])) {
                 $errors['email'] = get_string('requiredtemplate', 'tool_uploaduser');
             }
         }
-
         return $errors;
     }
 
index 7439b27..46862a7 100644 (file)
@@ -39,6 +39,7 @@ class create_and_clean_temp_stuff extends backup_execution_step {
         backup_helper::check_and_create_backup_dir($this->get_backupid());// Create backup temp dir
         backup_helper::clear_backup_dir($this->get_backupid(), $progress);           // Empty temp dir, just in case
         backup_helper::delete_old_backup_dirs(time() - (4 * 60 * 60), $progress);    // Delete > 4 hours temp dirs
+        backup_controller_dbops::drop_backup_ids_temp_table($this->get_backupid()); // Drop ids temp table
         backup_controller_dbops::create_backup_ids_temp_table($this->get_backupid()); // Create ids temp table
         $progress->end_progress();
     }
index 7550261..b46ed6b 100644 (file)
@@ -161,6 +161,9 @@ class restore_section_task extends restore_task {
         $section_included = new restore_section_included_setting($settingname, base_setting::IS_BOOLEAN, true);
         if (is_number($this->info->title)) {
             $label = get_string('includesection', 'backup', $this->info->title);
+        } elseif (empty($this->info->title)) { // Don't throw error if title is empty, gracefully continue restore.
+            $this->log('Section title missing in backup for section id '.$this->info->sectionid, backup::LOG_WARNING, $this->name);
+            $label = get_string('unnamedsection', 'backup');
         } else {
             $label = $this->info->title;
         }
index cb4577c..6d066b4 100644 (file)
@@ -160,8 +160,10 @@ abstract class backup_controller_dbops extends backup_dbops {
         $dbman = $DB->get_manager(); // We are going to use database_manager services
 
         $targettablename = 'backup_ids_temp';
-        $table = new xmldb_table($targettablename);
-        $dbman->drop_table($table); // And drop it
+        if ($dbman->table_exists($targettablename)) {
+            $table = new xmldb_table($targettablename);
+            $dbman->drop_table($table); // And drop it
+        }
     }
 
     /**
index a1aafb8..a6d5bce 100644 (file)
@@ -978,6 +978,15 @@ abstract class restore_dbops {
             );
 
             if (empty($file->repositoryid)) {
+                // If contenthash is empty then gracefully skip adding file.
+                if (empty($file->contenthash)) {
+                    $result = new stdClass();
+                    $result->code = 'file_missing_in_backup';
+                    $result->message = sprintf('missing file (%s) contenthash in backup for component %s', $file->filename, $component);
+                    $result->level = backup::LOG_WARNING;
+                    $results[] = $result;
+                    continue;
+                }
                 // this is a regular file, it must be present in the backup pool
                 $backuppath = $basepath . backup_file_manager::get_backup_content_file_location($file->contenthash);
 
index 66c2b3b..929d9a0 100644 (file)
@@ -44,12 +44,15 @@ $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type));
 if ($badge->type == BADGE_TYPE_COURSE) {
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $PAGE->set_context($context);
 $PAGE->set_url('/badges/action.php', array('id' => $badge->id));
-$PAGE->set_pagelayout('standard');
-navigation_node::override_active_url($navurl);
 
 if ($return !== 0) {
     $returnurl = new moodle_url($return);
index 834af0c..9c3db8c 100644 (file)
@@ -50,6 +50,11 @@ if ($badge->type == BADGE_TYPE_COURSE) {
     }
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 require_capability('moodle/badges:awardbadge', $context);
@@ -60,11 +65,9 @@ $PAGE->set_context($context);
 
 // Set up navigation and breadcrumbs.
 $strrecipients = get_string('recipients', 'badges');
-navigation_node::override_active_url($navurl);
 $PAGE->navbar->add($badge->name, new moodle_url('overview.php', array('id' => $badge->id)))->add($strrecipients);
 $PAGE->set_title($strrecipients);
 $PAGE->set_heading($badge->name);
-$PAGE->set_pagelayout('standard');
 
 if (!$badge->is_active()) {
     echo $OUTPUT->header();
index 20848d2..ad4b5a6 100644 (file)
@@ -48,18 +48,19 @@ if ($badge->type == BADGE_TYPE_COURSE) {
     }
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $currenturl = new moodle_url('/badges/criteria.php', array('id' => $badge->id));
 
 $PAGE->set_context($context);
 $PAGE->set_url($currenturl);
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
-
-// Set up navigation and breadcrumbs.
-navigation_node::override_active_url($navurl);
 $PAGE->navbar->add($badge->name);
 
 $output = $PAGE->get_renderer('core', 'badges');
index 51b3e89..3af6984 100644 (file)
@@ -48,14 +48,17 @@ if ($badge->is_active() || $badge->is_locked()) {
 if ($badge->type == BADGE_TYPE_COURSE) {
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $PAGE->set_context($context);
 $PAGE->set_url('/badges/criteria_action.php');
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
-navigation_node::override_active_url($navurl);
 
 if ($delete && has_capability('moodle/badges:configurecriteria', $context)) {
     if (!$confirm) {
index 6f52fa0..32efa61 100644 (file)
@@ -58,14 +58,17 @@ if ($badge->is_active() || $badge->is_locked()) {
 if ($badge->type == BADGE_TYPE_COURSE) {
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $PAGE->set_context($context);
 $PAGE->set_url('/badges/criteria_settings.php');
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
-navigation_node::override_active_url($navurl);
 $PAGE->navbar->add($badge->name, new moodle_url('overview.php', array('id' => $badge->id)))->add(get_string('criteria_' . $type, 'badges'));
 
 $cparams = array('criteriatype' => $type, 'badgeid' => $badge->id);
index b0a4783..61e9cc6 100644 (file)
@@ -53,18 +53,19 @@ if ($badge->type == BADGE_TYPE_COURSE) {
     }
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $currenturl = new moodle_url('/badges/edit.php', array('id' => $badge->id, 'action' => $action));
 
 $PAGE->set_context($context);
 $PAGE->set_url($currenturl);
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
-
-// Set up navigation and breadcrumbs.
-navigation_node::override_active_url($navurl);
 $PAGE->navbar->add($badge->name);
 
 $output = $PAGE->get_renderer('core', 'badges');
index d476cfc..6c73990 100644 (file)
@@ -79,7 +79,7 @@ if ($type == BADGE_TYPE_SITE) {
     $PAGE->set_context(context_system::instance());
     $PAGE->set_pagelayout('admin');
     $PAGE->set_heading($title . ': ' . $hdr);
-    navigation_node::override_active_url(new moodle_url('/badges/index.php', array('type' => BADGE_TYPE_SITE)));
+    navigation_node::override_active_url(new moodle_url('/badges/index.php', array('type' => BADGE_TYPE_SITE)), true);
 } else {
     require_login($course);
     $coursecontext = context_course::instance($course->id);
index e2dec7f..7801674 100644 (file)
@@ -46,18 +46,19 @@ if ($badge->type == BADGE_TYPE_COURSE) {
     }
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $currenturl = new moodle_url('/badges/overview.php', array('id' => $badge->id));
 
 $PAGE->set_context($context);
 $PAGE->set_url($currenturl);
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
-
-// Set up navigation and breadcrumbs.
-navigation_node::override_active_url($navurl);
 $PAGE->navbar->add($badge->name);
 
 echo $OUTPUT->header();
index d05a562..4e77e3d 100644 (file)
@@ -60,15 +60,18 @@ if ($badge->type == BADGE_TYPE_COURSE) {
     }
     require_login($badge->courseid);
     $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+    $PAGE->set_pagelayout('standard');
+    navigation_node::override_active_url($navurl);
+} else {
+    $PAGE->set_pagelayout('admin');
+    navigation_node::override_active_url($navurl, true);
 }
 
 $PAGE->set_context($context);
 $PAGE->set_url('/badges/recipients.php', array('id' => $badgeid, 'sort' => $sortby, 'dir' => $sorthow));
-$PAGE->set_pagelayout('standard');
 $PAGE->set_heading($badge->name);
 $PAGE->set_title($badge->name);
 $PAGE->navbar->add($badge->name);
-navigation_node::override_active_url($navurl);
 
 $output = $PAGE->get_renderer('core', 'badges');
 
index a7224e5..b87920c 100644 (file)
@@ -130,7 +130,7 @@ $communityid = optional_param('communityid', '', PARAM_INT);
 if ($remove != -1 and !empty($communityid) and confirm_sesskey()) {
     $communitymanager->block_community_remove_course($communityid, $USER->id);
     echo $OUTPUT->header();
-    echo $renderer->remove_success(new moodle_url(get_referer(false)));
+    echo $renderer->remove_success(new moodle_url('/course/view.php', array('id' => $courseid)));
     echo $OUTPUT->footer();
     die();
 }
index b2ec8ab..bbfc989 100644 (file)
@@ -38,6 +38,7 @@ class block_community_manager {
         $community = $this->block_community_get_course($course->url, $userid);
 
         if (empty($community)) {
+            $community = new stdClass();
             $community->userid = $userid;
             $community->coursename = $course->name;
             $community->coursedescription = $course->description;
index 5c9aa7d..d0542ac 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js differ
index 190c180..ce342d8 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js differ
index bed94d7..55e4047 100644 (file)
Binary files a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js and b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js differ
index c7ed370..97e8bdc 100644 (file)
@@ -180,6 +180,8 @@ var NODETYPE = {
     CUSTOM : 60,
     // @type int Setting = 70
     SETTING : 70,
+    // @type int site administration = 71
+    SITEADMIN : 71,
     // @type int User context = 80
     USER : 80,
     // @type int Container = 90
@@ -257,6 +259,26 @@ TREE.prototype = {
             M.block_navigation.expandablebranchcount++;
             this.branches[branch.get('id')] = branch;
         }
+        // Create siteadmin branch.
+        if (window.siteadminexpansion) {
+            var siteadminbranch = new BRANCH({
+                tree: this,
+                branchobj: window.siteadminexpansion,
+                overrides : {
+                    expandable : true,
+                    children : [],
+                    haschildren : true
+                }
+            }).wire();
+            M.block_navigation.expandablebranchcount++;
+            this.branches[siteadminbranch.get('id')] = siteadminbranch;
+            // Remove link on site admin with JS to keep old UI.
+            var siteadminlinknode = siteadminbranch.node.get('childNodes').item(0);
+            if (siteadminlinknode) {
+                var siteadminnode = Y.Node.create('<span tabindex="0">'+siteadminlinknode.get('innerHTML')+'</span>');
+                siteadminbranch.node.replaceChild(siteadminnode, siteadminlinknode);
+            }
+        }
         if (M.block_navigation.expandablebranchcount > 0) {
             // Delegate some events to handle AJAX loading.
             Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this);
@@ -586,7 +608,13 @@ BRANCH.prototype = {
             instance : this.get('tree').get('instance')
         };
 
-        Y.io(M.cfg.wwwroot+'/lib/ajax/getnavbranch.php', {
+        var ajaxfile = '/lib/ajax/getnavbranch.php';
+        // For siteadmin navigation get tree from getsiteadminbranch.php.
+        if (this.get('type') === NODETYPE.SITEADMIN) {
+            ajaxfile = '/lib/ajax/getsiteadminbranch.php';
+        }
+
+        Y.io(M.cfg.wwwroot + ajaxfile, {
             method:'POST',
             data:  build_querystring(params),
             on: {
index 2c6e451..eb8b42a 100644 (file)
@@ -31,6 +31,7 @@
 .dir-rtl .block_settings .block_tree .tree_item.branch {background-position: center right;}
 .dir-rtl .block_settings .block_tree .root_node.leaf {padding-right:0px;}
 .dir-rtl .block_settings .block_tree li.item_with_icon > p img { right: 0; left: auto;}
+.jsenabled .block_settings .block_tree .tree_item.branch.loadingbranch {background-image:url([[pix:i/loading_small]]);}
 
 .jsenabled.dir-rtl .block_settings .block_tree .tree_item.emptybranch {background-image: url([[pix:t/collapsed_empty_rtl]]);background-position: center right;}
 .jsenabled.dir-rtl .block_settings .block_tree .collapsed .tree_item.branch {background-image: url([[pix:t/collapsed_rtl]]);}
index a1a4704..a4e4210 100644 (file)
@@ -265,8 +265,7 @@ class blog_entry implements renderable {
         // Trigger an event for the new entry.
         $event = \core\event\blog_entry_created::create(array(
             'objectid'      => $this->id,
-            'relateduserid' => $this->userid,
-            'other'         => array('subject' => $this->subject)
+            'relateduserid' => $this->userid
         ));
         $event->set_custom_data($this);
         $event->trigger();
@@ -308,8 +307,7 @@ class blog_entry implements renderable {
 
         $event = \core\event\blog_entry_updated::create(array(
             'objectid'      => $entry->id,
-            'relateduserid' => $entry->userid,
-            'other'         => array('subject' => $entry->subject)
+            'relateduserid' => $entry->userid
         ));
         $event->set_custom_data($entry);
         $event->trigger();
@@ -333,9 +331,8 @@ class blog_entry implements renderable {
 
         $event = \core\event\blog_entry_deleted::create(array(
             'objectid'      => $this->id,
-            'relateduserid' => $this->userid,
-            'other'         => array('record' => (array) $record)
-        ));
+            'relateduserid' => $this->userid
+            ));
         $event->add_record_snapshot("post", $record);
         $event->set_custom_data($this);
         $event->trigger();
index b470ffc..7367119 100644 (file)
@@ -59,19 +59,40 @@ abstract class type_base {
     public abstract function get_months();
 
     /**
-     * Returns the minimum year of the calendar.
+     * Returns the minimum year for the calendar.
      *
-     * @return int the minumum year
+     * @return int The minimum year
      */
     public abstract function get_min_year();
 
     /**
-     * Returns the maximum year of the calendar.
+     * Returns the maximum year for the calendar
      *
-     * @return int the max year
+     * @return int The maximum year
      */
     public abstract function get_max_year();
 
+    /**
+     * Returns an array of years.
+     *
+     * @param int $minyear
+     * @param int $maxyear
+     * @return array the years
+     */
+    public abstract function get_years($minyear = null, $maxyear = null);
+
+    /**
+     * Returns a multidimensional array with information for day, month, year
+     * and the order they are displayed when selecting a date.
+     * The order in the array will be the order displayed when selecting a date.
+     * Override this function to change the date selector order.
+     *
+     * @param int $minyear The year to start with
+     * @param int $maxyear The year to finish with
+     * @return array Full date information
+     */
+    public abstract function get_date_order($minyear = null, $maxyear = null);
+
     /**
      * Returns the number of days in a week.
      *
index 862cdc7..e596edf 100644 (file)
@@ -76,23 +76,66 @@ class structure extends type_base {
     }
 
     /**
-     * Returns the minimum year of the calendar.
+     * Returns the minimum year for the calendar.
      *
-     * @return int the minumum year
+     * @return int The minimum year
      */
     public function get_min_year() {
-        return 1970;
+        return 1900;
     }
 
     /**
-     * Returns the maximum year of the calendar.
+     * Returns the maximum year for the calendar
      *
-     * @return int the max year
+     * @return int The maximum year
      */
     public function get_max_year() {
         return 2050;
     }
 
+    /**
+     * Returns an array of years.
+     *
+     * @param int $minyear
+     * @param int $maxyear
+     * @return array the years.
+     */
+    public function get_years($minyear = null, $maxyear = null) {
+        if (is_null($minyear)) {
+            $minyear = $this->get_min_year();
+        }
+
+        if (is_null($maxyear)) {
+            $maxyear = $this->get_max_year();
+        }
+
+        $years = array();
+        for ($i = $minyear; $i <= $maxyear; $i++) {
+            $years[$i] = $i;
+        }
+
+        return $years;
+    }
+
+    /**
+     * Returns a multidimensional array with information for day, month, year
+     * and the order they are displayed when selecting a date.
+     * The order in the array will be the order displayed when selecting a date.
+     * Override this function to change the date selector order.
+     *
+     * @param int $minyear The year to start with.
+     * @param int $maxyear The year to finish with.
+     * @return array Full date information.
+     */
+    public function get_date_order($minyear = null, $maxyear = null) {
+        $dateinfo = array();
+        $dateinfo['day'] = $this->get_days();
+        $dateinfo['month'] = $this->get_months();
+        $dateinfo['year'] = $this->get_years($minyear, $maxyear);
+
+        return $dateinfo;
+    }
+
     /**
      * Returns the number of days in a week.
      *
index cf50cfc..0c9ee7d 100644 (file)
@@ -76,23 +76,66 @@ class structure extends type_base {
     }
 
     /**
-     * Returns the minimum year of the calendar.
+     * Returns the minimum year for the calendar.
      *
-     * @return int the minumum year
+     * @return int The minimum year
      */
     public function get_min_year() {
         return 1900;
     }
 
     /**
-     * Returns the maximum year of the calendar.
+     * Returns the maximum year for the calendar
      *
-     * @return int the max year
+     * @return int The maximum year
      */
     public function get_max_year() {
         return 2050;
     }
 
+    /**
+     * Returns an array of years.
+     *
+     * @param int $minyear
+     * @param int $maxyear
+     * @return array the years
+     */
+    public function get_years($minyear = null, $maxyear = null) {
+        if (is_null($minyear)) {
+            $minyear = $this->get_min_year();
+        }
+
+        if (is_null($maxyear)) {
+            $maxyear = $this->get_max_year();
+        }
+
+        $years = array();
+        for ($i = $minyear; $i <= $maxyear; $i++) {
+            $years[$i] = $i;
+        }
+
+        return $years;
+    }
+
+    /**
+     * Returns a multidimensional array with information for day, month, year
+     * and the order they are displayed when selecting a date.
+     * The order in the array will be the order displayed when selecting a date.
+     * Override this function to change the date selector order.
+     *
+     * @param int $minyear The year to start with
+     * @param int $maxyear The year to finish with
+     * @return array Full date information
+     */
+    public function get_date_order($minyear = null, $maxyear = null) {
+        $dateinfo = array();
+        $dateinfo['day'] = $this->get_days();
+        $dateinfo['month'] = $this->get_months();
+        $dateinfo['year'] = $this->get_years($minyear, $maxyear);
+
+        return $dateinfo;
+    }
+
     /**
      * Returns the number of days in a week.
      *
index 2da394d..c50e3a0 100644 (file)
@@ -36,6 +36,7 @@ require_capability('moodle/cohort:assign', $context);
 
 $PAGE->set_context($context);
 $PAGE->set_url('/cohort/assign.php', array('id'=>$id));
+$PAGE->set_pagelayout('admin');
 
 $returnurl = new moodle_url('/cohort/index.php', array('contextid'=>$cohort->contextid));
 
@@ -51,11 +52,8 @@ if (optional_param('cancel', false, PARAM_BOOL)) {
 if ($context->contextlevel == CONTEXT_COURSECAT) {
     $category = $DB->get_record('course_categories', array('id'=>$context->instanceid), '*', MUST_EXIST);
     navigation_node::override_active_url(new moodle_url('/cohort/index.php', array('contextid'=>$cohort->contextid)));
-    $PAGE->set_pagelayout('report');
-
 } else {
     navigation_node::override_active_url(new moodle_url('/cohort/index.php', array()));
-    $PAGE->set_pagelayout('admin');
 }
 $PAGE->navbar->add(get_string('assign', 'cohort'));
 
index 3a18ddb..a585f35 100644 (file)
@@ -62,15 +62,14 @@ if (!empty($cohort->component)) {
 $PAGE->set_context($context);
 $PAGE->set_url('/cohort/edit.php', array('contextid'=>$context->id, 'id'=>$cohort->id));
 $PAGE->set_context($context);
+$PAGE->set_pagelayout('admin');
 
 if ($context->contextlevel == CONTEXT_COURSECAT) {
     $category = $DB->get_record('course_categories', array('id'=>$context->instanceid), '*', MUST_EXIST);
     navigation_node::override_active_url(new moodle_url('/cohort/index.php', array('contextid'=>$cohort->contextid)));
-    $PAGE->set_pagelayout('report');
 
 } else {
     navigation_node::override_active_url(new moodle_url('/cohort/index.php', array()));
-    $PAGE->set_pagelayout('admin');
 }
 
 if ($delete and $cohort->id) {
index 3c31556..b0c30bd 100644 (file)
@@ -56,7 +56,7 @@ if (!$manager) {
 $strcohorts = get_string('cohorts', 'cohort');
 
 if ($category) {
-    $PAGE->set_pagelayout('report');
+    $PAGE->set_pagelayout('admin');
     $PAGE->set_context($context);
     $PAGE->set_url('/cohort/index.php', array('contextid'=>$context->id));
     $PAGE->set_title($strcohorts);
diff --git a/completion/tests/behat/restrict_activity_by_date.feature b/completion/tests/behat/restrict_activity_by_date.feature
new file mode 100644 (file)
index 0000000..fe1a0f2
--- /dev/null
@@ -0,0 +1,68 @@
+@core @core_completion
+Feature: Restrict activity availability through date conditions
+  In order to control activity access through date condition
+  As a teacher
+  I need to set allow access dates to restrict activity access
+
+  Background:
+    Given the following "courses" exists:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | Frist | teacher1@asd.com |
+      | student1 | Student | First | student1@asd.com |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+    And I log in as "admin"
+    And I set the following administration settings values:
+      | Enable conditional access | 1 |
+    And I log out
+
+  @javascript
+  Scenario: Show activity greyed-out to students when available from date is in future
+    Given I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1"
+    And I fill the moodle form with:
+      | Assignment name | Test assignment 1 |
+      | Description | This assignment is restricted by date |
+      | assignsubmission_onlinetext_enabled | 1 |
+      | assignsubmission_file_enabled | 0 |
+      | id_availablefrom_day | 31 |
+      | id_availablefrom_month | 12 |
+      | id_availablefrom_year | 2050 |
+      | id_showavailability | 1 |
+    And I click on "id_availablefrom_enabled" "checkbox"
+    And I press "Save and return to course"
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    Then I should see "Available from 31 December 2050."
+    And "Test assignment 1" activity should be hidden
+    And I log out
+
+  @javascript
+  Scenario: Show activity hidden to students when available until date is in past
+    Given I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "2"
+    And I fill the moodle form with:
+      | Assignment name | Test assignment 2 |
+      | Description | This assignment is restricted by date |
+      | assignsubmission_onlinetext_enabled | 1 |
+      | assignsubmission_file_enabled | 0 |
+      | id_availableuntil_day | 1 |
+      | id_availableuntil_month | 2 |
+      | id_availableuntil_year | 2013 |
+      | id_showavailability | 0 |
+    And I click on "id_availableuntil_enabled" "checkbox"
+    And I press "Save and return to course"
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    Then I should not see "Test assignment 2"
diff --git a/completion/tests/behat/restrict_activity_by_grade.feature b/completion/tests/behat/restrict_activity_by_grade.feature
new file mode 100644 (file)
index 0000000..e3de103
--- /dev/null
@@ -0,0 +1,63 @@
+@core @core_completion
+Feature: Restrict activity availability through grade conditions
+  In order to control activity access through grade condition
+  As a teacher
+  I need to set grade condition to restrict activity access
+
+  @javascript
+  Scenario: Show activity greyed-out to students when grade condition is not satisfied
+    Given the following "courses" exists:
+      | fullname | shortname | category |
+      | Course 1 | C1 | 0 |
+    And the following "users" exists:
+      | username | firstname | lastname | email |
+      | teacher1 | Teacher | Frist | teacher1@asd.com |
+      | student1 | Student | First | student1@asd.com |
+    And the following "course enrolments" exists:
+      | user | course | role |
+      | teacher1 | C1 | editingteacher |
+      | student1 | C1 | student |
+    And I log in as "admin"
+    And I set the following administration settings values:
+      | Enable conditional access | 1 |
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Grade assignment |
+      | Description | Grade this assignment to revoke restriction on restricted assignment |
+      | assignsubmission_onlinetext_enabled | 1 |
+      | assignsubmission_file_enabled | 0 |
+    And I add a "Page" to section "2" and I fill the form with:
+      | Name | Test page name |
+      | Description | Restricted page, till grades in Grade assignment is at least 20% |
+      | Page content | Test page contents |
+      | id_conditiongradegroup_0_conditiongradeitemid | 2 |
+      | id_conditiongradegroup_0_conditiongrademin | 20 |
+      | id_showavailability | 1 |
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    Then I should see "Not available until you achieve a required score in Grade assignment"
+    And "Test page name" activity should be hidden
+    And I follow "Grade assignment"
+    And I press "Add submission"
+    And I fill the moodle form with:
+      | Online text | I'm the student submission |
+    And I press "Save changes"
+    And I should see "Submitted for grading"
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Grade assignment"
+    And I follow "View/grade all submissions"
+    And I click on "Grade Student First" "link" in the "Student First" "table_row"
+    And I fill the moodle form with:
+      | Grade | 21 |
+    And I press "Save changes"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And "Test page name" activity should be visible
+    And I should not see "Not available until you achieve a required score in Grade assignment"
index 35b7f09..03505dc 100644 (file)
@@ -1,11 +1,10 @@
 @core @core_completion
-Feature: Restrict sections availability through completion conditions
-  In order to control section's contents access through activities completion
+Feature: Restrict sections availability through completion or grade conditions
+  In order to control section's contents access through activities completion or grade condition
   As a teacher
   I need to restrict sections availability using different conditions
 
-  @javascript
-  Scenario: Show section greyed-out to students when completion conditions are not satisfied
+  Background:
     Given the following "courses" exists:
       | fullname | shortname | category |
       | Course 1 | C1 | 0 |
@@ -22,7 +21,10 @@ Feature: Restrict sections availability through completion conditions
       | Enable completion tracking | 1 |
       | Enable conditional access | 1 |
     And I log out
-    And I log in as "teacher1"
+
+  @javascript
+  Scenario: Show section greyed-out to student when completion condition is not satisfied
+    Given I log in as "teacher1"
     And I follow "Course 1"
     And I turn editing mode on
     And I follow "Edit settings"
@@ -36,12 +38,10 @@ Feature: Restrict sections availability through completion conditions
       | Name | Test page name |
       | Description | Test page description |
       | Page content | Test page contents |
-    When I click on "Edit summary" "link" in the "#section-2" "css_element"
-    And I fill the moodle form with:
+    When I edit the section "2" and I fill the form with:
       | id_conditioncompletiongroup_0_conditionsourcecmid | Test label |
       | id_conditioncompletiongroup_0_conditionrequiredcompletion | must be marked complete |
       | Before section can be accessed | Show section greyed-out, with restriction information |
-    And I press "Save changes"
     And I log out
     And I log in as "student1"
     And I follow "Course 1"
@@ -50,3 +50,47 @@ Feature: Restrict sections availability through completion conditions
     And I press "Not completed: Test label. Select to mark as complete."
     And I should see "Test page name"
     And I should not see "Not available until the activity Test label is marked complete."
+
+  @javascript
+  Scenario: Show section greyed-out to student when grade condition is not satisfied
+    Given I log in as "teacher1"
+    And I follow "Course 1"
+    And I turn editing mode on
+    And I add a "Assignment" to section "1" and I fill the form with:
+      | Assignment name | Grade assignment |
+      | Description | Grade this assignment to revoke restriction on restricted assignment |
+      | assignsubmission_onlinetext_enabled | 1 |
+      | assignsubmission_file_enabled | 0 |
+    And I add a "Page" to section "2" and I fill the form with:
+      | Name | Test page name |
+      | Description | Restricted section page resource, till grades in Grade assignment is at least 20% |
+      | Page content | Test page contents |
+    And I edit the section "2" and I fill the form with:
+      | id_conditiongradegroup_0_conditiongradeitemid | 2 |
+      | id_conditiongradegroup_0_conditiongrademin | 20 |
+      | Before section can be accessed | 1 |
+    And I log out
+    When I log in as "student1"
+    And I follow "Course 1"
+    Then I should see "Not available until you achieve a required score in Grade assignment"
+    And "Test page name" activity should be hidden
+    And I follow "Grade assignment"
+    And I press "Add submission"
+    And I fill the moodle form with:
+      | Online text | I'm the student submission |
+    And I press "Save changes"
+    And I should see "Submitted for grading"
+    And I log out
+    And I log in as "teacher1"
+    And I follow "Course 1"
+    And I follow "Grade assignment"
+    And I follow "View/grade all submissions"
+    And I click on "Grade Student First" "link" in the "Student First" "table_row"
+    And I fill the moodle form with:
+      | Grade | 21 |
+    And I press "Save changes"
+    And I log out
+    And I log in as "student1"
+    And I follow "Course 1"
+    And "Test page name" activity should be visible
+    And I should not see "Not available until you achieve a required score in Grade assignment"
\ No newline at end of file
index c5bf4be..3050973 100644 (file)
@@ -237,6 +237,8 @@ $CFG->admin = 'admin';
 //      $CFG->session_handler_class = '\core\session\memcached';
 //      $CFG->session_memcached_save_path = '127.0.0.1:11211';
 //      $CFG->session_memcached_prefix = 'memc.sess.key.';
+//      $CFG->session_memcached_acquire_lock_timeout = 120;
+//      $CFG->session_memcached_lock_expire = 7200;       // Ignored if memcached extension <= 2.1.0
 //
 // Following setting allows you to alter how frequently is timemodified updated in sessions table.
 //      $CFG->session_update_timemodified_frequency = 20; // In seconds.
index 8979c8c..ce02da9 100644 (file)
@@ -208,6 +208,20 @@ class helper {
             );
         }
 
+        // Resort.
+        if ($category->can_resort_subcategories() && $category->has_children()) {
+            $actions['resortbyname'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'name')),
+                'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
+                'string' => new \lang_string('resortsubcategoriesbyname', 'moodle')
+            );
+            $actions['resortbyidnumber'] = array(
+                'url' => new \moodle_url($baseurl, array('action' => 'resortcategories', 'resort' => 'idnumber')),
+                'icon' => new \pix_icon('t/sort', new \lang_string('sort')),
+                'string' => new \lang_string('resortsubcategoriesbyidnumber', 'moodle')
+            );
+        }
+
         // Delete.
         if ($category->can_delete_full()) {
             $actions['delete'] = array(
index 943727a..fa26e1b 100644 (file)
@@ -264,7 +264,7 @@ class core_course_management_renderer extends plugin_renderer_base {
         }
 
         $hasitems = false;
-        if ($createtoplevel || $createsubcategory) {
+        if ($createtoplevel) {
             $hasitems = true;
             $menu = new action_menu;
             if ($createtoplevel) {
@@ -294,29 +294,28 @@ class core_course_management_renderer extends plugin_renderer_base {
         if (coursecat::can_approve_course_requests()) {
             $actions[] = html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
         }
-        if ($category->can_resort_subcategories()) {
+        if (coursecat::get(0)->can_resort_subcategories()) {
             $hasitems = true;
-            $params = $this->page->url->params();
+            $params = array();
             $params['action'] = 'resortcategories';
             $params['sesskey'] = sesskey();
+            if ($this->page->url->get_param('categoryid') !== null) {
+                $params['selectedcategoryid'] = $this->page->url->get_param('categoryid');
+            }
             $baseurl = new moodle_url('/course/management.php', $params);
             $menu = new action_menu(array(
                 new action_menu_link_secondary(
                     new moodle_url($baseurl, array('resort' => 'name')),
                     null,
-                    get_string('resortbyname')
+                    get_string('resortcategoriesbyname')
                 ),
                 new action_menu_link_secondary(
                     new moodle_url($baseurl, array('resort' => 'idnumber')),
                     null,
-                    get_string('resortbyidnumber')
+                    get_string('resortcategoriesbyidnumber')
                 )
             ));
-            if ($category->id === 0) {
-                $menu->actiontext = get_string('resortcategories');
-            } else {
-                $menu->actiontext = get_string('resortsubcategories');
-            }
+            $menu->actiontext = get_string('resortcategories');
             $menu->actionicon = new pix_icon('t/contextmenu', ' ', 'moodle', array('class' => 'iconsmall', 'title' => ''));
             $actions[] = $this->render($menu);
         }
@@ -385,7 +384,11 @@ class core_course_management_renderer extends plugin_renderer_base {
             );
         }
         if (coursecat::can_change_parent_any()) {
-            $options = coursecat::make_categories_list('moodle/category:manage');
+            $options = array();
+            if (has_capability('moodle/category:manage', context_system::instance())) {
+                $options[0] = coursecat::get(0)->get_formatted_name();
+            }
+            $options += coursecat::make_categories_list('moodle/category:manage');
             $select = html_writer::select(
                 $options,
                 'movecategoriesto',
index 2f720f5..31d4817 100644 (file)
@@ -28,24 +28,26 @@ require_once($CFG->dirroot . '/course/lib.php');
 $id = required_param('id', PARAM_INT); // Course ID.
 $delete = optional_param('delete', '', PARAM_ALPHANUM); // Confirmation hash.
 
-$PAGE->set_url('/course/delete.php', array('id' => $id));
-$PAGE->set_context(context_system::instance());
-require_login();
-
 $course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
 $coursecontext = context_course::instance($course->id);
 
-if ((int)$SITE->id === (int)$course->id || !can_delete_course($id)) {
+require_login();
+
+if ($SITE->id == $course->id || !can_delete_course($id)) {
     // Can not delete frontpage or don't have permission to delete the course.
     print_error('cannotdeletecourse');
 }
 
+$categorycontext = context_coursecat::instance($course->category);
+$PAGE->set_url('/course/delete.php', array('id' => $id));
+$PAGE->set_context($categorycontext);
+$PAGE->set_pagelayout('admin');
+navigation_node::override_active_url(new moodle_url('/course/management.php', array('categoryid'=>$course->category)));
+
 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext));
 $coursefullname = format_string($course->fullname, true, array('context' => $coursecontext));
 $categoryurl = new moodle_url('/course/management.php', array('categoryid' => $course->category));
 
-navigation_node::override_active_url(new moodle_url('/course/management.php'));
-
 // Check if we've got confirmation.
 if ($delete === md5($course->timemodified)) {
     // We do - time to delete the course.
index 8126449..3fa6bb2 100644 (file)
@@ -599,6 +599,8 @@ class dndupload_ajax_processor {
      * Create the coursemodule to hold the file/content that has been uploaded
      */
     protected function create_course_module() {
+        global $CFG;
+
         if (!course_allowed_module($this->course, $this->module->name)) {
             throw new coding_exception("The module {$this->module->name} is not allowed to be added to this course");
         }
@@ -616,7 +618,7 @@ class dndupload_ajax_processor {
         // Set the correct default for completion tracking.
         $this->cm->completion = COMPLETION_TRACKING_NONE;
         $completion = new completion_info($this->course);
-        if ($completion->is_enabled()) {
+        if ($completion->is_enabled() && $CFG->completiondefault) {
             if (plugin_supports('mod', $this->cm->modulename, FEATURE_MODEDIT_DEFAULT_COMPLETION, true)) {
                 $this->cm->completion = COMPLETION_TRACKING_MANUAL;
             }
@@ -625,15 +627,7 @@ class dndupload_ajax_processor {
         if (!$this->cm->id = add_course_module($this->cm)) {
             throw new coding_exception("Unable to create the course module");
         }
-        // The following are used inside some few core functions, so may as well set them here.
         $this->cm->coursemodule = $this->cm->id;
-        $groupbuttons = ($this->course->groupmode or (!$this->course->groupmodeforce));
-        if ($groupbuttons and plugin_supports('mod', $this->module->name, FEATURE_GROUPS, 0)) {
-            $this->cm->groupmodelink = (!$this->course->groupmodeforce);
-        } else {
-            $this->cm->groupmodelink = false;
-            $this->cm->groupmode = false;
-        }
     }
 
     /**
@@ -700,8 +694,6 @@ class dndupload_ajax_processor {
             throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name);
         }
         $mod = $info->get_cm($this->cm->id);
-        $mod->groupmodelink = $this->cm->groupmodelink;
-        $mod->groupmode = $this->cm->groupmode;
 
         // Trigger course module created event.
         $event = \core\event\course_module_created::create(array(
index f2793a2..b457920 100644 (file)
@@ -45,6 +45,7 @@ if ($id) {
     $itemid = 0; // Initialise itemid, as all files in category description has item id 0.
     $title = $strtitle;
     $fullname = $coursecat->get_formatted_name();
+
 } else {
     $parent = required_param('parent', PARAM_INT);
     $url->param('parent', $parent);
@@ -54,6 +55,7 @@ if ($id) {
     } else {
         $context = context_system::instance();
     }
+    navigation_node::override_active_url(new moodle_url('/course/editcategory.php', array('parent' => $parent)));
 
     $category = new stdClass();
     $category->id = 0;
@@ -66,12 +68,6 @@ if ($id) {
 
 require_capability('moodle/category:manage', $context);
 
-// Page "Add new category" (with "Top" as a parent) does not exist in navigation.
-// We pretend we are on course management page.
-if ($id !== 0) {
-    navigation_node::override_active_url(new moodle_url('/course/management.php'));
-}
-
 $PAGE->set_context($context);
 $PAGE->set_url($url);
 $PAGE->set_pagelayout('admin');
index 229b29c..c296ec9 100644 (file)
@@ -533,7 +533,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
         $o.= html_writer::tag('div', '', array('class' => 'left side'));
         $o.= html_writer::tag('div', '', array('class' => 'right side'));
         $o.= html_writer::start_tag('div', array('class' => 'content'));
-        $o.= $this->output->heading(get_string('orphanedactivities'), 3, 'sectionname');
+        $o.= $this->output->heading(get_string('orphanedactivitiesinsectionno', '', $sectionno), 3, 'sectionname');
         return $o;
     }
 
index 7463b11..301e0a5 100644 (file)
@@ -27,6 +27,7 @@ require_once($CFG->dirroot.'/lib/coursecatlib.php');
 require_once($CFG->dirroot.'/course/lib.php');
 
 $categoryid = optional_param('categoryid', null, PARAM_INT);
+$selectedcategoryid = optional_param('selectedcategoryid', null, PARAM_INT);
 $courseid = optional_param('courseid', null, PARAM_INT);
 $action = optional_param('action', false, PARAM_ALPHA);
 $page = optional_param('page', 0, PARAM_INT);
@@ -48,7 +49,6 @@ if ($issearching) {
 }
 
 $url = new moodle_url('/course/management.php');
-navigation_node::override_active_url($url);
 $systemcontext = $context = context_system::instance();
 if ($courseid) {
     $record = get_course($courseid);
@@ -56,13 +56,18 @@ if ($courseid) {
     $category = coursecat::get($course->category);
     $categoryid = $category->id;
     $context = context_coursecat::instance($category->id);
+    $url->param('categoryid', $categoryid);
+    navigation_node::override_active_url($url);
     $url->param('courseid', $course->id);
+
 } else if ($categoryid) {
     $courseid = null;
     $course = null;
     $category = coursecat::get($categoryid);
     $context = context_coursecat::instance($category->id);
     $url->param('categoryid', $category->id);
+    navigation_node::override_active_url($url);
+
 } else {
     $course = null;
     $courseid = null;
@@ -72,6 +77,12 @@ if ($courseid) {
         $viewmode = 'categories';
     }
     $context = $systemcontext;
+    navigation_node::override_active_url($url);
+}
+
+// Check if there is a selected category param, and if there is apply it.
+if ($course === null && $selectedcategoryid !== null && $selectedcategoryid !== $categoryid) {
+    $url->param('categoryid', $selectedcategoryid);
 }
 
 if ($page !== 0) {
@@ -313,12 +324,20 @@ if ($action !== false && confirm_sesskey()) {
                     $a = new stdClass;
                     $a->count = $movecount;
                     $a->to = $movetocat->get_formatted_name();
-                    $notificationspass[] = get_string('movecategoriessuccess', 'moodle', $a);
+                    $movesuccessstrkey = 'movecategoriessuccess';
+                    if ($movetocatid == 0) {
+                        $movesuccessstrkey = 'movecategoriestotopsuccess';
+                    }
+                    $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
                 } else if ($movecount === 1) {
                     $a = new stdClass;
                     $a->moved = $cattomove->get_formatted_name();
                     $a->to = $movetocat->get_formatted_name();
-                    $notificationspass[] = get_string('movecategorysuccess', 'moodle', $a);
+                    $movesuccessstrkey = 'movecategorysuccess';
+                    if ($movetocatid == 0) {
+                        $movesuccessstrkey = 'movecategorytotopsuccess';
+                    }
+                    $notificationspass[] = get_string($movesuccessstrkey, 'moodle', $a);
                 }
             } else if ($bulkresortcategories) {
                 // Bulk resort selected categories.
index bf088d8..3e6ef68 100644 (file)
@@ -126,6 +126,9 @@ if (!empty($add)) {
     $url->param('update', $update);
     $PAGE->set_url($url);
 
+    // Select the "Edit settings" from navigation.
+    navigation_node::override_active_url(new moodle_url('/course/modedit.php', array('update'=>$update, 'return'=>1)));
+
     // Check the course module exists.
     $cm = get_coursemodule_from_id('', $update, 0, false, MUST_EXIST);
 
index 0517f39..f831b23 100644 (file)
@@ -37,6 +37,7 @@ if (!$course = $DB->get_record('course', array('id'=>$id))) {
 }
 
 $PAGE->set_url('/course/reset.php', array('id'=>$id));
+$PAGE->set_pagelayout('admin');
 
 require_login($course);
 require_capability('moodle/course:reset', context_course::instance($course->id));
index e572403..13c97cd 100644 (file)
@@ -85,13 +85,14 @@ class behat_course extends behat_base {
      * @return Given[]
      */
     public function i_go_to_the_courses_management_page() {
-
-        return array(
-            new Given('I am on homepage'),
-            new Given('I expand "' . get_string('administrationsite') . '" node'),
-            new Given('I expand "' . get_string('courses', 'admin') . '" node'),
-            new Given('I follow "' . get_string('coursemgmt', 'admin') . '"'),
-        );
+        if ($this->running_javascript()) {
+            $scenario = array(new Given('I expand "' . get_string('administrationsite') . '" node'));
+        } else {
+            $scenario = array(new Given('I follow "' . get_string('administrationsite') . '"'));
+        }
+        $scenario[] = new Given('I expand "' . get_string('courses', 'admin') . '" node');
+        $scenario[] = new Given('I follow "' . get_string('coursemgmt', 'admin') . '"');
+        return $scenario;
     }
 
     /**
@@ -226,6 +227,33 @@ class behat_course extends behat_base {
         }
     }
 
+    /**
+     * Go to editing section page for specified section number. You need to be in the course page and on editing mode.
+     *
+     * @Given /^I edit the section "(?P<section_number>\d+)"$/
+     * @param int $sectionnumber
+     */
+    public function i_edit_the_section($sectionnumber) {
+        return new Given('I click on "' . get_string('editsummary') . '" "link" in the "#section-' . $sectionnumber . '" "css_element"');
+    }
+
+    /**
+     * Edit specified section and fill the form data with the specified field/value pairs.
+     *
+     * @When /^I edit the section "(?P<section_number>\d+)" and I fill the form with:$/
+     * @param int $sectionnumber The section number
+     * @param TableNode $data The activity field/value data
+     * @return Given[]
+     */
+    public function i_edit_the_section_and_i_fill_the_form_with($sectionnumber, TableNode $data) {
+
+        return array(
+            new Given('I edit the section "' . $sectionnumber . '"'),
+            new Given('I fill the moodle form with:', $data),
+            new Given('I press "' . get_string('savechanges') . '"')
+        );
+    }
+
     /**
      * Checks if the specified course section hightlighting is turned on. You need to be in the course page on editing mode.
      *
@@ -946,6 +974,80 @@ class behat_course extends behat_base {
         $node->click();
     }
 
+    /**
+     * Clicks on a category checkbox in the management interface.
+     *
+     * @Given /^I select category "(?P<name>[^"]*)" in the management interface$/
+     * @param string $name
+     */
+    public function i_select_category_in_the_management_interface($name) {
+        $node = $this->get_management_category_listing_node_by_name($name);
+        $node->checkField('bcat[]');
+    }
+
+    /**
+     * Clicks course checkbox in the management interface.
+     *
+     * @Given /^I select course "(?P<name>[^"]*)" in the management interface$/
+     * @param string $name
+     */
+    public function i_select_course_in_the_management_interface($name) {
+        $node = $this->get_management_course_listing_node_by_name($name);
+        $node->checkField('bc[]');
+    }
+
+    /**
+     * Move selected categories to top level in the management interface.
+     *
+     * @Given /^I move category "(?P<idnumber>[^"]*)" to top level in the management interface$/
+     * @param string $idnumber
+     * @return Given[]
+     */
+    public function i_move_category_to_top_level_in_the_management_interface($idnumber) {
+        $id = $this->get_category_id($idnumber);
+        $selector = sprintf('.listitem-category[data-id="%d"] > div', $id);
+        $node = $this->find('css', $selector);
+        $node->checkField('bcat[]');
+        return array(
+            new Given('I select "' .  coursecat::get(0)->get_formatted_name() . '" from "menumovecategoriesto"'),
+            new Given('I press "bulkmovecategories"'),
+        );
+    }
+
+    /**
+     * Checks that a category is a subcategory of specific category.
+     *
+     * @Given /^I should see category "(?P<subcatidnumber>[^"]*)" as subcategory of "(?P<catidnumber>[^"]*)" in the management interface$/
+     * @throws ExpectationException
+     * @param string $subcatidnumber
+     * @param string $catidnumber
+     */
+    public function i_should_see_category_as_subcategory_of_in_the_management_interface($subcatidnumber, $catidnumber) {
+        $categorynodeid = $this->get_category_id($catidnumber);
+        $subcategoryid = $this->get_category_id($subcatidnumber);
+        $exception = new ExpectationException('The category '.$subcatidnumber.' is not a subcategory of '.$catidnumber, $this->getSession());
+        $selector = sprintf('#category-listing .listitem-category[data-id="%d"] .listitem-category[data-id="%d"]', $categorynodeid, $subcategoryid);
+        $this->find('css', $selector, $exception);
+    }
+
+    /**
+     * Checks that a category is not a subcategory of specific category.
+     *
+     * @Given /^I should not see category "(?P<subcatidnumber>[^"]*)" as subcategory of "(?P<catidnumber>[^"]*)" in the management interface$/
+     * @throws ExpectationException
+     * @param string $subcatidnumber
+     * @param string $catidnumber
+     */
+    public function i_should_not_see_category_as_subcategory_of_in_the_management_interface($subcatidnumber, $catidnumber) {
+        try {
+            $this->i_should_see_category_as_subcategory_of_in_the_management_interface($subcatidnumber, $catidnumber);
+        } catch (ExpectationException $e) {
+            // ExpectedException means that it is not highlighted.
+            return;
+        }
+        throw new ExpectationException('The category '.$subcatidnumber.' is a subcategory of '.$catidnumber, $this->getSession());
+    }
+
     /**
      * Click to expand a category revealing its sub categories within the management UI.
      *
@@ -1233,15 +1335,13 @@ class behat_course extends behat_base {
             throw new ExpectationException("Could not find the actions for $listingtype", $this->getSession());
         }
         $actionnode = $actionsnode->find('css', '.action-'.$action);
-        if ($this->running_javascript() && !$actionnode->isVisible()) {
-            $actionsnode->find('css', 'a.toggle-display')->click();
-            if ($actionnode) {
-                $actionnode = $listingnode->find('css', '.action-'.$action);
-            }
-        }
         if (!$actionnode) {
             throw new ExpectationException("Expected action was not available or not found ($action)", $this->getSession());
         }
+        if ($this->running_javascript() && !$actionnode->isVisible()) {
+            $actionsnode->find('css', 'a.toggle-display')->click();
+            $actionnode = $actionsnode->find('css', '.action-'.$action);
+        }
         $actionnode->click();
     }
 }
index 5dbc4f9..f435dce 100644 (file)
@@ -5,6 +5,7 @@ Feature: Test category management actions
   Test we can create a sub category
   Test we can edit a category
   Test we can delete a category
+  Test we can move a category
   Test we can assign roles within a category
   Test we can set permissions on a category
   Test we can manage cohorts within a category
@@ -210,3 +211,29 @@ Feature: Test category management actions
     And I should see category listing "Cat 1" before "Test category 2"
     And I should see "No courses in this category"
 
+  @javascript
+  Scenario: Test moving a categories through the management interface.
+    Given the following "categories" exists:
+      | name | category | idnumber |
+      | Cat 1 | 0 | CAT1 |
+      | Cat 2 | 0 | CAT2 |
+      | Cat 3 | 0 | CAT3 |
+
+    And I log in as "admin"
+    And I go to the courses management page
+    And I should see the "Course categories" management page
+    And I should see "Cat 1" in the "#category-listing ul.ml" "css_element"
+    And I should see "Cat 2" in the "#category-listing ul.ml" "css_element"
+    And I should see "Cat 3" in the "#category-listing ul.ml" "css_element"
+    And I select category "Cat 2" in the management interface
+    And I select category "Cat 3" in the management interface
+    And I select "Cat 1" from "menumovecategoriesto"
+    When I press "bulkmovecategories"
+    # Redirect
+    And I click on category "Cat 1" in the management interface
+    # Redirect
+    Then I should see category "CAT3" as subcategory of "CAT1" in the management interface
+    And I move category "CAT3" to top level in the management interface
+    # Redirect
+    And I should not see category "CAT3" as subcategory of "CAT1" in the management interface
+    Then I should see category "CAT2" as subcategory of "CAT1" in the management interface
index 147617f..ef6b7f8 100644 (file)
@@ -16,8 +16,8 @@ Feature: Test we can resort categories in the management interface.
     And I go to the courses management page
     And I should see the "Course categories" management page
     And I should see "Re-sort categories" in the ".category-listing-actions" "css_element"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by name" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by idnumber" in the ".category-listing-actions" "css_element"
     And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
     # Redirect.
     And I should see the "Course categories" management page
@@ -27,8 +27,8 @@ Feature: Test we can resort categories in the management interface.
   Examples:
     | sortby | cat1 | cat2 | cat3 |
     | "Re-sort categories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "Re-sort the top level categories by name"       | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "Re-sort the top level categories by idnumber"   | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   @javascript
   Scenario Outline: Test resorting categories with JS enabled.
@@ -45,8 +45,8 @@ Feature: Test we can resort categories in the management interface.
     And I should not see "By name" in the ".category-listing-actions" "css_element"
     And I should not see "By idnumber" in the ".category-listing-actions" "css_element"
     And I click on "Re-sort categories" "link"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by name" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by idnumber" in the ".category-listing-actions" "css_element"
     And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
     # Redirect.
     And I should see the "Course categories" management page
@@ -56,8 +56,8 @@ Feature: Test we can resort categories in the management interface.
   Examples:
     | sortby | cat1 | cat2 | cat3 |
     | "Re-sort categories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "Re-sort the top level categories by name"       | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "Re-sort the top level categories by idnumber"   | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   Scenario Outline: Test resorting subcategories.
     Given the following "categories" exists:
@@ -73,10 +73,7 @@ Feature: Test we can resort categories in the management interface.
     And I click on "Master cat" "link"
     # Redirect.
     And I should see the "Course categories and courses" management page
-    And I should see "Re-sort subcategories" in the ".category-listing-actions" "css_element"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
-    And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
+    And I click on <sortby> action for "Master cat" in management category listing
     # Redirect.
     And I should see the "Course categories and courses" management page
     And I should see category listing <cat1> before <cat2>
@@ -84,9 +81,8 @@ Feature: Test we can resort categories in the management interface.
 
   Examples:
     | sortby | cat1 | cat2 | cat3 |
-    | "Re-sort subcategories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "resortbyname"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "resortbyidnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   @javascript
   Scenario Outline: Test resorting subcategories with JS enabled.
@@ -103,13 +99,7 @@ Feature: Test we can resort categories in the management interface.
     And I click on "Master cat" "link"
   # Redirect.
     And I should see the "Course categories and courses" management page
-    And I should see "Re-sort subcategories" in the ".category-listing-actions" "css_element"
-    And I should not see "By name" in the ".category-listing-actions" "css_element"
-    And I should not see "By idnumber" in the ".category-listing-actions" "css_element"
-    And I click on "Re-sort subcategories" "link"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
-    And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
+    And I click on <sortby> action for "Master cat" in management category listing
   # Redirect.
     And I should see the "Course categories and courses" management page
     And I should see category listing <cat1> before <cat2>
@@ -117,9 +107,8 @@ Feature: Test we can resort categories in the management interface.
 
   Examples:
     | sortby | cat1 | cat2 | cat3 |
-    | "Re-sort subcategories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "resortbyname"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "resortbyidnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   # The scenario below this is the same but with JS enabled.
   Scenario: Test moving categories up and down by one.
index e9edfda..6dc9774 100644 (file)
@@ -246,8 +246,8 @@ Feature: Course category management interface performs as expected
     And I go to the courses management page
     And I should see the "Course categories" management page
     And I click on "Re-sort categories" "link"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by name" in the ".category-listing-actions" "css_element"
+    And I should see "Re-sort the top level categories by idnumber" in the ".category-listing-actions" "css_element"
     And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
     # Redirect.
     And I should see the "Course categories" management page
@@ -257,8 +257,8 @@ Feature: Course category management interface performs as expected
   Examples:
     | sortby | cat1 | cat2 | cat3 |
     | "Re-sort categories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "Re-sort the top level categories by name"       | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "Re-sort the top level categories by idnumber"   | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   @javascript
   Scenario Outline: Sub categories are displayed correctly when resorted
@@ -275,10 +275,7 @@ Feature: Course category management interface performs as expected
     And I click on "Master cat" "link"
     # Redirect.
     And I should see the "Course categories and courses" management page
-    And I click on "Re-sort subcategories" "link"
-    And I should see "By name" in the ".category-listing-actions" "css_element"
-    And I should see "By idnumber" in the ".category-listing-actions" "css_element"
-    And I click on <sortby> "link" in the ".category-listing-actions" "css_element"
+    And I click on <sortby> action for "Master cat" in management category listing
     # Redirect.
     And I should see the "Course categories and courses" management page
     And I should see category listing <cat1> before <cat2>
@@ -286,9 +283,8 @@ Feature: Course category management interface performs as expected
 
   Examples:
     | sortby | cat1 | cat2 | cat3 |
-    | "Re-sort subcategories" | "Social studies"          | "Applied sciences"        | "Extended social studies" |
-    | "By name"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
-    | "By idnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
+    | "resortbyname"            | "Applied sciences"        | "Extended social studies" | "Social studies" |
+    | "resortbyidnumber"        | "Extended social studies" | "Social studies" | "Applied sciences" |
 
   @javascript
   Scenario Outline: Test courses are displayed correctly after being resorted.
@@ -745,8 +741,7 @@ Feature: Course category management interface performs as expected
     And I should see "Cat 2-1-2" in the "#course-category-listings ul.ml" "css_element"
     And I should not see "Cat 2-1-1-1" in the "#course-category-listings ul.ml" "css_element"
     And I should see "Cat 2-1-2-1" in the "#course-category-listings ul.ml" "css_element"
-    And I click on "Re-sort subcategories" "link" in the ".category-listing-actions" "css_element"
-    And I click on "By idnumber" "link" in the ".category-listing-actions" "css_element"
+    And I click on "resortbyidnumber" action for "Cat 1" in management category listing
     # Redirect.
     And I should see the "Course categories and courses" management page
     And I should see "Cat 1" in the "#course-category-listings ul.ml" "css_element"
@@ -798,4 +793,4 @@ Feature: Course category management interface performs as expected
     # Redirect.
     And I should see the "Course categories and courses" management page
     And I should see "Cat A (1)" in the "#course-category-listings ul.ml" "css_element"
-    And I should not see "Cat B (2)" in the "#course-category-listings ul.ml" "css_element"
\ No newline at end of file
+    And I should not see "Cat B (2)" in the "#course-category-listings ul.ml" "css_element"
index b28522e..1935ec7 100644 (file)
@@ -1534,6 +1534,10 @@ class core_course_courselib_testcase extends advanced_testcase {
         $this->assertEquals($coursecontext->id, $event->contextid);
         $this->assertEquals($course, $event->get_record_snapshot('course', $course->id));
         $this->assertEquals('course_deleted', $event->get_legacy_eventname());
+        $eventdata = $event->get_data();
+        $this->assertSame($course->idnumber, $eventdata['other']['idnumber']);
+        $this->assertSame($course->fullname, $eventdata['other']['fullname']);
+        $this->assertSame($course->shortname, $eventdata['other']['shortname']);
         // The legacy data also passed the context in the course object.
         $course->context = $coursecontext;
         $this->assertEventLegacyData($course, $event);
index 73839e1..cd37afc 100644 (file)
@@ -58,7 +58,7 @@ $personalcontext = context_user::instance($user->id);
 $PAGE->set_url('/course/user.php', array('id'=>$id, 'user'=>$user->id, 'mode'=>$mode));
 
 require_login();
-$PAGE->set_pagelayout('admin');
+$PAGE->set_pagelayout('report');
 if (has_capability('moodle/user:viewuseractivitiesreport', $personalcontext) and !is_enrolled($coursecontext)) {
     // do not require parents to be enrolled in courses ;-)
     $PAGE->set_course($course);
index 2971198..8f18f7d 100644 (file)
@@ -873,6 +873,6 @@ YUI.add('moodle-course-toolboxes', function(Y) {
 
 },
 '@VERSION@', {
-    requires : ['base', 'node', 'io', 'moodle-course-coursebase']
+    requires : ['base', 'node', 'io', 'moodle-course-coursebase', 'moodle-course-util']
 }
 );
index f2e8a6d..42cb947 100644 (file)
@@ -26,7 +26,7 @@
 
 require('../config.php');
 
-$contextid  = optional_param('contextid', SYSCONTEXTID, PARAM_INT);
+$contextid  = optional_param('contextid', 0, PARAM_INT);
 $filepath   = optional_param('filepath', '', PARAM_PATH);
 $filename   = optional_param('filename', '', PARAM_FILE);
 // hard-coded to course legacy area
@@ -34,7 +34,12 @@ $component = 'course';
 $filearea  = 'legacy';
 $itemid    = 0;
 
+if (empty($contextid)) {
+    $contextid = context_course::instance(SITEID)->id;
+}
+
 $PAGE->set_url('/files/index.php', array('contextid'=>$contextid, 'filepath'=>$filepath, 'filename'=>$filename));
+navigation_node::override_active_url(new moodle_url('/files/index.php', array('contextid'=>$contextid)));
 
 if ($filepath === '') {
     $filepath = null;
index 4017ade..e27bcaa 100644 (file)
@@ -201,14 +201,14 @@ class core_files_renderer extends plugin_renderer_base {
     <div class="fp-navbar">
         <div class="filemanager-toolbar">
             <div class="fp-toolbar">
-                <div class="{!}fp-btn-add"><a role="button" href="#"><img src="'.$this->pix_url('a/add_file').'" /> '.$straddfile.'</a></div>
-                <div class="{!}fp-btn-mkdir"><a role="button" href="#"><img src="'.$this->pix_url('a/create_folder').'" /> '.$strmakedir.'</a></div>
-                <div class="{!}fp-btn-download"><a role="button" href="#"><img src="'.$this->pix_url('a/download_all').'" /> '.$strdownload.'</a></div>
+                <div class="{!}fp-btn-add"><a role="button" href="#"><img src="'.$this->pix_url('a/add_file').'" alt="'.$straddfile.'" /></a></div>
+                <div class="{!}fp-btn-mkdir"><a role="button" href="#"><img src="'.$this->pix_url('a/create_folder').'" alt="'.$strmakedir.'" /></a></div>
+                <div class="{!}fp-btn-download"><a role="button" href="#"><img src="'.$this->pix_url('a/download_all').'" alt="'.$strdownload.'" /></a></div>
             </div>
             <div class="{!}fp-viewbar">
-                <a title="'. get_string('displayicons', 'repository') .'" class="{!}fp-vb-icons" href="#"></a>
-                <a title="'. get_string('displaydetails', 'repository') .'" class="{!}fp-vb-details" href="#"></a>
-                <a title="'. get_string('displaytree', 'repository') .'" class="{!}fp-vb-tree" href="#"></a>
+                <a title="'. get_string('displayicons', 'repository') .'" class="{!}fp-vb-icons" href="#"><img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" /></a>
+                <a title="'. get_string('displaydetails', 'repository') .'" class="{!}fp-vb-details" href="#"><img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" /></a>
+                <a title="'. get_string('displaytree', 'repository') .'" class="{!}fp-vb-tree" href="#"><img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" /></a>
             </div>
         </div>
         <div class="fp-pathbar">
@@ -535,15 +535,15 @@ class core_files_renderer extends plugin_renderer_base {
                     <div class="{!}fp-tb-back"><a href="#">'.get_string('back', 'repository').'</a></div>
                     <div class="{!}fp-tb-search"><form></form></div>
                     <div class="{!}fp-tb-refresh"><a href="#"><img alt="'. get_string('refresh', 'repository') .'"  src="'.$this->pix_url('a/refresh').'" /></a></div>
-                    <div class="{!}fp-tb-logout"><img alt="'. get_string('logout', 'repository') .'" src="'.$this->pix_url('a/logout').'" /><a href="#"></a></div>
-                    <div class="{!}fp-tb-manage"><a href="#"><img alt="'. get_string('settings', 'repository') .'" src="'.$this->pix_url('a/setting').'" /> '.get_string('manageurl', 'repository').'</a></div>
-                    <div class="{!}fp-tb-help"><a href="#"><img alt="'. get_string('help', 'repository') .'" src="'.$this->pix_url('a/help').'" /> '.get_string('help').'</a></div>
+                    <div class="{!}fp-tb-logout"><a href="#"><img alt="'. get_string('logout', 'repository') .'" src="'.$this->pix_url('a/logout').'" /></a></div>
+                    <div class="{!}fp-tb-manage"><a href="#"><img alt="'. get_string('settings', 'repository') .'" src="'.$this->pix_url('a/setting').'" /></a></div>
+                    <div class="{!}fp-tb-help"><a href="#"><img alt="'. get_string('help', 'repository') .'" src="'.$this->pix_url('a/help').'" /></a></div>
                     <div class="{!}fp-tb-message"></div>
                 </div>
                 <div class="{!}fp-viewbar">
-                    <a title="'. get_string('displayicons', 'repository') .'" class="{!}fp-vb-icons" href="#"></a>
-                    <a title="'. get_string('displaydetails', 'repository') .'" class="{!}fp-vb-details" href="#"></a>
-                    <a title="'. get_string('displaytree', 'repository') .'" class="{!}fp-vb-tree" href="#"></a>
+                    <a title="'. get_string('displayicons', 'repository') .'" class="{!}fp-vb-icons" href="#"><img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" /></a>
+                    <a title="'. get_string('displaydetails', 'repository') .'" class="{!}fp-vb-details" href="#"><img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" /></a>
+                    <a title="'. get_string('displaytree', 'repository') .'" class="{!}fp-vb-tree" href="#"><img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" /></a>
                 </div>
                 <div class="fp-clear-left"></div>
             </div>
index 161b816..314db1e 100644 (file)
@@ -18,8 +18,8 @@ Feature: Course files
     Then I should see "Legacy course files"
     And I follow "Legacy course files"
     And I press "Edit legacy course files"
-    And I should see "Add..."
-    And I should see "Create folder"
+    And "Add..." "link" should be visible
+    And "Create folder" "link" should be visible
 
   @javascript
   Scenario: Add legacy file disabled
@@ -35,5 +35,5 @@ Feature: Course files
     Then I should see "Legacy course files"
     And I follow "Legacy course files"
     And I press "Edit legacy course files"
-    And I should not see "Add..."
-    And I should not see "Create folder"
+    And "Add..." "link" should not be visible
+    And "Create folder" "link" should not be visible
index 550b0f0..f453c97 100644 (file)
@@ -57,7 +57,7 @@ $isfrontpage = ($context->contextlevel == CONTEXT_COURSE && $context->instanceid
 $contextname = $context->get_context_name();
 
 if ($context->contextlevel == CONTEXT_COURSECAT) {
-    $heading = "$SITE->fullname: ".get_string("categories");
+    $heading = $SITE->fullname;
 } else if ($context->contextlevel == CONTEXT_COURSE) {
     $heading = $course->fullname;
 } else if ($context->contextlevel == CONTEXT_MODULE) {
@@ -119,16 +119,11 @@ if ($forfilter) {
 }
 $straction = get_string('filters', 'admin'); // Used by tabs.php
 
-/// Print the header and tabs
-if ($isfrontpage) {
-    admin_externalpage_setup('frontpagefilters');
-    echo $OUTPUT->header();
-} else {
-    $PAGE->set_cacheable(false);
-    $PAGE->set_title($title);
-    $PAGE->set_pagelayout('admin');
-    echo $OUTPUT->header();
-}
+// Print the header and tabs.
+$PAGE->set_cacheable(false);
+$PAGE->set_title($title);
+$PAGE->set_pagelayout('admin');
+echo $OUTPUT->header();
 
 /// Print heading.
 echo $OUTPUT->heading_with_help($title, 'filtersettings', 'filters');
index 6e21e46..5062056 100644 (file)
@@ -33,6 +33,7 @@ $action   = optional_param('action', '', PARAM_ALPHA);
 $scope    = optional_param('scope', 'custom', PARAM_ALPHA);
 
 $PAGE->set_url('/grade/edit/outcome/import.php', array('courseid' => $courseid));
+$PAGE->set_pagelayout('admin');
 
 /// Make sure they can even access this course
 if ($courseid) {
index 163e0f0..46ec518 100644 (file)
@@ -38,7 +38,7 @@ class import_outcomes_form extends moodleform {
         $mform->addElement('hidden', 'action', 'upload');
         $mform->setType('action', PARAM_ALPHANUMEXT);
         $mform->addElement('hidden', 'courseid', $PAGE->course->id);
-        $mform->setType('id', PARAM_INT);
+        $mform->setType('courseid', PARAM_INT);
 
         $scope = array();
         if (($PAGE->course->id > 1) && has_capability('moodle/grade:manage', context_system::instance())) {
index f156fa9..18a34ff 100644 (file)
@@ -262,6 +262,7 @@ $string['skipmodifprevhelp'] = 'Choose whether or not to skip courses that have
 $string['title'] = 'Title';
 $string['totalcategorysearchresults'] = 'Total categories: {$a}';
 $string['totalcoursesearchresults'] = 'Total courses: {$a}';
+$string['unnamedsection'] = 'Unnamed section';
 $string['userinfo'] = 'Userinfo';
 $string['module'] = 'Module';
 $string['morecoursesearchresults'] = 'More than {$a} courses found, showing first {$a} results';
index f8dcbc1..7ea4073 100644 (file)
@@ -1145,6 +1145,8 @@ $string['movecontent'] = 'Move {$a}';
 $string['movecategorycontentto'] = 'Move into';
 $string['movecategorysuccess'] = 'Successfully moved category \'{$a->moved}\' into category \'{$a->to}\'';
 $string['movecategoriessuccess'] = 'Successfully moved {$a->count} categories into category \'{$a->to}\'';
+$string['movecategorytotopsuccess'] = 'Successfully moved category \'{$a->moved}\' to top level';
+$string['movecategoriestotopsuccess'] = 'Successfully moved {$a->count} categories to top level';
 $string['movecategoryto'] = 'Move category to:';
 $string['movecontentstoanothercategory'] = 'Move contents to another category';
 $string['movecourseto'] = 'Move course to:';
@@ -1319,7 +1321,7 @@ $string['optional'] = 'optional';
 $string['options'] = 'options';
 $string['order'] = 'Order';
 $string['originalpath'] = 'Original path';
-$string['orphanedactivities'] = 'Orphaned activities';
+$string['orphanedactivitiesinsectionno'] = 'Orphaned activities (section {$a})';
 $string['other'] = 'Other';
 $string['outline'] = 'Outline';
 $string['outlinereport'] = 'Outline report';
@@ -1470,7 +1472,10 @@ $string['resetstatus'] = 'Status';
 $string['resettask'] = 'Task';
 $string['resettodefaults'] = 'Reset to defaults';
 $string['resortcategories'] = 'Re-sort categories';
-$string['resortsubcategories'] = 'Re-sort subcategories';
+$string['resortcategoriesbyname'] = 'Re-sort the top level categories by name';
+$string['resortcategoriesbyidnumber'] = 'Re-sort the top level categories by idnumber';
+$string['resortsubcategoriesbyname'] = 'Re-sort subcategories by name';
+$string['resortsubcategoriesbyidnumber'] = 'Re-sort subcategories by idnumber';
 $string['resortcourses'] = 'Re-sort courses';
 $string['resortcoursesbyname'] = 'Re-sort courses by name';
 $string['resortbyname'] = 'By name';
@@ -1664,6 +1669,7 @@ $string['skypeid'] = 'Skype ID';
 $string['socialheadline'] = 'Social forum - latest topics';
 $string['someallowguest'] = 'Some courses may allow guest access';
 $string['someerrorswerefound'] = 'Some information was missing or incorrect. Look below for details.';
+$string['sort'] = 'Sort';
 $string['sortby'] = 'Sort by';
 $string['sortbyx'] = 'Sort by {$a} ascending';
 $string['sortbyxreverse'] = 'Sort by {$a} descending';
index 7d7bb69..45f07b4 100644 (file)
@@ -1528,7 +1528,6 @@ function delete_role($roleid) {
             'objectid' => $roleid,
             'other' =>
                 array(
-                    'name' => $role->name,
                     'shortname' => $role->shortname,
                     'description' => $role->description,
                     'archetype' => $role->archetype
index 2d3c61f..b300687 100644 (file)
@@ -6266,6 +6266,8 @@ function admin_externalpage_setup($section, $extrabutton = '', array $extraurlpa
         die;
     }
 
+    navigation_node::require_admin_tree();
+
     // $PAGE->set_extra_button($extrabutton); TODO
 
     if (!$actualurl) {
diff --git a/lib/ajax/getsiteadminbranch.php b/lib/ajax/getsiteadminbranch.php
new file mode 100644 (file)
index 0000000..a57959b
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file is used to deliver a branch from the site administration
+ * in XML format back to a page from an AJAX call
+ *
+ * @since 2.6
+ * @package core
+ * @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('AJAX_SCRIPT', true);
+require_once(dirname(__FILE__) . '/../../config.php');
+
+// This should be accessed by only valid logged in user.
+if (!isloggedin() or isguestuser()) {
+    die('Invalid access.');
+}
+
+// This identifies the type of the branch we want to get. Make sure it's SITE_ADMIN.
+$branchtype = required_param('type', PARAM_INT);
+if ($branchtype !== navigation_node::TYPE_SITE_ADMIN) {
+    die('Wrong node type passed.');
+}
+
+$PAGE->set_context(context_system::instance());
+$PAGE->set_url('/lib/ajax/getsiteadminbranch.php', array('type'=>$branchtype));
+
+$sitenavigation = new settings_navigation_ajax($PAGE);
+
+// Set XML headers.
+header('Content-type: text/plain; charset=utf-8');
+// Convert and output the branch as XML.
+$converter = new navigation_json();
+$branch = $sitenavigation->get('root');
+echo $converter->convert($branch);
index 7ba305e..4e1518a 100644 (file)
@@ -55,7 +55,7 @@ class blog_entry_created extends \core\event\base {
      *
      * @param \blog_entry $data A reference to the active blog_entry object.
      */
-    public function set_custom_data($data) {
+    public function set_custom_data(\blog_entry $data) {
         $this->customobject = $data;
     }
 
@@ -74,7 +74,7 @@ class blog_entry_created extends \core\event\base {
      * @return string
      */
     public function get_description() {
-        return 'Blog entry "'. $this->other['subject']. '" was created by user with id '. $this->userid;
+        return 'Blog entry id '. $this->objectid. ' was created by userid '. $this->userid;
     }
 
     /**
index b632082..b7275d5 100644 (file)
@@ -63,7 +63,7 @@ class blog_entry_deleted extends \core\event\base {
      *
      * @param \blog_entry $data A reference to the active blog_entry object.
      */
-    public function set_custom_data($data) {
+    public function set_custom_data(\blog_entry $data) {
         $this->customobject = $data;
     }
 
@@ -73,7 +73,7 @@ class blog_entry_deleted extends \core\event\base {
      * @return string
      */
     public function get_description() {
-        return "Blog entry ".$this->other['record']['subject']." was deleted by user with id ".$this->userid;
+        return 'Blog entry id '. $this->objectid. ' was deleted by userid '. $this->userid;
     }
 
     /**
index 5859f4b..777ac2e 100644 (file)
@@ -53,7 +53,7 @@ class blog_entry_updated extends base {
      *
      * @param \blog_entry $data A reference to the active blog_entry object.
      */
-    public function set_custom_data($data) {
+    public function set_custom_data(\blog_entry $data) {
         $this->customobject = $data;
     }
 
@@ -72,7 +72,7 @@ class blog_entry_updated extends base {
      * @return string
      */
     public function get_description() {
-        return 'User with id {$this->userid} updated blog entry {$this->other["subject"]';
+        return 'Blog entry id '. $this->objectid. ' was updated by userid '. $this->userid;
     }
 
     /**
@@ -108,7 +108,7 @@ class blog_entry_updated extends base {
      */
     protected function get_legacy_logdata() {
         return array(SITEID, 'blog', 'update', 'index.php?userid=' . $this->relateduserid . '&entryid=' . $this->objectid,
-                 $this->other['subject']);
+                 $this->customobject->subject);
     }
 }
 
index 4c03cf0..7492bd1 100644 (file)
@@ -87,7 +87,7 @@ abstract class content_viewed extends base {
      * @return string
      */
     public function get_description() {
-        return 'User with id ' . $this->userid . ' viewed content ' . $this->get_url();
+        return 'User with id ' . $this->userid . ' viewed content';
     }
 
     /**
index b77219a..6e42b60 100644 (file)
@@ -60,7 +60,7 @@ class course_completed extends base {
      * @return \moodle_url
      */
     public function get_url() {
-        return new moodle_url('/report/completion/index.php', array('course' => $this->courseid));
+        return new \moodle_url('/report/completion/index.php', array('course' => $this->courseid));
     }
 
     /**
index 1637054..36a3d80 100644 (file)
@@ -67,7 +67,7 @@ class course_completion_updated extends base {
      * @return \moodle_url
      */
     public function get_url() {
-        return new moodle_url('/course/completion.php', array('id' => $this->courseid));
+        return new \moodle_url('/course/completion.php', array('id' => $this->courseid));
     }
 
     /**
index db17175..0f704a7 100644 (file)
@@ -71,7 +71,7 @@ class course_deleted extends base {
     protected function get_legacy_eventdata() {
         $course = $this->get_record_snapshot('course', $this->objectid);
         $course->context = $this->context;
-
+        $course->timemodified = $this->data['timecreated'];
         return $course;
     }
 
index 72c0276..7436e83 100644 (file)
@@ -60,7 +60,7 @@ class course_module_completion_updated extends base {
      * @return \moodle_url
      */
     public function get_url() {
-        return new moodle_url('/report/completion/index.php', array('course' => $this->courseid));
+        return new \moodle_url('/report/completion/index.php', array('course' => $this->courseid));
     }
 
     /**
index 442c02e..9ed6fc8 100644 (file)
@@ -60,8 +60,8 @@ class course_module_created extends base {
      * @return string
      */
     public function get_description() {
-        return 'The '. $this->other['modulename'] . ' module ' . $this->other['name']. ' was created by user with id '.
-               $this->userid;
+        return 'The '. $this->other['modulename'] . ' module with instance id ' . $this->other['instanceid'] .
+                ' was created by user with id ' . $this->userid;
     }
 
     /**
index e6a7b19..ced4210 100644 (file)
@@ -60,8 +60,8 @@ class course_module_updated extends base {
      * @return string
      */
     public function get_description() {
-        return 'The ' . $this->other['modulename'] . ' module ' . $this->other['name']. ' was updated by user with id '.
-               $this->userid;
+        return 'The ' . $this->other['modulename'] . ' module with instance id ' . $this->other['instanceid'] .
+                ' was updated by user with id ' . $this->userid;
     }
 
     /**
index fc9e9a8..5213900 100644 (file)
@@ -56,7 +56,7 @@ class role_assigned extends base {
      * @return \moodle_url
      */
     public function get_url() {
-        return new moodle_url('/admin/roles/assign.php', array('contextid' => $this->contextid, 'roleid' => $this->objectid));
+        return new \moodle_url('/admin/roles/assign.php', array('contextid' => $this->contextid, 'roleid' => $this->objectid));
     }
 
     /**
index 035e42a..2e5a986 100644 (file)
@@ -56,7 +56,7 @@ class role_unassigned extends base {
      * @return \moodle_url
      */
     public function get_url() {
-        return new moodle_url('/admin/roles/assign.php', array('contextid' => $this->contextid, 'roleid' => $this->objectid));
+        return new \moodle_url('/admin/roles/assign.php', array('contextid' => $this->contextid, 'roleid' => $this->objectid));
     }
 
     /**
index 545d691..e04ee16 100644 (file)
@@ -58,8 +58,8 @@ class user_deleted extends base {
      * @return string
      */
     public function get_description() {
-        $user = (object)$this->other['user'];
-        return 'User profile deleted for user '.$user->firstname.' '.$user->lastname.' id ('.$user->id.')';
+        $user = $this->get_record_snapshot('user', $this->data['objectid']);
+        return 'User profile deleted for userid ' . $user->id;
     }
 
     /**
@@ -77,7 +77,13 @@ class user_deleted extends base {
      * @return \stdClass user data.
      */
     protected function get_legacy_eventdata() {
-        return (object)$this->other['user'];
+        $user = $this->get_record_snapshot('user', $this->data['objectid']);
+        $user->deleted = 0;
+        $user->username = $this->data['other']['username'];
+        $user->email = $this->data['other']['email'];
+        $user->idnumber = $this->data['other']['idnumber'];
+        $user->picture = $this->data['other']['picture'];
+        return $user;
     }
 
     /**
@@ -86,8 +92,8 @@ class user_deleted extends base {
      * @return array
      */
     protected function get_legacy_logdata() {
-        $user = (object)$this->other['user'];
-        return array(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname);
+        $user = $this->get_record_snapshot('user', $this->data['objectid']);
+        return array(SITEID, 'user', 'delete', "view.php?id=".$user->id, $user->firstname.' '.$user->lastname);
     }
 
     /**
@@ -97,9 +103,29 @@ class user_deleted extends base {
      * @return void
      */
     protected function validate_data() {
-        parent::validate_data();
-        if (!isset($this->other['user'])) {
-            throw new \coding_exception('user must be set in $other.');
+        global $CFG;
+
+        if ($CFG->debugdeveloper) {
+            parent::validate_data();
+            if (!isset($this->other['username'])) {
+                throw new \coding_exception('username must be set in $other.');
+            }
+
+            if (!isset($this->other['email'])) {
+                throw new \coding_exception('email must be set in $other.');
+            }
+
+            if (!isset($this->other['idnumber'])) {
+                throw new \coding_exception('idnumber must be set in $other.');
+            }
+
+            if (!isset($this->other['picture'])) {
+                throw new \coding_exception('picture must be set in $other.');
+            }
+
+            if (!isset($this->other['mnethostid'])) {
+                throw new \coding_exception('mnethostid must be set in $other.');
+            }
         }
     }
 }
index d45ca6d..064ccf5 100644 (file)
@@ -40,7 +40,7 @@ class user_enrolment_created extends base {
     protected function init() {
         $this->data['objecttable'] = 'user_enrolments';
         $this->data['crud'] = 'c';
-        $this->data['level'] = self::LEVEL_TEACHING;
+        $this->data['level'] = self::LEVEL_OTHER;
     }
 
     /**
index 82e523f..8992347 100644 (file)
@@ -40,7 +40,7 @@ class user_enrolment_deleted extends base {
     protected function init() {
         $this->data['objecttable'] = 'user_enrolments';
         $this->data['crud'] = 'd';
-        $this->data['level'] = self::LEVEL_TEACHING;
+        $this->data['level'] = self::LEVEL_OTHER;
     }
 
     /**
index 786f519..8e53236 100644 (file)
@@ -40,7 +40,7 @@ class user_enrolment_updated extends base {
     protected function init() {
         $this->data['objecttable'] = 'user_enrolments';
         $this->data['crud'] = 'u';
-        $this->data['level'] = self::LEVEL_TEACHING;
+        $this->data['level'] = self::LEVEL_OTHER;
     }
 
     /**
index a656175..995784a 100644 (file)
@@ -34,6 +34,14 @@ defined('MOODLE_INTERNAL') || die();
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 abstract class handler {
+    /**
+     * Start the session.
+     * @return bool success
+     */
+    public function start() {
+        return session_start();
+    }
+
     /**
      * Init session handler.
      */
index 2b1e7f0..c5e764c 100644 (file)
@@ -74,7 +74,7 @@ class manager {
             self::prepare_cookies();
             $newsid = empty($_COOKIE[session_name()]);
 
-            session_start();
+            self::$handler->start();
 
             self::initialise_user_session($newsid);
             self::check_security();
index 7281537..4e07f3c 100644 (file)
@@ -40,6 +40,13 @@ class memcached extends handler {
     protected $servers;
     /** @var string $prefix session key prefix  */
     protected $prefix;
+    /** @var int $acquiretimeout how long to wait for session lock */
+    protected $acquiretimeout = 120;
+    /**
+     * @var int $lockexpire how long to wait before expiring the lock so that other requests
+     * may continue execution, ignored if memcached <= 2.1.0.
+     */
+    protected $lockexpire = 7200;
 
     /**
      * Create new instance of handler.
@@ -64,6 +71,32 @@ class memcached extends handler {
         } else {
             $this->prefix = $CFG->session_memcached_prefix;
         }
+
+        if (!empty($CFG->session_memcached_acquire_lock_timeout)) {
+            $this->acquiretimeout = (int)$CFG->session_memcached_acquire_lock_timeout;
+        }
+
+        if (!empty($CFG->session_memcached_lock_expire)) {
+            $this->lockexpire = (int)$CFG->session_memcached_lock_expire;
+        }
+    }
+
+    /**
+     * Start the session.
+     * @return bool success
+     */
+    public function start() {
+        // NOTE: memcached <= 2.1.0 expires session locks automatically after max_execution_time,
+        //       this leads to major difference compared to other session drivers that timeout
+        //       and stop the second request execution instead.
+
+        $default = ini_get('max_execution_time');
+        set_time_limit($this->acquiretimeout);
+
+        $result = parent::start();
+
+        set_time_limit($default);
+        return $result;
     }
 
     /**
@@ -81,11 +114,14 @@ class memcached extends handler {
             throw new exception('sessionhandlerproblem', 'error', '', null, '$CFG->session_memcached_save_path must be specified in config.php');
         }
 
-        // NOTE: we cannot set any lock acquiring timeout here - bad luck.
         ini_set('session.save_handler', 'memcached');
         ini_set('session.save_path', $this->savepath);
         ini_set('memcached.sess_prefix', $this->prefix);
         ini_set('memcached.sess_locking', '1'); // Locking is required!
+
+        // Try to configure lock and expire timeouts - ignored if memcached <=2.1.0.
+        ini_set('memcached.sess_lock_max_wait', $this->acquiretimeout);
+        ini_set('memcached.sess_lock_expire', $this->lockexpire);
     }
 
     /**
index 971d138..3782b5c 100644 (file)
@@ -475,12 +475,13 @@ class core_useragent {
     }
 
     /**
-     * Checks the user agent is IE and that the version is equal to or greater than that specified.
+     * Checks the user agent is IE and returns its main properties:
+     * - browser version;
+     * - whether running in compatibility view.
      *
-     * @param string|int $version A version to check for, returns true if its equal to or greater than that specified.
-     * @return bool
+     * @return bool|array False if not IE, otherwise an associative array of properties.
      */
-    public static function check_ie_version($version = null) {
+    public static function check_ie_properties() {
         // Internet Explorer.
         $useragent = self::get_user_agent_string();
         if ($useragent === false) {
@@ -490,25 +491,71 @@ class core_useragent {
             // Reject Opera.
             return false;
         }
-        // In case of IE we have to deal with BC of the version parameter.
-        if (is_null($version)) {
-            $version = 5.5; // Anything older is not considered a browser at all!
-        }
-        // IE uses simple versions, let's cast it to float to simplify the logic here.
-        $version = round($version, 1);
         // See: http://www.useragentstring.com/pages/Internet%20Explorer/.
         if (preg_match("/MSIE ([0-9\.]+)/", $useragent, $match)) {
             $browser = $match[1];
+        // See: http://msdn.microsoft.com/en-us/library/ie/bg182625%28v=vs.85%29.aspx for IE11+ useragent details.
+        } else if (preg_match("/Trident\/[0-9\.]+/", $useragent) && preg_match("/rv:([0-9\.]+)/", $useragent, $match)) {
+            $browser = $match[1];
         } else {
             return false;
         }
+        $compat_view = false;
         // IE8 and later versions may pretend to be IE7 for intranet sites, use Trident version instead,
         // the Trident should always describe the capabilities of IE in any emulation mode.
         if ($browser === '7.0' and preg_match("/Trident\/([0-9\.]+)/", $useragent, $match)) {
+            $compat_view = true;
             $browser = $match[1] + 4; // NOTE: Hopefully this will work also for future IE versions.
         }
         $browser = round($browser, 1);
-        return ($browser >= $version);
+        return array(
+            'version'    => $browser,
+            'compatview' => $compat_view
+        );
+    }
+
+    /**
+     * Checks the user agent is IE and that the version is equal to or greater than that specified.
+     *
+     * @param string|int $version A version to check for, returns true if its equal to or greater than that specified.
+     * @return bool
+     */
+    public static function check_ie_version($version = null) {
+        // Internet Explorer.
+        $properties = self::check_ie_properties();
+        if (!is_array($properties)) {
+            return false;
+        }
+        // In case of IE we have to deal with BC of the version parameter.
+        if (is_null($version)) {
+            $version = 5.5; // Anything older is not considered a browser at all!
+        }
+        // IE uses simple versions, let's cast it to float to simplify the logic here.
+        $version = round($version, 1);
+        return ($properties['version'] >= $version);
+    }
+
+    /**
+     * Checks the user agent is IE and that IE is running under Compatibility View setting.
+     *
+     * @return bool true if internet explorer runs in Compatibility View mode.
+     */
+    public static function check_ie_compatibility_view() {
+        // IE User Agent string when in Compatibility View:
+        // - IE  8: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; ...)".
+        // - IE  9: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; ...)".
+        // - IE 10: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; ...)".
+        // - IE 11: "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; ...)".
+        // Refs:
+        // - http://blogs.msdn.com/b/ie/archive/2009/01/09/the-internet-explorer-8-user-agent-string-updated-edition.aspx.
+        // - http://blogs.msdn.com/b/ie/archive/2010/03/23/introducing-ie9-s-user-agent-string.aspx.
+        // - http://blogs.msdn.com/b/ie/archive/2011/04/15/the-ie10-user-agent-string.aspx.
+        // - http://msdn.microsoft.com/en-us/library/ie/hh869301%28v=vs.85%29.aspx.
+        $properties = self::check_ie_properties();
+        if (!is_array($properties)) {
+            return false;
+        }
+        return $properties['compatview'];
     }
 
     /**
@@ -829,4 +876,27 @@ class core_useragent {
         }
         return $instance->supportssvg;
     }
+
+    /**
+     * Returns true if the user agent supports the MIME media type for JSON text, as defined in RFC 4627.
+     *
+     * @return bool
+     */
+    public static function supports_json_contenttype() {
+        // Modern browsers other than IE correctly supports 'application/json' media type.
+        if (!self::is_ie()) {
+            return true;
+        }
+
+        // IE8+ supports 'application/json' media type, when NOT in Compatibility View mode.
+        // Refs:
+        // - http://blogs.msdn.com/b/ie/archive/2008/09/10/native-json-in-ie8.aspx;
+        // - MDL-39810: issues when using 'text/plain' in Compatibility View for the body of an HTTP POST response.
+        if (self::check_ie_version(8) && !self::check_ie_compatibility_view()) {
+            return true;
+        }
+
+        // This browser does not support json.
+        return false;
+    }
 }
index 8f941ea..a30f58e 100644 (file)
@@ -2043,7 +2043,7 @@ class coursecat implements renderable, cacheable_object, IteratorAggregate {
             $context = $this->get_context();
             return format_string($this->name, true, array('context' => $context) + $options);
         } else {
-            return ''; // TODO 'Top'?.
+            return get_string('top');
         }
     }
 
index 99e5f32..d3ef19f 100644 (file)
@@ -42,9 +42,10 @@ $handlers = array(
  *       (it is just abusing cron to do very time consuming things which is wrong any way)
  *
  * TODO: this has to be moved into separate queueing framework....
+ * TODO: MDL-25508, MDL-41541
  */
     'portfolio_send' => array (
-        'handlerfile'      => '/lib/portfolio.php',
+        'handlerfile'      => '/lib/portfoliolib.php',
         'handlerfunction'  => 'portfolio_handle_event',    // argument to call_user_func(), could be an array
         'schedule'         => 'cron',
         'internal'         => 0,
index 2bf05c5..edf21a9 100644 (file)
@@ -2739,5 +2739,40 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013102201.00);
     }
 
+    if ($oldversion < 2013102500.01) {
+        // Find all fileareas that have missing root folder entry and add the root folder entry.
+        if (empty($CFG->filesrootrecordsfixed)) {
+            $sql = "SELECT distinct f1.contextid, f1.component, f1.filearea, f1.itemid
+                FROM {files} f1 left JOIN {files} f2
+                    ON f1.contextid = f2.contextid
+                    AND f1.component = f2.component
+                    AND f1.filearea = f2.filearea
+                    AND f1.itemid = f2.itemid
+                    AND f2.filename = '.'
+                    AND f2.filepath = '/'
+                WHERE (f1.component <> 'user' or f1.filearea <> 'draft')
+                and f2.id is null";
+            $rs = $DB->get_recordset_sql($sql);
+            $defaults = array('filepath' => '/',
+                            'filename' => '.',
+                            'userid' => $USER->id,
+                            'filesize' => 0,
+                            'timecreated' => time(),
+                            'timemodified' => time(),
+                            'contenthash' => sha1(''));
+            foreach ($rs as $r) {
+                $pathhash = sha1("/$r->contextid/$r->component/$r->filearea/$r->itemid".'/.');
+                $DB->insert_record('files', (array)$r + $defaults +
+                        array('pathnamehash' => $pathhash));
+            }
+            $rs->close();
+            // To skip running the same script on the upgrade to the next major release.
+            set_config('filesrootrecordsfixed', 1);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013102500.01);
+    }
+
     return true;
 }
index e8a5aae..156d39c 100644 (file)
@@ -373,7 +373,6 @@ abstract class moodle_database {
             $this->database_manager = null;
         }
         $this->tables  = null;
-        $this->metacache = null;
     }
 
     /**
@@ -962,26 +961,11 @@ abstract class moodle_database {
      */
     public function reset_caches() {
         $this->tables = null;
-        $this->metacache = null;
         // Purge MUC as well
         $identifiers = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
         cache_helper::purge_by_definition('core', 'databasemeta', $identifiers);
     }
 
-    /**
-     * Call before using $this->metacache.
-     *
-     * Note: this is necessary because we want to write to database in shutdown handler
-     *       and it needs to use the caches, but MUC would be already disposed.
-     */
-    protected function init_caches() {
-        if ($this->metacache) {
-            return;
-        }
-        $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
-        $this->metacache = cache::make('core', 'databasemeta', $properties);
-    }
-
     /**
      * Returns the sql generator used for db manipulation.
      * Used mostly in upgrade.php scripts.
index 88c3575..2ad78aa 100644 (file)
@@ -398,8 +398,9 @@ class mssql_native_moodle_database extends moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -495,7 +496,7 @@ class mssql_native_moodle_database extends moodle_database {
         $this->free_result($result);
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index f80c479..5196484 100644 (file)
@@ -511,8 +511,9 @@ class mysqli_native_moodle_database extends moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -618,7 +619,7 @@ class mysqli_native_moodle_database extends moodle_database {
         }
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index 5f412ef..95985f9 100644 (file)
@@ -470,8 +470,9 @@ class oci_native_moodle_database extends moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -663,7 +664,7 @@ class oci_native_moodle_database extends moodle_database {
         }
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index 3ae868d..3754d9b 100644 (file)
@@ -385,8 +385,9 @@ class pgsql_native_moodle_database extends moodle_database {
      */
     public function get_columns($table, $usecache=true) {
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -569,7 +570,7 @@ class pgsql_native_moodle_database extends moodle_database {
         pg_free_result($result);
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index c711197..7828eb7 100644 (file)
@@ -201,8 +201,9 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database {
     public function get_columns($table, $usecache=true) {
 
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -299,7 +300,7 @@ class sqlite3_pdo_moodle_database extends pdo_moodle_database {
         }
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index 3d45697..e8d8281 100644 (file)
@@ -462,8 +462,9 @@ class sqlsrv_native_moodle_database extends moodle_database {
      */
     public function get_columns($table, $usecache = true) {
         if ($usecache) {
-            $this->init_caches();
-            if ($data = $this->metacache->get($table)) {
+            $properties = array('dbfamily' => $this->get_dbfamily(), 'settings' => $this->get_settings_hash());
+            $cache = cache::make('core', 'databasemeta', $properties);
+            if ($data = $cache->get($table)) {
                 return $data;
             }
         }
@@ -559,7 +560,7 @@ class sqlsrv_native_moodle_database extends moodle_database {
         $this->free_result($result);
 
         if ($usecache) {
-            $result = $this->metacache->set($table, $structure);
+            $cache->set($table, $structure);
         }
 
         return $structure;
index 8487e9c..7147da3 100644 (file)
@@ -122,5 +122,18 @@ fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastet
         upgrade_plugin_savepoint(true, 2013070500, 'editor', 'tinymce');
     }
 
+    if ($oldversion < 2013102900) {
+        // Reset redesigned editor toolbar setting.
+        $currentorder = get_config('editor_tinymce', 'customtoolbar');
+        // Start with a wrap.
+        $neworder = "wrap,". $currentorder;
+        // Replace all separators with wraps to allow for proper display of groups.
+        $neworder = preg_replace('/\|\|*/', "wrap", $neworder);
+        // Insert a wrap between the format selector and the bold button.
+        $neworder = str_replace("formatselect,bold", "formatselect,wrap,bold", $neworder);
+        set_config('customtoolbar', $neworder, 'editor_tinymce');
+        upgrade_plugin_savepoint(true, 2013102900, 'editor', 'tinymce');
+    }
+
     return true;
 }
index 9e17c83..87bc00a 100644 (file)
@@ -30,7 +30,7 @@ $string['availablebuttons'] = 'Available buttons';
 $string['customconfig'] = 'Custom configuration';
 $string['customconfig_desc'] = 'Custom advanced TinyMCE configuration in JSON format, for example: {"option1" : "value2", "option2" : "value2"}. Any options specified here override standard and plugin settings.';
 $string['customtoolbar'] = 'Editor toolbar';
-$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "|" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.<br />The first row will always be shown, where as the visibility of second and third toolbars can be toggled';
+$string['customtoolbar_desc'] = 'Each line contains a list of comma separated button names, use "wrap" as a group separator, empty lines are ignored. See <a href="{$a}" target="_blank">{$a}</a> for the list of default TinyMCE buttons.<br />The first row will always be shown, where as the visibility of second and third toolbars can be toggled.';
 $string['fontselectlist'] = 'Available fonts list';
 $string['pluginname'] = 'TinyMCE HTML editor';
 $string['settings'] = 'General settings';
index 57ce3d9..2efdfbc 100644 (file)
@@ -59,7 +59,7 @@ header('Content-Type: text/html; charset=utf-8');
 header('X-UA-Compatible: IE=edge');
 ?>
 <!DOCTYPE html>
-<html <?php echo $htmllang ?>
+<html <?php echo $htmllang ?>>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
 <title><?php print_string('title', 'tinymce_dragmath')?></title>
@@ -78,8 +78,8 @@ header('X-UA-Compatible: IE=edge');
 </object>
 <form name="form" action="#">
     <div class="mceActionPanel">
-        <input type="submit" id="insert" name="insert" value="{#insert}" onclick="return DragMathDialog.insert();" />
-        <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="return tinyMCEPopup.close();" />
+        <input type="submit" id="insert" name="insert" value="<?php print_string('common:insert', 'editor_tinymce'); ?>" onclick="return DragMathDialog.insert();" />
+        <input type="button" id="cancel" name="cancel" value="<?php print_string('cancel'); ?>" onclick="return tinyMCEPopup.close();" />
     </div>
 </form>
 
index 7505977..e3d7c1b 100644 (file)
Binary files a/lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.png and b/lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.png differ
diff --git a/lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.svg b/lib/editor/tinymce/plugins/moodlemedia/tinymce/img/icon.svg
new file mode 100644 (file)
index 0000000..69c89a6
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In  -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+        xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+        x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"\r
+        xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<path style="fill:#999999;" d="M0,0v16h16V0H0z M3,15H1v-2h2V15z M3,11H1V9h2V11z M3,7H1V5h2V7z M3,3H1V1h2V3z M12,15H4V1h8V15z\r
+        M15,15h-2v-2h2V15z M15,11h-2V9h2V11z M15,7h-2V5h2V7z M15,3h-2V1h2V3z M10,8l-4,3V5L10,8z"/>\r
+</svg>\r
index e23f60a..4a0148c 100644 (file)
@@ -36,8 +36,6 @@ class tinymce_pdw extends editor_tinymce_plugin {
 
         $rowsnumber = $this->count_button_rows($params);
         if ($rowsnumber > 1) {
-            // Add button before 'undo' in advancedbuttons1.
-            $this->add_button_before($params, 1, '|', '');
             $this->add_button_before($params, 1, 'pdw_toggle', '');
             $params['pdw_toggle_on'] = 1;
             $params['pdw_toggle_toolbars'] = join(',', range(2, $rowsnumber));
index cf2fcb0..17f7516 100644 (file)
@@ -15,3 +15,4 @@ Upgrade procedure:
 5/ reimplement patch in MDL-40668
 6/ add in "DOM.setStyle(ifr, 'width',DOM.getSize(ifrcon).w); // Resize iframe" (without quotes)
    after "DOM.setStyle(ifr, 'height',DOM.getSize(ifr).h + dy); // Resize iframe"
+7/ reimplement patch in MDL-42481
index 8691147..22e42b7 100644 (file)
 \r
             // For very small text areas - allow the editable region to be smaller than the size of the toolbars.\r
             if (rows >= 3) {\r
+                // This set of changes addresses MDL-42481.\r
+                // Moodle collapses form sections by setting display to none on the fcontainer element.\r
+                // In order to calculate the offsetWidth, the iframe must be visible within the DOM, otherwise it's offsetWidth is\r
+                // calculate as 0px.\r
+                // We attempt to find any collapsed element, uncollapse them, then calculate the width and height, and finally\r
+                // collapse them again.\r
+                var collapsedContainer = DOM.getParent(ifr, 'fieldset.collapsed');\r
+                if (collapsedContainer) {\r
+                    DOM.removeClass(collapsedContainer, 'collapsed');\r
+                }\r
+\r
                 DOM.setStyle(ifr, 'height',DOM.getSize(ifr).h + dy); // Resize iframe\r
                 DOM.setStyle(ifr, 'width',DOM.getSize(ifrcon).w); // Resize iframe\r
                 ed.theme.deltaHeight += dy; // For resize cookie\r
+\r
+                if (collapsedContainer) {\r
+                    // We have a collapsedContainer, so collapse it again.\r
+                    DOM.addClass(collapsedContainer, 'collapsed');\r
+                }\r
             }\r
+\r
                },\r
 \r
                /**\r
index 9f0021a..b65b192 100644 (file)
@@ -25,7 +25,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 // The current plugin version (Date: YYYYMMDDXX).
-$plugin->version   = 2013070500;
+$plugin->version   = 2013100700;
 // Required Moodle version.
 $plugin->requires  = 2013050100;
 // Full name of the plugin (used for diagnostics).
index af3d992..d8d57df 100644 (file)
          */
         Wrap : function(id, s) {
             this.parent(id, s);
-            this.groupEndClass = 'mceToolbarEnd';
-            this.groupStartClass = 'mceToolbarStart';
+            this.groupEndClass = 'mceGroupEnd';
+            this.toolbarEndClass = 'mceLast';
+            this.groupEndPlaceholder = 'mceToolbarEndPlaceholder';
+            this.groupStartClass = 'mceGroupStart';
             this.wrapClass = 'mceWrap';
+            this.noWrapClass = 'mceNoWrap';
+            this.toolbarClass = 'mceToolbar';
+            this.selectListArrowClass = 'mceOpen';
             this.setDisabled(true);
         },
 
                                                             'aria-orientation' : 'vertical',
                                                             tabindex : '-1'});
             return '</td>' +
-                   '<td style="position: relative" class="' + this.groupEndClass + '">' + separator + '</td>' +
+                   '<td style="position: relative" class="' + this.groupEndPlaceholder + '">' + separator + '</td>' +
                    '<td style="position: relative" class="' + this.groupStartClass + ' ' + this.wrapClass + '">' + separator + '</td>';
-        }
+        },
+
+        postRender : function() {
+            var self = this;
+            // Add a class to the item prior to the wrap.
+            YUI().use('node', function(Y) {
+                var endGroupElements = tinymce.DOM.select('td.' + self.groupEndPlaceholder),
+                    index = 0, curElement, endOfLast,
+                    endBarElements = tinymce.DOM.select('td.' + self.toolbarEndClass);
 
+                for (index = 0; index < endGroupElements.length; index++) {
+                    if (!endGroupElements.hasOwnProperty(index)) {
+                          continue;
+                    }
+                    curElement = Y.one(endGroupElements[index]);
+                    endOfLast = curElement.previous('td').previous('td');
+                    if (endOfLast) {
+                        endOfLast.addClass(self.groupEndClass);
+                    }
+                }
+                for (index = 0; index < endBarElements.length; index++) {
+                    if (!endBarElements.hasOwnProperty(index)) {
+                        continue;
+                    }
+                    curElement = Y.one(endBarElements[index]);
+                    endOfLast = curElement.previous('td');
+                    if (endOfLast) {
+                        endOfLast.addClass(self.groupEndClass);
+                    }
+                }
+                // Any separators closer together than 5 buttons get the noWrapClass.
+                var toolbars = Y.all('table.' + self.toolbarClass),
+                    buttonWrapPoint = 5;
 
+                toolbars.each(function(toolbar) {
+                    var count = 0;
+                    widgets = toolbar.all('td.' + self.wrapClass + ', td > a');
+                    widgets.each(function(widget) {
+                        if (widget.hasClass(self.wrapClass)) {
+                            if (count >= buttonWrapPoint) {
+                                count = 0;
+                            } else {
+                                widget.addClass(self.noWrapClass);
+                            }
+                        } else {
+                            if (widget.hasClass(self.selectListArrowClass) ||
+                                    (widget.getAttribute('role') === 'button')) {
+                                count++;
+                            } else {
+                                // Count select inputs as 3 buttons. The down arrow on the select also gets counted so 2+1 = 3.
+                                count += 2;
+                            }
+                        }
+                    });
+                });
+
+            });
+        }
     });
 
     tinymce.create('tinymce.plugins.wrapPlugin', {
index da3828d..6b16074 100644 (file)
@@ -15,6 +15,7 @@ Upgrade procedure:
 4/ update ./thirdpartylibs.xml
 5/ execute cli/update_lang_files.php and review changes in lang/en/editor_tinymce.php
 6/ use search/replace to fix oversized zIndexes
+7/ add moodle-has-zindex to the class definition in createColorSplitButton() in tiny_mce_src.js and tiny_mce.js
 
 
 Changes:
index 3699c51..b8ca304 100644 (file)
@@ -31,11 +31,11 @@ if ($ADMIN->fulltree) {
     require_once(__DIR__.'/adminlib.php');
     $settings->add(new tiynce_subplugins_settings());
     $settings->add(new admin_setting_heading('tinymcegeneralheader', new lang_string('settings'), ''));
-    $default = "formatselect,bold,italic,wrap,bullist,numlist,|,link,unlink,|,image
+    $default = "wrap,formatselect,wrap,bold,italic,wrap,bullist,numlist,wrap,link,unlink,wrap,image
 
-undo,redo,|,underline,strikethrough,sub,sup,|,justifyleft,justifycenter,justifyright,wrap,outdent,indent,|,forecolor,backcolor,|,ltr,rtl,|,nonbreaking,charmap,table
+undo,redo,wrap,underline,strikethrough,sub,sup,wrap,justifyleft,justifycenter,justifyright,wrap,outdent,indent,wrap,forecolor,backcolor,wrap,ltr,rtl,wrap,nonbreaking,charmap,table
 
-fontselect,fontsizeselect,wrap,code,search,replace,|,cleanup,removeformat,pastetext,pasteword,|,fullscreen";
+fontselect,fontsizeselect,wrap,code,search,replace,wrap,cleanup,removeformat,pastetext,pasteword,wrap,fullscreen";
     $settings->add(new admin_setting_configtextarea('editor_tinymce/customtoolbar',
         get_string('customtoolbar', 'editor_tinymce'), get_string('customtoolbar_desc', 'editor_tinymce', 'http://www.tinymce.com/wiki.php/TinyMCE3x:Buttons/controls'), $default, PARAM_RAW, 100, 8));
     $settings->add(new admin_setting_configtextarea('editor_tinymce/fontselectlist',
index 9398912..86703ef 100644 (file)
@@ -3,8 +3,14 @@
         float: left;
         display: inline-block;
     }
-    .mceToolbar .mceWrap {
+    .moodleSkin .mceLayout .mceToolbar .mceWrap {
         clear: left;
+        width: 100%;
+        height: 8px;
+    }
+    .moodleSkin .mceLayout .mceToolbar .mceNoWrap {
+        clear: none;
+        width: 0px;
     }
 
     .o2k7Skin tr.mceLast .mceToolbar tr td.mceWrap,
index 93c2f08..a3c8e6a 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/abbr.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/abbr.png differ
index be8883c..3bc7d46 100644 (file)
@@ -5,16 +5,16 @@
 ]>\r
 <svg version="1.1"\r
         xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
-        x="0px" y="0px" width="16px" height="16px" viewBox="-0.3 -3.6 16 16"\r
-        style="overflow:visible;enable-background:new -0.3 -3.6 16 16;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+        x="0px" y="0px" width="16px" height="16px" viewBox="0 -3.9 16 16" style="overflow:visible;enable-background:new 0 -3.9 16 16;"\r
+        xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M0,8c0.3,0,0.5-0.2,0.7-0.4c0.1-0.2,0.3-0.5,0.5-1L3.8,0h0.3l2.7,6.3C7.2,7,7.4,7.5,7.5,7.7\r
-       S7.9,8,8.2,8v0.3H4.3V8c0.4,0,0.6,0,0.8-0.1s0.2-0.2,0.2-0.4c0-0.1,0-0.2-0.1-0.4c0-0.1-0.1-0.2-0.2-0.4L4.7,5.9H2\r
-       C1.8,6.4,1.7,6.7,1.6,6.8C1.5,7.2,1.5,7.4,1.5,7.5c0,0.2,0.1,0.3,0.3,0.4C2,7.9,2.2,8,2.4,8v0.3H0V8z M4.5,5.4L3.4,2.7H3.2L2.2,5.4\r
-       H4.5z M9.8,0.2v3.1C10,3.1,10.1,3,10.3,2.9c0.3-0.2,0.6-0.2,0.9-0.2c0.7,0,1.2,0.3,1.6,0.8s0.6,1.2,0.6,1.9c0,1-0.3,1.8-0.8,2.3\r
-       s-1.2,0.8-2,0.8c-0.3,0-0.6-0.1-0.8-0.2S9.4,8,9.2,7.8L8.3,8.4H8.1V1.1c0-0.3,0-0.4-0.1-0.5C7.9,0.5,7.7,0.5,7.5,0.5V0.2H9.8z\r
-        M9.9,7.6c0.1,0.3,0.4,0.4,0.7,0.4c0.4,0,0.7-0.2,0.9-0.7c0.2-0.4,0.3-1,0.3-1.8c0-0.6-0.1-1.2-0.2-1.6s-0.4-0.7-0.9-0.7\r
-       c-0.3,0-0.5,0.1-0.6,0.3C9.9,3.7,9.8,3.9,9.8,4v3.2C9.8,7.3,9.8,7.5,9.9,7.6z M14,6.7c0.2-0.2,0.4-0.3,0.7-0.3s0.5,0.1,0.7,0.3\r
-       s0.3,0.4,0.3,0.7S15.6,8,15.4,8.1S15,8.4,14.7,8.4S14.2,8.3,14,8.1s-0.3-0.4-0.3-0.7S13.8,6.9,14,6.7z"/>\r
+<path style="fill:#999999;" d="M15,6.2c0.3,0,0.5,0.1,0.7,0.3S16,6.9,16,7.1s-0.1,0.5-0.3,0.7S15.3,8.1,15,8.1S14.5,8,14.3,7.8\r
+       S14,7.4,14,7.1s0.1-0.5,0.3-0.7S14.8,6.2,15,6.2z M10.3,0v3c0.5-0.5,1-0.7,1.5-0.7c0.4,0,0.7,0.1,1.1,0.3s0.6,0.5,0.8,0.9\r
+       s0.3,0.9,0.3,1.4c0,0.6-0.1,1.1-0.4,1.6s-0.6,0.9-1,1.1s-0.9,0.4-1.4,0.4c-0.3,0-0.6,0-0.8-0.1S10,7.7,9.8,7.5L8.8,8.1H8.7v-7\r
+       c0-0.3,0-0.5,0-0.6c0-0.1-0.1-0.2-0.2-0.2S8.2,0.2,8,0.2V0H10.3z M10.3,3.5V6c0,0.5,0,0.8,0,0.9c0,0.2,0.1,0.4,0.3,0.6\r
+       s0.3,0.2,0.6,0.2c0.2,0,0.4-0.1,0.5-0.2s0.3-0.3,0.4-0.7s0.1-0.9,0.1-1.8c0-0.8-0.1-1.4-0.3-1.7C11.7,3.1,11.5,3,11.2,3\r
+       C10.9,3,10.6,3.2,10.3,3.5z M4.9,5.8H2.1L1.8,6.6C1.6,6.9,1.6,7.1,1.6,7.3c0,0.2,0.1,0.4,0.3,0.5C2,7.8,2.2,7.9,2.6,7.9v0.2H0V7.9\r
+       c0.3,0,0.5-0.2,0.7-0.4s0.4-0.6,0.7-1.2L4.2,0h0.1l2.9,6.5c0.3,0.6,0.5,1,0.7,1.2C8,7.8,8.2,7.9,8.4,7.9v0.2H4.6V7.9h0.2\r
+       c0.3,0,0.5,0,0.7-0.1c0.1-0.1,0.1-0.2,0.1-0.3c0-0.1,0-0.1,0-0.2c0,0-0.1-0.2-0.2-0.4L4.9,5.8z M4.7,5.4L3.5,2.7L2.3,5.4H4.7z"/>\r
 </svg>\r
index 73488d8..40b68a4 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/acronym.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/acronym.png differ
index 3d4dc46..bde1557 100644 (file)
@@ -5,20 +5,17 @@
 ]>\r
 <svg version="1.1"\r
         xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
-        x="0px" y="0px" width="16px" height="16px" viewBox="0 -4.6 16 16" style="overflow:visible;enable-background:new 0 -4.6 16 16;"\r
+        x="0px" y="0px" width="16px" height="16px" viewBox="0 -3.9 16 16" style="overflow:visible;enable-background:new 0 -3.9 16 16;"\r
         xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M0,6c0.2,0,0.4-0.1,0.5-0.3c0.1-0.1,0.2-0.4,0.4-0.8l2-4.9h0.3l2,4.7c0.2,0.5,0.4,0.9,0.5,1\r
-       C5.8,5.9,5.9,6,6.1,6v0.2H3.2V6c0.3,0,0.5,0,0.6-0.1c0.1,0,0.1-0.1,0.1-0.3c0-0.1,0-0.2-0.1-0.3c0-0.1-0.1-0.2-0.1-0.3L3.5,4.4h-2\r
-       C1.4,4.8,1.3,5,1.2,5.1C1.2,5.4,1.1,5.5,1.1,5.6c0,0.1,0.1,0.2,0.3,0.3C1.5,6,1.6,6,1.8,6v0.2H0V6z M3.4,4.1L2.5,2H2.4L1.6,4.1H3.4z\r
-        M5.6,6c0.2,0,0.4,0,0.5-0.1c0.2-0.1,0.3-0.3,0.3-0.5V1c0-0.3-0.1-0.4-0.3-0.5C6,0.4,5.8,0.4,5.6,0.4V0.1h2.8c0.5,0,1,0.1,1.3,0.2\r
-       c0.7,0.2,1,0.7,1,1.3c0,0.4-0.1,0.7-0.4,0.9C10,2.7,9.7,2.8,9.4,2.9V3C9.7,3,10,3.1,10.3,3.3C10.8,3.6,11,4,11,4.5\r
-       c0,0.5-0.2,0.9-0.7,1.2C9.9,6.1,9.2,6.2,8.5,6.2H5.6V6z M8.9,2.6c0.2-0.2,0.3-0.5,0.3-1C9.2,1.3,9.2,1,9,0.7\r
-       C8.9,0.5,8.7,0.4,8.3,0.4c-0.2,0-0.3,0-0.4,0.1S7.8,0.7,7.8,0.8v2C8.4,2.9,8.7,2.8,8.9,2.6z M7.9,5.7C8,5.9,8.1,5.9,8.3,5.9\r
-       c0.4,0,0.7-0.1,0.9-0.3c0.2-0.2,0.3-0.6,0.3-1c0-0.6-0.2-1.1-0.6-1.3C8.7,3.2,8.3,3.1,7.8,3.1v2.2C7.8,5.5,7.8,5.6,7.9,5.7z\r
-        M15.2,0.2c0.4,0.1,0.6,0.2,0.6,0.2c0.1,0,0.2,0,0.3-0.1c0.1-0.1,0.1-0.2,0.1-0.3h0.3v2.1h-0.2C16,1.7,15.8,1.3,15.6,1\r
-       c-0.4-0.5-0.9-0.7-1.4-0.7c-0.6,0-1,0.3-1.3,0.8c-0.3,0.5-0.4,1.2-0.4,2.1c0,0.6,0.1,1.2,0.2,1.6c0.3,0.8,0.8,1.2,1.5,1.2\r
-       c0.5,0,0.9-0.1,1.3-0.4c0.2-0.1,0.5-0.4,0.8-0.7l0.3,0.2c-0.4,0.4-0.7,0.7-0.9,0.9c-0.5,0.3-1,0.5-1.6,0.5c-0.9,0-1.6-0.3-2.2-0.8\r
-       c-0.7-0.6-1-1.4-1-2.4c0-1,0.3-1.8,1-2.4C12.4,0.3,13.2,0,14,0C14.4,0,14.8,0.1,15.2,0.2z"/>\r
+<path style="fill:#999999;" d="M13.8,3.8C14.5,4,15,4.2,15.3,4.5C15.8,4.8,16,5.3,16,5.9c0,0.6-0.2,1.1-0.7,1.5\r
+       c-0.6,0.5-1.4,0.7-2.6,0.7h-4V7.8c0.4,0,0.6,0,0.7-0.1s0.2-0.2,0.3-0.3s0.1-0.4,0.1-0.8V1.5c0-0.4,0-0.7-0.1-0.8S9.5,0.5,9.4,0.4\r
+       S9,0.3,8.7,0.3V0.1h3.8c0.9,0,1.6,0.1,1.9,0.2s0.7,0.4,0.9,0.7s0.3,0.7,0.3,1c0,0.4-0.1,0.7-0.4,1S14.5,3.7,13.8,3.8z M11.6,4.1v2.5\r
+       l0,0.3c0,0.2,0.1,0.4,0.2,0.5s0.3,0.2,0.5,0.2c0.3,0,0.6-0.1,0.9-0.2s0.5-0.3,0.6-0.6s0.2-0.6,0.2-0.9c0-0.4-0.1-0.7-0.3-1\r
+       S13.3,4.4,13,4.3S12.2,4.1,11.6,4.1z M11.6,3.7c0.6,0,1-0.1,1.2-0.2s0.5-0.3,0.6-0.5s0.2-0.5,0.2-0.9s-0.1-0.6-0.2-0.9\r
+       s-0.3-0.4-0.6-0.5s-0.7-0.2-1.2-0.2V3.7z M4.9,5.8H2.1L1.8,6.6C1.6,6.9,1.6,7.1,1.6,7.3c0,0.2,0.1,0.4,0.3,0.5\r
+       C2,7.8,2.2,7.9,2.6,7.9v0.2H0V7.9c0.3,0,0.5-0.2,0.7-0.4s0.4-0.6,0.7-1.2L4.2,0h0.1l2.9,6.5c0.3,0.6,0.5,1,0.7,1.2\r
+       C8,7.8,8.2,7.9,8.4,7.9v0.2H4.6V7.9h0.2c0.3,0,0.5,0,0.7-0.1c0.1-0.1,0.1-0.2,0.1-0.3c0-0.1,0-0.1,0-0.2c0,0-0.1-0.2-0.2-0.4\r
+       L4.9,5.8z M4.7,5.4L3.5,2.7L2.3,5.4H4.7z"/>\r
 </svg>\r
index 2d76266..19bf15b 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_center.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_center.png differ
index f6eae29..5b4bea9 100644 (file)
@@ -9,5 +9,5 @@
         xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M0,0h16v2H0V0z M0,6h16v2H0V6z M0,12h16v2H0V12z M3,3h10v2H3V3z M3,9h10v2H3V9z"/>\r
+<path style="fill:#999999;" d="M0,12h16v2H0V12z M13,9H3v2h10V9z M0,8h16V6H0V8z M13,3H3v2h10V3z M16,0H0v2h16V0z"/>\r
 </svg>\r
index 1d87f1c..524002d 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_left.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_left.png differ
index b792e41..5e79a65 100644 (file)
@@ -9,5 +9,5 @@
         xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M0,0h16v2H0V0z M0,3h10v2H0V3z M0,6h16v2H0V6z M0,9h10v2H0V9z M0,12h16v2H0V12z"/>\r
+<path style="fill:#999999;" d="M0,12h16v2H0V12z M10,9H0v2h10V9z M0,8h16V6H0V8z M10,3H0v2h10V3z M16,2V0H0v2H16z"/>\r
 </svg>\r
index 113b735..ab92fb6 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_right.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/align_right.png differ
index c636b9e..961a31e 100644 (file)
@@ -9,5 +9,5 @@
         xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M0,0h16v2H0V0z M0,6h16v2H0V6z M0,12h16v2H0V12z M6,3h10v2H6V3z M6,9h10v2H6V9z"/>\r
+<path style="fill:#999999;" d="M0,12h16v2H0V12z M0,0v2h16V0H0z M6,11h10V9H6V11z M0,8h16V6H0V8z M6,5h10V3H6V5z"/>\r
 </svg>\r
diff --git a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.png b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.png
new file mode 100644 (file)
index 0000000..f5137ee
Binary files /dev/null and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.png differ
diff --git a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.svg b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/attributes.svg
new file mode 100644 (file)
index 0000000..937f444
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In  -->\r
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
+       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
+]>\r
+<svg version="1.1"\r
+        xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
+        x="0px" y="0px" width="16px" height="16px" viewBox="0 -0.1 16 16" style="overflow:visible;enable-background:new 0 -0.1 16 16;"\r
+        xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
+<defs>\r
+</defs>\r
+<path style="fill:#999999;" d="M14,5.4v9.5H0v-13h10.5l-2,2H1v10h12V6.4L14,5.4z M14.5,3.5l1.1-1.1C16,2,16,1.4,15.6,1l-0.7-0.7\r
+       c-0.4-0.4-1-0.4-1.4,0l-1.1,1.1L14.5,3.5z M13.7,4.3L8.1,9.9L6,9.9l0-2.1l5.6-5.6L13.7,4.3z"/>\r
+</svg>\r
index 0f9b1cf..a372dd6 100644 (file)
Binary files a/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bold.png and b/lib/editor/tinymce/tiny_mce/3.5.8/themes/advanced/skins/moodle/img/bold.png differ
index 3f460e3..010f748 100644 (file)
@@ -5,12 +5,14 @@
 ]>\r
 <svg version="1.1"\r
         xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"\r
-        x="0px" y="0px" width="16px" height="16px" viewBox="-2.3 0 16 16" style="overflow:visible;enable-background:new -2.3 0 16 16;"\r
+        x="0px" y="0px" width="16px" height="16px" viewBox="-1 -1 16 16" style="overflow:visible;enable-background:new -1 -1 16 16;"\r
         xml:space="preserve" preserveAspectRatio="xMinYMid meet">\r
 <defs>\r
 </defs>\r
-<path style="fill:#999999;" d="M10.8,9.2c0.4,0.7,0.6,1.5,0.6,2.3c0,1.3-0.4,2.3-1.3,3.2S8.1,16,6.9,16H3.4H1.1H0V0h1.1h2.3h2.3\r
-       C7,0,8.1,0.4,8.9,1.3c0.9,0.9,1.3,2,1.3,3.2c0,1.1-0.4,2.1-1.1,2.9C9.9,7.9,10.4,8.5,10.8,9.2z M3.4,6.9h1.8c0.5,0,0.9-0.2,1.3-0.7\r
-       c0.4-0.5,0.5-1,0.5-1.6C7.1,4,6.9,3.4,6.5,3C6.2,2.5,5.7,2.3,5.2,2.3H3.4V6.9z M7.6,13c0.4-0.5,0.6-1,0.6-1.6c0-0.6-0.2-1.2-0.6-1.6\r
-       C7.2,9.4,6.8,9.1,6.3,9.1H3.4v4.6h2.9C6.8,13.7,7.2,13.5,7.6,13z"/>\r
+<path style="fill:#999999;" d="M0,14.6c0.9-0.1,1.5-0.2,1.8-0.4s0.4-0.8,0.4-1.6V2.5c0-0.8-0.1-1.4-0.4-1.6C1.5,0.6,0.9,0.5,0,0.4V0\r
+       h6.3c1.8,0,3.3,0.3,4.3,0.9c1.1,0.6,1.6,1.6,1.6,3c0,1.1-0.4,1.9-1.1,2.4c-0.4,0.3-1.1,0.6-1.9,0.8c1,0.3,1.9,0.7,2.7,1.3\r
+       C12.7,9,13,9.8,13,10.8c0,1.8-0.8,3-2.5,3.7C9.7,14.8,8.6,15,7.4,15H0V14.6z M8.5,6.4C9.5,5.9,10,5.1,10,4c0-1.4-0.6-2.3-1.7-2.7\r
+       C7.7,1,6.8,0.8,5.5,0.8C5,0.8,4.7,0.9,4.6,1C4.5,1,4.5,1.3,4.5,1.6v5.1l2.2,0C7.4,6.7,8,6.6,8.5,6.4z M9.3,13.5\r
+       c0.8-0.5,1.2-1.3,1.2-2.6c0-1.3-0.5-2.1-1.4-2.6C8.1,7.8,7,7.6,5.6,7.6c-0.3,0-0.6,0-0.7,0s-0.2,0-0.4,0v5.6c0,0.4,0.1,0.6,0.3,0.8\r
+       c0.2,0.1,0.7,0.2,1.5,0.2C7.5,14.2,8.5,14,9.3,13.5z"/>\r
 </svg>\r